//===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Wasm object file writer information.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/BinaryFormat/Wasm.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionWasm.h"
#include "llvm/MC/MCSymbolWasm.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/MCWasmObjectWriter.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/StringSaver.h"
#include <vector>

using namespace llvm;

#define DEBUG_TYPE "mc"

namespace {

// For patching purposes, we need to remember where each section starts, both
// for patching up the section size field, and for patching up references to
// locations within the section.
struct SectionBookkeeping {
  // Where the size of the section is written.
  uint64_t SizeOffset;
  // Where the contents of the section starts (after the header).
  uint64_t ContentsOffset;
};

// The signature of a wasm function, in a struct capable of being used as a
// DenseMap key.
struct WasmFunctionType {
  // Support empty and tombstone instances, needed by DenseMap.
  enum { Plain, Empty, Tombstone } State;

  // The return types of the function.
  SmallVector<wasm::ValType, 1> Returns;

  // The parameter types of the function.
  SmallVector<wasm::ValType, 4> Params;

  WasmFunctionType() : State(Plain) {}

  bool operator==(const WasmFunctionType &Other) const {
    return State == Other.State && Returns == Other.Returns &&
           Params == Other.Params;
  }
};

// Traits for using WasmFunctionType in a DenseMap.
struct WasmFunctionTypeDenseMapInfo {
  static WasmFunctionType getEmptyKey() {
    WasmFunctionType FuncTy;
    FuncTy.State = WasmFunctionType::Empty;
    return FuncTy;
  }
  static WasmFunctionType getTombstoneKey() {
    WasmFunctionType FuncTy;
    FuncTy.State = WasmFunctionType::Tombstone;
    return FuncTy;
  }
  static unsigned getHashValue(const WasmFunctionType &FuncTy) {
    uintptr_t Value = FuncTy.State;
    for (wasm::ValType Ret : FuncTy.Returns)
      Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Ret));
    for (wasm::ValType Param : FuncTy.Params)
      Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Param));
    return Value;
  }
  static bool isEqual(const WasmFunctionType &LHS,
                      const WasmFunctionType &RHS) {
    return LHS == RHS;
  }
};

// A wasm data segment.  A wasm binary contains only a single data section
// but that can contain many segments, each with their own virtual location
// in memory.  Each MCSection data created by llvm is modeled as its own
// wasm data segment.
struct WasmDataSegment {
  MCSectionWasm *Section;
  StringRef Name;
  uint32_t Offset;
  uint32_t Alignment;
  uint32_t Flags;
  SmallVector<char, 4> Data;
};

// A wasm import to be written into the import section.
struct WasmImport {
  StringRef ModuleName;
  StringRef FieldName;
  unsigned Kind;
  int32_t Type;
  bool IsMutable;
};

// A wasm function to be written into the function section.
struct WasmFunction {
  int32_t Type;
  const MCSymbolWasm *Sym;
};

// A wasm export to be written into the export section.
struct WasmExport {
  StringRef FieldName;
  unsigned Kind;
  uint32_t Index;
};

// A wasm global to be written into the global section.
struct WasmGlobal {
  wasm::ValType Type;
  bool IsMutable;
  bool HasImport;
  uint64_t InitialValue;
  uint32_t ImportIndex;
};

// Information about a single relocation.
struct WasmRelocationEntry {
  uint64_t Offset;                  // Where is the relocation.
  const MCSymbolWasm *Symbol;       // The symbol to relocate with.
  int64_t Addend;                   // A value to add to the symbol.
  unsigned Type;                    // The type of the relocation.
  const MCSectionWasm *FixupSection;// The section the relocation is targeting.

  WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
                      int64_t Addend, unsigned Type,
                      const MCSectionWasm *FixupSection)
      : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type),
        FixupSection(FixupSection) {}

  bool hasAddend() const {
    switch (Type) {
    case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
    case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
    case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
      return true;
    default:
      return false;
    }
  }

  void print(raw_ostream &Out) const {
    Out << "Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend
        << ", Type=" << Type
        << ", FixupSection=" << FixupSection->getSectionName();
  }

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
  LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
#endif
};

#if !defined(NDEBUG)
raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
  Rel.print(OS);
  return OS;
}
#endif

class WasmObjectWriter : public MCObjectWriter {
  /// Helper struct for containing some precomputed information on symbols.
  struct WasmSymbolData {
    const MCSymbolWasm *Symbol;
    StringRef Name;

    // Support lexicographic sorting.
    bool operator<(const WasmSymbolData &RHS) const { return Name < RHS.Name; }
  };

  /// The target specific Wasm writer instance.
  std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;

  // Relocations for fixing up references in the code section.
  std::vector<WasmRelocationEntry> CodeRelocations;

  // Relocations for fixing up references in the data section.
  std::vector<WasmRelocationEntry> DataRelocations;

  // Index values to use for fixing up call_indirect type indices.
  // Maps function symbols to the index of the type of the function
  DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices;
  // Maps function symbols to the table element index space. Used
  // for TABLE_INDEX relocation types (i.e. address taken functions).
  DenseMap<const MCSymbolWasm *, uint32_t> IndirectSymbolIndices;
  // Maps function/global symbols to the function/global index space.
  DenseMap<const MCSymbolWasm *, uint32_t> SymbolIndices;

  DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo>
      FunctionTypeIndices;
  SmallVector<WasmFunctionType, 4> FunctionTypes;
  SmallVector<WasmGlobal, 4> Globals;
  unsigned NumGlobalImports = 0;

  // TargetObjectWriter wrappers.
  bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
  unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup) const {
    return TargetObjectWriter->getRelocType(Target, Fixup);
  }

  void startSection(SectionBookkeeping &Section, unsigned SectionId,
                    const char *Name = nullptr);
  void endSection(SectionBookkeeping &Section);

public:
  WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
                   raw_pwrite_stream &OS)
      : MCObjectWriter(OS, /*IsLittleEndian=*/true),
        TargetObjectWriter(std::move(MOTW)) {}

private:
  ~WasmObjectWriter() override;

  void reset() override {
    CodeRelocations.clear();
    DataRelocations.clear();
    TypeIndices.clear();
    SymbolIndices.clear();
    IndirectSymbolIndices.clear();
    FunctionTypeIndices.clear();
    FunctionTypes.clear();
    Globals.clear();
    MCObjectWriter::reset();
    NumGlobalImports = 0;
  }

  void writeHeader(const MCAssembler &Asm);

  void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
                        const MCFragment *Fragment, const MCFixup &Fixup,
                        MCValue Target, uint64_t &FixedValue) override;

  void executePostLayoutBinding(MCAssembler &Asm,
                                const MCAsmLayout &Layout) override;

  void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;

  void writeString(const StringRef Str) {
    encodeULEB128(Str.size(), getStream());
    writeBytes(Str);
  }

  void writeValueType(wasm::ValType Ty) {
    encodeSLEB128(int32_t(Ty), getStream());
  }

  void writeTypeSection(ArrayRef<WasmFunctionType> FunctionTypes);
  void writeImportSection(ArrayRef<WasmImport> Imports, uint32_t DataSize,
                          uint32_t NumElements);
  void writeFunctionSection(ArrayRef<WasmFunction> Functions);
  void writeGlobalSection();
  void writeExportSection(ArrayRef<WasmExport> Exports);
  void writeElemSection(ArrayRef<uint32_t> TableElems);
  void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
                        ArrayRef<WasmFunction> Functions);
  void writeDataSection(ArrayRef<WasmDataSegment> Segments);
  void writeNameSection(ArrayRef<WasmFunction> Functions,
                        ArrayRef<WasmImport> Imports,
                        uint32_t NumFuncImports);
  void writeCodeRelocSection();
  void writeDataRelocSection();
  void writeLinkingMetaDataSection(
      ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
      const SmallVector<std::pair<StringRef, uint32_t>, 4> &SymbolFlags,
      const SmallVector<std::pair<uint16_t, uint32_t>, 2> &InitFuncs);

  uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
  void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
                        uint64_t ContentsOffset);

  void writeRelocations(ArrayRef<WasmRelocationEntry> Relocations);
  uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
  uint32_t getFunctionType(const MCSymbolWasm& Symbol);
  uint32_t registerFunctionType(const MCSymbolWasm& Symbol);
};

} // end anonymous namespace

WasmObjectWriter::~WasmObjectWriter() {}

// Write out a section header and a patchable section size field.
void WasmObjectWriter::startSection(SectionBookkeeping &Section,
                                    unsigned SectionId,
                                    const char *Name) {
  assert((Name != nullptr) == (SectionId == wasm::WASM_SEC_CUSTOM) &&
         "Only custom sections can have names");

  DEBUG(dbgs() << "startSection " << SectionId << ": " << Name << "\n");
  encodeULEB128(SectionId, getStream());

  Section.SizeOffset = getStream().tell();

  // The section size. We don't know the size yet, so reserve enough space
  // for any 32-bit value; we'll patch it later.
  encodeULEB128(UINT32_MAX, getStream());

  // The position where the section starts, for measuring its size.
  Section.ContentsOffset = getStream().tell();

  // Custom sections in wasm also have a string identifier.
  if (SectionId == wasm::WASM_SEC_CUSTOM) {
    assert(Name);
    writeString(StringRef(Name));
  }
}

// Now that the section is complete and we know how big it is, patch up the
// section size field at the start of the section.
void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
  uint64_t Size = getStream().tell() - Section.ContentsOffset;
  if (uint32_t(Size) != Size)
    report_fatal_error("section size does not fit in a uint32_t");

  DEBUG(dbgs() << "endSection size=" << Size << "\n");

  // Write the final section size to the payload_len field, which follows
  // the section id byte.
  uint8_t Buffer[16];
  unsigned SizeLen = encodeULEB128(Size, Buffer, 5);
  assert(SizeLen == 5);
  getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset);
}

// Emit the Wasm header.
void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
  writeBytes(StringRef(wasm::WasmMagic, sizeof(wasm::WasmMagic)));
  writeLE32(wasm::WasmVersion);
}

void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
                                                const MCAsmLayout &Layout) {
}

void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
                                        const MCAsmLayout &Layout,
                                        const MCFragment *Fragment,
                                        const MCFixup &Fixup, MCValue Target,
                                        uint64_t &FixedValue) {
  MCAsmBackend &Backend = Asm.getBackend();
  bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
                 MCFixupKindInfo::FKF_IsPCRel;
  const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
  uint64_t C = Target.getConstant();
  uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
  MCContext &Ctx = Asm.getContext();

  // The .init_array isn't translated as data, so don't do relocations in it.
  if (FixupSection.getSectionName().startswith(".init_array"))
    return;

  if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
    assert(RefB->getKind() == MCSymbolRefExpr::VK_None &&
           "Should not have constructed this");

    // Let A, B and C being the components of Target and R be the location of
    // the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
    // If it is pcrel, we want to compute (A - B + C - R).

    // In general, Wasm has no relocations for -B. It can only represent (A + C)
    // or (A + C - R). If B = R + K and the relocation is not pcrel, we can
    // replace B to implement it: (A - R - K + C)
    if (IsPCRel) {
      Ctx.reportError(
          Fixup.getLoc(),
          "No relocation available to represent this relative expression");
      return;
    }

    const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());

    if (SymB.isUndefined()) {
      Ctx.reportError(Fixup.getLoc(),
                      Twine("symbol '") + SymB.getName() +
                          "' can not be undefined in a subtraction expression");
      return;
    }

    assert(!SymB.isAbsolute() && "Should have been folded");
    const MCSection &SecB = SymB.getSection();
    if (&SecB != &FixupSection) {
      Ctx.reportError(Fixup.getLoc(),
                      "Cannot represent a difference across sections");
      return;
    }

    uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
    uint64_t K = SymBOffset - FixupOffset;
    IsPCRel = true;
    C -= K;
  }

  // We either rejected the fixup or folded B into C at this point.
  const MCSymbolRefExpr *RefA = Target.getSymA();
  const auto *SymA = RefA ? cast<MCSymbolWasm>(&RefA->getSymbol()) : nullptr;

  if (SymA && SymA->isVariable()) {
    const MCExpr *Expr = SymA->getVariableValue();
    const auto *Inner = cast<MCSymbolRefExpr>(Expr);
    if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
      llvm_unreachable("weakref used in reloc not yet implemented");
  }

  // Put any constant offset in an addend. Offsets can be negative, and
  // LLVM expects wrapping, in contrast to wasm's immediates which can't
  // be negative and don't wrap.
  FixedValue = 0;

  if (SymA)
    SymA->setUsedInReloc();

  assert(!IsPCRel);
  assert(SymA);

  unsigned Type = getRelocType(Target, Fixup);

  WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
  DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");

  if (FixupSection.isWasmData())
    DataRelocations.push_back(Rec);
  else if (FixupSection.getKind().isText())
    CodeRelocations.push_back(Rec);
  else if (!FixupSection.getKind().isMetadata())
    // TODO(sbc): Add support for debug sections.
    llvm_unreachable("unexpected section type");
}

// Write X as an (unsigned) LEB value at offset Offset in Stream, padded
// to allow patching.
static void
WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
  uint8_t Buffer[5];
  unsigned SizeLen = encodeULEB128(X, Buffer, 5);
  assert(SizeLen == 5);
  Stream.pwrite((char *)Buffer, SizeLen, Offset);
}

// Write X as an signed LEB value at offset Offset in Stream, padded
// to allow patching.
static void
WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) {
  uint8_t Buffer[5];
  unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
  assert(SizeLen == 5);
  Stream.pwrite((char *)Buffer, SizeLen, Offset);
}

// Write X as a plain integer value at offset Offset in Stream.
static void WriteI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
  uint8_t Buffer[4];
  support::endian::write32le(Buffer, X);
  Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
}

static const MCSymbolWasm* ResolveSymbol(const MCSymbolWasm& Symbol) {
  if (Symbol.isVariable()) {
    const MCExpr *Expr = Symbol.getVariableValue();
    auto *Inner = cast<MCSymbolRefExpr>(Expr);
    return cast<MCSymbolWasm>(&Inner->getSymbol());
  }
  return &Symbol;
}

// Compute a value to write into the code at the location covered
// by RelEntry. This value isn't used by the static linker, since
// we have addends; it just serves to make the code more readable
// and to make standalone wasm modules directly usable.
uint32_t
WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
  const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol);

  // For undefined symbols, use a hopefully invalid value.
  if (!Sym->isDefined(/*SetUsed=*/false))
    return UINT32_MAX;

  uint32_t GlobalIndex = SymbolIndices[Sym];
  const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports];
  uint64_t Address = Global.InitialValue + RelEntry.Addend;

  // Ignore overflow. LLVM allows address arithmetic to silently wrap.
  uint32_t Value = Address;

  return Value;
}

static void addData(SmallVectorImpl<char> &DataBytes,
                    MCSectionWasm &DataSection) {
  DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n");

  DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));

  size_t LastFragmentSize = 0;
  for (const MCFragment &Frag : DataSection) {
    if (Frag.hasInstructions())
      report_fatal_error("only data supported in data sections");

    if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
      if (Align->getValueSize() != 1)
        report_fatal_error("only byte values supported for alignment");
      // If nops are requested, use zeros, as this is the data section.
      uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
      uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(),
                                                 Align->getAlignment()),
                                         DataBytes.size() +
                                             Align->getMaxBytesToEmit());
      DataBytes.resize(Size, Value);
    } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
      DataBytes.insert(DataBytes.end(), Fill->getSize(), Fill->getValue());
    } else {
      const auto &DataFrag = cast<MCDataFragment>(Frag);
      const SmallVectorImpl<char> &Contents = DataFrag.getContents();

      DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
      LastFragmentSize = Contents.size();
    }
  }

  // Don't allow empty segments, or segments that end with zero-sized
  // fragment, otherwise the linker cannot map symbols to a unique
  // data segment.  This can be triggered by zero-sized structs
  // See: test/MC/WebAssembly/bss.ll
  if (LastFragmentSize == 0)
    DataBytes.resize(DataBytes.size() + 1);
  DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
}

uint32_t WasmObjectWriter::getRelocationIndexValue(
    const WasmRelocationEntry &RelEntry) {
  switch (RelEntry.Type) {
  case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
  case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
    if (!IndirectSymbolIndices.count(RelEntry.Symbol))
      report_fatal_error("symbol not found in table index space: " +
                         RelEntry.Symbol->getName());
    return IndirectSymbolIndices[RelEntry.Symbol];
  case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
  case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
    if (!SymbolIndices.count(RelEntry.Symbol))
      report_fatal_error("symbol not found in function/global index space: " +
                         RelEntry.Symbol->getName());
    return SymbolIndices[RelEntry.Symbol];
  case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
    if (!TypeIndices.count(RelEntry.Symbol))
      report_fatal_error("symbol not found in type index space: " +
                         RelEntry.Symbol->getName());
    return TypeIndices[RelEntry.Symbol];
  default:
    llvm_unreachable("invalid relocation type");
  }
}

// Apply the portions of the relocation records that we can handle ourselves
// directly.
void WasmObjectWriter::applyRelocations(
    ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset) {
  raw_pwrite_stream &Stream = getStream();
  for (const WasmRelocationEntry &RelEntry : Relocations) {
    uint64_t Offset = ContentsOffset +
                      RelEntry.FixupSection->getSectionOffset() +
                      RelEntry.Offset;

    DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
    switch (RelEntry.Type) {
    case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
    case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
    case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
    case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: {
      uint32_t Index = getRelocationIndexValue(RelEntry);
      WritePatchableSLEB(Stream, Index, Offset);
      break;
    }
    case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: {
      uint32_t Index = getRelocationIndexValue(RelEntry);
      WriteI32(Stream, Index, Offset);
      break;
    }
    case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
      uint32_t Value = getProvisionalValue(RelEntry);
      WritePatchableSLEB(Stream, Value, Offset);
      break;
    }
    case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: {
      uint32_t Value = getProvisionalValue(RelEntry);
      WritePatchableLEB(Stream, Value, Offset);
      break;
    }
    case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: {
      uint32_t Value = getProvisionalValue(RelEntry);
      WriteI32(Stream, Value, Offset);
      break;
    }
    default:
      llvm_unreachable("invalid relocation type");
    }
  }
}

// Write out the portions of the relocation records that the linker will
// need to handle.
void WasmObjectWriter::writeRelocations(
    ArrayRef<WasmRelocationEntry> Relocations) {
  raw_pwrite_stream &Stream = getStream();
  for (const WasmRelocationEntry& RelEntry : Relocations) {

    uint64_t Offset = RelEntry.Offset +
                      RelEntry.FixupSection->getSectionOffset();
    uint32_t Index = getRelocationIndexValue(RelEntry);

    encodeULEB128(RelEntry.Type, Stream);
    encodeULEB128(Offset, Stream);
    encodeULEB128(Index, Stream);
    if (RelEntry.hasAddend())
      encodeSLEB128(RelEntry.Addend, Stream);
  }
}

void WasmObjectWriter::writeTypeSection(
    ArrayRef<WasmFunctionType> FunctionTypes) {
  if (FunctionTypes.empty())
    return;

  SectionBookkeeping Section;
  startSection(Section, wasm::WASM_SEC_TYPE);

  encodeULEB128(FunctionTypes.size(), getStream());

  for (const WasmFunctionType &FuncTy : FunctionTypes) {
    encodeSLEB128(wasm::WASM_TYPE_FUNC, getStream());
    encodeULEB128(FuncTy.Params.size(), getStream());
    for (wasm::ValType Ty : FuncTy.Params)
      writeValueType(Ty);
    encodeULEB128(FuncTy.Returns.size(), getStream());
    for (wasm::ValType Ty : FuncTy.Returns)
      writeValueType(Ty);
  }

  endSection(Section);
}

void WasmObjectWriter::writeImportSection(ArrayRef<WasmImport> Imports,
                                          uint32_t DataSize,
                                          uint32_t NumElements) {
  if (Imports.empty())
    return;

  uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;

  SectionBookkeeping Section;
  startSection(Section, wasm::WASM_SEC_IMPORT);

  encodeULEB128(Imports.size(), getStream());
  for (const WasmImport &Import : Imports) {
    writeString(Import.ModuleName);
    writeString(Import.FieldName);

    encodeULEB128(Import.Kind, getStream());

    switch (Import.Kind) {
    case wasm::WASM_EXTERNAL_FUNCTION:
      encodeULEB128(Import.Type, getStream());
      break;
    case wasm::WASM_EXTERNAL_GLOBAL:
      encodeSLEB128(int32_t(Import.Type), getStream());
      encodeULEB128(int32_t(Import.IsMutable), getStream());
      break;
    case wasm::WASM_EXTERNAL_MEMORY:
      encodeULEB128(0, getStream()); // flags
      encodeULEB128(NumPages, getStream()); // initial
      break;
    case wasm::WASM_EXTERNAL_TABLE:
      encodeSLEB128(int32_t(Import.Type), getStream());
      encodeULEB128(0, getStream()); // flags
      encodeULEB128(NumElements, getStream()); // initial
      break;
    default:
      llvm_unreachable("unsupported import kind");
    }
  }

  endSection(Section);
}

void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
  if (Functions.empty())
    return;

  SectionBookkeeping Section;
  startSection(Section, wasm::WASM_SEC_FUNCTION);

  encodeULEB128(Functions.size(), getStream());
  for (const WasmFunction &Func : Functions)
    encodeULEB128(Func.Type, getStream());

  endSection(Section);
}

void WasmObjectWriter::writeGlobalSection() {
  if (Globals.empty())
    return;

  SectionBookkeeping Section;
  startSection(Section, wasm::WASM_SEC_GLOBAL);

  encodeULEB128(Globals.size(), getStream());
  for (const WasmGlobal &Global : Globals) {
    writeValueType(Global.Type);
    write8(Global.IsMutable);

    if (Global.HasImport) {
      assert(Global.InitialValue == 0);
      write8(wasm::WASM_OPCODE_GET_GLOBAL);
      encodeULEB128(Global.ImportIndex, getStream());
    } else {
      assert(Global.ImportIndex == 0);
      write8(wasm::WASM_OPCODE_I32_CONST);
      encodeSLEB128(Global.InitialValue, getStream()); // offset
    }
    write8(wasm::WASM_OPCODE_END);
  }

  endSection(Section);
}

void WasmObjectWriter::writeExportSection(ArrayRef<WasmExport> Exports) {
  if (Exports.empty())
    return;

  SectionBookkeeping Section;
  startSection(Section, wasm::WASM_SEC_EXPORT);

  encodeULEB128(Exports.size(), getStream());
  for (const WasmExport &Export : Exports) {
    writeString(Export.FieldName);
    encodeSLEB128(Export.Kind, getStream());
    encodeULEB128(Export.Index, getStream());
  }

  endSection(Section);
}

void WasmObjectWriter::writeElemSection(ArrayRef<uint32_t> TableElems) {
  if (TableElems.empty())
    return;

  SectionBookkeeping Section;
  startSection(Section, wasm::WASM_SEC_ELEM);

  encodeULEB128(1, getStream()); // number of "segments"
  encodeULEB128(0, getStream()); // the table index

  // init expr for starting offset
  write8(wasm::WASM_OPCODE_I32_CONST);
  encodeSLEB128(0, getStream());
  write8(wasm::WASM_OPCODE_END);

  encodeULEB128(TableElems.size(), getStream());
  for (uint32_t Elem : TableElems)
    encodeULEB128(Elem, getStream());

  endSection(Section);
}

void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
                                        const MCAsmLayout &Layout,
                                        ArrayRef<WasmFunction> Functions) {
  if (Functions.empty())
    return;

  SectionBookkeeping Section;
  startSection(Section, wasm::WASM_SEC_CODE);

  encodeULEB128(Functions.size(), getStream());

  for (const WasmFunction &Func : Functions) {
    auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection());

    int64_t Size = 0;
    if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
      report_fatal_error(".size expression must be evaluatable");

    encodeULEB128(Size, getStream());
    FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset);
    Asm.writeSectionData(&FuncSection, Layout);
  }

  // Apply fixups.
  applyRelocations(CodeRelocations, Section.ContentsOffset);

  endSection(Section);
}

void WasmObjectWriter::writeDataSection(ArrayRef<WasmDataSegment> Segments) {
  if (Segments.empty())
    return;

  SectionBookkeeping Section;
  startSection(Section, wasm::WASM_SEC_DATA);

  encodeULEB128(Segments.size(), getStream()); // count

  for (const WasmDataSegment & Segment : Segments) {
    encodeULEB128(0, getStream()); // memory index
    write8(wasm::WASM_OPCODE_I32_CONST);
    encodeSLEB128(Segment.Offset, getStream()); // offset
    write8(wasm::WASM_OPCODE_END);
    encodeULEB128(Segment.Data.size(), getStream()); // size
    Segment.Section->setSectionOffset(getStream().tell() - Section.ContentsOffset);
    writeBytes(Segment.Data); // data
  }

  // Apply fixups.
  applyRelocations(DataRelocations, Section.ContentsOffset);

  endSection(Section);
}

void WasmObjectWriter::writeNameSection(
    ArrayRef<WasmFunction> Functions,
    ArrayRef<WasmImport> Imports,
    unsigned NumFuncImports) {
  uint32_t TotalFunctions = NumFuncImports + Functions.size();
  if (TotalFunctions == 0)
    return;

  SectionBookkeeping Section;
  startSection(Section, wasm::WASM_SEC_CUSTOM, "name");
  SectionBookkeeping SubSection;
  startSection(SubSection, wasm::WASM_NAMES_FUNCTION);

  encodeULEB128(TotalFunctions, getStream());
  uint32_t Index = 0;
  for (const WasmImport &Import : Imports) {
    if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
      encodeULEB128(Index, getStream());
      writeString(Import.FieldName);
      ++Index;
    }
  }
  for (const WasmFunction &Func : Functions) {
    encodeULEB128(Index, getStream());
    writeString(Func.Sym->getName());
    ++Index;
  }

  endSection(SubSection);
  endSection(Section);
}

void WasmObjectWriter::writeCodeRelocSection() {
  // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
  // for descriptions of the reloc sections.

  if (CodeRelocations.empty())
    return;

  SectionBookkeeping Section;
  startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.CODE");

  encodeULEB128(wasm::WASM_SEC_CODE, getStream());
  encodeULEB128(CodeRelocations.size(), getStream());

  writeRelocations(CodeRelocations);

  endSection(Section);
}

void WasmObjectWriter::writeDataRelocSection() {
  // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
  // for descriptions of the reloc sections.

  if (DataRelocations.empty())
    return;

  SectionBookkeeping Section;
  startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.DATA");

  encodeULEB128(wasm::WASM_SEC_DATA, getStream());
  encodeULEB128(DataRelocations.size(), getStream());

  writeRelocations(DataRelocations);

  endSection(Section);
}

void WasmObjectWriter::writeLinkingMetaDataSection(
    ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
    const SmallVector<std::pair<StringRef, uint32_t>, 4> &SymbolFlags,
    const SmallVector<std::pair<uint16_t, uint32_t>, 2> &InitFuncs) {
  SectionBookkeeping Section;
  startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
  SectionBookkeeping SubSection;

  if (SymbolFlags.size() != 0) {
    startSection(SubSection, wasm::WASM_SYMBOL_INFO);
    encodeULEB128(SymbolFlags.size(), getStream());
    for (auto Pair: SymbolFlags) {
      writeString(Pair.first);
      encodeULEB128(Pair.second, getStream());
    }
    endSection(SubSection);
  }

  if (DataSize > 0) {
    startSection(SubSection, wasm::WASM_DATA_SIZE);
    encodeULEB128(DataSize, getStream());
    endSection(SubSection);
  }

  if (Segments.size()) {
    startSection(SubSection, wasm::WASM_SEGMENT_INFO);
    encodeULEB128(Segments.size(), getStream());
    for (const WasmDataSegment &Segment : Segments) {
      writeString(Segment.Name);
      encodeULEB128(Segment.Alignment, getStream());
      encodeULEB128(Segment.Flags, getStream());
    }
    endSection(SubSection);
  }

  if (!InitFuncs.empty()) {
    startSection(SubSection, wasm::WASM_INIT_FUNCS);
    encodeULEB128(InitFuncs.size(), getStream());
    for (auto &StartFunc : InitFuncs) {
      encodeULEB128(StartFunc.first, getStream()); // priority
      encodeULEB128(StartFunc.second, getStream()); // function index
    }
    endSection(SubSection);
  }

  endSection(Section);
}

uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm& Symbol) {
  assert(Symbol.isFunction());
  assert(TypeIndices.count(&Symbol));
  return TypeIndices[&Symbol];
}

uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm& Symbol) {
  assert(Symbol.isFunction());

  WasmFunctionType F;
  const MCSymbolWasm* ResolvedSym = ResolveSymbol(Symbol);
  F.Returns = ResolvedSym->getReturns();
  F.Params = ResolvedSym->getParams();

  auto Pair =
      FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
  if (Pair.second)
    FunctionTypes.push_back(F);
  TypeIndices[&Symbol] = Pair.first->second;

  DEBUG(dbgs() << "registerFunctionType: " << Symbol << " new:" << Pair.second << "\n");
  DEBUG(dbgs() << "  -> type index: " << Pair.first->second << "\n");
  return Pair.first->second;
}

void WasmObjectWriter::writeObject(MCAssembler &Asm,
                                   const MCAsmLayout &Layout) {
  DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
  MCContext &Ctx = Asm.getContext();
  wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32;

  // Collect information from the available symbols.
  SmallVector<WasmFunction, 4> Functions;
  SmallVector<uint32_t, 4> TableElems;
  SmallVector<WasmImport, 4> Imports;
  SmallVector<WasmExport, 4> Exports;
  SmallVector<std::pair<StringRef, uint32_t>, 4> SymbolFlags;
  SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
  unsigned NumFuncImports = 0;
  SmallVector<WasmDataSegment, 4> DataSegments;
  uint32_t DataSize = 0;

  // In the special .global_variables section, we've encoded global
  // variables used by the function. Translate them into the Globals
  // list.
  MCSectionWasm *GlobalVars =
      Ctx.getWasmSection(".global_variables", SectionKind::getMetadata());
  if (!GlobalVars->getFragmentList().empty()) {
    if (GlobalVars->getFragmentList().size() != 1)
      report_fatal_error("only one .global_variables fragment supported");
    const MCFragment &Frag = *GlobalVars->begin();
    if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
      report_fatal_error("only data supported in .global_variables");
    const auto &DataFrag = cast<MCDataFragment>(Frag);
    if (!DataFrag.getFixups().empty())
      report_fatal_error("fixups not supported in .global_variables");
    const SmallVectorImpl<char> &Contents = DataFrag.getContents();
    for (const uint8_t *p = (const uint8_t *)Contents.data(),
                     *end = (const uint8_t *)Contents.data() + Contents.size();
         p != end; ) {
      WasmGlobal G;
      if (end - p < 3)
        report_fatal_error("truncated global variable encoding");
      G.Type = wasm::ValType(int8_t(*p++));
      G.IsMutable = bool(*p++);
      G.HasImport = bool(*p++);
      if (G.HasImport) {
        G.InitialValue = 0;

        WasmImport Import;
        Import.ModuleName = (const char *)p;
        const uint8_t *nul = (const uint8_t *)memchr(p, '\0', end - p);
        if (!nul)
          report_fatal_error("global module name must be nul-terminated");
        p = nul + 1;
        nul = (const uint8_t *)memchr(p, '\0', end - p);
        if (!nul)
          report_fatal_error("global base name must be nul-terminated");
        Import.FieldName = (const char *)p;
        p = nul + 1;

        Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
        Import.Type = int32_t(G.Type);

        G.ImportIndex = NumGlobalImports;
        ++NumGlobalImports;

        Imports.push_back(Import);
      } else {
        unsigned n;
        G.InitialValue = decodeSLEB128(p, &n);
        G.ImportIndex = 0;
        if ((ptrdiff_t)n > end - p)
          report_fatal_error("global initial value must be valid SLEB128");
        p += n;
      }
      Globals.push_back(G);
    }
  }

  // For now, always emit the memory import, since loads and stores are not
  // valid without it. In the future, we could perhaps be more clever and omit
  // it if there are no loads or stores.
  MCSymbolWasm *MemorySym =
      cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__linear_memory"));
  WasmImport MemImport;
  MemImport.ModuleName = MemorySym->getModuleName();
  MemImport.FieldName = MemorySym->getName();
  MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
  Imports.push_back(MemImport);

  // For now, always emit the table section, since indirect calls are not
  // valid without it. In the future, we could perhaps be more clever and omit
  // it if there are no indirect calls.
  MCSymbolWasm *TableSym =
      cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__indirect_function_table"));
  WasmImport TableImport;
  TableImport.ModuleName = TableSym->getModuleName();
  TableImport.FieldName = TableSym->getName();
  TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
  TableImport.Type = wasm::WASM_TYPE_ANYFUNC;
  Imports.push_back(TableImport);

  // Populate FunctionTypeIndices and Imports.
  for (const MCSymbol &S : Asm.symbols()) {
    const auto &WS = static_cast<const MCSymbolWasm &>(S);

    // Register types for all functions, including those with private linkage
    // (making them
    // because wasm always needs a type signature.
    if (WS.isFunction())
      registerFunctionType(WS);

    if (WS.isTemporary())
      continue;

    // If the symbol is not defined in this translation unit, import it.
    if (!WS.isDefined(/*SetUsed=*/false) || WS.isVariable()) {
      WasmImport Import;
      Import.ModuleName = WS.getModuleName();
      Import.FieldName = WS.getName();

      if (WS.isFunction()) {
        Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
        Import.Type = getFunctionType(WS);
        SymbolIndices[&WS] = NumFuncImports;
        ++NumFuncImports;
      } else {
        Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
        Import.Type = int32_t(PtrType);
        Import.IsMutable = false;
        SymbolIndices[&WS] = NumGlobalImports;

        // If this global is the stack pointer, make it mutable.
        if (WS.getName() == "__stack_pointer")
          Import.IsMutable = true;

        ++NumGlobalImports;
      }

      Imports.push_back(Import);
    }
  }

  for (MCSection &Sec : Asm) {
    auto &Section = static_cast<MCSectionWasm &>(Sec);
    if (!Section.isWasmData())
      continue;

    // .init_array sections are handled specially elsewhere.
    if (cast<MCSectionWasm>(Sec).getSectionName().startswith(".init_array"))
      continue;

    DataSize = alignTo(DataSize, Section.getAlignment());
    DataSegments.emplace_back();
    WasmDataSegment &Segment = DataSegments.back();
    Segment.Name = Section.getSectionName();
    Segment.Offset = DataSize;
    Segment.Section = &Section;
    addData(Segment.Data, Section);
    Segment.Alignment = Section.getAlignment();
    Segment.Flags = 0;
    DataSize += Segment.Data.size();
    Section.setMemoryOffset(Segment.Offset);
  }

  // Handle regular defined and undefined symbols.
  for (const MCSymbol &S : Asm.symbols()) {
    // Ignore unnamed temporary symbols, which aren't ever exported, imported,
    // or used in relocations.
    if (S.isTemporary() && S.getName().empty())
      continue;

    const auto &WS = static_cast<const MCSymbolWasm &>(S);
    DEBUG(dbgs() << "MCSymbol: '" << S << "'"
                 << " isDefined=" << S.isDefined() << " isExternal="
                 << S.isExternal() << " isTemporary=" << S.isTemporary()
                 << " isFunction=" << WS.isFunction()
                 << " isWeak=" << WS.isWeak()
                 << " isHidden=" << WS.isHidden()
                 << " isVariable=" << WS.isVariable() << "\n");

    if (WS.isWeak() || WS.isHidden()) {
      uint32_t Flags = (WS.isWeak() ? wasm::WASM_SYMBOL_BINDING_WEAK : 0) |
          (WS.isHidden() ? wasm::WASM_SYMBOL_VISIBILITY_HIDDEN : 0);
      SymbolFlags.emplace_back(WS.getName(), Flags);
    }

    if (WS.isVariable())
      continue;

    unsigned Index;

    if (WS.isFunction()) {
      if (WS.isDefined(/*SetUsed=*/false)) {
        if (WS.getOffset() != 0)
          report_fatal_error(
              "function sections must contain one function each");

        if (WS.getSize() == 0)
          report_fatal_error(
              "function symbols must have a size set with .size");

        // A definition. Take the next available index.
        Index = NumFuncImports + Functions.size();

        // Prepare the function.
        WasmFunction Func;
        Func.Type = getFunctionType(WS);
        Func.Sym = &WS;
        SymbolIndices[&WS] = Index;
        Functions.push_back(Func);
      } else {
        // An import; the index was assigned above.
        Index = SymbolIndices.find(&WS)->second;
      }

      DEBUG(dbgs() << "  -> function index: " << Index << "\n");
   } else {
      if (WS.isTemporary() && !WS.getSize())
        continue;

      if (!WS.isDefined(/*SetUsed=*/false))
        continue;

      if (!WS.getSize())
        report_fatal_error("data symbols must have a size set with .size: " +
                           WS.getName());

      int64_t Size = 0;
      if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
        report_fatal_error(".size expression must be evaluatable");

      // For each global, prepare a corresponding wasm global holding its
      // address.  For externals these will also be named exports.
      Index = NumGlobalImports + Globals.size();
      auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());

      WasmGlobal Global;
      Global.Type = PtrType;
      Global.IsMutable = false;
      Global.HasImport = false;
      Global.InitialValue = DataSection.getMemoryOffset() + Layout.getSymbolOffset(WS);
      Global.ImportIndex = 0;
      SymbolIndices[&WS] = Index;
      DEBUG(dbgs() << "  -> global index: " << Index << "\n");
      Globals.push_back(Global);
    }

    // If the symbol is visible outside this translation unit, export it.
    if (WS.isDefined(/*SetUsed=*/false)) {
      WasmExport Export;
      Export.FieldName = WS.getName();
      Export.Index = Index;
      if (WS.isFunction())
        Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
      else
        Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
      DEBUG(dbgs() << "  -> export " << Exports.size() << "\n");
      Exports.push_back(Export);
      if (!WS.isExternal())
        SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
    }
  }

  // Handle weak aliases. We need to process these in a separate pass because
  // we need to have processed the target of the alias before the alias itself
  // and the symbols are not necessarily ordered in this way.
  for (const MCSymbol &S : Asm.symbols()) {
    if (!S.isVariable())
      continue;

    assert(S.isDefined(/*SetUsed=*/false));

    // Find the target symbol of this weak alias and export that index
    const auto &WS = static_cast<const MCSymbolWasm &>(S);
    const MCSymbolWasm *ResolvedSym = ResolveSymbol(WS);
    DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym << "'\n");
    assert(SymbolIndices.count(ResolvedSym) > 0);
    uint32_t Index = SymbolIndices.find(ResolvedSym)->second;
    DEBUG(dbgs() << "  -> index:" << Index << "\n");

    WasmExport Export;
    Export.FieldName = WS.getName();
    Export.Index = Index;
    if (WS.isFunction())
      Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
    else
      Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
    DEBUG(dbgs() << "  -> export " << Exports.size() << "\n");
    Exports.push_back(Export);

    if (!WS.isExternal())
      SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
  }

  {
    auto HandleReloc = [&](const WasmRelocationEntry &Rel) {
      // Functions referenced by a relocation need to prepared to be called
      // indirectly.
      const MCSymbolWasm& WS = *Rel.Symbol;
      if (WS.isFunction() && IndirectSymbolIndices.count(&WS) == 0) {
        switch (Rel.Type) {
        case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
        case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
        case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
        case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
          uint32_t Index = SymbolIndices.find(&WS)->second;
          IndirectSymbolIndices[&WS] = TableElems.size();
          DEBUG(dbgs() << "  -> adding to table: " << TableElems.size() << "\n");
          TableElems.push_back(Index);
          registerFunctionType(WS);
          break;
        }
        default:
          break;
        }
      }
    };

    for (const WasmRelocationEntry &RelEntry : CodeRelocations)
      HandleReloc(RelEntry);
    for (const WasmRelocationEntry &RelEntry : DataRelocations)
      HandleReloc(RelEntry);
  }

  // Translate .init_array section contents into start functions.
  for (const MCSection &S : Asm) {
    const auto &WS = static_cast<const MCSectionWasm &>(S);
    if (WS.getSectionName().startswith(".fini_array"))
      report_fatal_error(".fini_array sections are unsupported");
    if (!WS.getSectionName().startswith(".init_array"))
      continue;
    if (WS.getFragmentList().empty())
      continue;
    if (WS.getFragmentList().size() != 2)
      report_fatal_error("only one .init_array section fragment supported");
    const MCFragment &AlignFrag = *WS.begin();
    if (AlignFrag.getKind() != MCFragment::FT_Align)
      report_fatal_error(".init_array section should be aligned");
    if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (is64Bit() ? 8 : 4))
      report_fatal_error(".init_array section should be aligned for pointers");
    const MCFragment &Frag = *std::next(WS.begin());
    if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
      report_fatal_error("only data supported in .init_array section");
    uint16_t Priority = UINT16_MAX;
    if (WS.getSectionName().size() != 11) {
      if (WS.getSectionName()[11] != '.')
        report_fatal_error(".init_array section priority should start with '.'");
      if (WS.getSectionName().substr(12).getAsInteger(10, Priority))
        report_fatal_error("invalid .init_array section priority");
    }
    const auto &DataFrag = cast<MCDataFragment>(Frag);
    const SmallVectorImpl<char> &Contents = DataFrag.getContents();
    for (const uint8_t *p = (const uint8_t *)Contents.data(),
                     *end = (const uint8_t *)Contents.data() + Contents.size();
         p != end; ++p) {
      if (*p != 0)
        report_fatal_error("non-symbolic data in .init_array section");
    }
    for (const MCFixup &Fixup : DataFrag.getFixups()) {
      assert(Fixup.getKind() == MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
      const MCExpr *Expr = Fixup.getValue();
      auto *Sym = dyn_cast<MCSymbolRefExpr>(Expr);
      if (!Sym)
        report_fatal_error("fixups in .init_array should be symbol references");
      if (Sym->getKind() != MCSymbolRefExpr::VK_WebAssembly_FUNCTION)
        report_fatal_error("symbols in .init_array should be for functions");
      auto I = SymbolIndices.find(cast<MCSymbolWasm>(&Sym->getSymbol()));
      if (I == SymbolIndices.end())
        report_fatal_error("symbols in .init_array should be defined");
      uint32_t Index = I->second;
      InitFuncs.push_back(std::make_pair(Priority, Index));
    }
  }

  // Write out the Wasm header.
  writeHeader(Asm);

  writeTypeSection(FunctionTypes);
  writeImportSection(Imports, DataSize, TableElems.size());
  writeFunctionSection(Functions);
  // Skip the "table" section; we import the table instead.
  // Skip the "memory" section; we import the memory instead.
  writeGlobalSection();
  writeExportSection(Exports);
  writeElemSection(TableElems);
  writeCodeSection(Asm, Layout, Functions);
  writeDataSection(DataSegments);
  writeNameSection(Functions, Imports, NumFuncImports);
  writeCodeRelocSection();
  writeDataRelocSection();
  writeLinkingMetaDataSection(DataSegments, DataSize, SymbolFlags,
                              InitFuncs);

  // TODO: Translate the .comment section to the output.
  // TODO: Translate debug sections to the output.
}

std::unique_ptr<MCObjectWriter>
llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
                             raw_pwrite_stream &OS) {
  // FIXME: Can't use make_unique<WasmObjectWriter>(...) as WasmObjectWriter's
  //        destructor is private. Is that necessary?
  return std::unique_ptr<MCObjectWriter>(
      new WasmObjectWriter(std::move(MOTW), OS));
}
