1 //===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements Wasm object file writer information.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/BinaryFormat/Wasm.h"
15 #include "llvm/BinaryFormat/WasmTraits.h"
16 #include "llvm/Config/llvm-config.h"
17 #include "llvm/MC/MCAsmBackend.h"
18 #include "llvm/MC/MCAsmLayout.h"
19 #include "llvm/MC/MCAssembler.h"
20 #include "llvm/MC/MCContext.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCFixupKindInfo.h"
23 #include "llvm/MC/MCObjectWriter.h"
24 #include "llvm/MC/MCSectionWasm.h"
25 #include "llvm/MC/MCSymbolWasm.h"
26 #include "llvm/MC/MCValue.h"
27 #include "llvm/MC/MCWasmObjectWriter.h"
28 #include "llvm/Support/Casting.h"
29 #include "llvm/Support/Debug.h"
30 #include "llvm/Support/EndianStream.h"
31 #include "llvm/Support/ErrorHandling.h"
32 #include "llvm/Support/LEB128.h"
33 #include <vector>
34 
35 using namespace llvm;
36 
37 #define DEBUG_TYPE "mc"
38 
39 namespace {
40 
41 // When we create the indirect function table we start at 1, so that there is
42 // and empty slot at 0 and therefore calling a null function pointer will trap.
43 static const uint32_t InitialTableOffset = 1;
44 
45 // For patching purposes, we need to remember where each section starts, both
46 // for patching up the section size field, and for patching up references to
47 // locations within the section.
48 struct SectionBookkeeping {
49   // Where the size of the section is written.
50   uint64_t SizeOffset;
51   // Where the section header ends (without custom section name).
52   uint64_t PayloadOffset;
53   // Where the contents of the section starts.
54   uint64_t ContentsOffset;
55   uint32_t Index;
56 };
57 
58 // A wasm data segment.  A wasm binary contains only a single data section
59 // but that can contain many segments, each with their own virtual location
60 // in memory.  Each MCSection data created by llvm is modeled as its own
61 // wasm data segment.
62 struct WasmDataSegment {
63   MCSectionWasm *Section;
64   StringRef Name;
65   uint32_t InitFlags;
66   uint64_t Offset;
67   uint32_t Alignment;
68   uint32_t LinkingFlags;
69   SmallVector<char, 4> Data;
70 };
71 
72 // A wasm function to be written into the function section.
73 struct WasmFunction {
74   uint32_t SigIndex;
75   const MCSymbolWasm *Sym;
76 };
77 
78 // A wasm global to be written into the global section.
79 struct WasmGlobal {
80   wasm::WasmGlobalType Type;
81   uint64_t InitialValue;
82 };
83 
84 // Information about a single item which is part of a COMDAT.  For each data
85 // segment or function which is in the COMDAT, there is a corresponding
86 // WasmComdatEntry.
87 struct WasmComdatEntry {
88   unsigned Kind;
89   uint32_t Index;
90 };
91 
92 // Information about a single relocation.
93 struct WasmRelocationEntry {
94   uint64_t Offset;                   // Where is the relocation.
95   const MCSymbolWasm *Symbol;        // The symbol to relocate with.
96   int64_t Addend;                    // A value to add to the symbol.
97   unsigned Type;                     // The type of the relocation.
98   const MCSectionWasm *FixupSection; // The section the relocation is targeting.
99 
100   WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
101                       int64_t Addend, unsigned Type,
102                       const MCSectionWasm *FixupSection)
103       : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type),
104         FixupSection(FixupSection) {}
105 
106   bool hasAddend() const { return wasm::relocTypeHasAddend(Type); }
107 
108   void print(raw_ostream &Out) const {
109     Out << wasm::relocTypetoString(Type) << " Off=" << Offset
110         << ", Sym=" << *Symbol << ", Addend=" << Addend
111         << ", FixupSection=" << FixupSection->getName();
112   }
113 
114 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
115   LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
116 #endif
117 };
118 
119 static const uint32_t InvalidIndex = -1;
120 
121 struct WasmCustomSection {
122 
123   StringRef Name;
124   MCSectionWasm *Section;
125 
126   uint32_t OutputContentsOffset = 0;
127   uint32_t OutputIndex = InvalidIndex;
128 
129   WasmCustomSection(StringRef Name, MCSectionWasm *Section)
130       : Name(Name), Section(Section) {}
131 };
132 
133 #if !defined(NDEBUG)
134 raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
135   Rel.print(OS);
136   return OS;
137 }
138 #endif
139 
140 // Write X as an (unsigned) LEB value at offset Offset in Stream, padded
141 // to allow patching.
142 template <int W>
143 void writePatchableLEB(raw_pwrite_stream &Stream, uint64_t X, uint64_t Offset) {
144   uint8_t Buffer[W];
145   unsigned SizeLen = encodeULEB128(X, Buffer, W);
146   assert(SizeLen == W);
147   Stream.pwrite((char *)Buffer, SizeLen, Offset);
148 }
149 
150 // Write X as an signed LEB value at offset Offset in Stream, padded
151 // to allow patching.
152 template <int W>
153 void writePatchableSLEB(raw_pwrite_stream &Stream, int64_t X, uint64_t Offset) {
154   uint8_t Buffer[W];
155   unsigned SizeLen = encodeSLEB128(X, Buffer, W);
156   assert(SizeLen == W);
157   Stream.pwrite((char *)Buffer, SizeLen, Offset);
158 }
159 
160 // Write X as a plain integer value at offset Offset in Stream.
161 static void patchI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
162   uint8_t Buffer[4];
163   support::endian::write32le(Buffer, X);
164   Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
165 }
166 
167 static void patchI64(raw_pwrite_stream &Stream, uint64_t X, uint64_t Offset) {
168   uint8_t Buffer[8];
169   support::endian::write64le(Buffer, X);
170   Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
171 }
172 
173 bool isDwoSection(const MCSection &Sec) {
174   return Sec.getName().endswith(".dwo");
175 }
176 
177 class WasmObjectWriter : public MCObjectWriter {
178   support::endian::Writer *W;
179 
180   /// The target specific Wasm writer instance.
181   std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
182 
183   // Relocations for fixing up references in the code section.
184   std::vector<WasmRelocationEntry> CodeRelocations;
185   // Relocations for fixing up references in the data section.
186   std::vector<WasmRelocationEntry> DataRelocations;
187 
188   // Index values to use for fixing up call_indirect type indices.
189   // Maps function symbols to the index of the type of the function
190   DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices;
191   // Maps function symbols to the table element index space. Used
192   // for TABLE_INDEX relocation types (i.e. address taken functions).
193   DenseMap<const MCSymbolWasm *, uint32_t> TableIndices;
194   // Maps function/global/table symbols to the
195   // function/global/table/tag/section index space.
196   DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices;
197   DenseMap<const MCSymbolWasm *, uint32_t> GOTIndices;
198   // Maps data symbols to the Wasm segment and offset/size with the segment.
199   DenseMap<const MCSymbolWasm *, wasm::WasmDataReference> DataLocations;
200 
201   // Stores output data (index, relocations, content offset) for custom
202   // section.
203   std::vector<WasmCustomSection> CustomSections;
204   std::unique_ptr<WasmCustomSection> ProducersSection;
205   std::unique_ptr<WasmCustomSection> TargetFeaturesSection;
206   // Relocations for fixing up references in the custom sections.
207   DenseMap<const MCSectionWasm *, std::vector<WasmRelocationEntry>>
208       CustomSectionsRelocations;
209 
210   // Map from section to defining function symbol.
211   DenseMap<const MCSection *, const MCSymbol *> SectionFunctions;
212 
213   DenseMap<wasm::WasmSignature, uint32_t> SignatureIndices;
214   SmallVector<wasm::WasmSignature, 4> Signatures;
215   SmallVector<WasmDataSegment, 4> DataSegments;
216   unsigned NumFunctionImports = 0;
217   unsigned NumGlobalImports = 0;
218   unsigned NumTableImports = 0;
219   unsigned NumTagImports = 0;
220   uint32_t SectionCount = 0;
221 
222   enum class DwoMode {
223     AllSections,
224     NonDwoOnly,
225     DwoOnly,
226   };
227   bool IsSplitDwarf = false;
228   raw_pwrite_stream *OS = nullptr;
229   raw_pwrite_stream *DwoOS = nullptr;
230 
231   // TargetObjectWriter wranppers.
232   bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
233   bool isEmscripten() const { return TargetObjectWriter->isEmscripten(); }
234 
235   void startSection(SectionBookkeeping &Section, unsigned SectionId);
236   void startCustomSection(SectionBookkeeping &Section, StringRef Name);
237   void endSection(SectionBookkeeping &Section);
238 
239 public:
240   WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
241                    raw_pwrite_stream &OS_)
242       : TargetObjectWriter(std::move(MOTW)), OS(&OS_) {}
243 
244   WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
245                    raw_pwrite_stream &OS_, raw_pwrite_stream &DwoOS_)
246       : TargetObjectWriter(std::move(MOTW)), IsSplitDwarf(true), OS(&OS_),
247         DwoOS(&DwoOS_) {}
248 
249 private:
250   void reset() override {
251     CodeRelocations.clear();
252     DataRelocations.clear();
253     TypeIndices.clear();
254     WasmIndices.clear();
255     GOTIndices.clear();
256     TableIndices.clear();
257     DataLocations.clear();
258     CustomSections.clear();
259     ProducersSection.reset();
260     TargetFeaturesSection.reset();
261     CustomSectionsRelocations.clear();
262     SignatureIndices.clear();
263     Signatures.clear();
264     DataSegments.clear();
265     SectionFunctions.clear();
266     NumFunctionImports = 0;
267     NumGlobalImports = 0;
268     NumTableImports = 0;
269     MCObjectWriter::reset();
270   }
271 
272   void writeHeader(const MCAssembler &Asm);
273 
274   void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
275                         const MCFragment *Fragment, const MCFixup &Fixup,
276                         MCValue Target, uint64_t &FixedValue) override;
277 
278   void executePostLayoutBinding(MCAssembler &Asm,
279                                 const MCAsmLayout &Layout) override;
280   void prepareImports(SmallVectorImpl<wasm::WasmImport> &Imports,
281                       MCAssembler &Asm, const MCAsmLayout &Layout);
282   uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
283 
284   uint64_t writeOneObject(MCAssembler &Asm, const MCAsmLayout &Layout,
285                           DwoMode Mode);
286 
287   void writeString(const StringRef Str) {
288     encodeULEB128(Str.size(), W->OS);
289     W->OS << Str;
290   }
291 
292   void writeStringWithAlignment(const StringRef Str, unsigned Alignment);
293 
294   void writeI32(int32_t val) {
295     char Buffer[4];
296     support::endian::write32le(Buffer, val);
297     W->OS.write(Buffer, sizeof(Buffer));
298   }
299 
300   void writeI64(int64_t val) {
301     char Buffer[8];
302     support::endian::write64le(Buffer, val);
303     W->OS.write(Buffer, sizeof(Buffer));
304   }
305 
306   void writeValueType(wasm::ValType Ty) { W->OS << static_cast<char>(Ty); }
307 
308   void writeTypeSection(ArrayRef<wasm::WasmSignature> Signatures);
309   void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint64_t DataSize,
310                           uint32_t NumElements);
311   void writeFunctionSection(ArrayRef<WasmFunction> Functions);
312   void writeExportSection(ArrayRef<wasm::WasmExport> Exports);
313   void writeElemSection(const MCSymbolWasm *IndirectFunctionTable,
314                         ArrayRef<uint32_t> TableElems);
315   void writeDataCountSection();
316   uint32_t writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
317                             ArrayRef<WasmFunction> Functions);
318   uint32_t writeDataSection(const MCAsmLayout &Layout);
319   void writeTagSection(ArrayRef<uint32_t> TagTypes);
320   void writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals);
321   void writeTableSection(ArrayRef<wasm::WasmTable> Tables);
322   void writeRelocSection(uint32_t SectionIndex, StringRef Name,
323                          std::vector<WasmRelocationEntry> &Relocations);
324   void writeLinkingMetaDataSection(
325       ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
326       ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
327       const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats);
328   void writeCustomSection(WasmCustomSection &CustomSection,
329                           const MCAssembler &Asm, const MCAsmLayout &Layout);
330   void writeCustomRelocSections();
331 
332   uint64_t getProvisionalValue(const WasmRelocationEntry &RelEntry,
333                                const MCAsmLayout &Layout);
334   void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
335                         uint64_t ContentsOffset, const MCAsmLayout &Layout);
336 
337   uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
338   uint32_t getFunctionType(const MCSymbolWasm &Symbol);
339   uint32_t getTagType(const MCSymbolWasm &Symbol);
340   void registerFunctionType(const MCSymbolWasm &Symbol);
341   void registerTagType(const MCSymbolWasm &Symbol);
342 };
343 
344 } // end anonymous namespace
345 
346 // Write out a section header and a patchable section size field.
347 void WasmObjectWriter::startSection(SectionBookkeeping &Section,
348                                     unsigned SectionId) {
349   LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n");
350   W->OS << char(SectionId);
351 
352   Section.SizeOffset = W->OS.tell();
353 
354   // The section size. We don't know the size yet, so reserve enough space
355   // for any 32-bit value; we'll patch it later.
356   encodeULEB128(0, W->OS, 5);
357 
358   // The position where the section starts, for measuring its size.
359   Section.ContentsOffset = W->OS.tell();
360   Section.PayloadOffset = W->OS.tell();
361   Section.Index = SectionCount++;
362 }
363 
364 // Write a string with extra paddings for trailing alignment
365 // TODO: support alignment at asm and llvm level?
366 void WasmObjectWriter::writeStringWithAlignment(const StringRef Str,
367                                                 unsigned Alignment) {
368 
369   // Calculate the encoded size of str length and add pads based on it and
370   // alignment.
371   raw_null_ostream NullOS;
372   uint64_t StrSizeLength = encodeULEB128(Str.size(), NullOS);
373   uint64_t Offset = W->OS.tell() + StrSizeLength + Str.size();
374   uint64_t Paddings = offsetToAlignment(Offset, Align(Alignment));
375   Offset += Paddings;
376 
377   // LEB128 greater than 5 bytes is invalid
378   assert((StrSizeLength + Paddings) <= 5 && "too long string to align");
379 
380   encodeSLEB128(Str.size(), W->OS, StrSizeLength + Paddings);
381   W->OS << Str;
382 
383   assert(W->OS.tell() == Offset && "invalid padding");
384 }
385 
386 void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
387                                           StringRef Name) {
388   LLVM_DEBUG(dbgs() << "startCustomSection " << Name << "\n");
389   startSection(Section, wasm::WASM_SEC_CUSTOM);
390 
391   // The position where the section header ends, for measuring its size.
392   Section.PayloadOffset = W->OS.tell();
393 
394   // Custom sections in wasm also have a string identifier.
395   if (Name != "__clangast") {
396     writeString(Name);
397   } else {
398     // The on-disk hashtable in clangast needs to be aligned by 4 bytes.
399     writeStringWithAlignment(Name, 4);
400   }
401 
402   // The position where the custom section starts.
403   Section.ContentsOffset = W->OS.tell();
404 }
405 
406 // Now that the section is complete and we know how big it is, patch up the
407 // section size field at the start of the section.
408 void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
409   uint64_t Size = W->OS.tell();
410   // /dev/null doesn't support seek/tell and can report offset of 0.
411   // Simply skip this patching in that case.
412   if (!Size)
413     return;
414 
415   Size -= Section.PayloadOffset;
416   if (uint32_t(Size) != Size)
417     report_fatal_error("section size does not fit in a uint32_t");
418 
419   LLVM_DEBUG(dbgs() << "endSection size=" << Size << "\n");
420 
421   // Write the final section size to the payload_len field, which follows
422   // the section id byte.
423   writePatchableLEB<5>(static_cast<raw_pwrite_stream &>(W->OS), Size,
424                        Section.SizeOffset);
425 }
426 
427 // Emit the Wasm header.
428 void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
429   W->OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
430   W->write<uint32_t>(wasm::WasmVersion);
431 }
432 
433 void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
434                                                 const MCAsmLayout &Layout) {
435   // Some compilation units require the indirect function table to be present
436   // but don't explicitly reference it.  This is the case for call_indirect
437   // without the reference-types feature, and also function bitcasts in all
438   // cases.  In those cases the __indirect_function_table has the
439   // WASM_SYMBOL_NO_STRIP attribute.  Here we make sure this symbol makes it to
440   // the assembler, if needed.
441   if (auto *Sym = Asm.getContext().lookupSymbol("__indirect_function_table")) {
442     const auto *WasmSym = static_cast<const MCSymbolWasm *>(Sym);
443     if (WasmSym->isNoStrip())
444       Asm.registerSymbol(*Sym);
445   }
446 
447   // Build a map of sections to the function that defines them, for use
448   // in recordRelocation.
449   for (const MCSymbol &S : Asm.symbols()) {
450     const auto &WS = static_cast<const MCSymbolWasm &>(S);
451     if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {
452       const auto &Sec = static_cast<const MCSectionWasm &>(S.getSection());
453       auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));
454       if (!Pair.second)
455         report_fatal_error("section already has a defining function: " +
456                            Sec.getName());
457     }
458   }
459 }
460 
461 void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
462                                         const MCAsmLayout &Layout,
463                                         const MCFragment *Fragment,
464                                         const MCFixup &Fixup, MCValue Target,
465                                         uint64_t &FixedValue) {
466   // The WebAssembly backend should never generate FKF_IsPCRel fixups
467   assert(!(Asm.getBackend().getFixupKindInfo(Fixup.getKind()).Flags &
468            MCFixupKindInfo::FKF_IsPCRel));
469 
470   const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
471   uint64_t C = Target.getConstant();
472   uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
473   MCContext &Ctx = Asm.getContext();
474   bool IsLocRel = false;
475 
476   if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
477 
478     const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
479 
480     if (FixupSection.getKind().isText()) {
481       Ctx.reportError(Fixup.getLoc(),
482                       Twine("symbol '") + SymB.getName() +
483                           "' unsupported subtraction expression used in "
484                           "relocation in code section.");
485       return;
486     }
487 
488     if (SymB.isUndefined()) {
489       Ctx.reportError(Fixup.getLoc(),
490                       Twine("symbol '") + SymB.getName() +
491                           "' can not be undefined in a subtraction expression");
492       return;
493     }
494     const MCSection &SecB = SymB.getSection();
495     if (&SecB != &FixupSection) {
496       Ctx.reportError(Fixup.getLoc(),
497                       Twine("symbol '") + SymB.getName() +
498                           "' can not be placed in a different section");
499       return;
500     }
501     IsLocRel = true;
502     C += FixupOffset - Layout.getSymbolOffset(SymB);
503   }
504 
505   // We either rejected the fixup or folded B into C at this point.
506   const MCSymbolRefExpr *RefA = Target.getSymA();
507   const auto *SymA = cast<MCSymbolWasm>(&RefA->getSymbol());
508 
509   // The .init_array isn't translated as data, so don't do relocations in it.
510   if (FixupSection.getName().startswith(".init_array")) {
511     SymA->setUsedInInitArray();
512     return;
513   }
514 
515   if (SymA->isVariable()) {
516     const MCExpr *Expr = SymA->getVariableValue();
517     if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr))
518       if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
519         llvm_unreachable("weakref used in reloc not yet implemented");
520   }
521 
522   // Put any constant offset in an addend. Offsets can be negative, and
523   // LLVM expects wrapping, in contrast to wasm's immediates which can't
524   // be negative and don't wrap.
525   FixedValue = 0;
526 
527   unsigned Type =
528       TargetObjectWriter->getRelocType(Target, Fixup, FixupSection, IsLocRel);
529 
530   // Absolute offset within a section or a function.
531   // Currently only supported for for metadata sections.
532   // See: test/MC/WebAssembly/blockaddress.ll
533   if ((Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
534        Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
535        Type == wasm::R_WASM_SECTION_OFFSET_I32) &&
536       SymA->isDefined()) {
537     // SymA can be a temp data symbol that represents a function (in which case
538     // it needs to be replaced by the section symbol), [XXX and it apparently
539     // later gets changed again to a func symbol?] or it can be a real
540     // function symbol, in which case it can be left as-is.
541 
542     if (!FixupSection.getKind().isMetadata())
543       report_fatal_error("relocations for function or section offsets are "
544                          "only supported in metadata sections");
545 
546     const MCSymbol *SectionSymbol = nullptr;
547     const MCSection &SecA = SymA->getSection();
548     if (SecA.getKind().isText()) {
549       auto SecSymIt = SectionFunctions.find(&SecA);
550       if (SecSymIt == SectionFunctions.end())
551         report_fatal_error("section doesn\'t have defining symbol");
552       SectionSymbol = SecSymIt->second;
553     } else {
554       SectionSymbol = SecA.getBeginSymbol();
555     }
556     if (!SectionSymbol)
557       report_fatal_error("section symbol is required for relocation");
558 
559     C += Layout.getSymbolOffset(*SymA);
560     SymA = cast<MCSymbolWasm>(SectionSymbol);
561   }
562 
563   if (Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
564       Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64 ||
565       Type == wasm::R_WASM_TABLE_INDEX_SLEB ||
566       Type == wasm::R_WASM_TABLE_INDEX_SLEB64 ||
567       Type == wasm::R_WASM_TABLE_INDEX_I32 ||
568       Type == wasm::R_WASM_TABLE_INDEX_I64) {
569     // TABLE_INDEX relocs implicitly use the default indirect function table.
570     // We require the function table to have already been defined.
571     auto TableName = "__indirect_function_table";
572     MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(TableName));
573     if (!Sym) {
574       report_fatal_error("missing indirect function table symbol");
575     } else {
576       if (!Sym->isFunctionTable())
577         report_fatal_error("__indirect_function_table symbol has wrong type");
578       // Ensure that __indirect_function_table reaches the output.
579       Sym->setNoStrip();
580       Asm.registerSymbol(*Sym);
581     }
582   }
583 
584   // Relocation other than R_WASM_TYPE_INDEX_LEB are required to be
585   // against a named symbol.
586   if (Type != wasm::R_WASM_TYPE_INDEX_LEB) {
587     if (SymA->getName().empty())
588       report_fatal_error("relocations against un-named temporaries are not yet "
589                          "supported by wasm");
590 
591     SymA->setUsedInReloc();
592   }
593 
594   switch (RefA->getKind()) {
595   case MCSymbolRefExpr::VK_GOT:
596   case MCSymbolRefExpr::VK_WASM_GOT_TLS:
597     SymA->setUsedInGOT();
598     break;
599   default:
600     break;
601   }
602 
603   WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
604   LLVM_DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
605 
606   if (FixupSection.isWasmData()) {
607     DataRelocations.push_back(Rec);
608   } else if (FixupSection.getKind().isText()) {
609     CodeRelocations.push_back(Rec);
610   } else if (FixupSection.getKind().isMetadata()) {
611     CustomSectionsRelocations[&FixupSection].push_back(Rec);
612   } else {
613     llvm_unreachable("unexpected section type");
614   }
615 }
616 
617 // Compute a value to write into the code at the location covered
618 // by RelEntry. This value isn't used by the static linker; it just serves
619 // to make the object format more readable and more likely to be directly
620 // useable.
621 uint64_t
622 WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry,
623                                       const MCAsmLayout &Layout) {
624   if ((RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB ||
625        RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_I32) &&
626       !RelEntry.Symbol->isGlobal()) {
627     assert(GOTIndices.count(RelEntry.Symbol) > 0 && "symbol not found in GOT index space");
628     return GOTIndices[RelEntry.Symbol];
629   }
630 
631   switch (RelEntry.Type) {
632   case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
633   case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
634   case wasm::R_WASM_TABLE_INDEX_SLEB:
635   case wasm::R_WASM_TABLE_INDEX_SLEB64:
636   case wasm::R_WASM_TABLE_INDEX_I32:
637   case wasm::R_WASM_TABLE_INDEX_I64: {
638     // Provisional value is table address of the resolved symbol itself
639     const MCSymbolWasm *Base =
640         cast<MCSymbolWasm>(Layout.getBaseSymbol(*RelEntry.Symbol));
641     assert(Base->isFunction());
642     if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
643         RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
644       return TableIndices[Base] - InitialTableOffset;
645     else
646       return TableIndices[Base];
647   }
648   case wasm::R_WASM_TYPE_INDEX_LEB:
649     // Provisional value is same as the index
650     return getRelocationIndexValue(RelEntry);
651   case wasm::R_WASM_FUNCTION_INDEX_LEB:
652   case wasm::R_WASM_GLOBAL_INDEX_LEB:
653   case wasm::R_WASM_GLOBAL_INDEX_I32:
654   case wasm::R_WASM_TAG_INDEX_LEB:
655   case wasm::R_WASM_TABLE_NUMBER_LEB:
656     // Provisional value is function/global/tag Wasm index
657     assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space");
658     return WasmIndices[RelEntry.Symbol];
659   case wasm::R_WASM_FUNCTION_OFFSET_I32:
660   case wasm::R_WASM_FUNCTION_OFFSET_I64:
661   case wasm::R_WASM_SECTION_OFFSET_I32: {
662     if (!RelEntry.Symbol->isDefined())
663       return 0;
664     const auto &Section =
665         static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());
666     return Section.getSectionOffset() + RelEntry.Addend;
667   }
668   case wasm::R_WASM_MEMORY_ADDR_LEB:
669   case wasm::R_WASM_MEMORY_ADDR_LEB64:
670   case wasm::R_WASM_MEMORY_ADDR_SLEB:
671   case wasm::R_WASM_MEMORY_ADDR_SLEB64:
672   case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
673   case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
674   case wasm::R_WASM_MEMORY_ADDR_I32:
675   case wasm::R_WASM_MEMORY_ADDR_I64:
676   case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
677   case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
678   case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: {
679     // Provisional value is address of the global plus the offset
680     // For undefined symbols, use zero
681     if (!RelEntry.Symbol->isDefined())
682       return 0;
683     const wasm::WasmDataReference &SymRef = DataLocations[RelEntry.Symbol];
684     const WasmDataSegment &Segment = DataSegments[SymRef.Segment];
685     // Ignore overflow. LLVM allows address arithmetic to silently wrap.
686     return Segment.Offset + SymRef.Offset + RelEntry.Addend;
687   }
688   default:
689     llvm_unreachable("invalid relocation type");
690   }
691 }
692 
693 static void addData(SmallVectorImpl<char> &DataBytes,
694                     MCSectionWasm &DataSection) {
695   LLVM_DEBUG(errs() << "addData: " << DataSection.getName() << "\n");
696 
697   DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
698 
699   for (const MCFragment &Frag : DataSection) {
700     if (Frag.hasInstructions())
701       report_fatal_error("only data supported in data sections");
702 
703     if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
704       if (Align->getValueSize() != 1)
705         report_fatal_error("only byte values supported for alignment");
706       // If nops are requested, use zeros, as this is the data section.
707       uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
708       uint64_t Size =
709           std::min<uint64_t>(alignTo(DataBytes.size(), Align->getAlignment()),
710                              DataBytes.size() + Align->getMaxBytesToEmit());
711       DataBytes.resize(Size, Value);
712     } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
713       int64_t NumValues;
714       if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
715         llvm_unreachable("The fill should be an assembler constant");
716       DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues,
717                        Fill->getValue());
718     } else if (auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) {
719       const SmallVectorImpl<char> &Contents = LEB->getContents();
720       llvm::append_range(DataBytes, Contents);
721     } else {
722       const auto &DataFrag = cast<MCDataFragment>(Frag);
723       const SmallVectorImpl<char> &Contents = DataFrag.getContents();
724       llvm::append_range(DataBytes, Contents);
725     }
726   }
727 
728   LLVM_DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
729 }
730 
731 uint32_t
732 WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {
733   if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {
734     if (!TypeIndices.count(RelEntry.Symbol))
735       report_fatal_error("symbol not found in type index space: " +
736                          RelEntry.Symbol->getName());
737     return TypeIndices[RelEntry.Symbol];
738   }
739 
740   return RelEntry.Symbol->getIndex();
741 }
742 
743 // Apply the portions of the relocation records that we can handle ourselves
744 // directly.
745 void WasmObjectWriter::applyRelocations(
746     ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset,
747     const MCAsmLayout &Layout) {
748   auto &Stream = static_cast<raw_pwrite_stream &>(W->OS);
749   for (const WasmRelocationEntry &RelEntry : Relocations) {
750     uint64_t Offset = ContentsOffset +
751                       RelEntry.FixupSection->getSectionOffset() +
752                       RelEntry.Offset;
753 
754     LLVM_DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
755     auto Value = getProvisionalValue(RelEntry, Layout);
756 
757     switch (RelEntry.Type) {
758     case wasm::R_WASM_FUNCTION_INDEX_LEB:
759     case wasm::R_WASM_TYPE_INDEX_LEB:
760     case wasm::R_WASM_GLOBAL_INDEX_LEB:
761     case wasm::R_WASM_MEMORY_ADDR_LEB:
762     case wasm::R_WASM_TAG_INDEX_LEB:
763     case wasm::R_WASM_TABLE_NUMBER_LEB:
764       writePatchableLEB<5>(Stream, Value, Offset);
765       break;
766     case wasm::R_WASM_MEMORY_ADDR_LEB64:
767       writePatchableLEB<10>(Stream, Value, Offset);
768       break;
769     case wasm::R_WASM_TABLE_INDEX_I32:
770     case wasm::R_WASM_MEMORY_ADDR_I32:
771     case wasm::R_WASM_FUNCTION_OFFSET_I32:
772     case wasm::R_WASM_SECTION_OFFSET_I32:
773     case wasm::R_WASM_GLOBAL_INDEX_I32:
774     case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
775       patchI32(Stream, Value, Offset);
776       break;
777     case wasm::R_WASM_TABLE_INDEX_I64:
778     case wasm::R_WASM_MEMORY_ADDR_I64:
779     case wasm::R_WASM_FUNCTION_OFFSET_I64:
780       patchI64(Stream, Value, Offset);
781       break;
782     case wasm::R_WASM_TABLE_INDEX_SLEB:
783     case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
784     case wasm::R_WASM_MEMORY_ADDR_SLEB:
785     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
786     case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
787       writePatchableSLEB<5>(Stream, Value, Offset);
788       break;
789     case wasm::R_WASM_TABLE_INDEX_SLEB64:
790     case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
791     case wasm::R_WASM_MEMORY_ADDR_SLEB64:
792     case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
793     case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
794       writePatchableSLEB<10>(Stream, Value, Offset);
795       break;
796     default:
797       llvm_unreachable("invalid relocation type");
798     }
799   }
800 }
801 
802 void WasmObjectWriter::writeTypeSection(
803     ArrayRef<wasm::WasmSignature> Signatures) {
804   if (Signatures.empty())
805     return;
806 
807   SectionBookkeeping Section;
808   startSection(Section, wasm::WASM_SEC_TYPE);
809 
810   encodeULEB128(Signatures.size(), W->OS);
811 
812   for (const wasm::WasmSignature &Sig : Signatures) {
813     W->OS << char(wasm::WASM_TYPE_FUNC);
814     encodeULEB128(Sig.Params.size(), W->OS);
815     for (wasm::ValType Ty : Sig.Params)
816       writeValueType(Ty);
817     encodeULEB128(Sig.Returns.size(), W->OS);
818     for (wasm::ValType Ty : Sig.Returns)
819       writeValueType(Ty);
820   }
821 
822   endSection(Section);
823 }
824 
825 void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
826                                           uint64_t DataSize,
827                                           uint32_t NumElements) {
828   if (Imports.empty())
829     return;
830 
831   uint64_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
832 
833   SectionBookkeeping Section;
834   startSection(Section, wasm::WASM_SEC_IMPORT);
835 
836   encodeULEB128(Imports.size(), W->OS);
837   for (const wasm::WasmImport &Import : Imports) {
838     writeString(Import.Module);
839     writeString(Import.Field);
840     W->OS << char(Import.Kind);
841 
842     switch (Import.Kind) {
843     case wasm::WASM_EXTERNAL_FUNCTION:
844       encodeULEB128(Import.SigIndex, W->OS);
845       break;
846     case wasm::WASM_EXTERNAL_GLOBAL:
847       W->OS << char(Import.Global.Type);
848       W->OS << char(Import.Global.Mutable ? 1 : 0);
849       break;
850     case wasm::WASM_EXTERNAL_MEMORY:
851       encodeULEB128(Import.Memory.Flags, W->OS);
852       encodeULEB128(NumPages, W->OS); // initial
853       break;
854     case wasm::WASM_EXTERNAL_TABLE:
855       W->OS << char(Import.Table.ElemType);
856       encodeULEB128(0, W->OS);           // flags
857       encodeULEB128(NumElements, W->OS); // initial
858       break;
859     case wasm::WASM_EXTERNAL_TAG:
860       W->OS << char(0); // Reserved 'attribute' field
861       encodeULEB128(Import.SigIndex, W->OS);
862       break;
863     default:
864       llvm_unreachable("unsupported import kind");
865     }
866   }
867 
868   endSection(Section);
869 }
870 
871 void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
872   if (Functions.empty())
873     return;
874 
875   SectionBookkeeping Section;
876   startSection(Section, wasm::WASM_SEC_FUNCTION);
877 
878   encodeULEB128(Functions.size(), W->OS);
879   for (const WasmFunction &Func : Functions)
880     encodeULEB128(Func.SigIndex, W->OS);
881 
882   endSection(Section);
883 }
884 
885 void WasmObjectWriter::writeTagSection(ArrayRef<uint32_t> TagTypes) {
886   if (TagTypes.empty())
887     return;
888 
889   SectionBookkeeping Section;
890   startSection(Section, wasm::WASM_SEC_TAG);
891 
892   encodeULEB128(TagTypes.size(), W->OS);
893   for (uint32_t Index : TagTypes) {
894     W->OS << char(0); // Reserved 'attribute' field
895     encodeULEB128(Index, W->OS);
896   }
897 
898   endSection(Section);
899 }
900 
901 void WasmObjectWriter::writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals) {
902   if (Globals.empty())
903     return;
904 
905   SectionBookkeeping Section;
906   startSection(Section, wasm::WASM_SEC_GLOBAL);
907 
908   encodeULEB128(Globals.size(), W->OS);
909   for (const wasm::WasmGlobal &Global : Globals) {
910     encodeULEB128(Global.Type.Type, W->OS);
911     W->OS << char(Global.Type.Mutable);
912     W->OS << char(Global.InitExpr.Opcode);
913     switch (Global.Type.Type) {
914     case wasm::WASM_TYPE_I32:
915       encodeSLEB128(0, W->OS);
916       break;
917     case wasm::WASM_TYPE_I64:
918       encodeSLEB128(0, W->OS);
919       break;
920     case wasm::WASM_TYPE_F32:
921       writeI32(0);
922       break;
923     case wasm::WASM_TYPE_F64:
924       writeI64(0);
925       break;
926     case wasm::WASM_TYPE_EXTERNREF:
927       writeValueType(wasm::ValType::EXTERNREF);
928       break;
929     default:
930       llvm_unreachable("unexpected type");
931     }
932     W->OS << char(wasm::WASM_OPCODE_END);
933   }
934 
935   endSection(Section);
936 }
937 
938 void WasmObjectWriter::writeTableSection(ArrayRef<wasm::WasmTable> Tables) {
939   if (Tables.empty())
940     return;
941 
942   SectionBookkeeping Section;
943   startSection(Section, wasm::WASM_SEC_TABLE);
944 
945   encodeULEB128(Tables.size(), W->OS);
946   for (const wasm::WasmTable &Table : Tables) {
947     encodeULEB128(Table.Type.ElemType, W->OS);
948     encodeULEB128(Table.Type.Limits.Flags, W->OS);
949     encodeULEB128(Table.Type.Limits.Minimum, W->OS);
950     if (Table.Type.Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
951       encodeULEB128(Table.Type.Limits.Maximum, W->OS);
952   }
953   endSection(Section);
954 }
955 
956 void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) {
957   if (Exports.empty())
958     return;
959 
960   SectionBookkeeping Section;
961   startSection(Section, wasm::WASM_SEC_EXPORT);
962 
963   encodeULEB128(Exports.size(), W->OS);
964   for (const wasm::WasmExport &Export : Exports) {
965     writeString(Export.Name);
966     W->OS << char(Export.Kind);
967     encodeULEB128(Export.Index, W->OS);
968   }
969 
970   endSection(Section);
971 }
972 
973 void WasmObjectWriter::writeElemSection(
974     const MCSymbolWasm *IndirectFunctionTable, ArrayRef<uint32_t> TableElems) {
975   if (TableElems.empty())
976     return;
977 
978   assert(IndirectFunctionTable);
979 
980   SectionBookkeeping Section;
981   startSection(Section, wasm::WASM_SEC_ELEM);
982 
983   encodeULEB128(1, W->OS); // number of "segments"
984 
985   assert(WasmIndices.count(IndirectFunctionTable));
986   uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second;
987   uint32_t Flags = 0;
988   if (TableNumber)
989     Flags |= wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER;
990   encodeULEB128(Flags, W->OS);
991   if (Flags & wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER)
992     encodeULEB128(TableNumber, W->OS); // the table number
993 
994   // init expr for starting offset
995   W->OS << char(wasm::WASM_OPCODE_I32_CONST);
996   encodeSLEB128(InitialTableOffset, W->OS);
997   W->OS << char(wasm::WASM_OPCODE_END);
998 
999   if (Flags & wasm::WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND) {
1000     // We only write active function table initializers, for which the elem kind
1001     // is specified to be written as 0x00 and interpreted to mean "funcref".
1002     const uint8_t ElemKind = 0;
1003     W->OS << ElemKind;
1004   }
1005 
1006   encodeULEB128(TableElems.size(), W->OS);
1007   for (uint32_t Elem : TableElems)
1008     encodeULEB128(Elem, W->OS);
1009 
1010   endSection(Section);
1011 }
1012 
1013 void WasmObjectWriter::writeDataCountSection() {
1014   if (DataSegments.empty())
1015     return;
1016 
1017   SectionBookkeeping Section;
1018   startSection(Section, wasm::WASM_SEC_DATACOUNT);
1019   encodeULEB128(DataSegments.size(), W->OS);
1020   endSection(Section);
1021 }
1022 
1023 uint32_t WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
1024                                             const MCAsmLayout &Layout,
1025                                             ArrayRef<WasmFunction> Functions) {
1026   if (Functions.empty())
1027     return 0;
1028 
1029   SectionBookkeeping Section;
1030   startSection(Section, wasm::WASM_SEC_CODE);
1031 
1032   encodeULEB128(Functions.size(), W->OS);
1033 
1034   for (const WasmFunction &Func : Functions) {
1035     auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection());
1036 
1037     int64_t Size = 0;
1038     if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
1039       report_fatal_error(".size expression must be evaluatable");
1040 
1041     encodeULEB128(Size, W->OS);
1042     FuncSection.setSectionOffset(W->OS.tell() - Section.ContentsOffset);
1043     Asm.writeSectionData(W->OS, &FuncSection, Layout);
1044   }
1045 
1046   // Apply fixups.
1047   applyRelocations(CodeRelocations, Section.ContentsOffset, Layout);
1048 
1049   endSection(Section);
1050   return Section.Index;
1051 }
1052 
1053 uint32_t WasmObjectWriter::writeDataSection(const MCAsmLayout &Layout) {
1054   if (DataSegments.empty())
1055     return 0;
1056 
1057   SectionBookkeeping Section;
1058   startSection(Section, wasm::WASM_SEC_DATA);
1059 
1060   encodeULEB128(DataSegments.size(), W->OS); // count
1061 
1062   for (const WasmDataSegment &Segment : DataSegments) {
1063     encodeULEB128(Segment.InitFlags, W->OS); // flags
1064     if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1065       encodeULEB128(0, W->OS); // memory index
1066     if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1067       W->OS << char(is64Bit() ? wasm::WASM_OPCODE_I64_CONST
1068                               : wasm::WASM_OPCODE_I32_CONST);
1069       encodeSLEB128(Segment.Offset, W->OS); // offset
1070       W->OS << char(wasm::WASM_OPCODE_END);
1071     }
1072     encodeULEB128(Segment.Data.size(), W->OS); // size
1073     Segment.Section->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
1074     W->OS << Segment.Data; // data
1075   }
1076 
1077   // Apply fixups.
1078   applyRelocations(DataRelocations, Section.ContentsOffset, Layout);
1079 
1080   endSection(Section);
1081   return Section.Index;
1082 }
1083 
1084 void WasmObjectWriter::writeRelocSection(
1085     uint32_t SectionIndex, StringRef Name,
1086     std::vector<WasmRelocationEntry> &Relocs) {
1087   // See: https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md
1088   // for descriptions of the reloc sections.
1089 
1090   if (Relocs.empty())
1091     return;
1092 
1093   // First, ensure the relocations are sorted in offset order.  In general they
1094   // should already be sorted since `recordRelocation` is called in offset
1095   // order, but for the code section we combine many MC sections into single
1096   // wasm section, and this order is determined by the order of Asm.Symbols()
1097   // not the sections order.
1098   llvm::stable_sort(
1099       Relocs, [](const WasmRelocationEntry &A, const WasmRelocationEntry &B) {
1100         return (A.Offset + A.FixupSection->getSectionOffset()) <
1101                (B.Offset + B.FixupSection->getSectionOffset());
1102       });
1103 
1104   SectionBookkeeping Section;
1105   startCustomSection(Section, std::string("reloc.") + Name.str());
1106 
1107   encodeULEB128(SectionIndex, W->OS);
1108   encodeULEB128(Relocs.size(), W->OS);
1109   for (const WasmRelocationEntry &RelEntry : Relocs) {
1110     uint64_t Offset =
1111         RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
1112     uint32_t Index = getRelocationIndexValue(RelEntry);
1113 
1114     W->OS << char(RelEntry.Type);
1115     encodeULEB128(Offset, W->OS);
1116     encodeULEB128(Index, W->OS);
1117     if (RelEntry.hasAddend())
1118       encodeSLEB128(RelEntry.Addend, W->OS);
1119   }
1120 
1121   endSection(Section);
1122 }
1123 
1124 void WasmObjectWriter::writeCustomRelocSections() {
1125   for (const auto &Sec : CustomSections) {
1126     auto &Relocations = CustomSectionsRelocations[Sec.Section];
1127     writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1128   }
1129 }
1130 
1131 void WasmObjectWriter::writeLinkingMetaDataSection(
1132     ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
1133     ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1134     const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) {
1135   SectionBookkeeping Section;
1136   startCustomSection(Section, "linking");
1137   encodeULEB128(wasm::WasmMetadataVersion, W->OS);
1138 
1139   SectionBookkeeping SubSection;
1140   if (SymbolInfos.size() != 0) {
1141     startSection(SubSection, wasm::WASM_SYMBOL_TABLE);
1142     encodeULEB128(SymbolInfos.size(), W->OS);
1143     for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) {
1144       encodeULEB128(Sym.Kind, W->OS);
1145       encodeULEB128(Sym.Flags, W->OS);
1146       switch (Sym.Kind) {
1147       case wasm::WASM_SYMBOL_TYPE_FUNCTION:
1148       case wasm::WASM_SYMBOL_TYPE_GLOBAL:
1149       case wasm::WASM_SYMBOL_TYPE_TAG:
1150       case wasm::WASM_SYMBOL_TYPE_TABLE:
1151         encodeULEB128(Sym.ElementIndex, W->OS);
1152         if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
1153             (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
1154           writeString(Sym.Name);
1155         break;
1156       case wasm::WASM_SYMBOL_TYPE_DATA:
1157         writeString(Sym.Name);
1158         if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
1159           encodeULEB128(Sym.DataRef.Segment, W->OS);
1160           encodeULEB128(Sym.DataRef.Offset, W->OS);
1161           encodeULEB128(Sym.DataRef.Size, W->OS);
1162         }
1163         break;
1164       case wasm::WASM_SYMBOL_TYPE_SECTION: {
1165         const uint32_t SectionIndex =
1166             CustomSections[Sym.ElementIndex].OutputIndex;
1167         encodeULEB128(SectionIndex, W->OS);
1168         break;
1169       }
1170       default:
1171         llvm_unreachable("unexpected kind");
1172       }
1173     }
1174     endSection(SubSection);
1175   }
1176 
1177   if (DataSegments.size()) {
1178     startSection(SubSection, wasm::WASM_SEGMENT_INFO);
1179     encodeULEB128(DataSegments.size(), W->OS);
1180     for (const WasmDataSegment &Segment : DataSegments) {
1181       writeString(Segment.Name);
1182       encodeULEB128(Segment.Alignment, W->OS);
1183       encodeULEB128(Segment.LinkingFlags, W->OS);
1184     }
1185     endSection(SubSection);
1186   }
1187 
1188   if (!InitFuncs.empty()) {
1189     startSection(SubSection, wasm::WASM_INIT_FUNCS);
1190     encodeULEB128(InitFuncs.size(), W->OS);
1191     for (auto &StartFunc : InitFuncs) {
1192       encodeULEB128(StartFunc.first, W->OS);  // priority
1193       encodeULEB128(StartFunc.second, W->OS); // function index
1194     }
1195     endSection(SubSection);
1196   }
1197 
1198   if (Comdats.size()) {
1199     startSection(SubSection, wasm::WASM_COMDAT_INFO);
1200     encodeULEB128(Comdats.size(), W->OS);
1201     for (const auto &C : Comdats) {
1202       writeString(C.first);
1203       encodeULEB128(0, W->OS); // flags for future use
1204       encodeULEB128(C.second.size(), W->OS);
1205       for (const WasmComdatEntry &Entry : C.second) {
1206         encodeULEB128(Entry.Kind, W->OS);
1207         encodeULEB128(Entry.Index, W->OS);
1208       }
1209     }
1210     endSection(SubSection);
1211   }
1212 
1213   endSection(Section);
1214 }
1215 
1216 void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1217                                           const MCAssembler &Asm,
1218                                           const MCAsmLayout &Layout) {
1219   SectionBookkeeping Section;
1220   auto *Sec = CustomSection.Section;
1221   startCustomSection(Section, CustomSection.Name);
1222 
1223   Sec->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
1224   Asm.writeSectionData(W->OS, Sec, Layout);
1225 
1226   CustomSection.OutputContentsOffset = Section.ContentsOffset;
1227   CustomSection.OutputIndex = Section.Index;
1228 
1229   endSection(Section);
1230 
1231   // Apply fixups.
1232   auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1233   applyRelocations(Relocations, CustomSection.OutputContentsOffset, Layout);
1234 }
1235 
1236 uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {
1237   assert(Symbol.isFunction());
1238   assert(TypeIndices.count(&Symbol));
1239   return TypeIndices[&Symbol];
1240 }
1241 
1242 uint32_t WasmObjectWriter::getTagType(const MCSymbolWasm &Symbol) {
1243   assert(Symbol.isTag());
1244   assert(TypeIndices.count(&Symbol));
1245   return TypeIndices[&Symbol];
1246 }
1247 
1248 void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
1249   assert(Symbol.isFunction());
1250 
1251   wasm::WasmSignature S;
1252 
1253   if (auto *Sig = Symbol.getSignature()) {
1254     S.Returns = Sig->Returns;
1255     S.Params = Sig->Params;
1256   }
1257 
1258   auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
1259   if (Pair.second)
1260     Signatures.push_back(S);
1261   TypeIndices[&Symbol] = Pair.first->second;
1262 
1263   LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol
1264                     << " new:" << Pair.second << "\n");
1265   LLVM_DEBUG(dbgs() << "  -> type index: " << Pair.first->second << "\n");
1266 }
1267 
1268 void WasmObjectWriter::registerTagType(const MCSymbolWasm &Symbol) {
1269   assert(Symbol.isTag());
1270 
1271   // TODO Currently we don't generate imported exceptions, but if we do, we
1272   // should have a way of infering types of imported exceptions.
1273   wasm::WasmSignature S;
1274   if (auto *Sig = Symbol.getSignature()) {
1275     S.Returns = Sig->Returns;
1276     S.Params = Sig->Params;
1277   }
1278 
1279   auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
1280   if (Pair.second)
1281     Signatures.push_back(S);
1282   TypeIndices[&Symbol] = Pair.first->second;
1283 
1284   LLVM_DEBUG(dbgs() << "registerTagType: " << Symbol << " new:" << Pair.second
1285                     << "\n");
1286   LLVM_DEBUG(dbgs() << "  -> type index: " << Pair.first->second << "\n");
1287 }
1288 
1289 static bool isInSymtab(const MCSymbolWasm &Sym) {
1290   if (Sym.isUsedInReloc() || Sym.isUsedInInitArray())
1291     return true;
1292 
1293   if (Sym.isComdat() && !Sym.isDefined())
1294     return false;
1295 
1296   if (Sym.isTemporary())
1297     return false;
1298 
1299   if (Sym.isSection())
1300     return false;
1301 
1302   if (Sym.omitFromLinkingSection())
1303     return false;
1304 
1305   return true;
1306 }
1307 
1308 void WasmObjectWriter::prepareImports(
1309     SmallVectorImpl<wasm::WasmImport> &Imports, MCAssembler &Asm,
1310     const MCAsmLayout &Layout) {
1311   // For now, always emit the memory import, since loads and stores are not
1312   // valid without it. In the future, we could perhaps be more clever and omit
1313   // it if there are no loads or stores.
1314   wasm::WasmImport MemImport;
1315   MemImport.Module = "env";
1316   MemImport.Field = "__linear_memory";
1317   MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
1318   MemImport.Memory.Flags = is64Bit() ? wasm::WASM_LIMITS_FLAG_IS_64
1319                                      : wasm::WASM_LIMITS_FLAG_NONE;
1320   Imports.push_back(MemImport);
1321 
1322   // Populate SignatureIndices, and Imports and WasmIndices for undefined
1323   // symbols.  This must be done before populating WasmIndices for defined
1324   // symbols.
1325   for (const MCSymbol &S : Asm.symbols()) {
1326     const auto &WS = static_cast<const MCSymbolWasm &>(S);
1327 
1328     // Register types for all functions, including those with private linkage
1329     // (because wasm always needs a type signature).
1330     if (WS.isFunction()) {
1331       const auto *BS = Layout.getBaseSymbol(S);
1332       if (!BS)
1333         report_fatal_error(Twine(S.getName()) +
1334                            ": absolute addressing not supported!");
1335       registerFunctionType(*cast<MCSymbolWasm>(BS));
1336     }
1337 
1338     if (WS.isTag())
1339       registerTagType(WS);
1340 
1341     if (WS.isTemporary())
1342       continue;
1343 
1344     // If the symbol is not defined in this translation unit, import it.
1345     if (!WS.isDefined() && !WS.isComdat()) {
1346       if (WS.isFunction()) {
1347         wasm::WasmImport Import;
1348         Import.Module = WS.getImportModule();
1349         Import.Field = WS.getImportName();
1350         Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
1351         Import.SigIndex = getFunctionType(WS);
1352         Imports.push_back(Import);
1353         assert(WasmIndices.count(&WS) == 0);
1354         WasmIndices[&WS] = NumFunctionImports++;
1355       } else if (WS.isGlobal()) {
1356         if (WS.isWeak())
1357           report_fatal_error("undefined global symbol cannot be weak");
1358 
1359         wasm::WasmImport Import;
1360         Import.Field = WS.getImportName();
1361         Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1362         Import.Module = WS.getImportModule();
1363         Import.Global = WS.getGlobalType();
1364         Imports.push_back(Import);
1365         assert(WasmIndices.count(&WS) == 0);
1366         WasmIndices[&WS] = NumGlobalImports++;
1367       } else if (WS.isTag()) {
1368         if (WS.isWeak())
1369           report_fatal_error("undefined tag symbol cannot be weak");
1370 
1371         wasm::WasmImport Import;
1372         Import.Module = WS.getImportModule();
1373         Import.Field = WS.getImportName();
1374         Import.Kind = wasm::WASM_EXTERNAL_TAG;
1375         Import.SigIndex = getTagType(WS);
1376         Imports.push_back(Import);
1377         assert(WasmIndices.count(&WS) == 0);
1378         WasmIndices[&WS] = NumTagImports++;
1379       } else if (WS.isTable()) {
1380         if (WS.isWeak())
1381           report_fatal_error("undefined table symbol cannot be weak");
1382 
1383         wasm::WasmImport Import;
1384         Import.Module = WS.getImportModule();
1385         Import.Field = WS.getImportName();
1386         Import.Kind = wasm::WASM_EXTERNAL_TABLE;
1387         Import.Table = WS.getTableType();
1388         Imports.push_back(Import);
1389         assert(WasmIndices.count(&WS) == 0);
1390         WasmIndices[&WS] = NumTableImports++;
1391       }
1392     }
1393   }
1394 
1395   // Add imports for GOT globals
1396   for (const MCSymbol &S : Asm.symbols()) {
1397     const auto &WS = static_cast<const MCSymbolWasm &>(S);
1398     if (WS.isUsedInGOT()) {
1399       wasm::WasmImport Import;
1400       if (WS.isFunction())
1401         Import.Module = "GOT.func";
1402       else
1403         Import.Module = "GOT.mem";
1404       Import.Field = WS.getName();
1405       Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1406       Import.Global = {wasm::WASM_TYPE_I32, true};
1407       Imports.push_back(Import);
1408       assert(GOTIndices.count(&WS) == 0);
1409       GOTIndices[&WS] = NumGlobalImports++;
1410     }
1411   }
1412 }
1413 
1414 uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
1415                                        const MCAsmLayout &Layout) {
1416   support::endian::Writer MainWriter(*OS, support::little);
1417   W = &MainWriter;
1418   if (IsSplitDwarf) {
1419     uint64_t TotalSize = writeOneObject(Asm, Layout, DwoMode::NonDwoOnly);
1420     assert(DwoOS);
1421     support::endian::Writer DwoWriter(*DwoOS, support::little);
1422     W = &DwoWriter;
1423     return TotalSize + writeOneObject(Asm, Layout, DwoMode::DwoOnly);
1424   } else {
1425     return writeOneObject(Asm, Layout, DwoMode::AllSections);
1426   }
1427 }
1428 
1429 uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
1430                                           const MCAsmLayout &Layout,
1431                                           DwoMode Mode) {
1432   uint64_t StartOffset = W->OS.tell();
1433   SectionCount = 0;
1434   CustomSections.clear();
1435 
1436   LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
1437 
1438   // Collect information from the available symbols.
1439   SmallVector<WasmFunction, 4> Functions;
1440   SmallVector<uint32_t, 4> TableElems;
1441   SmallVector<wasm::WasmImport, 4> Imports;
1442   SmallVector<wasm::WasmExport, 4> Exports;
1443   SmallVector<uint32_t, 2> TagTypes;
1444   SmallVector<wasm::WasmGlobal, 1> Globals;
1445   SmallVector<wasm::WasmTable, 1> Tables;
1446   SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
1447   SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
1448   std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1449   uint64_t DataSize = 0;
1450   if (Mode != DwoMode::DwoOnly) {
1451     prepareImports(Imports, Asm, Layout);
1452   }
1453 
1454   // Populate DataSegments and CustomSections, which must be done before
1455   // populating DataLocations.
1456   for (MCSection &Sec : Asm) {
1457     auto &Section = static_cast<MCSectionWasm &>(Sec);
1458     StringRef SectionName = Section.getName();
1459 
1460     if (Mode == DwoMode::NonDwoOnly && isDwoSection(Sec))
1461       continue;
1462     if (Mode == DwoMode::DwoOnly && !isDwoSection(Sec))
1463       continue;
1464 
1465     LLVM_DEBUG(dbgs() << "Processing Section " << SectionName << "  group "
1466                       << Section.getGroup() << "\n";);
1467 
1468     // .init_array sections are handled specially elsewhere.
1469     if (SectionName.startswith(".init_array"))
1470       continue;
1471 
1472     // Code is handled separately
1473     if (Section.getKind().isText())
1474       continue;
1475 
1476     if (Section.isWasmData()) {
1477       uint32_t SegmentIndex = DataSegments.size();
1478       DataSize = alignTo(DataSize, Section.getAlignment());
1479       DataSegments.emplace_back();
1480       WasmDataSegment &Segment = DataSegments.back();
1481       Segment.Name = SectionName;
1482       Segment.InitFlags = Section.getPassive()
1483                               ? (uint32_t)wasm::WASM_DATA_SEGMENT_IS_PASSIVE
1484                               : 0;
1485       Segment.Offset = DataSize;
1486       Segment.Section = &Section;
1487       addData(Segment.Data, Section);
1488       Segment.Alignment = Log2_32(Section.getAlignment());
1489       Segment.LinkingFlags = Section.getSegmentFlags();
1490       DataSize += Segment.Data.size();
1491       Section.setSegmentIndex(SegmentIndex);
1492 
1493       if (const MCSymbolWasm *C = Section.getGroup()) {
1494         Comdats[C->getName()].emplace_back(
1495             WasmComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex});
1496       }
1497     } else {
1498       // Create custom sections
1499       assert(Sec.getKind().isMetadata());
1500 
1501       StringRef Name = SectionName;
1502 
1503       // For user-defined custom sections, strip the prefix
1504       if (Name.startswith(".custom_section."))
1505         Name = Name.substr(strlen(".custom_section."));
1506 
1507       MCSymbol *Begin = Sec.getBeginSymbol();
1508       if (Begin) {
1509         assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
1510         WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1511       }
1512 
1513       // Separate out the producers and target features sections
1514       if (Name == "producers") {
1515         ProducersSection = std::make_unique<WasmCustomSection>(Name, &Section);
1516         continue;
1517       }
1518       if (Name == "target_features") {
1519         TargetFeaturesSection =
1520             std::make_unique<WasmCustomSection>(Name, &Section);
1521         continue;
1522       }
1523 
1524       // Custom sections can also belong to COMDAT groups. In this case the
1525       // decriptor's "index" field is the section index (in the final object
1526       // file), but that is not known until after layout, so it must be fixed up
1527       // later
1528       if (const MCSymbolWasm *C = Section.getGroup()) {
1529         Comdats[C->getName()].emplace_back(
1530             WasmComdatEntry{wasm::WASM_COMDAT_SECTION,
1531                             static_cast<uint32_t>(CustomSections.size())});
1532       }
1533 
1534       CustomSections.emplace_back(Name, &Section);
1535     }
1536   }
1537 
1538   if (Mode != DwoMode::DwoOnly) {
1539     // Populate WasmIndices and DataLocations for defined symbols.
1540     for (const MCSymbol &S : Asm.symbols()) {
1541       // Ignore unnamed temporary symbols, which aren't ever exported, imported,
1542       // or used in relocations.
1543       if (S.isTemporary() && S.getName().empty())
1544         continue;
1545 
1546       const auto &WS = static_cast<const MCSymbolWasm &>(S);
1547       LLVM_DEBUG(dbgs()
1548                  << "MCSymbol: "
1549                  << toString(WS.getType().getValueOr(wasm::WASM_SYMBOL_TYPE_DATA))
1550                  << " '" << S << "'"
1551                  << " isDefined=" << S.isDefined() << " isExternal="
1552                  << S.isExternal() << " isTemporary=" << S.isTemporary()
1553                  << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden()
1554                  << " isVariable=" << WS.isVariable() << "\n");
1555 
1556       if (WS.isVariable())
1557         continue;
1558       if (WS.isComdat() && !WS.isDefined())
1559         continue;
1560 
1561       if (WS.isFunction()) {
1562         unsigned Index;
1563         if (WS.isDefined()) {
1564           if (WS.getOffset() != 0)
1565             report_fatal_error(
1566                 "function sections must contain one function each");
1567 
1568           if (WS.getSize() == nullptr)
1569             report_fatal_error(
1570                 "function symbols must have a size set with .size");
1571 
1572           // A definition. Write out the function body.
1573           Index = NumFunctionImports + Functions.size();
1574           WasmFunction Func;
1575           Func.SigIndex = getFunctionType(WS);
1576           Func.Sym = &WS;
1577           assert(WasmIndices.count(&WS) == 0);
1578           WasmIndices[&WS] = Index;
1579           Functions.push_back(Func);
1580 
1581           auto &Section = static_cast<MCSectionWasm &>(WS.getSection());
1582           if (const MCSymbolWasm *C = Section.getGroup()) {
1583             Comdats[C->getName()].emplace_back(
1584                 WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index});
1585           }
1586 
1587           if (WS.hasExportName()) {
1588             wasm::WasmExport Export;
1589             Export.Name = WS.getExportName();
1590             Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
1591             Export.Index = Index;
1592             Exports.push_back(Export);
1593           }
1594         } else {
1595           // An import; the index was assigned above.
1596           Index = WasmIndices.find(&WS)->second;
1597         }
1598 
1599         LLVM_DEBUG(dbgs() << "  -> function index: " << Index << "\n");
1600 
1601       } else if (WS.isData()) {
1602         if (!isInSymtab(WS))
1603           continue;
1604 
1605         if (!WS.isDefined()) {
1606           LLVM_DEBUG(dbgs() << "  -> segment index: -1"
1607                             << "\n");
1608           continue;
1609         }
1610 
1611         if (!WS.getSize())
1612           report_fatal_error("data symbols must have a size set with .size: " +
1613                              WS.getName());
1614 
1615         int64_t Size = 0;
1616         if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
1617           report_fatal_error(".size expression must be evaluatable");
1618 
1619         auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
1620         if (!DataSection.isWasmData())
1621           report_fatal_error("data symbols must live in a data section: " +
1622                              WS.getName());
1623 
1624         // For each data symbol, export it in the symtab as a reference to the
1625         // corresponding Wasm data segment.
1626         wasm::WasmDataReference Ref = wasm::WasmDataReference{
1627             DataSection.getSegmentIndex(), Layout.getSymbolOffset(WS),
1628             static_cast<uint64_t>(Size)};
1629         assert(DataLocations.count(&WS) == 0);
1630         DataLocations[&WS] = Ref;
1631         LLVM_DEBUG(dbgs() << "  -> segment index: " << Ref.Segment << "\n");
1632 
1633       } else if (WS.isGlobal()) {
1634         // A "true" Wasm global (currently just __stack_pointer)
1635         if (WS.isDefined()) {
1636           wasm::WasmGlobal Global;
1637           Global.Type = WS.getGlobalType();
1638           Global.Index = NumGlobalImports + Globals.size();
1639           switch (Global.Type.Type) {
1640           case wasm::WASM_TYPE_I32:
1641             Global.InitExpr.Opcode = wasm::WASM_OPCODE_I32_CONST;
1642             break;
1643           case wasm::WASM_TYPE_I64:
1644             Global.InitExpr.Opcode = wasm::WASM_OPCODE_I64_CONST;
1645             break;
1646           case wasm::WASM_TYPE_F32:
1647             Global.InitExpr.Opcode = wasm::WASM_OPCODE_F32_CONST;
1648             break;
1649           case wasm::WASM_TYPE_F64:
1650             Global.InitExpr.Opcode = wasm::WASM_OPCODE_F64_CONST;
1651             break;
1652           case wasm::WASM_TYPE_EXTERNREF:
1653             Global.InitExpr.Opcode = wasm::WASM_OPCODE_REF_NULL;
1654             break;
1655           default:
1656             llvm_unreachable("unexpected type");
1657           }
1658           assert(WasmIndices.count(&WS) == 0);
1659           WasmIndices[&WS] = Global.Index;
1660           Globals.push_back(Global);
1661         } else {
1662           // An import; the index was assigned above
1663           LLVM_DEBUG(dbgs() << "  -> global index: "
1664                             << WasmIndices.find(&WS)->second << "\n");
1665         }
1666       } else if (WS.isTable()) {
1667         if (WS.isDefined()) {
1668           wasm::WasmTable Table;
1669           Table.Index = NumTableImports + Tables.size();
1670           Table.Type = WS.getTableType();
1671           assert(WasmIndices.count(&WS) == 0);
1672           WasmIndices[&WS] = Table.Index;
1673           Tables.push_back(Table);
1674         }
1675         LLVM_DEBUG(dbgs() << " -> table index: "
1676                           << WasmIndices.find(&WS)->second << "\n");
1677       } else if (WS.isTag()) {
1678         // C++ exception symbol (__cpp_exception) or longjmp symbol
1679         // (__c_longjmp)
1680         unsigned Index;
1681         if (WS.isDefined()) {
1682           Index = NumTagImports + TagTypes.size();
1683           uint32_t SigIndex = getTagType(WS);
1684           assert(WasmIndices.count(&WS) == 0);
1685           WasmIndices[&WS] = Index;
1686           TagTypes.push_back(SigIndex);
1687         } else {
1688           // An import; the index was assigned above.
1689           assert(WasmIndices.count(&WS) > 0);
1690         }
1691         LLVM_DEBUG(dbgs() << "  -> tag index: " << WasmIndices.find(&WS)->second
1692                           << "\n");
1693 
1694       } else {
1695         assert(WS.isSection());
1696       }
1697     }
1698 
1699     // Populate WasmIndices and DataLocations for aliased symbols.  We need to
1700     // process these in a separate pass because we need to have processed the
1701     // target of the alias before the alias itself and the symbols are not
1702     // necessarily ordered in this way.
1703     for (const MCSymbol &S : Asm.symbols()) {
1704       if (!S.isVariable())
1705         continue;
1706 
1707       assert(S.isDefined());
1708 
1709       const auto *BS = Layout.getBaseSymbol(S);
1710       if (!BS)
1711         report_fatal_error(Twine(S.getName()) +
1712                            ": absolute addressing not supported!");
1713       const MCSymbolWasm *Base = cast<MCSymbolWasm>(BS);
1714 
1715       // Find the target symbol of this weak alias and export that index
1716       const auto &WS = static_cast<const MCSymbolWasm &>(S);
1717       LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *Base
1718                         << "'\n");
1719 
1720       if (Base->isFunction()) {
1721         assert(WasmIndices.count(Base) > 0);
1722         uint32_t WasmIndex = WasmIndices.find(Base)->second;
1723         assert(WasmIndices.count(&WS) == 0);
1724         WasmIndices[&WS] = WasmIndex;
1725         LLVM_DEBUG(dbgs() << "  -> index:" << WasmIndex << "\n");
1726       } else if (Base->isData()) {
1727         auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
1728         uint64_t Offset = Layout.getSymbolOffset(S);
1729         int64_t Size = 0;
1730         // For data symbol alias we use the size of the base symbol as the
1731         // size of the alias.  When an offset from the base is involved this
1732         // can result in a offset + size goes past the end of the data section
1733         // which out object format doesn't support.  So we must clamp it.
1734         if (!Base->getSize()->evaluateAsAbsolute(Size, Layout))
1735           report_fatal_error(".size expression must be evaluatable");
1736         const WasmDataSegment &Segment =
1737             DataSegments[DataSection.getSegmentIndex()];
1738         Size =
1739             std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset);
1740         wasm::WasmDataReference Ref = wasm::WasmDataReference{
1741             DataSection.getSegmentIndex(),
1742             static_cast<uint32_t>(Layout.getSymbolOffset(S)),
1743             static_cast<uint32_t>(Size)};
1744         DataLocations[&WS] = Ref;
1745         LLVM_DEBUG(dbgs() << "  -> index:" << Ref.Segment << "\n");
1746       } else {
1747         report_fatal_error("don't yet support global/tag aliases");
1748       }
1749     }
1750   }
1751 
1752   // Finally, populate the symbol table itself, in its "natural" order.
1753   for (const MCSymbol &S : Asm.symbols()) {
1754     const auto &WS = static_cast<const MCSymbolWasm &>(S);
1755     if (!isInSymtab(WS)) {
1756       WS.setIndex(InvalidIndex);
1757       continue;
1758     }
1759     LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n");
1760 
1761     uint32_t Flags = 0;
1762     if (WS.isWeak())
1763       Flags |= wasm::WASM_SYMBOL_BINDING_WEAK;
1764     if (WS.isHidden())
1765       Flags |= wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
1766     if (!WS.isExternal() && WS.isDefined())
1767       Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
1768     if (WS.isUndefined())
1769       Flags |= wasm::WASM_SYMBOL_UNDEFINED;
1770     if (WS.isNoStrip()) {
1771       Flags |= wasm::WASM_SYMBOL_NO_STRIP;
1772       if (isEmscripten()) {
1773         Flags |= wasm::WASM_SYMBOL_EXPORTED;
1774       }
1775     }
1776     if (WS.hasImportName())
1777       Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME;
1778     if (WS.hasExportName())
1779       Flags |= wasm::WASM_SYMBOL_EXPORTED;
1780     if (WS.isTLS())
1781       Flags |= wasm::WASM_SYMBOL_TLS;
1782 
1783     wasm::WasmSymbolInfo Info;
1784     Info.Name = WS.getName();
1785     Info.Kind = WS.getType().getValueOr(wasm::WASM_SYMBOL_TYPE_DATA);
1786     Info.Flags = Flags;
1787     if (!WS.isData()) {
1788       assert(WasmIndices.count(&WS) > 0);
1789       Info.ElementIndex = WasmIndices.find(&WS)->second;
1790     } else if (WS.isDefined()) {
1791       assert(DataLocations.count(&WS) > 0);
1792       Info.DataRef = DataLocations.find(&WS)->second;
1793     }
1794     WS.setIndex(SymbolInfos.size());
1795     SymbolInfos.emplace_back(Info);
1796   }
1797 
1798   {
1799     auto HandleReloc = [&](const WasmRelocationEntry &Rel) {
1800       // Functions referenced by a relocation need to put in the table.  This is
1801       // purely to make the object file's provisional values readable, and is
1802       // ignored by the linker, which re-calculates the relocations itself.
1803       if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1804           Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1805           Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1806           Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1807           Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1808           Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1809         return;
1810       assert(Rel.Symbol->isFunction());
1811       const MCSymbolWasm *Base =
1812           cast<MCSymbolWasm>(Layout.getBaseSymbol(*Rel.Symbol));
1813       uint32_t FunctionIndex = WasmIndices.find(Base)->second;
1814       uint32_t TableIndex = TableElems.size() + InitialTableOffset;
1815       if (TableIndices.try_emplace(Base, TableIndex).second) {
1816         LLVM_DEBUG(dbgs() << "  -> adding " << Base->getName()
1817                           << " to table: " << TableIndex << "\n");
1818         TableElems.push_back(FunctionIndex);
1819         registerFunctionType(*Base);
1820       }
1821     };
1822 
1823     for (const WasmRelocationEntry &RelEntry : CodeRelocations)
1824       HandleReloc(RelEntry);
1825     for (const WasmRelocationEntry &RelEntry : DataRelocations)
1826       HandleReloc(RelEntry);
1827   }
1828 
1829   // Translate .init_array section contents into start functions.
1830   for (const MCSection &S : Asm) {
1831     const auto &WS = static_cast<const MCSectionWasm &>(S);
1832     if (WS.getName().startswith(".fini_array"))
1833       report_fatal_error(".fini_array sections are unsupported");
1834     if (!WS.getName().startswith(".init_array"))
1835       continue;
1836     if (WS.getFragmentList().empty())
1837       continue;
1838 
1839     // init_array is expected to contain a single non-empty data fragment
1840     if (WS.getFragmentList().size() != 3)
1841       report_fatal_error("only one .init_array section fragment supported");
1842 
1843     auto IT = WS.begin();
1844     const MCFragment &EmptyFrag = *IT;
1845     if (EmptyFrag.getKind() != MCFragment::FT_Data)
1846       report_fatal_error(".init_array section should be aligned");
1847 
1848     IT = std::next(IT);
1849     const MCFragment &AlignFrag = *IT;
1850     if (AlignFrag.getKind() != MCFragment::FT_Align)
1851       report_fatal_error(".init_array section should be aligned");
1852     if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (is64Bit() ? 8 : 4))
1853       report_fatal_error(".init_array section should be aligned for pointers");
1854 
1855     const MCFragment &Frag = *std::next(IT);
1856     if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
1857       report_fatal_error("only data supported in .init_array section");
1858 
1859     uint16_t Priority = UINT16_MAX;
1860     unsigned PrefixLength = strlen(".init_array");
1861     if (WS.getName().size() > PrefixLength) {
1862       if (WS.getName()[PrefixLength] != '.')
1863         report_fatal_error(
1864             ".init_array section priority should start with '.'");
1865       if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1866         report_fatal_error("invalid .init_array section priority");
1867     }
1868     const auto &DataFrag = cast<MCDataFragment>(Frag);
1869     const SmallVectorImpl<char> &Contents = DataFrag.getContents();
1870     for (const uint8_t *
1871              P = (const uint8_t *)Contents.data(),
1872             *End = (const uint8_t *)Contents.data() + Contents.size();
1873          P != End; ++P) {
1874       if (*P != 0)
1875         report_fatal_error("non-symbolic data in .init_array section");
1876     }
1877     for (const MCFixup &Fixup : DataFrag.getFixups()) {
1878       assert(Fixup.getKind() ==
1879              MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
1880       const MCExpr *Expr = Fixup.getValue();
1881       auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1882       if (!SymRef)
1883         report_fatal_error("fixups in .init_array should be symbol references");
1884       const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1885       if (TargetSym.getIndex() == InvalidIndex)
1886         report_fatal_error("symbols in .init_array should exist in symtab");
1887       if (!TargetSym.isFunction())
1888         report_fatal_error("symbols in .init_array should be for functions");
1889       InitFuncs.push_back(
1890           std::make_pair(Priority, TargetSym.getIndex()));
1891     }
1892   }
1893 
1894   // Write out the Wasm header.
1895   writeHeader(Asm);
1896 
1897   uint32_t CodeSectionIndex, DataSectionIndex;
1898   if (Mode != DwoMode::DwoOnly) {
1899     writeTypeSection(Signatures);
1900     writeImportSection(Imports, DataSize, TableElems.size());
1901     writeFunctionSection(Functions);
1902     writeTableSection(Tables);
1903     // Skip the "memory" section; we import the memory instead.
1904     writeTagSection(TagTypes);
1905     writeGlobalSection(Globals);
1906     writeExportSection(Exports);
1907     const MCSymbol *IndirectFunctionTable =
1908         Asm.getContext().lookupSymbol("__indirect_function_table");
1909     writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
1910                      TableElems);
1911     writeDataCountSection();
1912 
1913     CodeSectionIndex = writeCodeSection(Asm, Layout, Functions);
1914     DataSectionIndex = writeDataSection(Layout);
1915   }
1916 
1917   // The Sections in the COMDAT list have placeholder indices (their index among
1918   // custom sections, rather than among all sections). Fix them up here.
1919   for (auto &Group : Comdats) {
1920     for (auto &Entry : Group.second) {
1921       if (Entry.Kind == wasm::WASM_COMDAT_SECTION) {
1922         Entry.Index += SectionCount;
1923       }
1924     }
1925   }
1926   for (auto &CustomSection : CustomSections)
1927     writeCustomSection(CustomSection, Asm, Layout);
1928 
1929   if (Mode != DwoMode::DwoOnly) {
1930     writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1931 
1932     writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);
1933     writeRelocSection(DataSectionIndex, "DATA", DataRelocations);
1934   }
1935   writeCustomRelocSections();
1936   if (ProducersSection)
1937     writeCustomSection(*ProducersSection, Asm, Layout);
1938   if (TargetFeaturesSection)
1939     writeCustomSection(*TargetFeaturesSection, Asm, Layout);
1940 
1941   // TODO: Translate the .comment section to the output.
1942   return W->OS.tell() - StartOffset;
1943 }
1944 
1945 std::unique_ptr<MCObjectWriter>
1946 llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
1947                              raw_pwrite_stream &OS) {
1948   return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
1949 }
1950 
1951 std::unique_ptr<MCObjectWriter>
1952 llvm::createWasmDwoObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
1953                                 raw_pwrite_stream &OS,
1954                                 raw_pwrite_stream &DwoOS) {
1955   return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS, DwoOS);
1956 }
1957