/*
 * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
 * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "BytecodeDumper.h"

#include "BytecodeGenerator.h"
#include "BytecodeGraph.h"
#include "BytecodeStructs.h"
#include "CodeBlock.h"
#include "JSCJSValueInlines.h"
#include "UnlinkedCodeBlockGenerator.h"
#include "UnlinkedMetadataTableInlines.h"
#include "WasmFunctionCodeBlockGenerator.h"
#include "WasmGeneratorTraits.h"
#include "WasmModuleInformation.h"
#include "WasmTypeDefinitionInlines.h"

namespace JSC {

template<typename InstructionStreamType>
void BytecodeDumperBase<InstructionStreamType>::printLocationAndOp(typename InstructionStreamType::Offset location, const char* op)
{
    m_currentLocation = location;
    m_out.printf("[%4u] %-18s ", location, op);
}

template<typename InstructionStreamType>
void BytecodeDumperBase<InstructionStreamType>::dumpValue(VirtualRegister reg)
{
    m_out.printf("%s", registerName(reg).data());
}

template<typename InstructionStreamType>
template<typename Traits>
void BytecodeDumperBase<InstructionStreamType>::dumpValue(GenericBoundLabel<Traits> label)
{
    int target = label.target();
    if (!target)
        target = outOfLineJumpOffset(m_currentLocation);
    auto targetOffset = target + m_currentLocation;
    m_out.print(target, "(->", targetOffset, ")");
}

template void BytecodeDumperBase<JSInstructionStream>::dumpValue(GenericBoundLabel<JSGeneratorTraits>);

#if ENABLE(WEBASSEMBLY)
template void BytecodeDumperBase<WasmInstructionStream>::dumpValue(GenericBoundLabel<Wasm::GeneratorTraits>);
#endif // ENABLE(WEBASSEMBLY)

template<class Block>
CString BytecodeDumper<Block>::registerName(VirtualRegister r) const
{
    if (r.isConstant())
        return constantName(r);

    return toCString(r);
}

template <class Block>
int BytecodeDumper<Block>::outOfLineJumpOffset(JSInstructionStream::Offset offset) const
{
    return m_block->outOfLineJumpOffset(offset);
}

template<class Block>
CString BytecodeDumper<Block>::constantName(VirtualRegister reg) const
{
    auto value = block()->getConstant(reg);
    return toCString(value, "(", reg, ")");
}

template<class Block>
void BytecodeDumper<Block>::dumpBytecode(const JSInstructionStream::Ref& it, const ICStatusMap&)
{
    ::JSC::dumpBytecode(this, it.offset(), it.ptr());
    this->m_out.print("\n");
}

template<class Block>
void BytecodeDumper<Block>::dumpBytecode(Block* block, PrintStream& out, const JSInstructionStream::Ref& it, const ICStatusMap& statusMap)
{
    BytecodeDumper dumper(block, out);
    dumper.dumpBytecode(it, statusMap);
}

template<class Block>
VM& CodeBlockBytecodeDumper<Block>::vm() const
{
    return this->block()->vm();
}

template<class Block>
const Identifier& CodeBlockBytecodeDumper<Block>::identifier(int index) const
{
    return this->block()->identifier(index);
}

template<class Block>
void CodeBlockBytecodeDumper<Block>::dumpIdentifiers()
{
    if (size_t count = this->block()->numberOfIdentifiers()) {
        this->m_out.printf("\nIdentifiers:\n");
        size_t i = 0;
        do {
            this->m_out.print("  id", static_cast<unsigned>(i), " = ", identifier(i), "\n");
            ++i;
        } while (i != count);
    }
}

template<class Block>
void CodeBlockBytecodeDumper<Block>::dumpConstants()
{
    if (!this->block()->constantRegisters().isEmpty()) {
        this->m_out.printf("\nConstants:\n");
        size_t i = 0;
        for (const auto& constant : this->block()->constantRegisters()) {
            const char* sourceCodeRepresentationDescription = nullptr;
            switch (this->block()->constantSourceCodeRepresentation(i)) {
            case SourceCodeRepresentation::Double:
                sourceCodeRepresentationDescription = ": in source as double";
                break;
            case SourceCodeRepresentation::Integer:
                sourceCodeRepresentationDescription = ": in source as integer";
                break;
            case SourceCodeRepresentation::Other:
                sourceCodeRepresentationDescription = "";
                break;
            case SourceCodeRepresentation::LinkTimeConstant:
                sourceCodeRepresentationDescription = ": in source as link-time-constant";
                break;
            }
            this->m_out.printf("   k%u = %s%s\n", static_cast<unsigned>(i), toCString(constant.get()).data(), sourceCodeRepresentationDescription);
            ++i;
        }
    }
}

template<class Block>
void CodeBlockBytecodeDumper<Block>::dumpExceptionHandlers()
{
    if (unsigned count = this->block()->numberOfExceptionHandlers()) {
        this->m_out.printf("\nException Handlers:\n");
        unsigned i = 0;
        do {
            const auto& handler = this->block()->exceptionHandler(i);
            this->m_out.printf("\t %d: { start: [%4d] end: [%4d] target: [%4d] } %s\n", i + 1, handler.start, handler.end, handler.target, handler.typeName());
            ++i;
        } while (i < count);
    }
}

template<class Block>
void CodeBlockBytecodeDumper<Block>::dumpSwitchJumpTables()
{
    if (unsigned count = this->block()->numberOfUnlinkedSwitchJumpTables()) {
        this->m_out.printf("Switch Jump Tables:\n");
        unsigned i = 0;
        do {
            this->m_out.printf("  %1d = {\n", i);
            const auto& switchJumpTable = this->block()->unlinkedSwitchJumpTable(i);
            int entry = 0;
            auto end = switchJumpTable.m_branchOffsets.end();
            for (auto iter = switchJumpTable.m_branchOffsets.begin(); iter != end; ++iter, ++entry) {
                if (!*iter)
                    continue;
                this->m_out.printf("\t\t%4d => %04d\n", entry + switchJumpTable.m_min, *iter);
            }
            this->m_out.printf("      }\n");
            ++i;
        } while (i < count);
    }
}

template<class Block>
void CodeBlockBytecodeDumper<Block>::dumpStringSwitchJumpTables()
{
    if (unsigned count = this->block()->numberOfUnlinkedStringSwitchJumpTables()) {
        this->m_out.printf("\nString Switch Jump Tables:\n");
        unsigned i = 0;
        do {
            this->m_out.printf("  %1d = {\n", i);
            for (const auto& entry : this->block()->unlinkedStringSwitchJumpTable(i).m_offsetTable)
                this->m_out.printf("\t\t\"%s\" => %04d\n", entry.key->utf8().data(), entry.value.m_branchOffset);
            this->m_out.printf("      }\n");
            ++i;
        } while (i < count);
    }
}

template <typename Block>
static void dumpHeader(Block* block, const JSInstructionStream& instructions, PrintStream& out)
{
    size_t instructionCount = 0;
    size_t wide16InstructionCount = 0;
    size_t wide32InstructionCount = 0;
    size_t instructionWithMetadataCount = 0;

    for (const auto& instruction : instructions) {
        if (instruction->isWide16())
            ++wide16InstructionCount;
        else if (instruction->isWide32())
            ++wide32InstructionCount;
        if (instruction->hasMetadata())
            ++instructionWithMetadataCount;
        ++instructionCount;
    }

    out.print(*block);
    out.printf(
        ": %lu instructions (%lu 16-bit instructions, %lu 32-bit instructions, %lu instructions with metadata); %lu bytes (%lu metadata bytes); %d parameter(s); %d callee register(s); %d variable(s)",
        static_cast<unsigned long>(instructionCount),
        static_cast<unsigned long>(wide16InstructionCount),
        static_cast<unsigned long>(wide32InstructionCount),
        static_cast<unsigned long>(instructionWithMetadataCount),
        static_cast<unsigned long>(instructions.sizeInBytes() + block->metadataSizeInBytes()),
        static_cast<unsigned long>(block->metadataSizeInBytes()),
        block->numParameters(), block->numCalleeLocals(), block->numVars());
    out.print("; scope at ", block->scopeRegister());
    out.printf("\n");
}

template <typename Dumper>
static void dumpFooter(Dumper& dumper)
{
    dumper.dumpIdentifiers();
    dumper.dumpConstants();
    dumper.dumpExceptionHandlers();
    dumper.dumpSwitchJumpTables();
    dumper.dumpStringSwitchJumpTables();
}

template<class Block>
void CodeBlockBytecodeDumper<Block>::dumpBlock(Block* block, const JSInstructionStream& instructions, PrintStream& out, const ICStatusMap& statusMap)
{
    dumpHeader(block, instructions, out);

    CodeBlockBytecodeDumper<Block> dumper(block, out);
    for (const auto& it : instructions)
        dumper.dumpBytecode(it, statusMap);

    dumpFooter(dumper);

    out.printf("\n");
}

template<class Block>
void CodeBlockBytecodeDumper<Block>::dumpGraph(Block* block, const JSInstructionStream& instructions, BytecodeGraph& graph, PrintStream& out, const ICStatusMap& icStatusMap)
{
    dumpHeader(block, instructions, out);

    CodeBlockBytecodeDumper<Block> dumper(block, out);

    out.printf("\n");

    Vector<Vector<unsigned>> predecessors;
    predecessors.resize(graph.size());
    for (auto& block : graph) {
        if (block.isEntryBlock() || block.isExitBlock())
            continue;
        for (auto successorIndex : block.successors()) {
            if (!predecessors[successorIndex].contains(block.index()))
                predecessors[successorIndex].append(block.index());
        }
    }

    for (auto& block : graph) {
        if (block.isEntryBlock() || block.isExitBlock())
            continue;

        out.print("bb#", block.index(), "\n");

        out.print("Predecessors: [");
        for (unsigned predecessor : predecessors[block.index()]) {
            if (!graph[predecessor].isEntryBlock())
                out.print(" #", predecessor);
        }
        out.print(" ]\n");

        for (unsigned i = 0; i < block.totalLength(); ) {
            auto& currentInstruction = instructions.at(i + block.leaderOffset());
            dumper.dumpBytecode(currentInstruction, icStatusMap);
            i += currentInstruction.ptr()->size();
        }

        out.print("Successors: [");
        for (unsigned successor : block.successors()) {
            if (!graph[successor].isExitBlock())
                out.print(" #", successor);
        }
        out.print(" ]\n\n");
    }

    dumpFooter(dumper);

    out.printf("\n");
}

template class BytecodeDumperBase<JSInstructionStream>;
template class BytecodeDumper<CodeBlock>;
template class CodeBlockBytecodeDumper<UnlinkedCodeBlockGenerator>;
template class CodeBlockBytecodeDumper<CodeBlock>;

#if ENABLE(WEBASSEMBLY)

template class BytecodeDumperBase<WasmInstructionStream>;

namespace Wasm {

void BytecodeDumper::dumpBlock(FunctionCodeBlockGenerator* block, const ModuleInformation& moduleInformation, PrintStream& out)
{
    size_t instructionCount = 0;
    size_t wide16InstructionCount = 0;
    size_t wide32InstructionCount = 0;

    for (auto it = block->instructions().begin(); it != block->instructions().end(); it += it->size()) {
        if (it->isWide16())
            ++wide16InstructionCount;
        else if (it->isWide32())
            ++wide32InstructionCount;
        ++instructionCount;
    }

    size_t functionIndexSpace = moduleInformation.importFunctionCount() + block->functionIndex();
    out.print(makeString(IndexOrName(functionIndexSpace, moduleInformation.nameSection->get(functionIndexSpace))));

    const auto& function = moduleInformation.functions[block->functionIndex()];
    TypeIndex typeIndex = moduleInformation.internalFunctionTypeIndices[block->functionIndex()];
    const auto& typeDefinition = TypeInformation::get(typeIndex);
    out.print(" : ", typeDefinition, "\n");
    out.print("wasm size: ", function.data.size(), " bytes\n");

    out.printf(
        "bytecode: %lu instructions (%lu 16-bit instructions, %lu 32-bit instructions); %lu bytes; %d parameter(s); %d local(s); %d callee register(s)\n",
        static_cast<unsigned long>(instructionCount),
        static_cast<unsigned long>(wide16InstructionCount),
        static_cast<unsigned long>(wide32InstructionCount),
        static_cast<unsigned long>(block->instructions().sizeInBytes()),
        block->numArguments(),
        block->numVars(),
        block->numCalleeLocals());

    BytecodeDumper dumper(block, out);
    for (auto it = block->instructions().begin(); it != block->instructions().end(); it += it->size()) {
        dumpWasm(&dumper, it.offset(), it.ptr());
        out.print("\n");
    }

    dumper.dumpConstants();

    out.printf("\n");
}

void BytecodeDumper::dumpConstants()
{
    FunctionCodeBlockGenerator* block = this->block();
    if (!block->constants().isEmpty()) {
        this->m_out.printf("\nConstants:\n");
        unsigned i = 0;
        for (const auto& constant : block->constants()) {
            Type type = block->constantTypes()[i];
            this->m_out.print("   const", i, " : ", type.kind, " = ", formatConstant(type, constant), "\n");
            ++i;
        }
    }
}

CString BytecodeDumper::constantName(VirtualRegister index) const
{
    FunctionCodeBlockGenerator* block = this->block();
    auto value = formatConstant(block->getConstantType(index), block->getConstant(index));
    return toCString(value, "(", VirtualRegister(index), ")");
}

CString BytecodeDumper::formatConstant(Type type, uint64_t constant) const
{
    switch (type.kind) {
    case TypeKind::I32:
        return toCString(static_cast<int32_t>(constant));
    case TypeKind::I64:
        return toCString(constant);
    case TypeKind::F32:
        return toCString(bitwise_cast<float>(static_cast<int32_t>(constant)));
        break;
    case TypeKind::F64:
        return toCString(bitwise_cast<double>(constant));
        break;
    default: {
        if (isFuncref(type) || isExternref(type)) {
            if (JSValue::decode(constant) == jsNull())
                return "null";
            return toCString(RawPointer(bitwise_cast<void*>(static_cast<uintptr_t>(constant))));
        }

        RELEASE_ASSERT_NOT_REACHED();
        return "";
    }
    }
}

CString BytecodeDumper::registerName(VirtualRegister r) const
{
    if (r.isConstant())
        return constantName(r);

    return toCString(r);
}

int BytecodeDumper::outOfLineJumpOffset(WasmInstructionStream::Offset offset) const
{
    return m_block->outOfLineJumpOffset(offset);
}

} // namespace Wasm

#endif // ENABLE(WEBASSEMBLY)
}
