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: {
4251c154a61SSam Clegg       assert(SymbolIndices.count(RelEntry.Symbol));
426d934cb88SDan Gohman       uint32_t Index = SymbolIndices[RelEntry.Symbol];
427d934cb88SDan Gohman       assert(RelEntry.Addend == 0);
428d934cb88SDan Gohman 
429d934cb88SDan Gohman       WritePatchableLEB(Stream, Index, Offset);
430d934cb88SDan Gohman       break;
431d934cb88SDan Gohman     }
432d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: {
4331c154a61SSam Clegg       assert(SymbolIndices.count(RelEntry.Symbol));
434d934cb88SDan Gohman       uint32_t Index = SymbolIndices[RelEntry.Symbol];
435d934cb88SDan Gohman       assert(RelEntry.Addend == 0);
436d934cb88SDan Gohman 
437d934cb88SDan Gohman       WritePatchableSLEB(Stream, Index, Offset);
438d934cb88SDan Gohman       break;
439d934cb88SDan Gohman     }
440d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: {
441d934cb88SDan Gohman       uint32_t Value = ProvisionalValue(RelEntry);
442d934cb88SDan Gohman 
443d934cb88SDan Gohman       WritePatchableSLEB(Stream, Value, Offset);
444d934cb88SDan Gohman       break;
445d934cb88SDan Gohman     }
446d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: {
447d934cb88SDan Gohman       uint32_t Value = ProvisionalValue(RelEntry);
448d934cb88SDan Gohman 
449d934cb88SDan Gohman       WritePatchableLEB(Stream, Value, Offset);
450d934cb88SDan Gohman       break;
451d934cb88SDan Gohman     }
452d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: {
4531c154a61SSam Clegg       assert(SymbolIndices.count(RelEntry.Symbol));
454d934cb88SDan Gohman       uint32_t Index = SymbolIndices[RelEntry.Symbol];
455d934cb88SDan Gohman       assert(RelEntry.Addend == 0);
456d934cb88SDan Gohman 
457d934cb88SDan Gohman       WriteI32(Stream, Index, Offset);
458d934cb88SDan Gohman       break;
459d934cb88SDan Gohman     }
460d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: {
461d934cb88SDan Gohman       uint32_t Value = ProvisionalValue(RelEntry);
462d934cb88SDan Gohman 
463d934cb88SDan Gohman       WriteI32(Stream, Value, Offset);
464d934cb88SDan Gohman       break;
465d934cb88SDan Gohman     }
466d934cb88SDan Gohman     default:
467d934cb88SDan Gohman       break;
468d934cb88SDan Gohman     }
469d934cb88SDan Gohman   }
470d934cb88SDan Gohman }
471d934cb88SDan Gohman 
472d934cb88SDan Gohman // Write out the portions of the relocation records that the linker will
473d934cb88SDan Gohman // need to handle.
474a06de028SSam Clegg static void
475a06de028SSam Clegg WriteRelocations(ArrayRef<WasmRelocationEntry> Relocations,
476d934cb88SDan Gohman                  raw_pwrite_stream &Stream,
477a06de028SSam Clegg                  DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices,
478a06de028SSam Clegg                  uint64_t HeaderSize) {
479d934cb88SDan Gohman   for (const WasmRelocationEntry RelEntry : Relocations) {
480d934cb88SDan Gohman     encodeULEB128(RelEntry.Type, Stream);
481d934cb88SDan Gohman 
482d934cb88SDan Gohman     uint64_t Offset = RelEntry.Offset +
483a06de028SSam Clegg                       RelEntry.FixupSection->getSectionOffset() + HeaderSize;
4841c154a61SSam Clegg     assert(SymbolIndices.count(RelEntry.Symbol));
485d934cb88SDan Gohman     uint32_t Index = SymbolIndices[RelEntry.Symbol];
486d934cb88SDan Gohman     int64_t Addend = RelEntry.Addend;
487d934cb88SDan Gohman 
488d934cb88SDan Gohman     switch (RelEntry.Type) {
489d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
490d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
491d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
492d934cb88SDan Gohman       encodeULEB128(Offset, Stream);
493d934cb88SDan Gohman       encodeULEB128(Index, Stream);
494d934cb88SDan Gohman       assert(Addend == 0 && "addends not supported for functions");
495d934cb88SDan Gohman       break;
496d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
497d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
498d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
499d934cb88SDan Gohman       encodeULEB128(Offset, Stream);
500d934cb88SDan Gohman       encodeULEB128(Index, Stream);
501d934cb88SDan Gohman       encodeSLEB128(Addend, Stream);
502d934cb88SDan Gohman       break;
503d934cb88SDan Gohman     default:
504d934cb88SDan Gohman       llvm_unreachable("unsupported relocation type");
505d934cb88SDan Gohman     }
506d934cb88SDan Gohman   }
50718eafb6cSDan Gohman }
50818eafb6cSDan Gohman 
509970d02c4SDan Gohman // Write out the the type relocation records that the linker will
510970d02c4SDan Gohman // need to handle.
511970d02c4SDan Gohman static void WriteTypeRelocations(
512970d02c4SDan Gohman     ArrayRef<WasmRelocationEntry> TypeIndexFixups,
513970d02c4SDan Gohman     ArrayRef<uint32_t> TypeIndexFixupTypes,
514970d02c4SDan Gohman     raw_pwrite_stream &Stream)
515970d02c4SDan Gohman {
516970d02c4SDan Gohman   for (size_t i = 0, e = TypeIndexFixups.size(); i < e; ++i) {
517970d02c4SDan Gohman     const WasmRelocationEntry &Fixup = TypeIndexFixups[i];
518970d02c4SDan Gohman     uint32_t Type = TypeIndexFixupTypes[i];
519970d02c4SDan Gohman 
520970d02c4SDan Gohman     assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB);
521970d02c4SDan Gohman     assert(Fixup.Addend == 0);
522970d02c4SDan Gohman 
523970d02c4SDan Gohman     uint64_t Offset = Fixup.Offset +
524970d02c4SDan Gohman                       Fixup.FixupSection->getSectionOffset();
525970d02c4SDan Gohman 
526970d02c4SDan Gohman     encodeULEB128(Fixup.Type, Stream);
527970d02c4SDan Gohman     encodeULEB128(Offset, Stream);
528970d02c4SDan Gohman     encodeULEB128(Type, Stream);
529970d02c4SDan Gohman   }
530970d02c4SDan Gohman }
531970d02c4SDan Gohman 
53218eafb6cSDan Gohman void WasmObjectWriter::writeObject(MCAssembler &Asm,
53318eafb6cSDan Gohman                                    const MCAsmLayout &Layout) {
53482607f56SDan Gohman   MCContext &Ctx = Asm.getContext();
535b879539aSDerek Schuff   wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32;
536d934cb88SDan Gohman 
537d934cb88SDan Gohman   // Collect information from the available symbols.
538b879539aSDerek Schuff   DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo>
539d934cb88SDan Gohman       FunctionTypeIndices;
540d934cb88SDan Gohman   SmallVector<WasmFunctionType, 4> FunctionTypes;
541d934cb88SDan Gohman   SmallVector<WasmFunction, 4> Functions;
542d934cb88SDan Gohman   SmallVector<uint32_t, 4> TableElems;
543d934cb88SDan Gohman   SmallVector<WasmGlobal, 4> Globals;
544d934cb88SDan Gohman   SmallVector<WasmImport, 4> Imports;
545d934cb88SDan Gohman   SmallVector<WasmExport, 4> Exports;
546d934cb88SDan Gohman   DenseMap<const MCSymbolWasm *, uint32_t> SymbolIndices;
547d934cb88SDan Gohman   SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken;
548d934cb88SDan Gohman   unsigned NumFuncImports = 0;
549d934cb88SDan Gohman   unsigned NumGlobalImports = 0;
550d934cb88SDan Gohman   SmallVector<char, 0> DataBytes;
551970d02c4SDan Gohman   uint32_t StackPointerGlobal = 0;
552970d02c4SDan Gohman   bool HasStackPointer = false;
553d934cb88SDan Gohman 
554d934cb88SDan Gohman   // Populate the IsAddressTaken set.
555d934cb88SDan Gohman   for (WasmRelocationEntry RelEntry : CodeRelocations) {
556d934cb88SDan Gohman     switch (RelEntry.Type) {
557d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
558d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
559d934cb88SDan Gohman       IsAddressTaken.insert(RelEntry.Symbol);
560d934cb88SDan Gohman       break;
561d934cb88SDan Gohman     default:
562d934cb88SDan Gohman       break;
563d934cb88SDan Gohman     }
564d934cb88SDan Gohman   }
565d934cb88SDan Gohman   for (WasmRelocationEntry RelEntry : DataRelocations) {
566d934cb88SDan Gohman     switch (RelEntry.Type) {
567d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
568d934cb88SDan Gohman     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
569d934cb88SDan Gohman       IsAddressTaken.insert(RelEntry.Symbol);
570d934cb88SDan Gohman       break;
571d934cb88SDan Gohman     default:
572d934cb88SDan Gohman       break;
573d934cb88SDan Gohman     }
574d934cb88SDan Gohman   }
575d934cb88SDan Gohman 
576d934cb88SDan Gohman   // Populate the Imports set.
577d934cb88SDan Gohman   for (const MCSymbol &S : Asm.symbols()) {
578d934cb88SDan Gohman     const auto &WS = static_cast<const MCSymbolWasm &>(S);
579b879539aSDerek Schuff     int32_t Type;
580d934cb88SDan Gohman 
581d934cb88SDan Gohman     if (WS.isFunction()) {
582d934cb88SDan Gohman       // Prepare the function's type, if we haven't seen it yet.
583d934cb88SDan Gohman       WasmFunctionType F;
584d934cb88SDan Gohman       F.Returns = WS.getReturns();
585d934cb88SDan Gohman       F.Params = WS.getParams();
586d934cb88SDan Gohman       auto Pair =
587d934cb88SDan Gohman           FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
588d934cb88SDan Gohman       if (Pair.second)
589d934cb88SDan Gohman         FunctionTypes.push_back(F);
590d934cb88SDan Gohman 
591d934cb88SDan Gohman       Type = Pair.first->second;
592d934cb88SDan Gohman     } else {
593b879539aSDerek Schuff       Type = int32_t(PtrType);
594d934cb88SDan Gohman     }
595d934cb88SDan Gohman 
596d934cb88SDan Gohman     // If the symbol is not defined in this translation unit, import it.
597d934cb88SDan Gohman     if (!WS.isTemporary() && !WS.isDefined(/*SetUsed=*/false)) {
598d934cb88SDan Gohman       WasmImport Import;
599d934cb88SDan Gohman       Import.ModuleName = WS.getModuleName();
600d934cb88SDan Gohman       Import.FieldName = WS.getName();
601d934cb88SDan Gohman 
602d934cb88SDan Gohman       if (WS.isFunction()) {
603d934cb88SDan Gohman         Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
604d934cb88SDan Gohman         Import.Type = Type;
605d934cb88SDan Gohman         SymbolIndices[&WS] = NumFuncImports;
606d934cb88SDan Gohman         ++NumFuncImports;
607d934cb88SDan Gohman       } else {
608d934cb88SDan Gohman         Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
609d934cb88SDan Gohman         Import.Type = Type;
610d934cb88SDan Gohman         SymbolIndices[&WS] = NumGlobalImports;
611d934cb88SDan Gohman         ++NumGlobalImports;
612d934cb88SDan Gohman       }
613d934cb88SDan Gohman 
614d934cb88SDan Gohman       Imports.push_back(Import);
615d934cb88SDan Gohman     }
616d934cb88SDan Gohman   }
617d934cb88SDan Gohman 
61882607f56SDan Gohman   // In the special .global_variables section, we've encoded global
61982607f56SDan Gohman   // variables used by the function. Translate them into the Globals
62082607f56SDan Gohman   // list.
62182607f56SDan Gohman   MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0);
62282607f56SDan Gohman   if (!GlobalVars->getFragmentList().empty()) {
62382607f56SDan Gohman     if (GlobalVars->getFragmentList().size() != 1)
62482607f56SDan Gohman       report_fatal_error("only one .global_variables fragment supported");
62582607f56SDan Gohman     const MCFragment &Frag = *GlobalVars->begin();
62682607f56SDan Gohman     if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
62782607f56SDan Gohman       report_fatal_error("only data supported in .global_variables");
62882607f56SDan Gohman     const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag);
62982607f56SDan Gohman     if (!DataFrag.getFixups().empty())
63082607f56SDan Gohman       report_fatal_error("fixups not supported in .global_variables");
63182607f56SDan Gohman     const SmallVectorImpl<char> &Contents = DataFrag.getContents();
632970d02c4SDan Gohman     for (const uint8_t *p = (const uint8_t *)Contents.data(),
633970d02c4SDan Gohman                      *end = (const uint8_t *)Contents.data() + Contents.size();
634970d02c4SDan Gohman          p != end; ) {
63582607f56SDan Gohman       WasmGlobal G;
636970d02c4SDan Gohman       if (end - p < 3)
637970d02c4SDan Gohman         report_fatal_error("truncated global variable encoding");
638970d02c4SDan Gohman       G.Type = wasm::ValType(int8_t(*p++));
639970d02c4SDan Gohman       G.IsMutable = bool(*p++);
640970d02c4SDan Gohman       G.HasImport = bool(*p++);
641970d02c4SDan Gohman       if (G.HasImport) {
64282607f56SDan Gohman         G.InitialValue = 0;
643970d02c4SDan Gohman 
644970d02c4SDan Gohman         WasmImport Import;
645970d02c4SDan Gohman         Import.ModuleName = (const char *)p;
646970d02c4SDan Gohman         const uint8_t *nul = (const uint8_t *)memchr(p, '\0', end - p);
647970d02c4SDan Gohman         if (!nul)
648970d02c4SDan Gohman           report_fatal_error("global module name must be nul-terminated");
649970d02c4SDan Gohman         p = nul + 1;
650970d02c4SDan Gohman         nul = (const uint8_t *)memchr(p, '\0', end - p);
651970d02c4SDan Gohman         if (!nul)
652970d02c4SDan Gohman           report_fatal_error("global base name must be nul-terminated");
653970d02c4SDan Gohman         Import.FieldName = (const char *)p;
654970d02c4SDan Gohman         p = nul + 1;
655970d02c4SDan Gohman 
656970d02c4SDan Gohman         Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
657970d02c4SDan Gohman         Import.Type = int32_t(G.Type);
658970d02c4SDan Gohman 
659970d02c4SDan Gohman         G.ImportIndex = NumGlobalImports;
660970d02c4SDan Gohman         ++NumGlobalImports;
661970d02c4SDan Gohman 
662970d02c4SDan Gohman         Imports.push_back(Import);
663970d02c4SDan Gohman       } else {
664970d02c4SDan Gohman         unsigned n;
665970d02c4SDan Gohman         G.InitialValue = decodeSLEB128(p, &n);
666970d02c4SDan Gohman         G.ImportIndex = 0;
667c8da0c0bSSimon Pilgrim         if ((ptrdiff_t)n > end - p)
668970d02c4SDan Gohman           report_fatal_error("global initial value must be valid SLEB128");
669970d02c4SDan Gohman         p += n;
670970d02c4SDan Gohman       }
67182607f56SDan Gohman       Globals.push_back(G);
67282607f56SDan Gohman     }
67382607f56SDan Gohman   }
67482607f56SDan Gohman 
675970d02c4SDan Gohman   // In the special .stack_pointer section, we've encoded the stack pointer
676970d02c4SDan Gohman   // index.
677970d02c4SDan Gohman   MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", 0, 0);
678970d02c4SDan Gohman   if (!StackPtr->getFragmentList().empty()) {
679970d02c4SDan Gohman     if (StackPtr->getFragmentList().size() != 1)
680970d02c4SDan Gohman       report_fatal_error("only one .stack_pointer fragment supported");
681970d02c4SDan Gohman     const MCFragment &Frag = *StackPtr->begin();
682970d02c4SDan Gohman     if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
683970d02c4SDan Gohman       report_fatal_error("only data supported in .stack_pointer");
684970d02c4SDan Gohman     const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag);
685970d02c4SDan Gohman     if (!DataFrag.getFixups().empty())
686970d02c4SDan Gohman       report_fatal_error("fixups not supported in .stack_pointer");
687970d02c4SDan Gohman     const SmallVectorImpl<char> &Contents = DataFrag.getContents();
688970d02c4SDan Gohman     if (Contents.size() != 4)
689970d02c4SDan Gohman       report_fatal_error("only one entry supported in .stack_pointer");
690970d02c4SDan Gohman     HasStackPointer = true;
691970d02c4SDan Gohman     StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
692970d02c4SDan Gohman   }
693970d02c4SDan Gohman 
694d934cb88SDan Gohman   // Handle defined symbols.
695d934cb88SDan Gohman   for (const MCSymbol &S : Asm.symbols()) {
696d934cb88SDan Gohman     // Ignore unnamed temporary symbols, which aren't ever exported, imported,
697d934cb88SDan Gohman     // or used in relocations.
698d934cb88SDan Gohman     if (S.isTemporary() && S.getName().empty())
699d934cb88SDan Gohman       continue;
700d934cb88SDan Gohman     const auto &WS = static_cast<const MCSymbolWasm &>(S);
701d934cb88SDan Gohman     unsigned Index;
702d934cb88SDan Gohman     if (WS.isFunction()) {
703d934cb88SDan Gohman       // Prepare the function's type, if we haven't seen it yet.
704d934cb88SDan Gohman       WasmFunctionType F;
705d934cb88SDan Gohman       F.Returns = WS.getReturns();
706d934cb88SDan Gohman       F.Params = WS.getParams();
707d934cb88SDan Gohman       auto Pair =
708d934cb88SDan Gohman           FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
709d934cb88SDan Gohman       if (Pair.second)
710d934cb88SDan Gohman         FunctionTypes.push_back(F);
711d934cb88SDan Gohman 
712b879539aSDerek Schuff       int32_t Type = Pair.first->second;
713d934cb88SDan Gohman 
714d934cb88SDan Gohman       if (WS.isDefined(/*SetUsed=*/false)) {
715d934cb88SDan Gohman         // A definition. Take the next available index.
716d934cb88SDan Gohman         Index = NumFuncImports + Functions.size();
717d934cb88SDan Gohman 
718d934cb88SDan Gohman         // Prepare the function.
719d934cb88SDan Gohman         WasmFunction Func;
720d934cb88SDan Gohman         Func.Type = Type;
721d934cb88SDan Gohman         Func.Sym = &WS;
722d934cb88SDan Gohman         SymbolIndices[&WS] = Index;
723d934cb88SDan Gohman         Functions.push_back(Func);
724d934cb88SDan Gohman       } else {
725d934cb88SDan Gohman         // An import; the index was assigned above.
726d934cb88SDan Gohman         Index = SymbolIndices.find(&WS)->second;
727d934cb88SDan Gohman       }
728d934cb88SDan Gohman 
729d934cb88SDan Gohman       // If needed, prepare the function to be called indirectly.
730d934cb88SDan Gohman       if (IsAddressTaken.count(&WS))
731d934cb88SDan Gohman         TableElems.push_back(Index);
732d934cb88SDan Gohman     } else {
733*c38e947eSSam Clegg       if (WS.isTemporary() && !WS.getSize())
734*c38e947eSSam Clegg         continue;
735*c38e947eSSam Clegg 
736*c38e947eSSam Clegg       if (WS.isDefined(false)) {
737d934cb88SDan Gohman         if (WS.getOffset() != 0)
738*c38e947eSSam Clegg           report_fatal_error("data sections must contain one variable each: " +
739*c38e947eSSam Clegg                              WS.getName());
740d934cb88SDan Gohman         if (!WS.getSize())
741*c38e947eSSam Clegg           report_fatal_error("data symbols must have a size set with .size: " +
742*c38e947eSSam Clegg                              WS.getName());
743d934cb88SDan Gohman 
744d934cb88SDan Gohman         int64_t Size = 0;
745d934cb88SDan Gohman         if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
746d934cb88SDan Gohman           report_fatal_error(".size expression must be evaluatable");
747d934cb88SDan Gohman 
748d934cb88SDan Gohman         MCSectionWasm &DataSection =
749d934cb88SDan Gohman             static_cast<MCSectionWasm &>(WS.getSection());
750d934cb88SDan Gohman 
751d934cb88SDan Gohman         if (uint64_t(Size) != Layout.getSectionFileSize(&DataSection))
752d934cb88SDan Gohman           report_fatal_error("data sections must contain at most one variable");
753d934cb88SDan Gohman 
754d934cb88SDan Gohman         DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
755d934cb88SDan Gohman 
756d934cb88SDan Gohman         DataSection.setSectionOffset(DataBytes.size());
757d934cb88SDan Gohman 
758d934cb88SDan Gohman         for (MCSection::iterator I = DataSection.begin(), E = DataSection.end();
759d934cb88SDan Gohman              I != E; ++I) {
760d934cb88SDan Gohman           const MCFragment &Frag = *I;
761d934cb88SDan Gohman           if (Frag.hasInstructions())
762d934cb88SDan Gohman             report_fatal_error("only data supported in data sections");
763d934cb88SDan Gohman 
764d934cb88SDan Gohman           if (const MCAlignFragment *Align = dyn_cast<MCAlignFragment>(&Frag)) {
765d934cb88SDan Gohman             if (Align->getValueSize() != 1)
766d934cb88SDan Gohman               report_fatal_error("only byte values supported for alignment");
767d934cb88SDan Gohman             // If nops are requested, use zeros, as this is the data section.
768d934cb88SDan Gohman             uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
769d934cb88SDan Gohman             uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(),
770d934cb88SDan Gohman                                                        Align->getAlignment()),
771d934cb88SDan Gohman                                                DataBytes.size() +
772d934cb88SDan Gohman                                                    Align->getMaxBytesToEmit());
773d934cb88SDan Gohman             DataBytes.resize(Size, Value);
774d934cb88SDan Gohman           } else if (const MCFillFragment *Fill =
775d934cb88SDan Gohman                                               dyn_cast<MCFillFragment>(&Frag)) {
776d934cb88SDan Gohman             DataBytes.insert(DataBytes.end(), Size, Fill->getValue());
777d934cb88SDan Gohman           } else {
778d934cb88SDan Gohman             const MCDataFragment &DataFrag = cast<MCDataFragment>(Frag);
779d934cb88SDan Gohman             const SmallVectorImpl<char> &Contents = DataFrag.getContents();
780d934cb88SDan Gohman 
781d934cb88SDan Gohman             DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
782d934cb88SDan Gohman           }
783d934cb88SDan Gohman         }
784d934cb88SDan Gohman 
7851c154a61SSam Clegg         // For each global, prepare a corresponding wasm global holding its
7861c154a61SSam Clegg         // address.  For externals these will also be named exports.
787d934cb88SDan Gohman         Index = NumGlobalImports + Globals.size();
788d934cb88SDan Gohman 
789d934cb88SDan Gohman         WasmGlobal Global;
790d934cb88SDan Gohman         Global.Type = PtrType;
791d934cb88SDan Gohman         Global.IsMutable = false;
792970d02c4SDan Gohman         Global.HasImport = false;
793d934cb88SDan Gohman         Global.InitialValue = DataSection.getSectionOffset();
794970d02c4SDan Gohman         Global.ImportIndex = 0;
795d934cb88SDan Gohman         SymbolIndices[&WS] = Index;
796d934cb88SDan Gohman         Globals.push_back(Global);
797d934cb88SDan Gohman       }
798d934cb88SDan Gohman     }
799d934cb88SDan Gohman 
800d934cb88SDan Gohman     // If the symbol is visible outside this translation unit, export it.
801d934cb88SDan Gohman     if (WS.isExternal()) {
802d934cb88SDan Gohman       assert(WS.isDefined(false));
803d934cb88SDan Gohman       WasmExport Export;
804d934cb88SDan Gohman       Export.FieldName = WS.getName();
805d934cb88SDan Gohman       Export.Index = Index;
806d934cb88SDan Gohman 
807d934cb88SDan Gohman       if (WS.isFunction())
808d934cb88SDan Gohman         Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
809d934cb88SDan Gohman       else
810d934cb88SDan Gohman         Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
811d934cb88SDan Gohman 
812d934cb88SDan Gohman       Exports.push_back(Export);
813d934cb88SDan Gohman     }
814d934cb88SDan Gohman   }
815d934cb88SDan Gohman 
816d934cb88SDan Gohman   // Add types for indirect function calls.
817970d02c4SDan Gohman   for (const WasmRelocationEntry &Fixup : TypeIndexFixups) {
818970d02c4SDan Gohman     assert(Fixup.Addend == 0);
819970d02c4SDan Gohman     assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB);
820970d02c4SDan Gohman 
821d934cb88SDan Gohman     WasmFunctionType F;
822d934cb88SDan Gohman     F.Returns = Fixup.Symbol->getReturns();
823d934cb88SDan Gohman     F.Params = Fixup.Symbol->getParams();
824d934cb88SDan Gohman     auto Pair =
825d934cb88SDan Gohman         FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
826d934cb88SDan Gohman     if (Pair.second)
827d934cb88SDan Gohman       FunctionTypes.push_back(F);
828d934cb88SDan Gohman 
829d934cb88SDan Gohman     TypeIndexFixupTypes.push_back(Pair.first->second);
830d934cb88SDan Gohman   }
831d934cb88SDan Gohman 
83218eafb6cSDan Gohman   // Write out the Wasm header.
83318eafb6cSDan Gohman   writeHeader(Asm);
83418eafb6cSDan Gohman 
835d934cb88SDan Gohman   SectionBookkeeping Section;
836d934cb88SDan Gohman 
837d934cb88SDan Gohman   // === Type Section =========================================================
838d934cb88SDan Gohman   if (!FunctionTypes.empty()) {
839d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_TYPE);
840d934cb88SDan Gohman 
841d934cb88SDan Gohman     encodeULEB128(FunctionTypes.size(), getStream());
842d934cb88SDan Gohman 
843d934cb88SDan Gohman     for (WasmFunctionType &FuncTy : FunctionTypes) {
844e2688c43SDerek Schuff       encodeSLEB128(wasm::WASM_TYPE_FUNC, getStream());
845d934cb88SDan Gohman       encodeULEB128(FuncTy.Params.size(), getStream());
846e2688c43SDerek Schuff       for (wasm::ValType Ty : FuncTy.Params)
847e2688c43SDerek Schuff         writeValueType(Ty);
848d934cb88SDan Gohman       encodeULEB128(FuncTy.Returns.size(), getStream());
849e2688c43SDerek Schuff       for (wasm::ValType Ty : FuncTy.Returns)
850e2688c43SDerek Schuff         writeValueType(Ty);
851d934cb88SDan Gohman     }
852d934cb88SDan Gohman 
853d934cb88SDan Gohman     endSection(Section);
854d934cb88SDan Gohman   }
855d934cb88SDan Gohman 
856d934cb88SDan Gohman   // === Import Section ========================================================
857d934cb88SDan Gohman   if (!Imports.empty()) {
858d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_IMPORT);
859d934cb88SDan Gohman 
860d934cb88SDan Gohman     encodeULEB128(Imports.size(), getStream());
861d934cb88SDan Gohman     for (const WasmImport &Import : Imports) {
862d934cb88SDan Gohman       StringRef ModuleName = Import.ModuleName;
863d934cb88SDan Gohman       encodeULEB128(ModuleName.size(), getStream());
864d934cb88SDan Gohman       writeBytes(ModuleName);
865d934cb88SDan Gohman 
866d934cb88SDan Gohman       StringRef FieldName = Import.FieldName;
867d934cb88SDan Gohman       encodeULEB128(FieldName.size(), getStream());
868d934cb88SDan Gohman       writeBytes(FieldName);
869d934cb88SDan Gohman 
870e2688c43SDerek Schuff       encodeULEB128(Import.Kind, getStream());
871d934cb88SDan Gohman 
872d934cb88SDan Gohman       switch (Import.Kind) {
873d934cb88SDan Gohman       case wasm::WASM_EXTERNAL_FUNCTION:
874d934cb88SDan Gohman         encodeULEB128(Import.Type, getStream());
875d934cb88SDan Gohman         break;
876d934cb88SDan Gohman       case wasm::WASM_EXTERNAL_GLOBAL:
877970d02c4SDan Gohman         encodeSLEB128(int32_t(Import.Type), getStream());
878e2688c43SDerek Schuff         encodeULEB128(0, getStream()); // mutability
879d934cb88SDan Gohman         break;
880d934cb88SDan Gohman       default:
881d934cb88SDan Gohman         llvm_unreachable("unsupported import kind");
882d934cb88SDan Gohman       }
883d934cb88SDan Gohman     }
884d934cb88SDan Gohman 
885d934cb88SDan Gohman     endSection(Section);
886d934cb88SDan Gohman   }
887d934cb88SDan Gohman 
888d934cb88SDan Gohman   // === Function Section ======================================================
889d934cb88SDan Gohman   if (!Functions.empty()) {
890d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_FUNCTION);
891d934cb88SDan Gohman 
892d934cb88SDan Gohman     encodeULEB128(Functions.size(), getStream());
893d934cb88SDan Gohman     for (const WasmFunction &Func : Functions)
894d934cb88SDan Gohman       encodeULEB128(Func.Type, getStream());
895d934cb88SDan Gohman 
896d934cb88SDan Gohman     endSection(Section);
897d934cb88SDan Gohman   }
898d934cb88SDan Gohman 
899d934cb88SDan Gohman   // === Table Section =========================================================
900d934cb88SDan Gohman   // For now, always emit the table section, since indirect calls are not
901d934cb88SDan Gohman   // valid without it. In the future, we could perhaps be more clever and omit
902d934cb88SDan Gohman   // it if there are no indirect calls.
903d934cb88SDan Gohman   startSection(Section, wasm::WASM_SEC_TABLE);
904d934cb88SDan Gohman 
905d934cb88SDan Gohman   // The number of tables, fixed to 1 for now.
906d934cb88SDan Gohman   encodeULEB128(1, getStream());
907d934cb88SDan Gohman 
908e2688c43SDerek Schuff   encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream());
909d934cb88SDan Gohman 
910d934cb88SDan Gohman   encodeULEB128(0, getStream());                 // flags
911d934cb88SDan Gohman   encodeULEB128(TableElems.size(), getStream()); // initial
912d934cb88SDan Gohman 
913d934cb88SDan Gohman   endSection(Section);
914d934cb88SDan Gohman 
915d934cb88SDan Gohman   // === Memory Section ========================================================
916d934cb88SDan Gohman   // For now, always emit the memory section, since loads and stores are not
917d934cb88SDan Gohman   // valid without it. In the future, we could perhaps be more clever and omit
918d934cb88SDan Gohman   // it if there are no loads or stores.
919ff0730b3SSam Clegg   uint32_t NumPages =
920ff0730b3SSam Clegg       (DataBytes.size() + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
921d934cb88SDan Gohman 
922ff0730b3SSam Clegg   startSection(Section, wasm::WASM_SEC_MEMORY);
923d934cb88SDan Gohman   encodeULEB128(1, getStream()); // number of memory spaces
924d934cb88SDan Gohman 
925d934cb88SDan Gohman   encodeULEB128(0, getStream()); // flags
926ff0730b3SSam Clegg   encodeULEB128(NumPages, getStream()); // initial
927d934cb88SDan Gohman 
928d934cb88SDan Gohman   endSection(Section);
929d934cb88SDan Gohman 
930d934cb88SDan Gohman   // === Global Section ========================================================
931d934cb88SDan Gohman   if (!Globals.empty()) {
932d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_GLOBAL);
933d934cb88SDan Gohman 
934d934cb88SDan Gohman     encodeULEB128(Globals.size(), getStream());
935d934cb88SDan Gohman     for (const WasmGlobal &Global : Globals) {
936b879539aSDerek Schuff       writeValueType(Global.Type);
937d934cb88SDan Gohman       write8(Global.IsMutable);
938d934cb88SDan Gohman 
939970d02c4SDan Gohman       if (Global.HasImport) {
940970d02c4SDan Gohman         assert(Global.InitialValue == 0);
941970d02c4SDan Gohman         write8(wasm::WASM_OPCODE_GET_GLOBAL);
942970d02c4SDan Gohman         encodeULEB128(Global.ImportIndex, getStream());
943970d02c4SDan Gohman       } else {
944970d02c4SDan Gohman         assert(Global.ImportIndex == 0);
945d934cb88SDan Gohman         write8(wasm::WASM_OPCODE_I32_CONST);
946d934cb88SDan Gohman         encodeSLEB128(Global.InitialValue, getStream()); // offset
947970d02c4SDan Gohman       }
948d934cb88SDan Gohman       write8(wasm::WASM_OPCODE_END);
949d934cb88SDan Gohman     }
950d934cb88SDan Gohman 
951d934cb88SDan Gohman     endSection(Section);
952d934cb88SDan Gohman   }
953d934cb88SDan Gohman 
954d934cb88SDan Gohman   // === Export Section ========================================================
955d934cb88SDan Gohman   if (!Exports.empty()) {
956d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_EXPORT);
957d934cb88SDan Gohman 
958d934cb88SDan Gohman     encodeULEB128(Exports.size(), getStream());
959d934cb88SDan Gohman     for (const WasmExport &Export : Exports) {
960d934cb88SDan Gohman       encodeULEB128(Export.FieldName.size(), getStream());
961d934cb88SDan Gohman       writeBytes(Export.FieldName);
962d934cb88SDan Gohman 
963e2688c43SDerek Schuff       encodeSLEB128(Export.Kind, getStream());
964d934cb88SDan Gohman 
965d934cb88SDan Gohman       encodeULEB128(Export.Index, getStream());
966d934cb88SDan Gohman     }
967d934cb88SDan Gohman 
968d934cb88SDan Gohman     endSection(Section);
969d934cb88SDan Gohman   }
970d934cb88SDan Gohman 
971d934cb88SDan Gohman #if 0 // TODO: Start Section
972d934cb88SDan Gohman   if (HaveStartFunction) {
973d934cb88SDan Gohman     // === Start Section =========================================================
974d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_START);
975d934cb88SDan Gohman 
976d934cb88SDan Gohman     encodeSLEB128(StartFunction, getStream());
977d934cb88SDan Gohman 
978d934cb88SDan Gohman     endSection(Section);
979d934cb88SDan Gohman   }
980d934cb88SDan Gohman #endif
981d934cb88SDan Gohman 
982d934cb88SDan Gohman   // === Elem Section ==========================================================
983d934cb88SDan Gohman   if (!TableElems.empty()) {
984d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_ELEM);
985d934cb88SDan Gohman 
986d934cb88SDan Gohman     encodeULEB128(1, getStream()); // number of "segments"
987d934cb88SDan Gohman     encodeULEB128(0, getStream()); // the table index
988d934cb88SDan Gohman 
989d934cb88SDan Gohman     // init expr for starting offset
990d934cb88SDan Gohman     write8(wasm::WASM_OPCODE_I32_CONST);
991d934cb88SDan Gohman     encodeSLEB128(0, getStream());
992d934cb88SDan Gohman     write8(wasm::WASM_OPCODE_END);
993d934cb88SDan Gohman 
994d934cb88SDan Gohman     encodeULEB128(TableElems.size(), getStream());
995d934cb88SDan Gohman     for (uint32_t Elem : TableElems)
996d934cb88SDan Gohman       encodeULEB128(Elem, getStream());
997d934cb88SDan Gohman 
998d934cb88SDan Gohman     endSection(Section);
999d934cb88SDan Gohman   }
1000d934cb88SDan Gohman 
1001d934cb88SDan Gohman   // === Code Section ==========================================================
1002d934cb88SDan Gohman   if (!Functions.empty()) {
1003d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_CODE);
1004d934cb88SDan Gohman 
1005d934cb88SDan Gohman     encodeULEB128(Functions.size(), getStream());
1006d934cb88SDan Gohman 
1007d934cb88SDan Gohman     for (const WasmFunction &Func : Functions) {
1008d934cb88SDan Gohman       MCSectionWasm &FuncSection =
1009d934cb88SDan Gohman           static_cast<MCSectionWasm &>(Func.Sym->getSection());
1010d934cb88SDan Gohman 
1011d934cb88SDan Gohman       if (Func.Sym->isVariable())
1012d934cb88SDan Gohman         report_fatal_error("weak symbols not supported yet");
1013d934cb88SDan Gohman 
1014d934cb88SDan Gohman       if (Func.Sym->getOffset() != 0)
1015d934cb88SDan Gohman         report_fatal_error("function sections must contain one function each");
1016d934cb88SDan Gohman 
1017d934cb88SDan Gohman       if (!Func.Sym->getSize())
1018d934cb88SDan Gohman         report_fatal_error("function symbols must have a size set with .size");
1019d934cb88SDan Gohman 
1020d934cb88SDan Gohman       int64_t Size = 0;
1021d934cb88SDan Gohman       if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
1022d934cb88SDan Gohman         report_fatal_error(".size expression must be evaluatable");
1023d934cb88SDan Gohman 
1024d934cb88SDan Gohman       encodeULEB128(Size, getStream());
1025d934cb88SDan Gohman 
1026d934cb88SDan Gohman       FuncSection.setSectionOffset(getStream().tell() -
1027d934cb88SDan Gohman                                    Section.ContentsOffset);
1028d934cb88SDan Gohman 
1029d934cb88SDan Gohman       Asm.writeSectionData(&FuncSection, Layout);
1030d934cb88SDan Gohman     }
1031d934cb88SDan Gohman 
1032d934cb88SDan Gohman     // Apply the type index fixups for call_indirect etc. instructions.
1033d934cb88SDan Gohman     for (size_t i = 0, e = TypeIndexFixups.size(); i < e; ++i) {
1034d934cb88SDan Gohman       uint32_t Type = TypeIndexFixupTypes[i];
1035d934cb88SDan Gohman       unsigned Padding = PaddingFor5ByteULEB128(Type);
1036d934cb88SDan Gohman 
1037970d02c4SDan Gohman       const WasmRelocationEntry &Fixup = TypeIndexFixups[i];
1038970d02c4SDan Gohman       assert(Fixup.Addend == 0);
1039970d02c4SDan Gohman       assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB);
1040d934cb88SDan Gohman       uint64_t Offset = Fixup.Offset +
1041d934cb88SDan Gohman                         Fixup.FixupSection->getSectionOffset();
1042d934cb88SDan Gohman 
1043d934cb88SDan Gohman       uint8_t Buffer[16];
1044d934cb88SDan Gohman       unsigned SizeLen = encodeULEB128(Type, Buffer, Padding);
1045d934cb88SDan Gohman       assert(SizeLen == 5);
1046d934cb88SDan Gohman       getStream().pwrite((char *)Buffer, SizeLen,
1047d934cb88SDan Gohman                          Section.ContentsOffset + Offset);
1048d934cb88SDan Gohman     }
1049d934cb88SDan Gohman 
1050d934cb88SDan Gohman     // Apply fixups.
1051d934cb88SDan Gohman     ApplyRelocations(CodeRelocations, getStream(), SymbolIndices,
1052d934cb88SDan Gohman                      Section.ContentsOffset);
1053d934cb88SDan Gohman 
1054d934cb88SDan Gohman     endSection(Section);
1055d934cb88SDan Gohman   }
1056d934cb88SDan Gohman 
1057d934cb88SDan Gohman   // === Data Section ==========================================================
1058a06de028SSam Clegg   uint32_t DataSectionHeaderSize = 0;
1059d934cb88SDan Gohman   if (!DataBytes.empty()) {
1060d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_DATA);
1061d934cb88SDan Gohman 
1062d934cb88SDan Gohman     encodeULEB128(1, getStream()); // count
1063d934cb88SDan Gohman     encodeULEB128(0, getStream()); // memory index
1064d934cb88SDan Gohman     write8(wasm::WASM_OPCODE_I32_CONST);
1065d934cb88SDan Gohman     encodeSLEB128(0, getStream()); // offset
1066d934cb88SDan Gohman     write8(wasm::WASM_OPCODE_END);
1067d934cb88SDan Gohman     encodeULEB128(DataBytes.size(), getStream()); // size
1068a06de028SSam Clegg     DataSectionHeaderSize = getStream().tell() - Section.ContentsOffset;
1069d934cb88SDan Gohman     writeBytes(DataBytes); // data
1070d934cb88SDan Gohman 
1071d934cb88SDan Gohman     // Apply fixups.
1072d934cb88SDan Gohman     ApplyRelocations(DataRelocations, getStream(), SymbolIndices,
1073a06de028SSam Clegg                      Section.ContentsOffset + DataSectionHeaderSize);
1074d934cb88SDan Gohman 
1075d934cb88SDan Gohman     endSection(Section);
1076d934cb88SDan Gohman   }
1077d934cb88SDan Gohman 
1078d934cb88SDan Gohman   // === Name Section ==========================================================
107913f080fbSDerek Schuff   uint32_t TotalFunctions = NumFuncImports + Functions.size();
108013f080fbSDerek Schuff   if (TotalFunctions != 0) {
1081d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_CUSTOM, "name");
108213f080fbSDerek Schuff     SectionBookkeeping SubSection;
108313f080fbSDerek Schuff     startSection(SubSection, wasm::WASM_NAMES_FUNCTION);
1084d934cb88SDan Gohman 
108513f080fbSDerek Schuff     encodeULEB128(TotalFunctions, getStream());
108613f080fbSDerek Schuff     uint32_t Index = 0;
1087d934cb88SDan Gohman     for (const WasmImport &Import : Imports) {
1088d934cb88SDan Gohman       if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
108913f080fbSDerek Schuff         encodeULEB128(Index, getStream());
1090d934cb88SDan Gohman         encodeULEB128(Import.FieldName.size(), getStream());
1091d934cb88SDan Gohman         writeBytes(Import.FieldName);
109213f080fbSDerek Schuff         ++Index;
1093d934cb88SDan Gohman       }
1094d934cb88SDan Gohman     }
1095d934cb88SDan Gohman     for (const WasmFunction &Func : Functions) {
109613f080fbSDerek Schuff       encodeULEB128(Index, getStream());
1097d934cb88SDan Gohman       encodeULEB128(Func.Sym->getName().size(), getStream());
1098d934cb88SDan Gohman       writeBytes(Func.Sym->getName());
109913f080fbSDerek Schuff       ++Index;
1100d934cb88SDan Gohman     }
1101d934cb88SDan Gohman 
110213f080fbSDerek Schuff     endSection(SubSection);
1103d934cb88SDan Gohman     endSection(Section);
1104d934cb88SDan Gohman   }
1105d934cb88SDan Gohman 
1106d934cb88SDan Gohman   // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
1107d934cb88SDan Gohman   // for descriptions of the reloc sections.
1108d934cb88SDan Gohman 
1109d934cb88SDan Gohman   // === Code Reloc Section ====================================================
1110d934cb88SDan Gohman   if (!CodeRelocations.empty()) {
1111d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.CODE");
1112d934cb88SDan Gohman 
1113e2688c43SDerek Schuff     encodeULEB128(wasm::WASM_SEC_CODE, getStream());
1114d934cb88SDan Gohman 
111503b19237SSam Clegg     encodeULEB128(CodeRelocations.size() + TypeIndexFixups.size(), getStream());
1116d934cb88SDan Gohman 
1117a06de028SSam Clegg     WriteRelocations(CodeRelocations, getStream(), SymbolIndices, 0);
1118970d02c4SDan Gohman     WriteTypeRelocations(TypeIndexFixups, TypeIndexFixupTypes, getStream());
1119d934cb88SDan Gohman 
1120d934cb88SDan Gohman     endSection(Section);
1121d934cb88SDan Gohman   }
1122d934cb88SDan Gohman 
1123d934cb88SDan Gohman   // === Data Reloc Section ====================================================
1124d934cb88SDan Gohman   if (!DataRelocations.empty()) {
1125d934cb88SDan Gohman     startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.DATA");
1126d934cb88SDan Gohman 
1127e2688c43SDerek Schuff     encodeULEB128(wasm::WASM_SEC_DATA, getStream());
1128d934cb88SDan Gohman 
1129d934cb88SDan Gohman     encodeULEB128(DataRelocations.size(), getStream());
1130d934cb88SDan Gohman 
1131a06de028SSam Clegg     WriteRelocations(DataRelocations, getStream(), SymbolIndices,
1132a06de028SSam Clegg                      DataSectionHeaderSize);
1133d934cb88SDan Gohman 
1134d934cb88SDan Gohman     endSection(Section);
1135d934cb88SDan Gohman   }
1136d934cb88SDan Gohman 
1137970d02c4SDan Gohman   // === Linking Metadata Section ==============================================
1138970d02c4SDan Gohman   if (HasStackPointer) {
1139970d02c4SDan Gohman     startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
1140970d02c4SDan Gohman 
1141970d02c4SDan Gohman     encodeULEB128(1, getStream()); // count
1142970d02c4SDan Gohman 
1143970d02c4SDan Gohman     encodeULEB128(wasm::WASM_STACK_POINTER, getStream()); // type
1144970d02c4SDan Gohman     encodeULEB128(StackPointerGlobal, getStream()); // id
1145970d02c4SDan Gohman 
1146970d02c4SDan Gohman     endSection(Section);
1147970d02c4SDan Gohman   }
1148970d02c4SDan Gohman 
1149d934cb88SDan Gohman   // TODO: Translate the .comment section to the output.
1150d934cb88SDan Gohman 
1151d934cb88SDan Gohman   // TODO: Translate debug sections to the output.
115218eafb6cSDan Gohman }
115318eafb6cSDan Gohman 
115418eafb6cSDan Gohman MCObjectWriter *llvm::createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW,
115518eafb6cSDan Gohman                                              raw_pwrite_stream &OS) {
115618eafb6cSDan Gohman   return new WasmObjectWriter(MOTW, OS);
115718eafb6cSDan Gohman }
1158