118eafb6cSDan Gohman //===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===//
218eafb6cSDan Gohman //
318eafb6cSDan Gohman //                     The LLVM Compiler Infrastructure
418eafb6cSDan Gohman //
518eafb6cSDan Gohman // This file is distributed under the University of Illinois Open Source
618eafb6cSDan Gohman // License. See LICENSE.TXT for details.
718eafb6cSDan Gohman //
818eafb6cSDan Gohman //===----------------------------------------------------------------------===//
918eafb6cSDan Gohman //
1018eafb6cSDan Gohman // This file implements Wasm object file writer information.
1118eafb6cSDan Gohman //
1218eafb6cSDan Gohman //===----------------------------------------------------------------------===//
1318eafb6cSDan Gohman 
1418eafb6cSDan Gohman #include "llvm/ADT/STLExtras.h"
1518eafb6cSDan Gohman #include "llvm/ADT/SmallPtrSet.h"
1618eafb6cSDan Gohman #include "llvm/MC/MCAsmBackend.h"
1718eafb6cSDan Gohman #include "llvm/MC/MCAsmInfo.h"
1818eafb6cSDan Gohman #include "llvm/MC/MCAsmLayout.h"
1918eafb6cSDan Gohman #include "llvm/MC/MCAssembler.h"
2018eafb6cSDan Gohman #include "llvm/MC/MCContext.h"
2118eafb6cSDan Gohman #include "llvm/MC/MCExpr.h"
2218eafb6cSDan Gohman #include "llvm/MC/MCFixupKindInfo.h"
2318eafb6cSDan Gohman #include "llvm/MC/MCObjectFileInfo.h"
2418eafb6cSDan Gohman #include "llvm/MC/MCObjectWriter.h"
2518eafb6cSDan Gohman #include "llvm/MC/MCSectionWasm.h"
2618eafb6cSDan Gohman #include "llvm/MC/MCSymbolWasm.h"
2718eafb6cSDan Gohman #include "llvm/MC/MCValue.h"
2818eafb6cSDan Gohman #include "llvm/MC/MCWasmObjectWriter.h"
29d934cb88SDan Gohman #include "llvm/Support/Casting.h"
3018eafb6cSDan Gohman #include "llvm/Support/Debug.h"
3118eafb6cSDan Gohman #include "llvm/Support/ErrorHandling.h"
32d934cb88SDan Gohman #include "llvm/Support/LEB128.h"
3318eafb6cSDan Gohman #include "llvm/Support/StringSaver.h"
347ea5adffSDan Gohman #include "llvm/Support/Wasm.h"
3518eafb6cSDan Gohman #include <vector>
3618eafb6cSDan Gohman 
3718eafb6cSDan Gohman using namespace llvm;
3818eafb6cSDan Gohman 
3918eafb6cSDan Gohman #undef DEBUG_TYPE
4018eafb6cSDan Gohman #define DEBUG_TYPE "reloc-info"
4118eafb6cSDan Gohman 
4218eafb6cSDan Gohman namespace {
43d934cb88SDan Gohman // For patching purposes, we need to remember where each section starts, both
44d934cb88SDan Gohman // for patching up the section size field, and for patching up references to
45d934cb88SDan Gohman // locations within the section.
46d934cb88SDan Gohman struct SectionBookkeeping {
47d934cb88SDan Gohman   // Where the size of the section is written.
48d934cb88SDan Gohman   uint64_t SizeOffset;
49d934cb88SDan Gohman   // Where the contents of the section starts (after the header).
50d934cb88SDan Gohman   uint64_t ContentsOffset;
51d934cb88SDan Gohman };
52d934cb88SDan Gohman 
5318eafb6cSDan Gohman class WasmObjectWriter : public MCObjectWriter {
5418eafb6cSDan Gohman   /// Helper struct for containing some precomputed information on symbols.
5518eafb6cSDan Gohman   struct WasmSymbolData {
5618eafb6cSDan Gohman     const MCSymbolWasm *Symbol;
5718eafb6cSDan Gohman     StringRef Name;
5818eafb6cSDan Gohman 
5918eafb6cSDan Gohman     // Support lexicographic sorting.
6018eafb6cSDan Gohman     bool operator<(const WasmSymbolData &RHS) const { return Name < RHS.Name; }
6118eafb6cSDan Gohman   };
6218eafb6cSDan Gohman 
6318eafb6cSDan Gohman   /// The target specific Wasm writer instance.
6418eafb6cSDan Gohman   std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
6518eafb6cSDan Gohman 
66d934cb88SDan Gohman   // Relocations for fixing up references in the code section.
67d934cb88SDan Gohman   std::vector<WasmRelocationEntry> CodeRelocations;
68d934cb88SDan Gohman 
69d934cb88SDan Gohman   // Relocations for fixing up references in the data section.
70d934cb88SDan Gohman   std::vector<WasmRelocationEntry> DataRelocations;
71d934cb88SDan Gohman 
72d934cb88SDan Gohman   // Fixups for call_indirect type indices.
73970d02c4SDan Gohman   std::vector<WasmRelocationEntry> TypeIndexFixups;
74d934cb88SDan Gohman 
75d934cb88SDan Gohman   // Index values to use for fixing up call_indirect type indices.
76d934cb88SDan Gohman   std::vector<uint32_t> TypeIndexFixupTypes;
77d934cb88SDan Gohman 
7818eafb6cSDan Gohman   // TargetObjectWriter wrappers.
7918eafb6cSDan Gohman   bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
8018eafb6cSDan Gohman   unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
8118eafb6cSDan Gohman                         const MCFixup &Fixup, bool IsPCRel) const {
8218eafb6cSDan Gohman     return TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel);
8318eafb6cSDan Gohman   }
8418eafb6cSDan Gohman 
85d934cb88SDan Gohman   void startSection(SectionBookkeeping &Section, unsigned SectionId,
86d934cb88SDan Gohman                     const char *Name = nullptr);
87d934cb88SDan Gohman   void endSection(SectionBookkeeping &Section);
88d934cb88SDan Gohman 
8918eafb6cSDan Gohman public:
9018eafb6cSDan Gohman   WasmObjectWriter(MCWasmObjectTargetWriter *MOTW, raw_pwrite_stream &OS)
9118eafb6cSDan Gohman       : MCObjectWriter(OS, /*IsLittleEndian=*/true), TargetObjectWriter(MOTW) {}
9218eafb6cSDan Gohman 
93d934cb88SDan Gohman private:
9418eafb6cSDan Gohman   void reset() override {
9518eafb6cSDan Gohman     MCObjectWriter::reset();
9618eafb6cSDan Gohman   }
9718eafb6cSDan Gohman 
9818eafb6cSDan Gohman   ~WasmObjectWriter() override;
9918eafb6cSDan Gohman 
10018eafb6cSDan Gohman   void writeHeader(const MCAssembler &Asm);
10118eafb6cSDan Gohman 
102e2688c43SDerek Schuff   void writeValueType(wasm::ValType Ty) {
103e2688c43SDerek Schuff     encodeSLEB128(int32_t(Ty), getStream());
104e2688c43SDerek Schuff   }
105e2688c43SDerek Schuff 
10618eafb6cSDan Gohman   void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
10718eafb6cSDan Gohman                         const MCFragment *Fragment, const MCFixup &Fixup,
10818eafb6cSDan Gohman                         MCValue Target, bool &IsPCRel,
10918eafb6cSDan Gohman                         uint64_t &FixedValue) override;
11018eafb6cSDan Gohman 
11118eafb6cSDan Gohman   void executePostLayoutBinding(MCAssembler &Asm,
11218eafb6cSDan Gohman                                 const MCAsmLayout &Layout) override;
11318eafb6cSDan Gohman 
11418eafb6cSDan Gohman   void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
11518eafb6cSDan Gohman };
11618eafb6cSDan Gohman } // end anonymous namespace
11718eafb6cSDan Gohman 
11818eafb6cSDan Gohman WasmObjectWriter::~WasmObjectWriter() {}
11918eafb6cSDan Gohman 
120d934cb88SDan Gohman // Return the padding size to write a 32-bit value into a 5-byte ULEB128.
121d934cb88SDan Gohman static unsigned PaddingFor5ByteULEB128(uint32_t X) {
122d934cb88SDan Gohman   return X == 0 ? 4 : (4u - (31u - countLeadingZeros(X)) / 7u);
123d934cb88SDan Gohman }
124d934cb88SDan Gohman 
125d934cb88SDan Gohman // Return the padding size to write a 32-bit value into a 5-byte SLEB128.
126d934cb88SDan Gohman static unsigned PaddingFor5ByteSLEB128(int32_t X) {
127d934cb88SDan Gohman   return 5 - getSLEB128Size(X);
128d934cb88SDan Gohman }
129d934cb88SDan Gohman 
130d934cb88SDan Gohman // Write out a section header and a patchable section size field.
131d934cb88SDan Gohman void WasmObjectWriter::startSection(SectionBookkeeping &Section,
132d934cb88SDan Gohman                                     unsigned SectionId,
133d934cb88SDan Gohman                                     const char *Name) {
134d934cb88SDan Gohman   assert((Name != nullptr) == (SectionId == wasm::WASM_SEC_CUSTOM) &&
135d934cb88SDan Gohman          "Only custom sections can have names");
136d934cb88SDan Gohman 
137e2688c43SDerek Schuff   encodeULEB128(SectionId, getStream());
138d934cb88SDan Gohman 
139d934cb88SDan Gohman   Section.SizeOffset = getStream().tell();
140d934cb88SDan Gohman 
141d934cb88SDan Gohman   // The section size. We don't know the size yet, so reserve enough space
142d934cb88SDan Gohman   // for any 32-bit value; we'll patch it later.
143d934cb88SDan Gohman   encodeULEB128(UINT32_MAX, getStream());
144d934cb88SDan Gohman 
145d934cb88SDan Gohman   // The position where the section starts, for measuring its size.
146d934cb88SDan Gohman   Section.ContentsOffset = getStream().tell();
147d934cb88SDan Gohman 
148d934cb88SDan Gohman   // Custom sections in wasm also have a string identifier.
149d934cb88SDan Gohman   if (SectionId == wasm::WASM_SEC_CUSTOM) {
150d934cb88SDan Gohman     encodeULEB128(strlen(Name), getStream());
151d934cb88SDan Gohman     writeBytes(Name);
152d934cb88SDan Gohman   }
153d934cb88SDan Gohman }
154d934cb88SDan Gohman 
155d934cb88SDan Gohman // Now that the section is complete and we know how big it is, patch up the
156d934cb88SDan Gohman // section size field at the start of the section.
157d934cb88SDan Gohman void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
158d934cb88SDan Gohman   uint64_t Size = getStream().tell() - Section.ContentsOffset;
159d934cb88SDan Gohman   if (uint32_t(Size) != Size)
160d934cb88SDan Gohman     report_fatal_error("section size does not fit in a uint32_t");
161d934cb88SDan Gohman 
162d934cb88SDan Gohman   unsigned Padding = PaddingFor5ByteULEB128(Size);
163d934cb88SDan Gohman 
164d934cb88SDan Gohman   // Write the final section size to the payload_len field, which follows
165d934cb88SDan Gohman   // the section id byte.
166d934cb88SDan Gohman   uint8_t Buffer[16];
167d934cb88SDan Gohman   unsigned SizeLen = encodeULEB128(Size, Buffer, Padding);
168d934cb88SDan Gohman   assert(SizeLen == 5);
169d934cb88SDan Gohman   getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset);
170d934cb88SDan Gohman }
171d934cb88SDan Gohman 
17218eafb6cSDan Gohman // Emit the Wasm header.
17318eafb6cSDan Gohman void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
1747ea5adffSDan Gohman   writeBytes(StringRef(wasm::WasmMagic, sizeof(wasm::WasmMagic)));
1757ea5adffSDan Gohman   writeLE32(wasm::WasmVersion);
17618eafb6cSDan Gohman }
17718eafb6cSDan Gohman 
17818eafb6cSDan Gohman void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
17918eafb6cSDan Gohman                                                 const MCAsmLayout &Layout) {
18018eafb6cSDan Gohman }
18118eafb6cSDan Gohman 
18218eafb6cSDan Gohman void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
18318eafb6cSDan Gohman                                         const MCAsmLayout &Layout,
18418eafb6cSDan Gohman                                         const MCFragment *Fragment,
18518eafb6cSDan Gohman                                         const MCFixup &Fixup, MCValue Target,
18618eafb6cSDan Gohman                                         bool &IsPCRel, uint64_t &FixedValue) {
187d934cb88SDan Gohman   MCSectionWasm &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
188d934cb88SDan Gohman   uint64_t C = Target.getConstant();
189d934cb88SDan Gohman   uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
190d934cb88SDan Gohman   MCContext &Ctx = Asm.getContext();
191d934cb88SDan Gohman 
192d934cb88SDan Gohman   if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
193d934cb88SDan Gohman     assert(RefB->getKind() == MCSymbolRefExpr::VK_None &&
194d934cb88SDan Gohman            "Should not have constructed this");
195d934cb88SDan Gohman 
196d934cb88SDan Gohman     // Let A, B and C being the components of Target and R be the location of
197d934cb88SDan Gohman     // the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
198d934cb88SDan Gohman     // If it is pcrel, we want to compute (A - B + C - R).
199d934cb88SDan Gohman 
200d934cb88SDan Gohman     // In general, Wasm has no relocations for -B. It can only represent (A + C)
201d934cb88SDan Gohman     // or (A + C - R). If B = R + K and the relocation is not pcrel, we can
202d934cb88SDan Gohman     // replace B to implement it: (A - R - K + C)
203d934cb88SDan Gohman     if (IsPCRel) {
204d934cb88SDan Gohman       Ctx.reportError(
205d934cb88SDan Gohman           Fixup.getLoc(),
206d934cb88SDan Gohman           "No relocation available to represent this relative expression");
207d934cb88SDan Gohman       return;
208d934cb88SDan Gohman     }
209d934cb88SDan Gohman 
210d934cb88SDan Gohman     const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
211d934cb88SDan Gohman 
212d934cb88SDan Gohman     if (SymB.isUndefined()) {
213d934cb88SDan Gohman       Ctx.reportError(Fixup.getLoc(),
214d934cb88SDan Gohman                       Twine("symbol '") + SymB.getName() +
215d934cb88SDan Gohman                           "' can not be undefined in a subtraction expression");
216d934cb88SDan Gohman       return;
217d934cb88SDan Gohman     }
218d934cb88SDan Gohman 
219d934cb88SDan Gohman     assert(!SymB.isAbsolute() && "Should have been folded");
220d934cb88SDan Gohman     const MCSection &SecB = SymB.getSection();
221d934cb88SDan Gohman     if (&SecB != &FixupSection) {
222d934cb88SDan Gohman       Ctx.reportError(Fixup.getLoc(),
223d934cb88SDan Gohman                       "Cannot represent a difference across sections");
224d934cb88SDan Gohman       return;
225d934cb88SDan Gohman     }
226d934cb88SDan Gohman 
227d934cb88SDan Gohman     uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
228d934cb88SDan Gohman     uint64_t K = SymBOffset - FixupOffset;
229d934cb88SDan Gohman     IsPCRel = true;
230d934cb88SDan Gohman     C -= K;
231d934cb88SDan Gohman   }
232d934cb88SDan Gohman 
233d934cb88SDan Gohman   // We either rejected the fixup or folded B into C at this point.
234d934cb88SDan Gohman   const MCSymbolRefExpr *RefA = Target.getSymA();
235d934cb88SDan Gohman   const auto *SymA = RefA ? cast<MCSymbolWasm>(&RefA->getSymbol()) : nullptr;
236d934cb88SDan Gohman 
237d934cb88SDan Gohman   bool ViaWeakRef = false;
238d934cb88SDan Gohman   if (SymA && SymA->isVariable()) {
239d934cb88SDan Gohman     const MCExpr *Expr = SymA->getVariableValue();
240d934cb88SDan Gohman     if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
241d934cb88SDan Gohman       if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) {
242d934cb88SDan Gohman         SymA = cast<MCSymbolWasm>(&Inner->getSymbol());
243d934cb88SDan Gohman         ViaWeakRef = true;
244d934cb88SDan Gohman       }
245d934cb88SDan Gohman     }
246d934cb88SDan Gohman   }
247d934cb88SDan Gohman 
248d934cb88SDan Gohman   // Put any constant offset in an addend. Offsets can be negative, and
249d934cb88SDan Gohman   // LLVM expects wrapping, in contrast to wasm's immediates which can't
250d934cb88SDan Gohman   // be negative and don't wrap.
251d934cb88SDan Gohman   FixedValue = 0;
252d934cb88SDan Gohman 
253d934cb88SDan Gohman   if (SymA) {
254d934cb88SDan Gohman     if (ViaWeakRef)
255d934cb88SDan Gohman       llvm_unreachable("weakref used in reloc not yet implemented");
256d934cb88SDan Gohman     else
257d934cb88SDan Gohman       SymA->setUsedInReloc();
258d934cb88SDan Gohman   }
259d934cb88SDan Gohman 
260d934cb88SDan Gohman   if (RefA) {
261d934cb88SDan Gohman     if (RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX) {
262970d02c4SDan Gohman       assert(C == 0);
263970d02c4SDan Gohman       WasmRelocationEntry Rec(FixupOffset, SymA, C,
264970d02c4SDan Gohman                               wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB,
265970d02c4SDan Gohman                               &FixupSection);
266970d02c4SDan Gohman       TypeIndexFixups.push_back(Rec);
267d934cb88SDan Gohman       return;
268d934cb88SDan Gohman     }
269d934cb88SDan Gohman   }
270d934cb88SDan Gohman 
271d934cb88SDan Gohman   unsigned Type = getRelocType(Ctx, Target, Fixup, IsPCRel);
272d934cb88SDan Gohman 
273d934cb88SDan Gohman   WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
274d934cb88SDan Gohman 
275d934cb88SDan Gohman   if (FixupSection.hasInstructions())
276d934cb88SDan Gohman     CodeRelocations.push_back(Rec);
277d934cb88SDan Gohman   else
278d934cb88SDan Gohman     DataRelocations.push_back(Rec);
279d934cb88SDan Gohman }
280d934cb88SDan Gohman 
281d934cb88SDan Gohman namespace {
282d934cb88SDan Gohman 
283d37dc2f7SDan Gohman // The signature of a wasm function, in a struct capable of being used as a
284d37dc2f7SDan Gohman // DenseMap key.
285d934cb88SDan Gohman struct WasmFunctionType {
286d934cb88SDan Gohman   // Support empty and tombstone instances, needed by DenseMap.
287d934cb88SDan Gohman   enum { Plain, Empty, Tombstone } State;
288d934cb88SDan Gohman 
289d934cb88SDan Gohman   // The return types of the function.
290e2688c43SDerek Schuff   SmallVector<wasm::ValType, 1> Returns;
291d934cb88SDan Gohman 
292d934cb88SDan Gohman   // The parameter types of the function.
293e2688c43SDerek Schuff   SmallVector<wasm::ValType, 4> Params;
294d934cb88SDan Gohman 
295d934cb88SDan Gohman   WasmFunctionType() : State(Plain) {}
296d934cb88SDan Gohman 
297d934cb88SDan Gohman   bool operator==(const WasmFunctionType &Other) const {
298d934cb88SDan Gohman     return State == Other.State && Returns == Other.Returns &&
299d934cb88SDan Gohman            Params == Other.Params;
300d934cb88SDan Gohman   }
301d934cb88SDan Gohman };
302d934cb88SDan Gohman 
303d934cb88SDan Gohman // Traits for using WasmFunctionType in a DenseMap.
304d934cb88SDan Gohman struct WasmFunctionTypeDenseMapInfo {
305d934cb88SDan Gohman   static WasmFunctionType getEmptyKey() {
306d934cb88SDan Gohman     WasmFunctionType FuncTy;
307d934cb88SDan Gohman     FuncTy.State = WasmFunctionType::Empty;
308d934cb88SDan Gohman     return FuncTy;
309d934cb88SDan Gohman   }
310d934cb88SDan Gohman   static WasmFunctionType getTombstoneKey() {
311d934cb88SDan Gohman     WasmFunctionType FuncTy;
312d934cb88SDan Gohman     FuncTy.State = WasmFunctionType::Tombstone;
313d934cb88SDan Gohman     return FuncTy;
314d934cb88SDan Gohman   }
315d934cb88SDan Gohman   static unsigned getHashValue(const WasmFunctionType &FuncTy) {
316d934cb88SDan Gohman     uintptr_t Value = FuncTy.State;
317e2688c43SDerek Schuff     for (wasm::ValType Ret : FuncTy.Returns)
318e2688c43SDerek Schuff       Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Ret));
319e2688c43SDerek Schuff     for (wasm::ValType Param : FuncTy.Params)
320e2688c43SDerek Schuff       Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Param));
321d934cb88SDan Gohman     return Value;
322d934cb88SDan Gohman   }
323d934cb88SDan Gohman   static bool isEqual(const WasmFunctionType &LHS,
324d934cb88SDan Gohman                       const WasmFunctionType &RHS) {
325d934cb88SDan Gohman     return LHS == RHS;
326d934cb88SDan Gohman   }
327d934cb88SDan Gohman };
328d934cb88SDan Gohman 
329d934cb88SDan Gohman // A wasm import to be written into the import section.
330d934cb88SDan Gohman struct WasmImport {
331d934cb88SDan Gohman   StringRef ModuleName;
332d934cb88SDan Gohman   StringRef FieldName;
333d934cb88SDan Gohman   unsigned Kind;
3349a4e45a0SDerek Schuff   int32_t Type;
335d934cb88SDan Gohman };
336d934cb88SDan Gohman 
337d934cb88SDan Gohman // A wasm function to be written into the function section.
338d934cb88SDan Gohman struct WasmFunction {
339b879539aSDerek Schuff   int32_t Type;
340d934cb88SDan Gohman   const MCSymbolWasm *Sym;
341d934cb88SDan Gohman };
342d934cb88SDan Gohman 
343d934cb88SDan Gohman // A wasm export to be written into the export section.
344d934cb88SDan Gohman struct WasmExport {
345d934cb88SDan Gohman   StringRef FieldName;
346d934cb88SDan Gohman   unsigned Kind;
347d934cb88SDan Gohman   uint32_t Index;
348d934cb88SDan Gohman };
349d934cb88SDan Gohman 
350d934cb88SDan Gohman // A wasm global to be written into the global section.
351d934cb88SDan Gohman struct WasmGlobal {
352b879539aSDerek Schuff   wasm::ValType Type;
353d934cb88SDan Gohman   bool IsMutable;
354970d02c4SDan Gohman   bool HasImport;
355970d02c4SDan Gohman   uint64_t InitialValue;
356970d02c4SDan Gohman   uint32_t ImportIndex;
357d934cb88SDan Gohman };
358d934cb88SDan Gohman 
359d934cb88SDan Gohman } // end anonymous namespace
360d934cb88SDan Gohman 
361d934cb88SDan Gohman // Write X as an (unsigned) LEB value at offset Offset in Stream, padded
362d934cb88SDan Gohman // to allow patching.
363d934cb88SDan Gohman static void
364d934cb88SDan Gohman WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
365d934cb88SDan Gohman   uint8_t Buffer[5];
366d934cb88SDan Gohman   unsigned Padding = PaddingFor5ByteULEB128(X);
367d934cb88SDan Gohman   unsigned SizeLen = encodeULEB128(X, Buffer, Padding);
368d934cb88SDan Gohman   assert(SizeLen == 5);
369d934cb88SDan Gohman   Stream.pwrite((char *)Buffer, SizeLen, Offset);
370d934cb88SDan Gohman }
371d934cb88SDan Gohman 
372d934cb88SDan Gohman // Write X as an signed LEB value at offset Offset in Stream, padded
373d934cb88SDan Gohman // to allow patching.
374d934cb88SDan Gohman static void
375d934cb88SDan Gohman WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) {
376d934cb88SDan Gohman   uint8_t Buffer[5];
377d934cb88SDan Gohman   unsigned Padding = PaddingFor5ByteSLEB128(X);
378d934cb88SDan Gohman   unsigned SizeLen = encodeSLEB128(X, Buffer, Padding);
379d934cb88SDan Gohman   assert(SizeLen == 5);
380d934cb88SDan Gohman   Stream.pwrite((char *)Buffer, SizeLen, Offset);
381d934cb88SDan Gohman }
382d934cb88SDan Gohman 
383d934cb88SDan Gohman // Write X as a plain integer value at offset Offset in Stream.
384d934cb88SDan Gohman static void WriteI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
385d934cb88SDan Gohman   uint8_t Buffer[4];
386d934cb88SDan Gohman   support::endian::write32le(Buffer, X);
387d934cb88SDan Gohman   Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
388d934cb88SDan Gohman }
389d934cb88SDan Gohman 
390d934cb88SDan Gohman // Compute a value to write into the code at the location covered
391d934cb88SDan Gohman // by RelEntry. This value isn't used by the static linker, since
392d934cb88SDan Gohman // we have addends; it just serves to make the code more readable
393d934cb88SDan Gohman // and to make standalone wasm modules directly usable.
394d934cb88SDan Gohman static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) {
395d934cb88SDan Gohman   const MCSymbolWasm *Sym = RelEntry.Symbol;
396d934cb88SDan Gohman 
397d934cb88SDan Gohman   // For undefined symbols, use a hopefully invalid value.
398d934cb88SDan Gohman   if (!Sym->isDefined(false))
399d934cb88SDan Gohman     return UINT32_MAX;
400d934cb88SDan Gohman 
401d934cb88SDan Gohman   MCSectionWasm &Section =
402d934cb88SDan Gohman     cast<MCSectionWasm>(RelEntry.Symbol->getSection(false));
403d934cb88SDan Gohman   uint64_t Address = Section.getSectionOffset() + RelEntry.Addend;
404d934cb88SDan Gohman 
405d934cb88SDan Gohman   // Ignore overflow. LLVM allows address arithmetic to silently wrap.
406d934cb88SDan Gohman   uint32_t Value = Address;
407d934cb88SDan Gohman 
408d934cb88SDan Gohman   return Value;
409d934cb88SDan Gohman }
410d934cb88SDan Gohman 
411d934cb88SDan Gohman // Apply the portions of the relocation records that we can handle ourselves
412d934cb88SDan Gohman // directly.
413d934cb88SDan Gohman static void ApplyRelocations(
414d934cb88SDan Gohman     ArrayRef<WasmRelocationEntry> Relocations,
415d934cb88SDan Gohman     raw_pwrite_stream &Stream,
416d934cb88SDan Gohman     DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices,
417d934cb88SDan Gohman     uint64_t ContentsOffset)
418d934cb88SDan Gohman {
419d934cb88SDan Gohman   for (const WasmRelocationEntry &RelEntry : Relocations) {
420d934cb88SDan Gohman     uint64_t Offset = ContentsOffset +
421d934cb88SDan Gohman                       RelEntry.FixupSection->getSectionOffset() +
422d934cb88SDan Gohman                       RelEntry.Offset;
423d934cb88SDan Gohman     switch (RelEntry.Type) {
424d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: {
425d934cb88SDan Gohman       uint32_t Index = SymbolIndices[RelEntry.Symbol];
426d934cb88SDan Gohman       assert(RelEntry.Addend == 0);
427d934cb88SDan Gohman 
428d934cb88SDan Gohman       WritePatchableLEB(Stream, Index, Offset);
429d934cb88SDan Gohman       break;
430d934cb88SDan Gohman     }
431d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: {
432d934cb88SDan Gohman       uint32_t Index = SymbolIndices[RelEntry.Symbol];
433d934cb88SDan Gohman       assert(RelEntry.Addend == 0);
434d934cb88SDan Gohman 
435d934cb88SDan Gohman       WritePatchableSLEB(Stream, Index, Offset);
436d934cb88SDan Gohman       break;
437d934cb88SDan Gohman     }
438d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: {
439d934cb88SDan Gohman       uint32_t Value = ProvisionalValue(RelEntry);
440d934cb88SDan Gohman 
441d934cb88SDan Gohman       WritePatchableSLEB(Stream, Value, Offset);
442d934cb88SDan Gohman       break;
443d934cb88SDan Gohman     }
444d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: {
445d934cb88SDan Gohman       uint32_t Value = ProvisionalValue(RelEntry);
446d934cb88SDan Gohman 
447d934cb88SDan Gohman       WritePatchableLEB(Stream, Value, Offset);
448d934cb88SDan Gohman       break;
449d934cb88SDan Gohman     }
450d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: {
451d934cb88SDan Gohman       uint32_t Index = SymbolIndices[RelEntry.Symbol];
452d934cb88SDan Gohman       assert(RelEntry.Addend == 0);
453d934cb88SDan Gohman 
454d934cb88SDan Gohman       WriteI32(Stream, Index, Offset);
455d934cb88SDan Gohman       break;
456d934cb88SDan Gohman     }
457d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: {
458d934cb88SDan Gohman       uint32_t Value = ProvisionalValue(RelEntry);
459d934cb88SDan Gohman 
460d934cb88SDan Gohman       WriteI32(Stream, Value, Offset);
461d934cb88SDan Gohman       break;
462d934cb88SDan Gohman     }
463d934cb88SDan Gohman     default:
464d934cb88SDan Gohman       break;
465d934cb88SDan Gohman     }
466d934cb88SDan Gohman   }
467d934cb88SDan Gohman }
468d934cb88SDan Gohman 
469d934cb88SDan Gohman // Write out the portions of the relocation records that the linker will
470d934cb88SDan Gohman // need to handle.
471d934cb88SDan Gohman static void WriteRelocations(
472d934cb88SDan Gohman     ArrayRef<WasmRelocationEntry> Relocations,
473d934cb88SDan Gohman     raw_pwrite_stream &Stream,
474d934cb88SDan Gohman     DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices)
475d934cb88SDan Gohman {
476d934cb88SDan Gohman   for (const WasmRelocationEntry RelEntry : Relocations) {
477d934cb88SDan Gohman     encodeULEB128(RelEntry.Type, Stream);
478d934cb88SDan Gohman 
479d934cb88SDan Gohman     uint64_t Offset = RelEntry.Offset +
480d934cb88SDan Gohman                       RelEntry.FixupSection->getSectionOffset();
481d934cb88SDan Gohman     uint32_t Index = SymbolIndices[RelEntry.Symbol];
482d934cb88SDan Gohman     int64_t Addend = RelEntry.Addend;
483d934cb88SDan Gohman 
484d934cb88SDan Gohman     switch (RelEntry.Type) {
485d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
486d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
487d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
488d934cb88SDan Gohman       encodeULEB128(Offset, Stream);
489d934cb88SDan Gohman       encodeULEB128(Index, Stream);
490d934cb88SDan Gohman       assert(Addend == 0 && "addends not supported for functions");
491d934cb88SDan Gohman       break;
492d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
493d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
494d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
495d934cb88SDan Gohman       encodeULEB128(Offset, Stream);
496d934cb88SDan Gohman       encodeULEB128(Index, Stream);
497d934cb88SDan Gohman       encodeSLEB128(Addend, Stream);
498d934cb88SDan Gohman       break;
499d934cb88SDan Gohman     default:
500d934cb88SDan Gohman       llvm_unreachable("unsupported relocation type");
501d934cb88SDan Gohman     }
502d934cb88SDan Gohman   }
50318eafb6cSDan Gohman }
50418eafb6cSDan Gohman 
505970d02c4SDan Gohman // Write out the the type relocation records that the linker will
506970d02c4SDan Gohman // need to handle.
507970d02c4SDan Gohman static void WriteTypeRelocations(
508970d02c4SDan Gohman     ArrayRef<WasmRelocationEntry> TypeIndexFixups,
509970d02c4SDan Gohman     ArrayRef<uint32_t> TypeIndexFixupTypes,
510970d02c4SDan Gohman     raw_pwrite_stream &Stream)
511970d02c4SDan Gohman {
512970d02c4SDan Gohman   for (size_t i = 0, e = TypeIndexFixups.size(); i < e; ++i) {
513970d02c4SDan Gohman     const WasmRelocationEntry &Fixup = TypeIndexFixups[i];
514970d02c4SDan Gohman     uint32_t Type = TypeIndexFixupTypes[i];
515970d02c4SDan Gohman 
516970d02c4SDan Gohman     assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB);
517970d02c4SDan Gohman     assert(Fixup.Addend == 0);
518970d02c4SDan Gohman 
519970d02c4SDan Gohman     uint64_t Offset = Fixup.Offset +
520970d02c4SDan Gohman                       Fixup.FixupSection->getSectionOffset();
521970d02c4SDan Gohman 
522970d02c4SDan Gohman     encodeULEB128(Fixup.Type, Stream);
523970d02c4SDan Gohman     encodeULEB128(Offset, Stream);
524970d02c4SDan Gohman     encodeULEB128(Type, Stream);
525970d02c4SDan Gohman   }
526970d02c4SDan Gohman }
527970d02c4SDan Gohman 
52818eafb6cSDan Gohman void WasmObjectWriter::writeObject(MCAssembler &Asm,
52918eafb6cSDan Gohman                                    const MCAsmLayout &Layout) {
53082607f56SDan Gohman   MCContext &Ctx = Asm.getContext();
531b879539aSDerek Schuff   wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32;
532d934cb88SDan Gohman 
533d934cb88SDan Gohman   // Collect information from the available symbols.
534b879539aSDerek Schuff   DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo>
535d934cb88SDan Gohman       FunctionTypeIndices;
536d934cb88SDan Gohman   SmallVector<WasmFunctionType, 4> FunctionTypes;
537d934cb88SDan Gohman   SmallVector<WasmFunction, 4> Functions;
538d934cb88SDan Gohman   SmallVector<uint32_t, 4> TableElems;
539d934cb88SDan Gohman   SmallVector<WasmGlobal, 4> Globals;
540d934cb88SDan Gohman   SmallVector<WasmImport, 4> Imports;
541d934cb88SDan Gohman   SmallVector<WasmExport, 4> Exports;
542d934cb88SDan Gohman   DenseMap<const MCSymbolWasm *, uint32_t> SymbolIndices;
543d934cb88SDan Gohman   SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken;
544d934cb88SDan Gohman   unsigned NumFuncImports = 0;
545d934cb88SDan Gohman   unsigned NumGlobalImports = 0;
546d934cb88SDan Gohman   SmallVector<char, 0> DataBytes;
547970d02c4SDan Gohman   uint32_t StackPointerGlobal = 0;
548970d02c4SDan Gohman   bool HasStackPointer = false;
549d934cb88SDan Gohman 
550d934cb88SDan Gohman   // Populate the IsAddressTaken set.
551d934cb88SDan Gohman   for (WasmRelocationEntry RelEntry : CodeRelocations) {
552d934cb88SDan Gohman     switch (RelEntry.Type) {
553d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
554d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
555d934cb88SDan Gohman       IsAddressTaken.insert(RelEntry.Symbol);
556d934cb88SDan Gohman       break;
557d934cb88SDan Gohman     default:
558d934cb88SDan Gohman       break;
559d934cb88SDan Gohman     }
560d934cb88SDan Gohman   }
561d934cb88SDan Gohman   for (WasmRelocationEntry RelEntry : DataRelocations) {
562d934cb88SDan Gohman     switch (RelEntry.Type) {
563d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
564d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
565d934cb88SDan Gohman       IsAddressTaken.insert(RelEntry.Symbol);
566d934cb88SDan Gohman       break;
567d934cb88SDan Gohman     default:
568d934cb88SDan Gohman       break;
569d934cb88SDan Gohman     }
570d934cb88SDan Gohman   }
571d934cb88SDan Gohman 
572d934cb88SDan Gohman   // Populate the Imports set.
573d934cb88SDan Gohman   for (const MCSymbol &S : Asm.symbols()) {
574d934cb88SDan Gohman     const auto &WS = static_cast<const MCSymbolWasm &>(S);
575b879539aSDerek Schuff     int32_t Type;
576d934cb88SDan Gohman 
577d934cb88SDan Gohman     if (WS.isFunction()) {
578d934cb88SDan Gohman       // Prepare the function's type, if we haven't seen it yet.
579d934cb88SDan Gohman       WasmFunctionType F;
580d934cb88SDan Gohman       F.Returns = WS.getReturns();
581d934cb88SDan Gohman       F.Params = WS.getParams();
582d934cb88SDan Gohman       auto Pair =
583d934cb88SDan Gohman           FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
584d934cb88SDan Gohman       if (Pair.second)
585d934cb88SDan Gohman         FunctionTypes.push_back(F);
586d934cb88SDan Gohman 
587d934cb88SDan Gohman       Type = Pair.first->second;
588d934cb88SDan Gohman     } else {
589b879539aSDerek Schuff       Type = int32_t(PtrType);
590d934cb88SDan Gohman     }
591d934cb88SDan Gohman 
592d934cb88SDan Gohman     // If the symbol is not defined in this translation unit, import it.
593d934cb88SDan Gohman     if (!WS.isTemporary() && !WS.isDefined(/*SetUsed=*/false)) {
594d934cb88SDan Gohman       WasmImport Import;
595d934cb88SDan Gohman       Import.ModuleName = WS.getModuleName();
596d934cb88SDan Gohman       Import.FieldName = WS.getName();
597d934cb88SDan Gohman 
598d934cb88SDan Gohman       if (WS.isFunction()) {
599d934cb88SDan Gohman         Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
600d934cb88SDan Gohman         Import.Type = Type;
601d934cb88SDan Gohman         SymbolIndices[&WS] = NumFuncImports;
602d934cb88SDan Gohman         ++NumFuncImports;
603d934cb88SDan Gohman       } else {
604d934cb88SDan Gohman         Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
605d934cb88SDan Gohman         Import.Type = Type;
606d934cb88SDan Gohman         SymbolIndices[&WS] = NumGlobalImports;
607d934cb88SDan Gohman         ++NumGlobalImports;
608d934cb88SDan Gohman       }
609d934cb88SDan Gohman 
610d934cb88SDan Gohman       Imports.push_back(Import);
611d934cb88SDan Gohman     }
612d934cb88SDan Gohman   }
613d934cb88SDan Gohman 
61482607f56SDan Gohman   // In the special .global_variables section, we've encoded global
61582607f56SDan Gohman   // variables used by the function. Translate them into the Globals
61682607f56SDan Gohman   // list.
61782607f56SDan Gohman   MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0);
61882607f56SDan Gohman   if (!GlobalVars->getFragmentList().empty()) {
61982607f56SDan Gohman     if (GlobalVars->getFragmentList().size() != 1)
62082607f56SDan Gohman       report_fatal_error("only one .global_variables fragment supported");
62182607f56SDan Gohman     const MCFragment &Frag = *GlobalVars->begin();
62282607f56SDan Gohman     if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
62382607f56SDan Gohman       report_fatal_error("only data supported in .global_variables");
62482607f56SDan Gohman     const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag);
62582607f56SDan Gohman     if (!DataFrag.getFixups().empty())
62682607f56SDan Gohman       report_fatal_error("fixups not supported in .global_variables");
62782607f56SDan Gohman     const SmallVectorImpl<char> &Contents = DataFrag.getContents();
628970d02c4SDan Gohman     for (const uint8_t *p = (const uint8_t *)Contents.data(),
629970d02c4SDan Gohman                      *end = (const uint8_t *)Contents.data() + Contents.size();
630970d02c4SDan Gohman          p != end; ) {
63182607f56SDan Gohman       WasmGlobal G;
632970d02c4SDan Gohman       if (end - p < 3)
633970d02c4SDan Gohman         report_fatal_error("truncated global variable encoding");
634970d02c4SDan Gohman       G.Type = wasm::ValType(int8_t(*p++));
635970d02c4SDan Gohman       G.IsMutable = bool(*p++);
636970d02c4SDan Gohman       G.HasImport = bool(*p++);
637970d02c4SDan Gohman       if (G.HasImport) {
63882607f56SDan Gohman         G.InitialValue = 0;
639970d02c4SDan Gohman 
640970d02c4SDan Gohman         WasmImport Import;
641970d02c4SDan Gohman         Import.ModuleName = (const char *)p;
642970d02c4SDan Gohman         const uint8_t *nul = (const uint8_t *)memchr(p, '\0', end - p);
643970d02c4SDan Gohman         if (!nul)
644970d02c4SDan Gohman           report_fatal_error("global module name must be nul-terminated");
645970d02c4SDan Gohman         p = nul + 1;
646970d02c4SDan Gohman         nul = (const uint8_t *)memchr(p, '\0', end - p);
647970d02c4SDan Gohman         if (!nul)
648970d02c4SDan Gohman           report_fatal_error("global base name must be nul-terminated");
649970d02c4SDan Gohman         Import.FieldName = (const char *)p;
650970d02c4SDan Gohman         p = nul + 1;
651970d02c4SDan Gohman 
652970d02c4SDan Gohman         Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
653970d02c4SDan Gohman         Import.Type = int32_t(G.Type);
654970d02c4SDan Gohman 
655970d02c4SDan Gohman         G.ImportIndex = NumGlobalImports;
656970d02c4SDan Gohman         ++NumGlobalImports;
657970d02c4SDan Gohman 
658970d02c4SDan Gohman         Imports.push_back(Import);
659970d02c4SDan Gohman       } else {
660970d02c4SDan Gohman         unsigned n;
661970d02c4SDan Gohman         G.InitialValue = decodeSLEB128(p, &n);
662970d02c4SDan Gohman         G.ImportIndex = 0;
663c8da0c0bSSimon Pilgrim         if ((ptrdiff_t)n > end - p)
664970d02c4SDan Gohman           report_fatal_error("global initial value must be valid SLEB128");
665970d02c4SDan Gohman         p += n;
666970d02c4SDan Gohman       }
66782607f56SDan Gohman       Globals.push_back(G);
66882607f56SDan Gohman     }
66982607f56SDan Gohman   }
67082607f56SDan Gohman 
671970d02c4SDan Gohman   // In the special .stack_pointer section, we've encoded the stack pointer
672970d02c4SDan Gohman   // index.
673970d02c4SDan Gohman   MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", 0, 0);
674970d02c4SDan Gohman   if (!StackPtr->getFragmentList().empty()) {
675970d02c4SDan Gohman     if (StackPtr->getFragmentList().size() != 1)
676970d02c4SDan Gohman       report_fatal_error("only one .stack_pointer fragment supported");
677970d02c4SDan Gohman     const MCFragment &Frag = *StackPtr->begin();
678970d02c4SDan Gohman     if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
679970d02c4SDan Gohman       report_fatal_error("only data supported in .stack_pointer");
680970d02c4SDan Gohman     const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag);
681970d02c4SDan Gohman     if (!DataFrag.getFixups().empty())
682970d02c4SDan Gohman       report_fatal_error("fixups not supported in .stack_pointer");
683970d02c4SDan Gohman     const SmallVectorImpl<char> &Contents = DataFrag.getContents();
684970d02c4SDan Gohman     if (Contents.size() != 4)
685970d02c4SDan Gohman       report_fatal_error("only one entry supported in .stack_pointer");
686970d02c4SDan Gohman     HasStackPointer = true;
687970d02c4SDan Gohman     StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
688970d02c4SDan Gohman   }
689970d02c4SDan Gohman 
690d934cb88SDan Gohman   // Handle defined symbols.
691d934cb88SDan Gohman   for (const MCSymbol &S : Asm.symbols()) {
692d934cb88SDan Gohman     // Ignore unnamed temporary symbols, which aren't ever exported, imported,
693d934cb88SDan Gohman     // or used in relocations.
694d934cb88SDan Gohman     if (S.isTemporary() && S.getName().empty())
695d934cb88SDan Gohman       continue;
696d934cb88SDan Gohman     const auto &WS = static_cast<const MCSymbolWasm &>(S);
697d934cb88SDan Gohman     unsigned Index;
698d934cb88SDan Gohman     if (WS.isFunction()) {
699d934cb88SDan Gohman       // Prepare the function's type, if we haven't seen it yet.
700d934cb88SDan Gohman       WasmFunctionType F;
701d934cb88SDan Gohman       F.Returns = WS.getReturns();
702d934cb88SDan Gohman       F.Params = WS.getParams();
703d934cb88SDan Gohman       auto Pair =
704d934cb88SDan Gohman           FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
705d934cb88SDan Gohman       if (Pair.second)
706d934cb88SDan Gohman         FunctionTypes.push_back(F);
707d934cb88SDan Gohman 
708b879539aSDerek Schuff       int32_t Type = Pair.first->second;
709d934cb88SDan Gohman 
710d934cb88SDan Gohman       if (WS.isDefined(/*SetUsed=*/false)) {
711d934cb88SDan Gohman         // A definition. Take the next available index.
712d934cb88SDan Gohman         Index = NumFuncImports + Functions.size();
713d934cb88SDan Gohman 
714d934cb88SDan Gohman         // Prepare the function.
715d934cb88SDan Gohman         WasmFunction Func;
716d934cb88SDan Gohman         Func.Type = Type;
717d934cb88SDan Gohman         Func.Sym = &WS;
718d934cb88SDan Gohman         SymbolIndices[&WS] = Index;
719d934cb88SDan Gohman         Functions.push_back(Func);
720d934cb88SDan Gohman       } else {
721d934cb88SDan Gohman         // An import; the index was assigned above.
722d934cb88SDan Gohman         Index = SymbolIndices.find(&WS)->second;
723d934cb88SDan Gohman       }
724d934cb88SDan Gohman 
725d934cb88SDan Gohman       // If needed, prepare the function to be called indirectly.
726d934cb88SDan Gohman       if (IsAddressTaken.count(&WS))
727d934cb88SDan Gohman         TableElems.push_back(Index);
728d934cb88SDan Gohman     } else {
729d934cb88SDan Gohman       // For now, ignore temporary non-function symbols.
730d934cb88SDan Gohman       if (S.isTemporary())
731d934cb88SDan Gohman         continue;
732d934cb88SDan Gohman 
733d934cb88SDan Gohman       if (WS.getOffset() != 0)
734d934cb88SDan Gohman         report_fatal_error("data sections must contain one variable each");
735d934cb88SDan Gohman       if (!WS.getSize())
736d934cb88SDan Gohman         report_fatal_error("data symbols must have a size set with .size");
737d934cb88SDan Gohman 
738d934cb88SDan Gohman       int64_t Size = 0;
739d934cb88SDan Gohman       if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
740d934cb88SDan Gohman         report_fatal_error(".size expression must be evaluatable");
741d934cb88SDan Gohman 
742d934cb88SDan Gohman       if (WS.isDefined(false)) {
743d934cb88SDan Gohman         MCSectionWasm &DataSection =
744d934cb88SDan Gohman             static_cast<MCSectionWasm &>(WS.getSection());
745d934cb88SDan Gohman 
746d934cb88SDan Gohman         if (uint64_t(Size) != Layout.getSectionFileSize(&DataSection))
747d934cb88SDan Gohman           report_fatal_error("data sections must contain at most one variable");
748d934cb88SDan Gohman 
749d934cb88SDan Gohman         DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
750d934cb88SDan Gohman 
751d934cb88SDan Gohman         DataSection.setSectionOffset(DataBytes.size());
752d934cb88SDan Gohman 
753d934cb88SDan Gohman         for (MCSection::iterator I = DataSection.begin(), E = DataSection.end();
754d934cb88SDan Gohman              I != E; ++I) {
755d934cb88SDan Gohman           const MCFragment &Frag = *I;
756d934cb88SDan Gohman           if (Frag.hasInstructions())
757d934cb88SDan Gohman             report_fatal_error("only data supported in data sections");
758d934cb88SDan Gohman 
759d934cb88SDan Gohman           if (const MCAlignFragment *Align = dyn_cast<MCAlignFragment>(&Frag)) {
760d934cb88SDan Gohman             if (Align->getValueSize() != 1)
761d934cb88SDan Gohman               report_fatal_error("only byte values supported for alignment");
762d934cb88SDan Gohman             // If nops are requested, use zeros, as this is the data section.
763d934cb88SDan Gohman             uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
764d934cb88SDan Gohman             uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(),
765d934cb88SDan Gohman                                                        Align->getAlignment()),
766d934cb88SDan Gohman                                                DataBytes.size() +
767d934cb88SDan Gohman                                                    Align->getMaxBytesToEmit());
768d934cb88SDan Gohman             DataBytes.resize(Size, Value);
769d934cb88SDan Gohman           } else if (const MCFillFragment *Fill =
770d934cb88SDan Gohman                                               dyn_cast<MCFillFragment>(&Frag)) {
771d934cb88SDan Gohman             DataBytes.insert(DataBytes.end(), Size, Fill->getValue());
772d934cb88SDan Gohman           } else {
773d934cb88SDan Gohman             const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag);
774d934cb88SDan Gohman             const SmallVectorImpl<char> &Contents = DataFrag.getContents();
775d934cb88SDan Gohman 
776d934cb88SDan Gohman             DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
777d934cb88SDan Gohman           }
778d934cb88SDan Gohman         }
779d934cb88SDan Gohman 
780d934cb88SDan Gohman         // For each external global, prepare a corresponding wasm global
781d934cb88SDan Gohman         // holding its address.
782d934cb88SDan Gohman         if (WS.isExternal()) {
783d934cb88SDan Gohman           Index = NumGlobalImports + Globals.size();
784d934cb88SDan Gohman 
785d934cb88SDan Gohman           WasmGlobal Global;
786d934cb88SDan Gohman           Global.Type = PtrType;
787d934cb88SDan Gohman           Global.IsMutable = false;
788970d02c4SDan Gohman           Global.HasImport = false;
789d934cb88SDan Gohman           Global.InitialValue = DataSection.getSectionOffset();
790970d02c4SDan Gohman           Global.ImportIndex = 0;
791d934cb88SDan Gohman           SymbolIndices[&WS] = Index;
792d934cb88SDan Gohman           Globals.push_back(Global);
793d934cb88SDan Gohman         }
794d934cb88SDan Gohman       }
795d934cb88SDan Gohman     }
796d934cb88SDan Gohman 
797d934cb88SDan Gohman     // If the symbol is visible outside this translation unit, export it.
798d934cb88SDan Gohman     if (WS.isExternal()) {
799d934cb88SDan Gohman       assert(WS.isDefined(false));
800d934cb88SDan Gohman       WasmExport Export;
801d934cb88SDan Gohman       Export.FieldName = WS.getName();
802d934cb88SDan Gohman       Export.Index = Index;
803d934cb88SDan Gohman 
804d934cb88SDan Gohman       if (WS.isFunction())
805d934cb88SDan Gohman         Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
806d934cb88SDan Gohman       else
807d934cb88SDan Gohman         Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
808d934cb88SDan Gohman 
809d934cb88SDan Gohman       Exports.push_back(Export);
810d934cb88SDan Gohman     }
811d934cb88SDan Gohman   }
812d934cb88SDan Gohman 
813d934cb88SDan Gohman   // Add types for indirect function calls.
814970d02c4SDan Gohman   for (const WasmRelocationEntry &Fixup : TypeIndexFixups) {
815970d02c4SDan Gohman     assert(Fixup.Addend == 0);
816970d02c4SDan Gohman     assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB);
817970d02c4SDan Gohman 
818d934cb88SDan Gohman     WasmFunctionType F;
819d934cb88SDan Gohman     F.Returns = Fixup.Symbol->getReturns();
820d934cb88SDan Gohman     F.Params = Fixup.Symbol->getParams();
821d934cb88SDan Gohman     auto Pair =
822d934cb88SDan Gohman         FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
823d934cb88SDan Gohman     if (Pair.second)
824d934cb88SDan Gohman       FunctionTypes.push_back(F);
825d934cb88SDan Gohman 
826d934cb88SDan Gohman     TypeIndexFixupTypes.push_back(Pair.first->second);
827d934cb88SDan Gohman   }
828d934cb88SDan Gohman 
82918eafb6cSDan Gohman   // Write out the Wasm header.
83018eafb6cSDan Gohman   writeHeader(Asm);
83118eafb6cSDan Gohman 
832d934cb88SDan Gohman   SectionBookkeeping Section;
833d934cb88SDan Gohman 
834d934cb88SDan Gohman   // === Type Section =========================================================
835d934cb88SDan Gohman   if (!FunctionTypes.empty()) {
836d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_TYPE);
837d934cb88SDan Gohman 
838d934cb88SDan Gohman     encodeULEB128(FunctionTypes.size(), getStream());
839d934cb88SDan Gohman 
840d934cb88SDan Gohman     for (WasmFunctionType &FuncTy : FunctionTypes) {
841e2688c43SDerek Schuff       encodeSLEB128(wasm::WASM_TYPE_FUNC, getStream());
842d934cb88SDan Gohman       encodeULEB128(FuncTy.Params.size(), getStream());
843e2688c43SDerek Schuff       for (wasm::ValType Ty : FuncTy.Params)
844e2688c43SDerek Schuff         writeValueType(Ty);
845d934cb88SDan Gohman       encodeULEB128(FuncTy.Returns.size(), getStream());
846e2688c43SDerek Schuff       for (wasm::ValType Ty : FuncTy.Returns)
847e2688c43SDerek Schuff         writeValueType(Ty);
848d934cb88SDan Gohman     }
849d934cb88SDan Gohman 
850d934cb88SDan Gohman     endSection(Section);
851d934cb88SDan Gohman   }
852d934cb88SDan Gohman 
853d934cb88SDan Gohman   // === Import Section ========================================================
854d934cb88SDan Gohman   if (!Imports.empty()) {
855d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_IMPORT);
856d934cb88SDan Gohman 
857d934cb88SDan Gohman     encodeULEB128(Imports.size(), getStream());
858d934cb88SDan Gohman     for (const WasmImport &Import : Imports) {
859d934cb88SDan Gohman       StringRef ModuleName = Import.ModuleName;
860d934cb88SDan Gohman       encodeULEB128(ModuleName.size(), getStream());
861d934cb88SDan Gohman       writeBytes(ModuleName);
862d934cb88SDan Gohman 
863d934cb88SDan Gohman       StringRef FieldName = Import.FieldName;
864d934cb88SDan Gohman       encodeULEB128(FieldName.size(), getStream());
865d934cb88SDan Gohman       writeBytes(FieldName);
866d934cb88SDan Gohman 
867e2688c43SDerek Schuff       encodeULEB128(Import.Kind, getStream());
868d934cb88SDan Gohman 
869d934cb88SDan Gohman       switch (Import.Kind) {
870d934cb88SDan Gohman       case wasm::WASM_EXTERNAL_FUNCTION:
871d934cb88SDan Gohman         encodeULEB128(Import.Type, getStream());
872d934cb88SDan Gohman         break;
873d934cb88SDan Gohman       case wasm::WASM_EXTERNAL_GLOBAL:
874970d02c4SDan Gohman         encodeSLEB128(int32_t(Import.Type), getStream());
875e2688c43SDerek Schuff         encodeULEB128(0, getStream()); // mutability
876d934cb88SDan Gohman         break;
877d934cb88SDan Gohman       default:
878d934cb88SDan Gohman         llvm_unreachable("unsupported import kind");
879d934cb88SDan Gohman       }
880d934cb88SDan Gohman     }
881d934cb88SDan Gohman 
882d934cb88SDan Gohman     endSection(Section);
883d934cb88SDan Gohman   }
884d934cb88SDan Gohman 
885d934cb88SDan Gohman   // === Function Section ======================================================
886d934cb88SDan Gohman   if (!Functions.empty()) {
887d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_FUNCTION);
888d934cb88SDan Gohman 
889d934cb88SDan Gohman     encodeULEB128(Functions.size(), getStream());
890d934cb88SDan Gohman     for (const WasmFunction &Func : Functions)
891d934cb88SDan Gohman       encodeULEB128(Func.Type, getStream());
892d934cb88SDan Gohman 
893d934cb88SDan Gohman     endSection(Section);
894d934cb88SDan Gohman   }
895d934cb88SDan Gohman 
896d934cb88SDan Gohman   // === Table Section =========================================================
897d934cb88SDan Gohman   // For now, always emit the table section, since indirect calls are not
898d934cb88SDan Gohman   // valid without it. In the future, we could perhaps be more clever and omit
899d934cb88SDan Gohman   // it if there are no indirect calls.
900d934cb88SDan Gohman   startSection(Section, wasm::WASM_SEC_TABLE);
901d934cb88SDan Gohman 
902d934cb88SDan Gohman   // The number of tables, fixed to 1 for now.
903d934cb88SDan Gohman   encodeULEB128(1, getStream());
904d934cb88SDan Gohman 
905e2688c43SDerek Schuff   encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream());
906d934cb88SDan Gohman 
907d934cb88SDan Gohman   encodeULEB128(0, getStream());                 // flags
908d934cb88SDan Gohman   encodeULEB128(TableElems.size(), getStream()); // initial
909d934cb88SDan Gohman 
910d934cb88SDan Gohman   endSection(Section);
911d934cb88SDan Gohman 
912d934cb88SDan Gohman   // === Memory Section ========================================================
913d934cb88SDan Gohman   // For now, always emit the memory section, since loads and stores are not
914d934cb88SDan Gohman   // valid without it. In the future, we could perhaps be more clever and omit
915d934cb88SDan Gohman   // it if there are no loads or stores.
916*ff0730b3SSam Clegg   uint32_t NumPages =
917*ff0730b3SSam Clegg       (DataBytes.size() + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
918d934cb88SDan Gohman 
919*ff0730b3SSam Clegg   startSection(Section, wasm::WASM_SEC_MEMORY);
920d934cb88SDan Gohman   encodeULEB128(1, getStream()); // number of memory spaces
921d934cb88SDan Gohman 
922d934cb88SDan Gohman   encodeULEB128(0, getStream()); // flags
923*ff0730b3SSam Clegg   encodeULEB128(NumPages, getStream()); // initial
924d934cb88SDan Gohman 
925d934cb88SDan Gohman   endSection(Section);
926d934cb88SDan Gohman 
927d934cb88SDan Gohman   // === Global Section ========================================================
928d934cb88SDan Gohman   if (!Globals.empty()) {
929d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_GLOBAL);
930d934cb88SDan Gohman 
931d934cb88SDan Gohman     encodeULEB128(Globals.size(), getStream());
932d934cb88SDan Gohman     for (const WasmGlobal &Global : Globals) {
933b879539aSDerek Schuff       writeValueType(Global.Type);
934d934cb88SDan Gohman       write8(Global.IsMutable);
935d934cb88SDan Gohman 
936970d02c4SDan Gohman       if (Global.HasImport) {
937970d02c4SDan Gohman         assert(Global.InitialValue == 0);
938970d02c4SDan Gohman         write8(wasm::WASM_OPCODE_GET_GLOBAL);
939970d02c4SDan Gohman         encodeULEB128(Global.ImportIndex, getStream());
940970d02c4SDan Gohman       } else {
941970d02c4SDan Gohman         assert(Global.ImportIndex == 0);
942d934cb88SDan Gohman         write8(wasm::WASM_OPCODE_I32_CONST);
943d934cb88SDan Gohman         encodeSLEB128(Global.InitialValue, getStream()); // offset
944970d02c4SDan Gohman       }
945d934cb88SDan Gohman       write8(wasm::WASM_OPCODE_END);
946d934cb88SDan Gohman     }
947d934cb88SDan Gohman 
948d934cb88SDan Gohman     endSection(Section);
949d934cb88SDan Gohman   }
950d934cb88SDan Gohman 
951d934cb88SDan Gohman   // === Export Section ========================================================
952d934cb88SDan Gohman   if (!Exports.empty()) {
953d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_EXPORT);
954d934cb88SDan Gohman 
955d934cb88SDan Gohman     encodeULEB128(Exports.size(), getStream());
956d934cb88SDan Gohman     for (const WasmExport &Export : Exports) {
957d934cb88SDan Gohman       encodeULEB128(Export.FieldName.size(), getStream());
958d934cb88SDan Gohman       writeBytes(Export.FieldName);
959d934cb88SDan Gohman 
960e2688c43SDerek Schuff       encodeSLEB128(Export.Kind, getStream());
961d934cb88SDan Gohman 
962d934cb88SDan Gohman       encodeULEB128(Export.Index, getStream());
963d934cb88SDan Gohman     }
964d934cb88SDan Gohman 
965d934cb88SDan Gohman     endSection(Section);
966d934cb88SDan Gohman   }
967d934cb88SDan Gohman 
968d934cb88SDan Gohman #if 0 // TODO: Start Section
969d934cb88SDan Gohman   if (HaveStartFunction) {
970d934cb88SDan Gohman     // === Start Section =========================================================
971d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_START);
972d934cb88SDan Gohman 
973d934cb88SDan Gohman     encodeSLEB128(StartFunction, getStream());
974d934cb88SDan Gohman 
975d934cb88SDan Gohman     endSection(Section);
976d934cb88SDan Gohman   }
977d934cb88SDan Gohman #endif
978d934cb88SDan Gohman 
979d934cb88SDan Gohman   // === Elem Section ==========================================================
980d934cb88SDan Gohman   if (!TableElems.empty()) {
981d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_ELEM);
982d934cb88SDan Gohman 
983d934cb88SDan Gohman     encodeULEB128(1, getStream()); // number of "segments"
984d934cb88SDan Gohman     encodeULEB128(0, getStream()); // the table index
985d934cb88SDan Gohman 
986d934cb88SDan Gohman     // init expr for starting offset
987d934cb88SDan Gohman     write8(wasm::WASM_OPCODE_I32_CONST);
988d934cb88SDan Gohman     encodeSLEB128(0, getStream());
989d934cb88SDan Gohman     write8(wasm::WASM_OPCODE_END);
990d934cb88SDan Gohman 
991d934cb88SDan Gohman     encodeULEB128(TableElems.size(), getStream());
992d934cb88SDan Gohman     for (uint32_t Elem : TableElems)
993d934cb88SDan Gohman       encodeULEB128(Elem, getStream());
994d934cb88SDan Gohman 
995d934cb88SDan Gohman     endSection(Section);
996d934cb88SDan Gohman   }
997d934cb88SDan Gohman 
998d934cb88SDan Gohman   // === Code Section ==========================================================
999d934cb88SDan Gohman   if (!Functions.empty()) {
1000d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_CODE);
1001d934cb88SDan Gohman 
1002d934cb88SDan Gohman     encodeULEB128(Functions.size(), getStream());
1003d934cb88SDan Gohman 
1004d934cb88SDan Gohman     for (const WasmFunction &Func : Functions) {
1005d934cb88SDan Gohman       MCSectionWasm &FuncSection =
1006d934cb88SDan Gohman           static_cast<MCSectionWasm &>(Func.Sym->getSection());
1007d934cb88SDan Gohman 
1008d934cb88SDan Gohman       if (Func.Sym->isVariable())
1009d934cb88SDan Gohman         report_fatal_error("weak symbols not supported yet");
1010d934cb88SDan Gohman 
1011d934cb88SDan Gohman       if (Func.Sym->getOffset() != 0)
1012d934cb88SDan Gohman         report_fatal_error("function sections must contain one function each");
1013d934cb88SDan Gohman 
1014d934cb88SDan Gohman       if (!Func.Sym->getSize())
1015d934cb88SDan Gohman         report_fatal_error("function symbols must have a size set with .size");
1016d934cb88SDan Gohman 
1017d934cb88SDan Gohman       int64_t Size = 0;
1018d934cb88SDan Gohman       if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
1019d934cb88SDan Gohman         report_fatal_error(".size expression must be evaluatable");
1020d934cb88SDan Gohman 
1021d934cb88SDan Gohman       encodeULEB128(Size, getStream());
1022d934cb88SDan Gohman 
1023d934cb88SDan Gohman       FuncSection.setSectionOffset(getStream().tell() -
1024d934cb88SDan Gohman                                    Section.ContentsOffset);
1025d934cb88SDan Gohman 
1026d934cb88SDan Gohman       Asm.writeSectionData(&FuncSection, Layout);
1027d934cb88SDan Gohman     }
1028d934cb88SDan Gohman 
1029d934cb88SDan Gohman     // Apply the type index fixups for call_indirect etc. instructions.
1030d934cb88SDan Gohman     for (size_t i = 0, e = TypeIndexFixups.size(); i < e; ++i) {
1031d934cb88SDan Gohman       uint32_t Type = TypeIndexFixupTypes[i];
1032d934cb88SDan Gohman       unsigned Padding = PaddingFor5ByteULEB128(Type);
1033d934cb88SDan Gohman 
1034970d02c4SDan Gohman       const WasmRelocationEntry &Fixup = TypeIndexFixups[i];
1035970d02c4SDan Gohman       assert(Fixup.Addend == 0);
1036970d02c4SDan Gohman       assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB);
1037d934cb88SDan Gohman       uint64_t Offset = Fixup.Offset +
1038d934cb88SDan Gohman                         Fixup.FixupSection->getSectionOffset();
1039d934cb88SDan Gohman 
1040d934cb88SDan Gohman       uint8_t Buffer[16];
1041d934cb88SDan Gohman       unsigned SizeLen = encodeULEB128(Type, Buffer, Padding);
1042d934cb88SDan Gohman       assert(SizeLen == 5);
1043d934cb88SDan Gohman       getStream().pwrite((char *)Buffer, SizeLen,
1044d934cb88SDan Gohman                          Section.ContentsOffset + Offset);
1045d934cb88SDan Gohman     }
1046d934cb88SDan Gohman 
1047d934cb88SDan Gohman     // Apply fixups.
1048d934cb88SDan Gohman     ApplyRelocations(CodeRelocations, getStream(), SymbolIndices,
1049d934cb88SDan Gohman                      Section.ContentsOffset);
1050d934cb88SDan Gohman 
1051d934cb88SDan Gohman     endSection(Section);
1052d934cb88SDan Gohman   }
1053d934cb88SDan Gohman 
1054d934cb88SDan Gohman   // === Data Section ==========================================================
1055d934cb88SDan Gohman   if (!DataBytes.empty()) {
1056d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_DATA);
1057d934cb88SDan Gohman 
1058d934cb88SDan Gohman     encodeULEB128(1, getStream()); // count
1059d934cb88SDan Gohman     encodeULEB128(0, getStream()); // memory index
1060d934cb88SDan Gohman     write8(wasm::WASM_OPCODE_I32_CONST);
1061d934cb88SDan Gohman     encodeSLEB128(0, getStream()); // offset
1062d934cb88SDan Gohman     write8(wasm::WASM_OPCODE_END);
1063d934cb88SDan Gohman     encodeULEB128(DataBytes.size(), getStream()); // size
1064d934cb88SDan Gohman     writeBytes(DataBytes); // data
1065d934cb88SDan Gohman 
1066d934cb88SDan Gohman     // Apply fixups.
1067d934cb88SDan Gohman     ApplyRelocations(DataRelocations, getStream(), SymbolIndices,
1068d934cb88SDan Gohman                      Section.ContentsOffset);
1069d934cb88SDan Gohman 
1070d934cb88SDan Gohman     endSection(Section);
1071d934cb88SDan Gohman   }
1072d934cb88SDan Gohman 
1073d934cb88SDan Gohman   // === Name Section ==========================================================
107413f080fbSDerek Schuff   uint32_t TotalFunctions = NumFuncImports + Functions.size();
107513f080fbSDerek Schuff   if (TotalFunctions != 0) {
1076d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_CUSTOM, "name");
107713f080fbSDerek Schuff     SectionBookkeeping SubSection;
107813f080fbSDerek Schuff     startSection(SubSection, wasm::WASM_NAMES_FUNCTION);
1079d934cb88SDan Gohman 
108013f080fbSDerek Schuff     encodeULEB128(TotalFunctions, getStream());
108113f080fbSDerek Schuff     uint32_t Index = 0;
1082d934cb88SDan Gohman     for (const WasmImport &Import : Imports) {
1083d934cb88SDan Gohman       if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
108413f080fbSDerek Schuff         encodeULEB128(Index, getStream());
1085d934cb88SDan Gohman         encodeULEB128(Import.FieldName.size(), getStream());
1086d934cb88SDan Gohman         writeBytes(Import.FieldName);
108713f080fbSDerek Schuff         ++Index;
1088d934cb88SDan Gohman       }
1089d934cb88SDan Gohman     }
1090d934cb88SDan Gohman     for (const WasmFunction &Func : Functions) {
109113f080fbSDerek Schuff       encodeULEB128(Index, getStream());
1092d934cb88SDan Gohman       encodeULEB128(Func.Sym->getName().size(), getStream());
1093d934cb88SDan Gohman       writeBytes(Func.Sym->getName());
109413f080fbSDerek Schuff       ++Index;
1095d934cb88SDan Gohman     }
1096d934cb88SDan Gohman 
109713f080fbSDerek Schuff     endSection(SubSection);
1098d934cb88SDan Gohman     endSection(Section);
1099d934cb88SDan Gohman   }
1100d934cb88SDan Gohman 
1101d934cb88SDan Gohman   // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
1102d934cb88SDan Gohman   // for descriptions of the reloc sections.
1103d934cb88SDan Gohman 
1104d934cb88SDan Gohman   // === Code Reloc Section ====================================================
1105d934cb88SDan Gohman   if (!CodeRelocations.empty()) {
1106d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.CODE");
1107d934cb88SDan Gohman 
1108e2688c43SDerek Schuff     encodeULEB128(wasm::WASM_SEC_CODE, getStream());
1109d934cb88SDan Gohman 
111003b19237SSam Clegg     encodeULEB128(CodeRelocations.size() + TypeIndexFixups.size(), getStream());
1111d934cb88SDan Gohman 
1112d934cb88SDan Gohman     WriteRelocations(CodeRelocations, getStream(), SymbolIndices);
1113970d02c4SDan Gohman     WriteTypeRelocations(TypeIndexFixups, TypeIndexFixupTypes, getStream());
1114d934cb88SDan Gohman 
1115d934cb88SDan Gohman     endSection(Section);
1116d934cb88SDan Gohman   }
1117d934cb88SDan Gohman 
1118d934cb88SDan Gohman   // === Data Reloc Section ====================================================
1119d934cb88SDan Gohman   if (!DataRelocations.empty()) {
1120d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.DATA");
1121d934cb88SDan Gohman 
1122e2688c43SDerek Schuff     encodeULEB128(wasm::WASM_SEC_DATA, getStream());
1123d934cb88SDan Gohman 
1124d934cb88SDan Gohman     encodeULEB128(DataRelocations.size(), getStream());
1125d934cb88SDan Gohman 
1126d934cb88SDan Gohman     WriteRelocations(DataRelocations, getStream(), SymbolIndices);
1127d934cb88SDan Gohman 
1128d934cb88SDan Gohman     endSection(Section);
1129d934cb88SDan Gohman   }
1130d934cb88SDan Gohman 
1131970d02c4SDan Gohman   // === Linking Metadata Section ==============================================
1132970d02c4SDan Gohman   if (HasStackPointer) {
1133970d02c4SDan Gohman     startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
1134970d02c4SDan Gohman 
1135970d02c4SDan Gohman     encodeULEB128(1, getStream()); // count
1136970d02c4SDan Gohman 
1137970d02c4SDan Gohman     encodeULEB128(wasm::WASM_STACK_POINTER, getStream()); // type
1138970d02c4SDan Gohman     encodeULEB128(StackPointerGlobal, getStream()); // id
1139970d02c4SDan Gohman 
1140970d02c4SDan Gohman     endSection(Section);
1141970d02c4SDan Gohman   }
1142970d02c4SDan Gohman 
1143d934cb88SDan Gohman   // TODO: Translate the .comment section to the output.
1144d934cb88SDan Gohman 
1145d934cb88SDan Gohman   // TODO: Translate debug sections to the output.
114618eafb6cSDan Gohman }
114718eafb6cSDan Gohman 
114818eafb6cSDan Gohman MCObjectWriter *llvm::createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW,
114918eafb6cSDan Gohman                                              raw_pwrite_stream &OS) {
115018eafb6cSDan Gohman   return new WasmObjectWriter(MOTW, OS);
115118eafb6cSDan Gohman }
1152