1 //===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements Wasm object file writer information.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/SmallPtrSet.h"
16 #include "llvm/BinaryFormat/Wasm.h"
17 #include "llvm/MC/MCAsmBackend.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCAsmLayout.h"
20 #include "llvm/MC/MCAssembler.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCFixupKindInfo.h"
24 #include "llvm/MC/MCObjectFileInfo.h"
25 #include "llvm/MC/MCObjectWriter.h"
26 #include "llvm/MC/MCSectionWasm.h"
27 #include "llvm/MC/MCSymbolWasm.h"
28 #include "llvm/MC/MCValue.h"
29 #include "llvm/MC/MCWasmObjectWriter.h"
30 #include "llvm/Support/Casting.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/ErrorHandling.h"
33 #include "llvm/Support/LEB128.h"
34 #include "llvm/Support/StringSaver.h"
35 #include <vector>
36 
37 using namespace llvm;
38 
39 #undef DEBUG_TYPE
40 #define DEBUG_TYPE "reloc-info"
41 
42 namespace {
43 
44 // For patching purposes, we need to remember where each section starts, both
45 // for patching up the section size field, and for patching up references to
46 // locations within the section.
47 struct SectionBookkeeping {
48   // Where the size of the section is written.
49   uint64_t SizeOffset;
50   // Where the contents of the section starts (after the header).
51   uint64_t ContentsOffset;
52 };
53 
54 // The signature of a wasm function, in a struct capable of being used as a
55 // DenseMap key.
56 struct WasmFunctionType {
57   // Support empty and tombstone instances, needed by DenseMap.
58   enum { Plain, Empty, Tombstone } State;
59 
60   // The return types of the function.
61   SmallVector<wasm::ValType, 1> Returns;
62 
63   // The parameter types of the function.
64   SmallVector<wasm::ValType, 4> Params;
65 
66   WasmFunctionType() : State(Plain) {}
67 
68   bool operator==(const WasmFunctionType &Other) const {
69     return State == Other.State && Returns == Other.Returns &&
70            Params == Other.Params;
71   }
72 };
73 
74 // Traits for using WasmFunctionType in a DenseMap.
75 struct WasmFunctionTypeDenseMapInfo {
76   static WasmFunctionType getEmptyKey() {
77     WasmFunctionType FuncTy;
78     FuncTy.State = WasmFunctionType::Empty;
79     return FuncTy;
80   }
81   static WasmFunctionType getTombstoneKey() {
82     WasmFunctionType FuncTy;
83     FuncTy.State = WasmFunctionType::Tombstone;
84     return FuncTy;
85   }
86   static unsigned getHashValue(const WasmFunctionType &FuncTy) {
87     uintptr_t Value = FuncTy.State;
88     for (wasm::ValType Ret : FuncTy.Returns)
89       Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Ret));
90     for (wasm::ValType Param : FuncTy.Params)
91       Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Param));
92     return Value;
93   }
94   static bool isEqual(const WasmFunctionType &LHS,
95                       const WasmFunctionType &RHS) {
96     return LHS == RHS;
97   }
98 };
99 
100 // A wasm import to be written into the import section.
101 struct WasmImport {
102   StringRef ModuleName;
103   StringRef FieldName;
104   unsigned Kind;
105   int32_t Type;
106 };
107 
108 // A wasm function to be written into the function section.
109 struct WasmFunction {
110   int32_t Type;
111   const MCSymbolWasm *Sym;
112 };
113 
114 // A wasm export to be written into the export section.
115 struct WasmExport {
116   StringRef FieldName;
117   unsigned Kind;
118   uint32_t Index;
119 };
120 
121 // A wasm global to be written into the global section.
122 struct WasmGlobal {
123   wasm::ValType Type;
124   bool IsMutable;
125   bool HasImport;
126   uint64_t InitialValue;
127   uint32_t ImportIndex;
128 };
129 
130 // Information about a single relocation.
131 struct WasmRelocationEntry {
132   uint64_t Offset;                  // Where is the relocation.
133   const MCSymbolWasm *Symbol;       // The symbol to relocate with.
134   int64_t Addend;                   // A value to add to the symbol.
135   unsigned Type;                    // The type of the relocation.
136   const MCSectionWasm *FixupSection;// The section the relocation is targeting.
137 
138   WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
139                       int64_t Addend, unsigned Type,
140                       const MCSectionWasm *FixupSection)
141       : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type),
142         FixupSection(FixupSection) {}
143 
144   bool hasAddend() const {
145     switch (Type) {
146     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
147     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
148     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
149       return true;
150     default:
151       return false;
152     }
153   }
154 
155   void print(raw_ostream &Out) const {
156     Out << "Off=" << Offset << ", Sym=" << Symbol << ", Addend=" << Addend
157         << ", Type=" << Type << ", FixupSection=" << FixupSection;
158   }
159 
160 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
161   LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
162 #endif
163 };
164 
165 #if !defined(NDEBUG)
166 raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
167   Rel.print(OS);
168   return OS;
169 }
170 #endif
171 
172 class WasmObjectWriter : public MCObjectWriter {
173   /// Helper struct for containing some precomputed information on symbols.
174   struct WasmSymbolData {
175     const MCSymbolWasm *Symbol;
176     StringRef Name;
177 
178     // Support lexicographic sorting.
179     bool operator<(const WasmSymbolData &RHS) const { return Name < RHS.Name; }
180   };
181 
182   /// The target specific Wasm writer instance.
183   std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
184 
185   // Relocations for fixing up references in the code section.
186   std::vector<WasmRelocationEntry> CodeRelocations;
187 
188   // Relocations for fixing up references in the data section.
189   std::vector<WasmRelocationEntry> DataRelocations;
190 
191   // Index values to use for fixing up call_indirect type indices.
192   // Maps function symbols to the index of the type of the function
193   DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices;
194   // Maps function symbols to the table element index space. Used
195   // for TABLE_INDEX relocation types (i.e. address taken functions).
196   DenseMap<const MCSymbolWasm *, uint32_t> IndirectSymbolIndices;
197   // Maps function/global symbols to the function/global index space.
198   DenseMap<const MCSymbolWasm *, uint32_t> SymbolIndices;
199 
200   DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo>
201       FunctionTypeIndices;
202 
203   // TargetObjectWriter wrappers.
204   bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
205   unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup) const {
206     return TargetObjectWriter->getRelocType(Target, Fixup);
207   }
208 
209   void startSection(SectionBookkeeping &Section, unsigned SectionId,
210                     const char *Name = nullptr);
211   void endSection(SectionBookkeeping &Section);
212 
213 public:
214   WasmObjectWriter(MCWasmObjectTargetWriter *MOTW, raw_pwrite_stream &OS)
215       : MCObjectWriter(OS, /*IsLittleEndian=*/true), TargetObjectWriter(MOTW) {}
216 
217 private:
218   ~WasmObjectWriter() override;
219 
220   void reset() override {
221     CodeRelocations.clear();
222     DataRelocations.clear();
223     TypeIndices.clear();
224     SymbolIndices.clear();
225     IndirectSymbolIndices.clear();
226     FunctionTypeIndices.clear();
227     MCObjectWriter::reset();
228   }
229 
230   void writeHeader(const MCAssembler &Asm);
231 
232   void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
233                         const MCFragment *Fragment, const MCFixup &Fixup,
234                         MCValue Target, bool &IsPCRel,
235                         uint64_t &FixedValue) override;
236 
237   void executePostLayoutBinding(MCAssembler &Asm,
238                                 const MCAsmLayout &Layout) override;
239 
240   void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
241 
242   void writeString(const StringRef Str) {
243     encodeULEB128(Str.size(), getStream());
244     writeBytes(Str);
245   }
246 
247   void writeValueType(wasm::ValType Ty) {
248     encodeSLEB128(int32_t(Ty), getStream());
249   }
250 
251   void writeTypeSection(const SmallVector<WasmFunctionType, 4> &FunctionTypes);
252   void writeImportSection(const SmallVector<WasmImport, 4> &Imports);
253   void writeFunctionSection(const SmallVector<WasmFunction, 4> &Functions);
254   void writeTableSection(uint32_t NumElements);
255   void writeMemorySection(const SmallVector<char, 0> &DataBytes);
256   void writeGlobalSection(const SmallVector<WasmGlobal, 4> &Globals);
257   void writeExportSection(const SmallVector<WasmExport, 4> &Exports);
258   void writeElemSection(const SmallVector<uint32_t, 4> &TableElems);
259   void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
260                         const SmallVector<WasmFunction, 4> &Functions);
261   uint64_t
262   writeDataSection(const SmallVector<char, 0> &DataBytes);
263   void writeNameSection(const SmallVector<WasmFunction, 4> &Functions,
264                         const SmallVector<WasmImport, 4> &Imports,
265                         uint32_t NumFuncImports);
266   void writeCodeRelocSection();
267   void writeDataRelocSection(uint64_t DataSectionHeaderSize);
268   void writeLinkingMetaDataSection(uint32_t DataSize, uint32_t DataAlignment,
269                                    ArrayRef<StringRef> WeakSymbols,
270                                    bool HasStackPointer,
271                                    uint32_t StackPointerGlobal);
272 
273   void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
274                         uint64_t ContentsOffset);
275 
276   void writeRelocations(ArrayRef<WasmRelocationEntry> Relocations,
277                         uint64_t HeaderSize);
278   uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
279 };
280 
281 } // end anonymous namespace
282 
283 WasmObjectWriter::~WasmObjectWriter() {}
284 
285 // Return the padding size to write a 32-bit value into a 5-byte ULEB128.
286 static unsigned PaddingFor5ByteULEB128(uint32_t X) {
287   return X == 0 ? 4 : (4u - (31u - countLeadingZeros(X)) / 7u);
288 }
289 
290 // Return the padding size to write a 32-bit value into a 5-byte SLEB128.
291 static unsigned PaddingFor5ByteSLEB128(int32_t X) {
292   return 5 - getSLEB128Size(X);
293 }
294 
295 // Write out a section header and a patchable section size field.
296 void WasmObjectWriter::startSection(SectionBookkeeping &Section,
297                                     unsigned SectionId,
298                                     const char *Name) {
299   assert((Name != nullptr) == (SectionId == wasm::WASM_SEC_CUSTOM) &&
300          "Only custom sections can have names");
301 
302   DEBUG(dbgs() << "startSection " << SectionId << ": " << Name << "\n");
303   encodeULEB128(SectionId, getStream());
304 
305   Section.SizeOffset = getStream().tell();
306 
307   // The section size. We don't know the size yet, so reserve enough space
308   // for any 32-bit value; we'll patch it later.
309   encodeULEB128(UINT32_MAX, getStream());
310 
311   // The position where the section starts, for measuring its size.
312   Section.ContentsOffset = getStream().tell();
313 
314   // Custom sections in wasm also have a string identifier.
315   if (SectionId == wasm::WASM_SEC_CUSTOM) {
316     assert(Name);
317     writeString(StringRef(Name));
318   }
319 }
320 
321 // Now that the section is complete and we know how big it is, patch up the
322 // section size field at the start of the section.
323 void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
324   uint64_t Size = getStream().tell() - Section.ContentsOffset;
325   if (uint32_t(Size) != Size)
326     report_fatal_error("section size does not fit in a uint32_t");
327 
328   DEBUG(dbgs() << "endSection size=" << Size << "\n");
329   unsigned Padding = PaddingFor5ByteULEB128(Size);
330 
331   // Write the final section size to the payload_len field, which follows
332   // the section id byte.
333   uint8_t Buffer[16];
334   unsigned SizeLen = encodeULEB128(Size, Buffer, Padding);
335   assert(SizeLen == 5);
336   getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset);
337 }
338 
339 // Emit the Wasm header.
340 void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
341   writeBytes(StringRef(wasm::WasmMagic, sizeof(wasm::WasmMagic)));
342   writeLE32(wasm::WasmVersion);
343 }
344 
345 void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
346                                                 const MCAsmLayout &Layout) {
347 }
348 
349 void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
350                                         const MCAsmLayout &Layout,
351                                         const MCFragment *Fragment,
352                                         const MCFixup &Fixup, MCValue Target,
353                                         bool &IsPCRel, uint64_t &FixedValue) {
354   const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
355   uint64_t C = Target.getConstant();
356   uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
357   MCContext &Ctx = Asm.getContext();
358 
359   if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
360     assert(RefB->getKind() == MCSymbolRefExpr::VK_None &&
361            "Should not have constructed this");
362 
363     // Let A, B and C being the components of Target and R be the location of
364     // the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
365     // If it is pcrel, we want to compute (A - B + C - R).
366 
367     // In general, Wasm has no relocations for -B. It can only represent (A + C)
368     // or (A + C - R). If B = R + K and the relocation is not pcrel, we can
369     // replace B to implement it: (A - R - K + C)
370     if (IsPCRel) {
371       Ctx.reportError(
372           Fixup.getLoc(),
373           "No relocation available to represent this relative expression");
374       return;
375     }
376 
377     const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
378 
379     if (SymB.isUndefined()) {
380       Ctx.reportError(Fixup.getLoc(),
381                       Twine("symbol '") + SymB.getName() +
382                           "' can not be undefined in a subtraction expression");
383       return;
384     }
385 
386     assert(!SymB.isAbsolute() && "Should have been folded");
387     const MCSection &SecB = SymB.getSection();
388     if (&SecB != &FixupSection) {
389       Ctx.reportError(Fixup.getLoc(),
390                       "Cannot represent a difference across sections");
391       return;
392     }
393 
394     uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
395     uint64_t K = SymBOffset - FixupOffset;
396     IsPCRel = true;
397     C -= K;
398   }
399 
400   // We either rejected the fixup or folded B into C at this point.
401   const MCSymbolRefExpr *RefA = Target.getSymA();
402   const auto *SymA = RefA ? cast<MCSymbolWasm>(&RefA->getSymbol()) : nullptr;
403 
404   bool ViaWeakRef = false;
405   if (SymA && SymA->isVariable()) {
406     const MCExpr *Expr = SymA->getVariableValue();
407     if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
408       if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) {
409         SymA = cast<MCSymbolWasm>(&Inner->getSymbol());
410         ViaWeakRef = true;
411       }
412     }
413   }
414 
415   // Put any constant offset in an addend. Offsets can be negative, and
416   // LLVM expects wrapping, in contrast to wasm's immediates which can't
417   // be negative and don't wrap.
418   FixedValue = 0;
419 
420   if (SymA) {
421     if (ViaWeakRef)
422       llvm_unreachable("weakref used in reloc not yet implemented");
423     else
424       SymA->setUsedInReloc();
425   }
426 
427   assert(!IsPCRel);
428   assert(SymA);
429 
430   unsigned Type = getRelocType(Target, Fixup);
431 
432   WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
433   DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
434 
435   if (FixupSection.hasInstructions())
436     CodeRelocations.push_back(Rec);
437   else
438     DataRelocations.push_back(Rec);
439 }
440 
441 // Write X as an (unsigned) LEB value at offset Offset in Stream, padded
442 // to allow patching.
443 static void
444 WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
445   uint8_t Buffer[5];
446   unsigned Padding = PaddingFor5ByteULEB128(X);
447   unsigned SizeLen = encodeULEB128(X, Buffer, Padding);
448   assert(SizeLen == 5);
449   Stream.pwrite((char *)Buffer, SizeLen, Offset);
450 }
451 
452 // Write X as an signed LEB value at offset Offset in Stream, padded
453 // to allow patching.
454 static void
455 WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) {
456   uint8_t Buffer[5];
457   unsigned Padding = PaddingFor5ByteSLEB128(X);
458   unsigned SizeLen = encodeSLEB128(X, Buffer, Padding);
459   assert(SizeLen == 5);
460   Stream.pwrite((char *)Buffer, SizeLen, Offset);
461 }
462 
463 // Write X as a plain integer value at offset Offset in Stream.
464 static void WriteI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
465   uint8_t Buffer[4];
466   support::endian::write32le(Buffer, X);
467   Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
468 }
469 
470 // Compute a value to write into the code at the location covered
471 // by RelEntry. This value isn't used by the static linker, since
472 // we have addends; it just serves to make the code more readable
473 // and to make standalone wasm modules directly usable.
474 static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) {
475   const MCSymbolWasm *Sym = RelEntry.Symbol;
476 
477   // For undefined symbols, use a hopefully invalid value.
478   if (!Sym->isDefined(/*SetUsed=*/false))
479     return UINT32_MAX;
480 
481   const auto &Section = cast<MCSectionWasm>(RelEntry.Symbol->getSection(false));
482   uint64_t Address = Section.getSectionOffset() + RelEntry.Addend;
483 
484   // Ignore overflow. LLVM allows address arithmetic to silently wrap.
485   uint32_t Value = Address;
486 
487   return Value;
488 }
489 
490 uint32_t WasmObjectWriter::getRelocationIndexValue(
491     const WasmRelocationEntry &RelEntry) {
492   switch (RelEntry.Type) {
493   case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
494   case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
495     if (!IndirectSymbolIndices.count(RelEntry.Symbol))
496       report_fatal_error("symbol not found table index space:" +
497                          RelEntry.Symbol->getName());
498     return IndirectSymbolIndices[RelEntry.Symbol];
499   case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
500   case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
501   case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB:
502   case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
503   case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
504     if (!SymbolIndices.count(RelEntry.Symbol))
505       report_fatal_error("symbol not found function/global index space:" +
506                          RelEntry.Symbol->getName());
507     return SymbolIndices[RelEntry.Symbol];
508   case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
509     if (!TypeIndices.count(RelEntry.Symbol))
510       report_fatal_error("symbol not found in type index space:" +
511                          RelEntry.Symbol->getName());
512     return TypeIndices[RelEntry.Symbol];
513   default:
514     llvm_unreachable("invalid relocation type");
515   }
516 }
517 
518 // Apply the portions of the relocation records that we can handle ourselves
519 // directly.
520 void WasmObjectWriter::applyRelocations(
521     ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset) {
522   raw_pwrite_stream &Stream = getStream();
523   for (const WasmRelocationEntry &RelEntry : Relocations) {
524     uint64_t Offset = ContentsOffset +
525                       RelEntry.FixupSection->getSectionOffset() +
526                       RelEntry.Offset;
527 
528     DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
529     switch (RelEntry.Type) {
530     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
531     case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
532     case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
533     case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: {
534       uint32_t Index = getRelocationIndexValue(RelEntry);
535       WritePatchableSLEB(Stream, Index, Offset);
536       break;
537     }
538     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: {
539       uint32_t Index = getRelocationIndexValue(RelEntry);
540       WriteI32(Stream, Index, Offset);
541       break;
542     }
543     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: {
544       uint32_t Value = ProvisionalValue(RelEntry);
545       WritePatchableSLEB(Stream, Value, Offset);
546       break;
547     }
548     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: {
549       uint32_t Value = ProvisionalValue(RelEntry);
550       WritePatchableLEB(Stream, Value, Offset);
551       break;
552     }
553     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: {
554       uint32_t Value = ProvisionalValue(RelEntry);
555       WriteI32(Stream, Value, Offset);
556       break;
557     }
558     default:
559       llvm_unreachable("invalid relocation type");
560     }
561   }
562 }
563 
564 // Write out the portions of the relocation records that the linker will
565 // need to handle.
566 void WasmObjectWriter::writeRelocations(
567     ArrayRef<WasmRelocationEntry> Relocations, uint64_t HeaderSize) {
568   raw_pwrite_stream &Stream = getStream();
569   for (const WasmRelocationEntry& RelEntry : Relocations) {
570 
571     uint64_t Offset = RelEntry.Offset +
572                       RelEntry.FixupSection->getSectionOffset() + HeaderSize;
573     uint32_t Index = getRelocationIndexValue(RelEntry);
574 
575     encodeULEB128(RelEntry.Type, Stream);
576     encodeULEB128(Offset, Stream);
577     encodeULEB128(Index, Stream);
578     if (RelEntry.hasAddend())
579       encodeSLEB128(RelEntry.Addend, Stream);
580   }
581 }
582 
583 void WasmObjectWriter::writeTypeSection(
584     const SmallVector<WasmFunctionType, 4> &FunctionTypes) {
585   if (FunctionTypes.empty())
586     return;
587 
588   SectionBookkeeping Section;
589   startSection(Section, wasm::WASM_SEC_TYPE);
590 
591   encodeULEB128(FunctionTypes.size(), getStream());
592 
593   for (const WasmFunctionType &FuncTy : FunctionTypes) {
594     encodeSLEB128(wasm::WASM_TYPE_FUNC, getStream());
595     encodeULEB128(FuncTy.Params.size(), getStream());
596     for (wasm::ValType Ty : FuncTy.Params)
597       writeValueType(Ty);
598     encodeULEB128(FuncTy.Returns.size(), getStream());
599     for (wasm::ValType Ty : FuncTy.Returns)
600       writeValueType(Ty);
601   }
602 
603   endSection(Section);
604 }
605 
606 
607 void WasmObjectWriter::writeImportSection(
608     const SmallVector<WasmImport, 4> &Imports) {
609   if (Imports.empty())
610     return;
611 
612   SectionBookkeeping Section;
613   startSection(Section, wasm::WASM_SEC_IMPORT);
614 
615   encodeULEB128(Imports.size(), getStream());
616   for (const WasmImport &Import : Imports) {
617     writeString(Import.ModuleName);
618     writeString(Import.FieldName);
619 
620     encodeULEB128(Import.Kind, getStream());
621 
622     switch (Import.Kind) {
623     case wasm::WASM_EXTERNAL_FUNCTION:
624       encodeULEB128(Import.Type, getStream());
625       break;
626     case wasm::WASM_EXTERNAL_GLOBAL:
627       encodeSLEB128(int32_t(Import.Type), getStream());
628       encodeULEB128(0, getStream()); // mutability
629       break;
630     default:
631       llvm_unreachable("unsupported import kind");
632     }
633   }
634 
635   endSection(Section);
636 }
637 
638 void WasmObjectWriter::writeFunctionSection(
639     const SmallVector<WasmFunction, 4> &Functions) {
640   if (Functions.empty())
641     return;
642 
643   SectionBookkeeping Section;
644   startSection(Section, wasm::WASM_SEC_FUNCTION);
645 
646   encodeULEB128(Functions.size(), getStream());
647   for (const WasmFunction &Func : Functions)
648     encodeULEB128(Func.Type, getStream());
649 
650   endSection(Section);
651 }
652 
653 void WasmObjectWriter::writeTableSection(uint32_t NumElements) {
654   // For now, always emit the table section, since indirect calls are not
655   // valid without it. In the future, we could perhaps be more clever and omit
656   // it if there are no indirect calls.
657 
658   SectionBookkeeping Section;
659   startSection(Section, wasm::WASM_SEC_TABLE);
660 
661   encodeULEB128(1, getStream());                       // The number of tables.
662                                                        // Fixed to 1 for now.
663   encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); // Type of table
664   encodeULEB128(0, getStream());                       // flags
665   encodeULEB128(NumElements, getStream());             // initial
666 
667   endSection(Section);
668 }
669 
670 void WasmObjectWriter::writeMemorySection(
671     const SmallVector<char, 0> &DataBytes) {
672   // For now, always emit the memory section, since loads and stores are not
673   // valid without it. In the future, we could perhaps be more clever and omit
674   // it if there are no loads or stores.
675   SectionBookkeeping Section;
676   uint32_t NumPages =
677       (DataBytes.size() + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
678 
679   startSection(Section, wasm::WASM_SEC_MEMORY);
680   encodeULEB128(1, getStream()); // number of memory spaces
681 
682   encodeULEB128(0, getStream()); // flags
683   encodeULEB128(NumPages, getStream()); // initial
684 
685   endSection(Section);
686 }
687 
688 void WasmObjectWriter::writeGlobalSection(
689     const SmallVector<WasmGlobal, 4> &Globals) {
690   if (Globals.empty())
691     return;
692 
693   SectionBookkeeping Section;
694   startSection(Section, wasm::WASM_SEC_GLOBAL);
695 
696   encodeULEB128(Globals.size(), getStream());
697   for (const WasmGlobal &Global : Globals) {
698     writeValueType(Global.Type);
699     write8(Global.IsMutable);
700 
701     if (Global.HasImport) {
702       assert(Global.InitialValue == 0);
703       write8(wasm::WASM_OPCODE_GET_GLOBAL);
704       encodeULEB128(Global.ImportIndex, getStream());
705     } else {
706       assert(Global.ImportIndex == 0);
707       write8(wasm::WASM_OPCODE_I32_CONST);
708       encodeSLEB128(Global.InitialValue, getStream()); // offset
709     }
710     write8(wasm::WASM_OPCODE_END);
711   }
712 
713   endSection(Section);
714 }
715 
716 void WasmObjectWriter::writeExportSection(
717     const SmallVector<WasmExport, 4> &Exports) {
718   if (Exports.empty())
719     return;
720 
721   SectionBookkeeping Section;
722   startSection(Section, wasm::WASM_SEC_EXPORT);
723 
724   encodeULEB128(Exports.size(), getStream());
725   for (const WasmExport &Export : Exports) {
726     writeString(Export.FieldName);
727     encodeSLEB128(Export.Kind, getStream());
728     encodeULEB128(Export.Index, getStream());
729   }
730 
731   endSection(Section);
732 }
733 
734 void WasmObjectWriter::writeElemSection(
735     const SmallVector<uint32_t, 4> &TableElems) {
736   if (TableElems.empty())
737     return;
738 
739   SectionBookkeeping Section;
740   startSection(Section, wasm::WASM_SEC_ELEM);
741 
742   encodeULEB128(1, getStream()); // number of "segments"
743   encodeULEB128(0, getStream()); // the table index
744 
745   // init expr for starting offset
746   write8(wasm::WASM_OPCODE_I32_CONST);
747   encodeSLEB128(0, getStream());
748   write8(wasm::WASM_OPCODE_END);
749 
750   encodeULEB128(TableElems.size(), getStream());
751   for (uint32_t Elem : TableElems)
752     encodeULEB128(Elem, getStream());
753 
754   endSection(Section);
755 }
756 
757 void WasmObjectWriter::writeCodeSection(
758     const MCAssembler &Asm, const MCAsmLayout &Layout,
759     const SmallVector<WasmFunction, 4> &Functions) {
760   if (Functions.empty())
761     return;
762 
763   SectionBookkeeping Section;
764   startSection(Section, wasm::WASM_SEC_CODE);
765 
766   encodeULEB128(Functions.size(), getStream());
767 
768   for (const WasmFunction &Func : Functions) {
769     auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection());
770 
771     int64_t Size = 0;
772     if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
773       report_fatal_error(".size expression must be evaluatable");
774 
775     encodeULEB128(Size, getStream());
776 
777     FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset);
778 
779     Asm.writeSectionData(&FuncSection, Layout);
780   }
781 
782   // Apply fixups.
783   applyRelocations(CodeRelocations, Section.ContentsOffset);
784 
785   endSection(Section);
786 }
787 
788 uint64_t WasmObjectWriter::writeDataSection(
789     const SmallVector<char, 0> &DataBytes) {
790   if (DataBytes.empty())
791     return 0;
792 
793   SectionBookkeeping Section;
794   startSection(Section, wasm::WASM_SEC_DATA);
795 
796   encodeULEB128(1, getStream()); // count
797   encodeULEB128(0, getStream()); // memory index
798   write8(wasm::WASM_OPCODE_I32_CONST);
799   encodeSLEB128(0, getStream()); // offset
800   write8(wasm::WASM_OPCODE_END);
801   encodeULEB128(DataBytes.size(), getStream()); // size
802   uint32_t HeaderSize = getStream().tell() - Section.ContentsOffset;
803   writeBytes(DataBytes); // data
804 
805   // Apply fixups.
806   applyRelocations(DataRelocations, Section.ContentsOffset + HeaderSize);
807 
808   endSection(Section);
809   return HeaderSize;
810 }
811 
812 void WasmObjectWriter::writeNameSection(
813     const SmallVector<WasmFunction, 4> &Functions,
814     const SmallVector<WasmImport, 4> &Imports,
815     unsigned NumFuncImports) {
816   uint32_t TotalFunctions = NumFuncImports + Functions.size();
817   if (TotalFunctions == 0)
818     return;
819 
820   SectionBookkeeping Section;
821   startSection(Section, wasm::WASM_SEC_CUSTOM, "name");
822   SectionBookkeeping SubSection;
823   startSection(SubSection, wasm::WASM_NAMES_FUNCTION);
824 
825   encodeULEB128(TotalFunctions, getStream());
826   uint32_t Index = 0;
827   for (const WasmImport &Import : Imports) {
828     if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
829       encodeULEB128(Index, getStream());
830       writeString(Import.FieldName);
831       ++Index;
832     }
833   }
834   for (const WasmFunction &Func : Functions) {
835     encodeULEB128(Index, getStream());
836     writeString(Func.Sym->getName());
837     ++Index;
838   }
839 
840   endSection(SubSection);
841   endSection(Section);
842 }
843 
844 void WasmObjectWriter::writeCodeRelocSection() {
845   // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
846   // for descriptions of the reloc sections.
847 
848   if (CodeRelocations.empty())
849     return;
850 
851   SectionBookkeeping Section;
852   startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.CODE");
853 
854   encodeULEB128(wasm::WASM_SEC_CODE, getStream());
855   encodeULEB128(CodeRelocations.size(), getStream());
856 
857   writeRelocations(CodeRelocations, 0);
858 
859   endSection(Section);
860 }
861 
862 void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) {
863   // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
864   // for descriptions of the reloc sections.
865 
866   if (DataRelocations.empty())
867     return;
868 
869   SectionBookkeeping Section;
870   startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.DATA");
871 
872   encodeULEB128(wasm::WASM_SEC_DATA, getStream());
873   encodeULEB128(DataRelocations.size(), getStream());
874 
875   writeRelocations(DataRelocations, DataSectionHeaderSize);
876 
877   endSection(Section);
878 }
879 
880 void WasmObjectWriter::writeLinkingMetaDataSection(
881     uint32_t DataSize, uint32_t DataAlignment, ArrayRef<StringRef> WeakSymbols,
882     bool HasStackPointer, uint32_t StackPointerGlobal) {
883   SectionBookkeeping Section;
884   startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
885   SectionBookkeeping SubSection;
886 
887   if (HasStackPointer) {
888     startSection(SubSection, wasm::WASM_STACK_POINTER);
889     encodeULEB128(StackPointerGlobal, getStream()); // id
890     endSection(SubSection);
891   }
892 
893   if (WeakSymbols.size() != 0) {
894     startSection(SubSection, wasm::WASM_SYMBOL_INFO);
895     encodeULEB128(WeakSymbols.size(), getStream());
896     for (const StringRef Export: WeakSymbols) {
897       writeString(Export);
898       encodeULEB128(wasm::WASM_SYMBOL_FLAG_WEAK, getStream());
899     }
900     endSection(SubSection);
901   }
902 
903   if (DataSize > 0) {
904     startSection(SubSection, wasm::WASM_DATA_SIZE);
905     encodeULEB128(DataSize, getStream());
906     endSection(SubSection);
907 
908     startSection(SubSection, wasm::WASM_DATA_ALIGNMENT);
909     encodeULEB128(DataAlignment, getStream());
910     endSection(SubSection);
911   }
912 
913   endSection(Section);
914 }
915 
916 void WasmObjectWriter::writeObject(MCAssembler &Asm,
917                                    const MCAsmLayout &Layout) {
918   DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
919   MCContext &Ctx = Asm.getContext();
920   wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32;
921 
922   // Collect information from the available symbols.
923   SmallVector<WasmFunctionType, 4> FunctionTypes;
924   SmallVector<WasmFunction, 4> Functions;
925   SmallVector<uint32_t, 4> TableElems;
926   SmallVector<WasmGlobal, 4> Globals;
927   SmallVector<WasmImport, 4> Imports;
928   SmallVector<WasmExport, 4> Exports;
929   SmallVector<StringRef, 4> WeakSymbols;
930   SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken;
931   unsigned NumFuncImports = 0;
932   unsigned NumGlobalImports = 0;
933   SmallVector<char, 0> DataBytes;
934   uint32_t DataAlignment = 1;
935   uint32_t StackPointerGlobal = 0;
936   bool HasStackPointer = false;
937 
938   // Populate the IsAddressTaken set.
939   for (const WasmRelocationEntry &RelEntry : CodeRelocations) {
940     switch (RelEntry.Type) {
941     case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
942     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB:
943       IsAddressTaken.insert(RelEntry.Symbol);
944       break;
945     default:
946       break;
947     }
948   }
949   for (const WasmRelocationEntry &RelEntry : DataRelocations) {
950     switch (RelEntry.Type) {
951     case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
952     case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32:
953       IsAddressTaken.insert(RelEntry.Symbol);
954       break;
955     default:
956       break;
957     }
958   }
959 
960   // Populate the Imports set.
961   for (const MCSymbol &S : Asm.symbols()) {
962     const auto &WS = static_cast<const MCSymbolWasm &>(S);
963     int32_t Type;
964 
965     if (WS.isFunction()) {
966       // Prepare the function's type, if we haven't seen it yet.
967       WasmFunctionType F;
968       F.Returns = WS.getReturns();
969       F.Params = WS.getParams();
970       auto Pair =
971           FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
972       if (Pair.second)
973         FunctionTypes.push_back(F);
974 
975       Type = Pair.first->second;
976     } else {
977       Type = int32_t(PtrType);
978     }
979 
980     // If the symbol is not defined in this translation unit, import it.
981     if (!WS.isTemporary() && !WS.isDefined(/*SetUsed=*/false)) {
982       WasmImport Import;
983       Import.ModuleName = WS.getModuleName();
984       Import.FieldName = WS.getName();
985 
986       if (WS.isFunction()) {
987         Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
988         Import.Type = Type;
989         SymbolIndices[&WS] = NumFuncImports;
990         ++NumFuncImports;
991       } else {
992         Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
993         Import.Type = Type;
994         SymbolIndices[&WS] = NumGlobalImports;
995         ++NumGlobalImports;
996       }
997 
998       Imports.push_back(Import);
999     }
1000   }
1001 
1002   // In the special .global_variables section, we've encoded global
1003   // variables used by the function. Translate them into the Globals
1004   // list.
1005   MCSectionWasm *GlobalVars = Ctx.getWasmSection(".global_variables", 0, 0);
1006   if (!GlobalVars->getFragmentList().empty()) {
1007     if (GlobalVars->getFragmentList().size() != 1)
1008       report_fatal_error("only one .global_variables fragment supported");
1009     const MCFragment &Frag = *GlobalVars->begin();
1010     if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
1011       report_fatal_error("only data supported in .global_variables");
1012     const auto &DataFrag = cast<MCDataFragment>(Frag);
1013     if (!DataFrag.getFixups().empty())
1014       report_fatal_error("fixups not supported in .global_variables");
1015     const SmallVectorImpl<char> &Contents = DataFrag.getContents();
1016     for (const uint8_t *p = (const uint8_t *)Contents.data(),
1017                      *end = (const uint8_t *)Contents.data() + Contents.size();
1018          p != end; ) {
1019       WasmGlobal G;
1020       if (end - p < 3)
1021         report_fatal_error("truncated global variable encoding");
1022       G.Type = wasm::ValType(int8_t(*p++));
1023       G.IsMutable = bool(*p++);
1024       G.HasImport = bool(*p++);
1025       if (G.HasImport) {
1026         G.InitialValue = 0;
1027 
1028         WasmImport Import;
1029         Import.ModuleName = (const char *)p;
1030         const uint8_t *nul = (const uint8_t *)memchr(p, '\0', end - p);
1031         if (!nul)
1032           report_fatal_error("global module name must be nul-terminated");
1033         p = nul + 1;
1034         nul = (const uint8_t *)memchr(p, '\0', end - p);
1035         if (!nul)
1036           report_fatal_error("global base name must be nul-terminated");
1037         Import.FieldName = (const char *)p;
1038         p = nul + 1;
1039 
1040         Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1041         Import.Type = int32_t(G.Type);
1042 
1043         G.ImportIndex = NumGlobalImports;
1044         ++NumGlobalImports;
1045 
1046         Imports.push_back(Import);
1047       } else {
1048         unsigned n;
1049         G.InitialValue = decodeSLEB128(p, &n);
1050         G.ImportIndex = 0;
1051         if ((ptrdiff_t)n > end - p)
1052           report_fatal_error("global initial value must be valid SLEB128");
1053         p += n;
1054       }
1055       Globals.push_back(G);
1056     }
1057   }
1058 
1059   // In the special .stack_pointer section, we've encoded the stack pointer
1060   // index.
1061   MCSectionWasm *StackPtr = Ctx.getWasmSection(".stack_pointer", 0, 0);
1062   if (!StackPtr->getFragmentList().empty()) {
1063     if (StackPtr->getFragmentList().size() != 1)
1064       report_fatal_error("only one .stack_pointer fragment supported");
1065     const MCFragment &Frag = *StackPtr->begin();
1066     if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
1067       report_fatal_error("only data supported in .stack_pointer");
1068     const auto &DataFrag = cast<MCDataFragment>(Frag);
1069     if (!DataFrag.getFixups().empty())
1070       report_fatal_error("fixups not supported in .stack_pointer");
1071     const SmallVectorImpl<char> &Contents = DataFrag.getContents();
1072     if (Contents.size() != 4)
1073       report_fatal_error("only one entry supported in .stack_pointer");
1074     HasStackPointer = true;
1075     StackPointerGlobal = NumGlobalImports + *(const int32_t *)Contents.data();
1076   }
1077 
1078   // Handle regular defined and undefined symbols.
1079   for (const MCSymbol &S : Asm.symbols()) {
1080     // Ignore unnamed temporary symbols, which aren't ever exported, imported,
1081     // or used in relocations.
1082     if (S.isTemporary() && S.getName().empty())
1083       continue;
1084 
1085     // Variable references (weak references) are handled in a second pass
1086     if (S.isVariable())
1087       continue;
1088 
1089     const auto &WS = static_cast<const MCSymbolWasm &>(S);
1090     DEBUG(dbgs() << "MCSymbol: '" << S << "'"
1091                  << " isDefined=" << S.isDefined() << " isExternal="
1092                  << S.isExternal() << " isTemporary=" << S.isTemporary()
1093                  << " isFunction=" << WS.isFunction()
1094                  << " isWeak=" << WS.isWeak()
1095                  << " isVariable=" << WS.isVariable() << "\n");
1096 
1097     if (WS.isWeak())
1098       WeakSymbols.push_back(WS.getName());
1099 
1100     unsigned Index;
1101 
1102     if (WS.isFunction()) {
1103       // Prepare the function's type, if we haven't seen it yet.
1104       WasmFunctionType F;
1105       F.Returns = WS.getReturns();
1106       F.Params = WS.getParams();
1107       auto Pair =
1108           FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
1109       if (Pair.second)
1110         FunctionTypes.push_back(F);
1111 
1112       int32_t Type = Pair.first->second;
1113 
1114       if (WS.isDefined(/*SetUsed=*/false)) {
1115         if (WS.getOffset() != 0)
1116           report_fatal_error(
1117               "function sections must contain one function each");
1118 
1119         if (WS.getSize() == 0)
1120           report_fatal_error(
1121               "function symbols must have a size set with .size");
1122 
1123         // A definition. Take the next available index.
1124         Index = NumFuncImports + Functions.size();
1125 
1126         // Prepare the function.
1127         WasmFunction Func;
1128         Func.Type = Type;
1129         Func.Sym = &WS;
1130         SymbolIndices[&WS] = Index;
1131         Functions.push_back(Func);
1132       } else {
1133         // Should be no such thing as weak undefined symbol
1134         assert(!WS.isVariable());
1135 
1136         // An import; the index was assigned above.
1137         Index = SymbolIndices.find(&WS)->second;
1138       }
1139 
1140       // If needed, prepare the function to be called indirectly.
1141       if (IsAddressTaken.count(&WS)) {
1142         IndirectSymbolIndices[&WS] = TableElems.size();
1143         TableElems.push_back(Index);
1144       }
1145     } else {
1146       if (WS.isTemporary() && !WS.getSize())
1147         continue;
1148 
1149       if (!WS.isDefined(/*SetUsed=*/false))
1150         continue;
1151 
1152       if (WS.getOffset() != 0)
1153         report_fatal_error("data sections must contain one variable each: " +
1154                            WS.getName());
1155       if (!WS.getSize())
1156         report_fatal_error("data symbols must have a size set with .size: " +
1157                            WS.getName());
1158 
1159       int64_t Size = 0;
1160       if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
1161         report_fatal_error(".size expression must be evaluatable");
1162 
1163       auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
1164 
1165       if (uint64_t(Size) != Layout.getSectionFileSize(&DataSection))
1166         report_fatal_error("data sections must contain at most one variable");
1167 
1168       DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
1169       DataAlignment = std::max(DataAlignment, DataSection.getAlignment());
1170 
1171       DataSection.setSectionOffset(DataBytes.size());
1172 
1173       for (const MCFragment &Frag : DataSection) {
1174         if (Frag.hasInstructions())
1175           report_fatal_error("only data supported in data sections");
1176 
1177         if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
1178           if (Align->getValueSize() != 1)
1179             report_fatal_error("only byte values supported for alignment");
1180           // If nops are requested, use zeros, as this is the data section.
1181           uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
1182           uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(),
1183                                                      Align->getAlignment()),
1184                                              DataBytes.size() +
1185                                                  Align->getMaxBytesToEmit());
1186           DataBytes.resize(Size, Value);
1187         } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
1188           DataBytes.insert(DataBytes.end(), Size, Fill->getValue());
1189         } else {
1190           const auto &DataFrag = cast<MCDataFragment>(Frag);
1191           const SmallVectorImpl<char> &Contents = DataFrag.getContents();
1192 
1193           DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
1194         }
1195       }
1196 
1197       // For each global, prepare a corresponding wasm global holding its
1198       // address.  For externals these will also be named exports.
1199       Index = NumGlobalImports + Globals.size();
1200 
1201       WasmGlobal Global;
1202       Global.Type = PtrType;
1203       Global.IsMutable = false;
1204       Global.HasImport = false;
1205       Global.InitialValue = DataSection.getSectionOffset();
1206       Global.ImportIndex = 0;
1207       SymbolIndices[&WS] = Index;
1208       Globals.push_back(Global);
1209     }
1210 
1211     // If the symbol is visible outside this translation unit, export it.
1212     if (WS.isExternal() && WS.isDefined(/*SetUsed=*/false)) {
1213       WasmExport Export;
1214       Export.FieldName = WS.getName();
1215       Export.Index = Index;
1216       if (WS.isFunction())
1217         Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
1218       else
1219         Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1220       Exports.push_back(Export);
1221     }
1222   }
1223 
1224   // Handle weak aliases
1225   for (const MCSymbol &S : Asm.symbols()) {
1226     if (!S.isVariable())
1227       continue;
1228     assert(S.isExternal());
1229     assert(S.isDefined(/*SetUsed=*/false));
1230 
1231     const auto &WS = static_cast<const MCSymbolWasm &>(S);
1232 
1233     // Find the target symbol of this weak alias
1234     const MCExpr *Expr = WS.getVariableValue();
1235     auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr);
1236     const auto *ResolvedSym = cast<MCSymbolWasm>(&Inner->getSymbol());
1237     uint32_t Index = SymbolIndices.find(ResolvedSym)->second;
1238     DEBUG(dbgs() << "Weak alias: '" << WS << "' -> '" << ResolvedSym << "' = " << Index << "\n");
1239     SymbolIndices[&WS] = Index;
1240 
1241     WasmExport Export;
1242     Export.FieldName = WS.getName();
1243     Export.Index = Index;
1244     if (WS.isFunction())
1245       Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
1246     else
1247       Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1248     WeakSymbols.push_back(Export.FieldName);
1249     Exports.push_back(Export);
1250   }
1251 
1252   // Add types for indirect function calls.
1253   for (const WasmRelocationEntry &Fixup : CodeRelocations) {
1254     if (Fixup.Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB)
1255       continue;
1256 
1257     WasmFunctionType F;
1258     F.Returns = Fixup.Symbol->getReturns();
1259     F.Params = Fixup.Symbol->getParams();
1260     auto Pair =
1261         FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
1262     if (Pair.second)
1263       FunctionTypes.push_back(F);
1264 
1265     TypeIndices[Fixup.Symbol] = Pair.first->second;
1266   }
1267 
1268   // Write out the Wasm header.
1269   writeHeader(Asm);
1270 
1271   writeTypeSection(FunctionTypes);
1272   writeImportSection(Imports);
1273   writeFunctionSection(Functions);
1274   writeTableSection(TableElems.size());
1275   writeMemorySection(DataBytes);
1276   writeGlobalSection(Globals);
1277   writeExportSection(Exports);
1278   // TODO: Start Section
1279   writeElemSection(TableElems);
1280   writeCodeSection(Asm, Layout, Functions);
1281   uint64_t DataSectionHeaderSize = writeDataSection(DataBytes);
1282   writeNameSection(Functions, Imports, NumFuncImports);
1283   writeCodeRelocSection();
1284   writeDataRelocSection(DataSectionHeaderSize);
1285   writeLinkingMetaDataSection(DataBytes.size(), DataAlignment, WeakSymbols, HasStackPointer, StackPointerGlobal);
1286 
1287   // TODO: Translate the .comment section to the output.
1288   // TODO: Translate debug sections to the output.
1289 }
1290 
1291 MCObjectWriter *llvm::createWasmObjectWriter(MCWasmObjectTargetWriter *MOTW,
1292                                              raw_pwrite_stream &OS) {
1293   return new WasmObjectWriter(MOTW, OS);
1294 }
1295