// Copyright 2011 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/disassembler.h"

#include <memory>
#include <vector>

#include "src/assembler-inl.h"
#include "src/code-reference.h"
#include "src/code-stubs.h"
#include "src/debug/debug.h"
#include "src/deoptimizer.h"
#include "src/disasm.h"
#include "src/ic/ic.h"
#include "src/macro-assembler.h"
#include "src/objects-inl.h"
#include "src/snapshot/serializer-common.h"
#include "src/string-stream.h"
#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-engine.h"

namespace v8 {
namespace internal {

#ifdef ENABLE_DISASSEMBLER

class V8NameConverter: public disasm::NameConverter {
 public:
  explicit V8NameConverter(Isolate* isolate, CodeReference code = {})
      : isolate_(isolate), code_(code) {}
  const char* NameOfAddress(byte* pc) const override;
  const char* NameInCode(byte* addr) const override;
  const char* RootRelativeName(int offset) const override;

  const CodeReference& code() const { return code_; }

 private:
  Isolate* isolate_;
  CodeReference code_;

  EmbeddedVector<char, 128> v8_buffer_;
};


const char* V8NameConverter::NameOfAddress(byte* pc) const {
  if (!code_.is_null()) {
    const char* name =
        isolate_ ? isolate_->builtins()->Lookup(reinterpret_cast<Address>(pc))
                 : nullptr;

    if (name != nullptr) {
      SNPrintF(v8_buffer_, "%p  (%s)", static_cast<void*>(pc), name);
      return v8_buffer_.start();
    }

    int offs = static_cast<int>(reinterpret_cast<Address>(pc) -
                                code_.instruction_start());
    // print as code offset, if it seems reasonable
    if (0 <= offs && offs < code_.instruction_size()) {
      SNPrintF(v8_buffer_, "%p  <+0x%x>", static_cast<void*>(pc), offs);
      return v8_buffer_.start();
    }

    wasm::WasmCode* wasm_code =
        isolate_ ? isolate_->wasm_engine()->code_manager()->LookupCode(
                       reinterpret_cast<Address>(pc))
                 : nullptr;
    if (wasm_code != nullptr) {
      SNPrintF(v8_buffer_, "%p  (%s)", static_cast<void*>(pc),
               wasm::GetWasmCodeKindAsString(wasm_code->kind()));
      return v8_buffer_.start();
    }
  }

  return disasm::NameConverter::NameOfAddress(pc);
}


const char* V8NameConverter::NameInCode(byte* addr) const {
  // The V8NameConverter is used for well known code, so we can "safely"
  // dereference pointers in generated code.
  return code_.is_null() ? "" : reinterpret_cast<const char*>(addr);
}

const char* V8NameConverter::RootRelativeName(int offset) const {
  if (isolate_ == nullptr) return nullptr;

  const int kRootsStart = 0;
  const int kRootsEnd = Heap::roots_to_external_reference_table_offset();
  const int kExtRefsStart = Heap::roots_to_external_reference_table_offset();
  const int kExtRefsEnd = Heap::roots_to_builtins_offset();

  if (kRootsStart <= offset && offset < kRootsEnd) {
    uint32_t offset_in_roots_table = offset - kRootsStart;

    // Fail safe in the unlikely case of an arbitrary root-relative offset.
    if (offset_in_roots_table % kPointerSize != 0) return nullptr;

    Heap::RootListIndex root_index =
        static_cast<Heap::RootListIndex>(offset_in_roots_table / kPointerSize);

    HeapStringAllocator allocator;
    StringStream accumulator(&allocator);
    isolate_->heap()->root(root_index)->ShortPrint(&accumulator);
    std::unique_ptr<char[]> obj_name = accumulator.ToCString();

    SNPrintF(v8_buffer_, "root (%s)", obj_name.get());
    return v8_buffer_.start();
  } else if (kExtRefsStart <= offset && offset < kExtRefsEnd) {
    uint32_t offset_in_extref_table = offset - kExtRefsStart;

    // Fail safe in the unlikely case of an arbitrary root-relative offset.
    if (offset_in_extref_table % ExternalReferenceTable::EntrySize() != 0) {
      return nullptr;
    }

    // Likewise if the external reference table is uninitialized.
    if (!isolate_->heap()->external_reference_table()->is_initialized()) {
      return nullptr;
    }

    SNPrintF(v8_buffer_, "external reference (%s)",
             isolate_->heap()->external_reference_table()->NameFromOffset(
                 offset_in_extref_table));
    return v8_buffer_.start();
  } else {
    return nullptr;
  }
}

static void DumpBuffer(std::ostream* os, StringBuilder* out) {
  (*os) << out->Finalize() << std::endl;
  out->Reset();
}


static const int kOutBufferSize = 2048 + String::kMaxShortPrintLength;
static const int kRelocInfoPosition = 57;

static void PrintRelocInfo(StringBuilder* out, Isolate* isolate,
                           const ExternalReferenceEncoder* ref_encoder,
                           std::ostream* os, RelocInfo* relocinfo,
                           bool first_reloc_info = true) {
  // Indent the printing of the reloc info.
  if (first_reloc_info) {
    // The first reloc info is printed after the disassembled instruction.
    out->AddPadding(' ', kRelocInfoPosition - out->position());
  } else {
    // Additional reloc infos are printed on separate lines.
    DumpBuffer(os, out);
    out->AddPadding(' ', kRelocInfoPosition);
  }

  RelocInfo::Mode rmode = relocinfo->rmode();
  if (rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) {
    out->AddFormatted("    ;; debug: deopt position, script offset '%d'",
                      static_cast<int>(relocinfo->data()));
  } else if (rmode == RelocInfo::DEOPT_INLINING_ID) {
    out->AddFormatted("    ;; debug: deopt position, inlining id '%d'",
                      static_cast<int>(relocinfo->data()));
  } else if (rmode == RelocInfo::DEOPT_REASON) {
    DeoptimizeReason reason = static_cast<DeoptimizeReason>(relocinfo->data());
    out->AddFormatted("    ;; debug: deopt reason '%s'",
                      DeoptimizeReasonToString(reason));
  } else if (rmode == RelocInfo::DEOPT_ID) {
    out->AddFormatted("    ;; debug: deopt index %d",
                      static_cast<int>(relocinfo->data()));
  } else if (rmode == RelocInfo::EMBEDDED_OBJECT) {
    HeapStringAllocator allocator;
    StringStream accumulator(&allocator);
    relocinfo->target_object()->ShortPrint(&accumulator);
    std::unique_ptr<char[]> obj_name = accumulator.ToCString();
    out->AddFormatted("    ;; object: %s", obj_name.get());
  } else if (rmode == RelocInfo::EXTERNAL_REFERENCE) {
    const char* reference_name =
        ref_encoder ? ref_encoder->NameOfAddress(
                          isolate, relocinfo->target_external_reference())
                    : "unknown";
    out->AddFormatted("    ;; external reference (%s)", reference_name);
  } else if (RelocInfo::IsCodeTargetMode(rmode)) {
    out->AddFormatted("    ;; code:");
    Code* code = isolate->heap()->GcSafeFindCodeForInnerPointer(
        relocinfo->target_address());
    Code::Kind kind = code->kind();
    if (kind == Code::STUB) {
      // Get the STUB key and extract major and minor key.
      uint32_t key = code->stub_key();
      uint32_t minor_key = CodeStub::MinorKeyFromKey(key);
      CodeStub::Major major_key = CodeStub::GetMajorKey(code);
      DCHECK(major_key == CodeStub::MajorKeyFromKey(key));
      out->AddFormatted(" %s, %s, ", Code::Kind2String(kind),
                        CodeStub::MajorName(major_key));
      out->AddFormatted("minor: %d", minor_key);
    } else if (code->is_builtin()) {
      out->AddFormatted(" Builtin::%s", Builtins::name(code->builtin_index()));
    } else {
      out->AddFormatted(" %s", Code::Kind2String(kind));
    }
  } else if (RelocInfo::IsRuntimeEntry(rmode) && isolate &&
             isolate->deoptimizer_data() != nullptr) {
    // A runtime entry relocinfo might be a deoptimization bailout.
    Address addr = relocinfo->target_address();
    DeoptimizeKind type;
    if (Deoptimizer::IsDeoptimizationEntry(isolate, addr, &type)) {
      int id = relocinfo->GetDeoptimizationId(isolate, type);
      out->AddFormatted("    ;; %s deoptimization bailout %d",
                        Deoptimizer::MessageFor(type), id);
    } else {
      out->AddFormatted("    ;; %s", RelocInfo::RelocModeName(rmode));
    }
  } else {
    out->AddFormatted("    ;; %s", RelocInfo::RelocModeName(rmode));
  }
}

static int DecodeIt(Isolate* isolate, ExternalReferenceEncoder* ref_encoder,
                    std::ostream* os, const V8NameConverter& converter,
                    byte* begin, byte* end, Address current_pc) {
  v8::internal::EmbeddedVector<char, 128> decode_buffer;
  v8::internal::EmbeddedVector<char, kOutBufferSize> out_buffer;
  StringBuilder out(out_buffer.start(), out_buffer.length());
  byte* pc = begin;
  disasm::Disassembler d(converter,
                         disasm::Disassembler::kContinueOnUnimplementedOpcode);
  RelocIterator* it = nullptr;
  if (!converter.code().is_null()) {
    it = new RelocIterator(converter.code());
  } else {
    // No relocation information when printing code stubs.
  }
  int constants = -1;  // no constants being decoded at the start

  while (pc < end) {
    // First decode instruction so that we know its length.
    byte* prev_pc = pc;
    if (constants > 0) {
      SNPrintF(decode_buffer,
               "%08x       constant",
               *reinterpret_cast<int32_t*>(pc));
      constants--;
      pc += 4;
    } else {
      int num_const = d.ConstantPoolSizeAt(pc);
      if (num_const >= 0) {
        SNPrintF(decode_buffer,
                 "%08x       constant pool begin (num_const = %d)",
                 *reinterpret_cast<int32_t*>(pc), num_const);
        constants = num_const;
        pc += 4;
      } else if (it != nullptr && !it->done() &&
                 it->rinfo()->pc() == reinterpret_cast<Address>(pc) &&
                 it->rinfo()->rmode() == RelocInfo::INTERNAL_REFERENCE) {
        // raw pointer embedded in code stream, e.g., jump table
        byte* ptr = *reinterpret_cast<byte**>(pc);
        SNPrintF(
            decode_buffer, "%08" V8PRIxPTR "      jump table entry %4" PRIuS,
            reinterpret_cast<intptr_t>(ptr), static_cast<size_t>(ptr - begin));
        pc += sizeof(ptr);
      } else {
        decode_buffer[0] = '\0';
        pc += d.InstructionDecode(decode_buffer, pc);
      }
    }

    // Collect RelocInfo for this instruction (prev_pc .. pc-1)
    std::vector<const char*> comments;
    std::vector<Address> pcs;
    std::vector<RelocInfo::Mode> rmodes;
    std::vector<intptr_t> datas;
    if (it != nullptr) {
      while (!it->done() && it->rinfo()->pc() < reinterpret_cast<Address>(pc)) {
        if (RelocInfo::IsComment(it->rinfo()->rmode())) {
          // For comments just collect the text.
          comments.push_back(
              reinterpret_cast<const char*>(it->rinfo()->data()));
        } else {
          // For other reloc info collect all data.
          pcs.push_back(it->rinfo()->pc());
          rmodes.push_back(it->rinfo()->rmode());
          datas.push_back(it->rinfo()->data());
        }
        it->next();
      }
    }

    // Comments.
    for (size_t i = 0; i < comments.size(); i++) {
      out.AddFormatted("                  %s", comments[i]);
      DumpBuffer(os, &out);
    }

    // Instruction address and instruction offset.
    if (FLAG_log_colour && reinterpret_cast<Address>(prev_pc) == current_pc) {
      // If this is the given "current" pc, make it yellow and bold.
      out.AddFormatted("\033[33;1m");
    }
    out.AddFormatted("%p  %4" V8PRIxPTRDIFF "  ", static_cast<void*>(prev_pc),
                     prev_pc - begin);

    // Instruction.
    out.AddFormatted("%s", decode_buffer.start());

    // Print all the reloc info for this instruction which are not comments.
    for (size_t i = 0; i < pcs.size(); i++) {
      // Put together the reloc info
      const CodeReference& host = converter.code();
      Address constant_pool =
          host.is_null() ? kNullAddress : host.constant_pool();
      RelocInfo relocinfo(pcs[i], rmodes[i], datas[i], nullptr, constant_pool);

      bool first_reloc_info = (i == 0);
      PrintRelocInfo(&out, isolate, ref_encoder, os, &relocinfo,
                     first_reloc_info);
    }

    // If this is a constant pool load and we haven't found any RelocInfo
    // already, check if we can find some RelocInfo for the target address in
    // the constant pool.
    if (pcs.empty() && !converter.code().is_null()) {
      RelocInfo dummy_rinfo(reinterpret_cast<Address>(prev_pc), RelocInfo::NONE,
                            0, nullptr);
      if (dummy_rinfo.IsInConstantPool()) {
        Address constant_pool_entry_address =
            dummy_rinfo.constant_pool_entry_address();
        RelocIterator reloc_it(converter.code());
        while (!reloc_it.done()) {
          if (reloc_it.rinfo()->IsInConstantPool() &&
              (reloc_it.rinfo()->constant_pool_entry_address() ==
               constant_pool_entry_address)) {
            PrintRelocInfo(&out, isolate, ref_encoder, os, reloc_it.rinfo());
            break;
          }
          reloc_it.next();
        }
      }
    }

    if (FLAG_log_colour && reinterpret_cast<Address>(prev_pc) == current_pc) {
      out.AddFormatted("\033[m");
    }

    DumpBuffer(os, &out);
  }

  // Emit comments following the last instruction (if any).
  if (it != nullptr) {
    for ( ; !it->done(); it->next()) {
      if (RelocInfo::IsComment(it->rinfo()->rmode())) {
        out.AddFormatted("                  %s",
                         reinterpret_cast<const char*>(it->rinfo()->data()));
        DumpBuffer(os, &out);
      }
    }
  }

  delete it;
  return static_cast<int>(pc - begin);
}

int Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin,
                         byte* end, CodeReference code, Address current_pc) {
  V8NameConverter v8NameConverter(isolate, code);
  if (isolate) {
    // We have an isolate, so support external reference names.
    SealHandleScope shs(isolate);
    DisallowHeapAllocation no_alloc;
    ExternalReferenceEncoder ref_encoder(isolate);
    return DecodeIt(isolate, &ref_encoder, os, v8NameConverter, begin, end,
                    current_pc);
  } else {
    // No isolate => isolate-independent code. No external reference names.
    return DecodeIt(nullptr, nullptr, os, v8NameConverter, begin, end,
                    current_pc);
  }
}

#else  // ENABLE_DISASSEMBLER

int Disassembler::Decode(Isolate* isolate, std::ostream* os, byte* begin,
                         byte* end, CodeReference code, Address current_pc) {
  return 0;
}

#endif  // ENABLE_DISASSEMBLER

}  // namespace internal
}  // namespace v8
