//===-- WasmDumper.cpp - Wasm-specific object file dumper -----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Wasm-specific dumper for llvm-readobj.
//
//===----------------------------------------------------------------------===//

#include "Error.h"
#include "ObjDumper.h"
#include "llvm-readobj.h"
#include "llvm/Object/Wasm.h"
#include "llvm/Support/ScopedPrinter.h"

using namespace llvm;
using namespace object;

namespace {

static const EnumEntry<unsigned> WasmSymbolTypes[] = {
#define ENUM_ENTRY(X) { #X, wasm::WASM_SYMBOL_TYPE_##X }
  ENUM_ENTRY(FUNCTION),
  ENUM_ENTRY(DATA),
  ENUM_ENTRY(GLOBAL),
  ENUM_ENTRY(SECTION),
#undef ENUM_ENTRY
};

static const EnumEntry<uint32_t> WasmSectionTypes[] = {
#define ENUM_ENTRY(X) { #X, wasm::WASM_SEC_##X }
  ENUM_ENTRY(CUSTOM),
  ENUM_ENTRY(TYPE),
  ENUM_ENTRY(IMPORT),
  ENUM_ENTRY(FUNCTION),
  ENUM_ENTRY(TABLE),
  ENUM_ENTRY(MEMORY),
  ENUM_ENTRY(GLOBAL),
  ENUM_ENTRY(EXPORT),
  ENUM_ENTRY(START),
  ENUM_ENTRY(ELEM),
  ENUM_ENTRY(CODE),
  ENUM_ENTRY(DATA),
#undef ENUM_ENTRY
};

class WasmDumper : public ObjDumper {
public:
  WasmDumper(const WasmObjectFile *Obj, ScopedPrinter &Writer)
      : ObjDumper(Writer), Obj(Obj) {}

  void printFileHeaders() override;
  void printSections() override;
  void printRelocations() override;
  void printSymbols() override;
  void printDynamicSymbols() override { llvm_unreachable("unimplemented"); }
  void printUnwindInfo() override { llvm_unreachable("unimplemented"); }
  void printStackMap() const override { llvm_unreachable("unimplemented"); }

protected:
  void printSymbol(const SymbolRef &Sym);
  void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);

private:
  const WasmObjectFile *Obj;
};

void WasmDumper::printFileHeaders() {
  W.printHex("Version", Obj->getHeader().Version);
}

void WasmDumper::printRelocation(const SectionRef &Section,
                                 const RelocationRef &Reloc) {
  SmallString<64> RelocTypeName;
  uint64_t RelocType = Reloc.getType();
  Reloc.getTypeName(RelocTypeName);
  const wasm::WasmRelocation &WasmReloc = Obj->getWasmRelocation(Reloc);

  StringRef SymName;
  symbol_iterator SI = Reloc.getSymbol();
  if (SI != Obj->symbol_end())
    SymName = error(SI->getName());

  bool HasAddend = false;
  switch (RelocType) {
  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
  case wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
  case wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32:
    HasAddend = true;
    break;
  default:
    break;
  }
  if (opts::ExpandRelocs) {
    DictScope Group(W, "Relocation");
    W.printNumber("Type", RelocTypeName, RelocType);
    W.printHex("Offset", Reloc.getOffset());
    if (!SymName.empty())
      W.printString("Symbol", SymName);
    else
      W.printHex("Index", WasmReloc.Index);
    if (HasAddend)
      W.printNumber("Addend", WasmReloc.Addend);
  } else {
    raw_ostream& OS = W.startLine();
    OS << W.hex(Reloc.getOffset()) << " " << RelocTypeName << " ";
    if (!SymName.empty())
      OS << SymName;
    else
      OS << WasmReloc.Index;
    if (HasAddend)
      OS << " " << WasmReloc.Addend;
    OS << "\n";
  }
}

void WasmDumper::printRelocations() {
  ListScope D(W, "Relocations");

  int SectionNumber = 0;
  for (const SectionRef &Section : Obj->sections()) {
    bool PrintedGroup = false;
    StringRef Name;
    error(Section.getName(Name));
    ++SectionNumber;

    for (const RelocationRef &Reloc : Section.relocations()) {
      if (!PrintedGroup) {
        W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
        W.indent();
        PrintedGroup = true;
      }

      printRelocation(Section, Reloc);
    }

    if (PrintedGroup) {
      W.unindent();
      W.startLine() << "}\n";
    }
  }
}

void WasmDumper::printSymbols() {
  ListScope Group(W, "Symbols");

  for (const SymbolRef &Symbol : Obj->symbols())
    printSymbol(Symbol);
}

void WasmDumper::printSections() {
  ListScope Group(W, "Sections");
  for (const SectionRef &Section : Obj->sections()) {
    const WasmSection &WasmSec = Obj->getWasmSection(Section);
    DictScope SectionD(W, "Section");
    W.printEnum("Type", WasmSec.Type, makeArrayRef(WasmSectionTypes));
    W.printNumber("Size", static_cast<uint64_t>(WasmSec.Content.size()));
    W.printNumber("Offset", WasmSec.Offset);
    switch (WasmSec.Type) {
    case wasm::WASM_SEC_CUSTOM:
      W.printString("Name", WasmSec.Name);
      if (WasmSec.Name == "linking") {
        const wasm::WasmLinkingData &LinkingData = Obj->linkingData();
        if (!LinkingData.InitFunctions.empty()) {
          ListScope Group(W, "InitFunctions");
          for (const wasm::WasmInitFunc &F: LinkingData.InitFunctions)
            W.startLine() << F.Symbol << " (priority=" << F.Priority << ")\n";
        }
      }
      break;
    case wasm::WASM_SEC_DATA: {
      ListScope Group(W, "Segments");
      for (const WasmSegment &Segment : Obj->dataSegments()) {
        const wasm::WasmDataSegment& Seg = Segment.Data;
        DictScope Group(W, "Segment");
        if (!Seg.Name.empty())
          W.printString("Name", Seg.Name);
        W.printNumber("Size", static_cast<uint64_t>(Seg.Content.size()));
        if (Seg.Offset.Opcode == wasm::WASM_OPCODE_I32_CONST)
          W.printNumber("Offset", Seg.Offset.Value.Int32);
      }
      break;
    }
    case wasm::WASM_SEC_MEMORY:
      ListScope Group(W, "Memories");
      for (const wasm::WasmLimits &Memory : Obj->memories()) {
        DictScope Group(W, "Memory");
        W.printNumber("InitialPages", Memory.Initial);
        if (Memory.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) {
          W.printNumber("MaxPages", WasmSec.Offset);
        }
      }
      break;
    }

    if (opts::SectionRelocations) {
      ListScope D(W, "Relocations");
      for (const RelocationRef &Reloc : Section.relocations())
        printRelocation(Section, Reloc);
    }

    if (opts::SectionData) {
      W.printBinaryBlock("SectionData", WasmSec.Content);
    }
  }
}

void WasmDumper::printSymbol(const SymbolRef &Sym) {
  DictScope D(W, "Symbol");
  WasmSymbol Symbol = Obj->getWasmSymbol(Sym.getRawDataRefImpl());
  W.printString("Name", Symbol.Info.Name);
  W.printEnum("Type", Symbol.Info.Kind, makeArrayRef(WasmSymbolTypes));
  W.printHex("Flags", Symbol.Info.Flags);
}

}

namespace llvm {

std::error_code createWasmDumper(const object::ObjectFile *Obj,
                                 ScopedPrinter &Writer,
                                 std::unique_ptr<ObjDumper> &Result) {
  const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(Obj);
  assert(WasmObj && "createWasmDumper called with non-wasm object");

  Result.reset(new WasmDumper(WasmObj, Writer));
  return readobj_error::success;
}

} // namespace llvm
