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