WasmObjectWriter.cpp revision 360784
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/ADT/SmallPtrSet.h"
15#include "llvm/BinaryFormat/Wasm.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/ErrorHandling.h"
31#include "llvm/Support/LEB128.h"
32#include "llvm/Support/StringSaver.h"
33#include <vector>
34
35using namespace llvm;
36
37#define DEBUG_TYPE "mc"
38
39namespace {
40
41// Went we ceate the indirect function table we start at 1, so that there is
42// and emtpy slot at 0 and therefore calling a null function pointer will trap.
43static 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.
48struct 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// The signature of a wasm function or event, in a struct capable of being used
59// as a DenseMap key.
60// TODO: Consider using wasm::WasmSignature directly instead.
61struct WasmSignature {
62  // Support empty and tombstone instances, needed by DenseMap.
63  enum { Plain, Empty, Tombstone } State = Plain;
64
65  // The return types of the function.
66  SmallVector<wasm::ValType, 1> Returns;
67
68  // The parameter types of the function.
69  SmallVector<wasm::ValType, 4> Params;
70
71  bool operator==(const WasmSignature &Other) const {
72    return State == Other.State && Returns == Other.Returns &&
73           Params == Other.Params;
74  }
75};
76
77// Traits for using WasmSignature in a DenseMap.
78struct WasmSignatureDenseMapInfo {
79  static WasmSignature getEmptyKey() {
80    WasmSignature Sig;
81    Sig.State = WasmSignature::Empty;
82    return Sig;
83  }
84  static WasmSignature getTombstoneKey() {
85    WasmSignature Sig;
86    Sig.State = WasmSignature::Tombstone;
87    return Sig;
88  }
89  static unsigned getHashValue(const WasmSignature &Sig) {
90    uintptr_t Value = Sig.State;
91    for (wasm::ValType Ret : Sig.Returns)
92      Value += DenseMapInfo<uint32_t>::getHashValue(uint32_t(Ret));
93    for (wasm::ValType Param : Sig.Params)
94      Value += DenseMapInfo<uint32_t>::getHashValue(uint32_t(Param));
95    return Value;
96  }
97  static bool isEqual(const WasmSignature &LHS, const WasmSignature &RHS) {
98    return LHS == RHS;
99  }
100};
101
102// A wasm data segment.  A wasm binary contains only a single data section
103// but that can contain many segments, each with their own virtual location
104// in memory.  Each MCSection data created by llvm is modeled as its own
105// wasm data segment.
106struct WasmDataSegment {
107  MCSectionWasm *Section;
108  StringRef Name;
109  uint32_t InitFlags;
110  uint32_t Offset;
111  uint32_t Alignment;
112  uint32_t LinkerFlags;
113  SmallVector<char, 4> Data;
114};
115
116// A wasm function to be written into the function section.
117struct WasmFunction {
118  uint32_t SigIndex;
119  const MCSymbolWasm *Sym;
120};
121
122// A wasm global to be written into the global section.
123struct WasmGlobal {
124  wasm::WasmGlobalType Type;
125  uint64_t InitialValue;
126};
127
128// Information about a single item which is part of a COMDAT.  For each data
129// segment or function which is in the COMDAT, there is a corresponding
130// WasmComdatEntry.
131struct WasmComdatEntry {
132  unsigned Kind;
133  uint32_t Index;
134};
135
136// Information about a single relocation.
137struct WasmRelocationEntry {
138  uint64_t Offset;                   // Where is the relocation.
139  const MCSymbolWasm *Symbol;        // The symbol to relocate with.
140  int64_t Addend;                    // A value to add to the symbol.
141  unsigned Type;                     // The type of the relocation.
142  const MCSectionWasm *FixupSection; // The section the relocation is targeting.
143
144  WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
145                      int64_t Addend, unsigned Type,
146                      const MCSectionWasm *FixupSection)
147      : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type),
148        FixupSection(FixupSection) {}
149
150  bool hasAddend() const { return wasm::relocTypeHasAddend(Type); }
151
152  void print(raw_ostream &Out) const {
153    Out << wasm::relocTypetoString(Type) << " Off=" << Offset
154        << ", Sym=" << *Symbol << ", Addend=" << Addend
155        << ", FixupSection=" << FixupSection->getSectionName();
156  }
157
158#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
159  LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
160#endif
161};
162
163static const uint32_t InvalidIndex = -1;
164
165struct WasmCustomSection {
166
167  StringRef Name;
168  MCSectionWasm *Section;
169
170  uint32_t OutputContentsOffset;
171  uint32_t OutputIndex;
172
173  WasmCustomSection(StringRef Name, MCSectionWasm *Section)
174      : Name(Name), Section(Section), OutputContentsOffset(0),
175        OutputIndex(InvalidIndex) {}
176};
177
178#if !defined(NDEBUG)
179raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
180  Rel.print(OS);
181  return OS;
182}
183#endif
184
185// Write X as an (unsigned) LEB value at offset Offset in Stream, padded
186// to allow patching.
187static void writePatchableLEB(raw_pwrite_stream &Stream, uint32_t X,
188                              uint64_t Offset) {
189  uint8_t Buffer[5];
190  unsigned SizeLen = encodeULEB128(X, Buffer, 5);
191  assert(SizeLen == 5);
192  Stream.pwrite((char *)Buffer, SizeLen, Offset);
193}
194
195// Write X as an signed LEB value at offset Offset in Stream, padded
196// to allow patching.
197static void writePatchableSLEB(raw_pwrite_stream &Stream, int32_t X,
198                               uint64_t Offset) {
199  uint8_t Buffer[5];
200  unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
201  assert(SizeLen == 5);
202  Stream.pwrite((char *)Buffer, SizeLen, Offset);
203}
204
205// Write X as a plain integer value at offset Offset in Stream.
206static void writeI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
207  uint8_t Buffer[4];
208  support::endian::write32le(Buffer, X);
209  Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
210}
211
212class WasmObjectWriter : public MCObjectWriter {
213  support::endian::Writer W;
214
215  /// The target specific Wasm writer instance.
216  std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
217
218  // Relocations for fixing up references in the code section.
219  std::vector<WasmRelocationEntry> CodeRelocations;
220  uint32_t CodeSectionIndex;
221
222  // Relocations for fixing up references in the data section.
223  std::vector<WasmRelocationEntry> DataRelocations;
224  uint32_t DataSectionIndex;
225
226  // Index values to use for fixing up call_indirect type indices.
227  // Maps function symbols to the index of the type of the function
228  DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices;
229  // Maps function symbols to the table element index space. Used
230  // for TABLE_INDEX relocation types (i.e. address taken functions).
231  DenseMap<const MCSymbolWasm *, uint32_t> TableIndices;
232  // Maps function/global symbols to the function/global/event/section index
233  // space.
234  DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices;
235  DenseMap<const MCSymbolWasm *, uint32_t> GOTIndices;
236  // Maps data symbols to the Wasm segment and offset/size with the segment.
237  DenseMap<const MCSymbolWasm *, wasm::WasmDataReference> DataLocations;
238
239  // Stores output data (index, relocations, content offset) for custom
240  // section.
241  std::vector<WasmCustomSection> CustomSections;
242  std::unique_ptr<WasmCustomSection> ProducersSection;
243  std::unique_ptr<WasmCustomSection> TargetFeaturesSection;
244  // Relocations for fixing up references in the custom sections.
245  DenseMap<const MCSectionWasm *, std::vector<WasmRelocationEntry>>
246      CustomSectionsRelocations;
247
248  // Map from section to defining function symbol.
249  DenseMap<const MCSection *, const MCSymbol *> SectionFunctions;
250
251  DenseMap<WasmSignature, uint32_t, WasmSignatureDenseMapInfo> SignatureIndices;
252  SmallVector<WasmSignature, 4> Signatures;
253  SmallVector<WasmDataSegment, 4> DataSegments;
254  unsigned NumFunctionImports = 0;
255  unsigned NumGlobalImports = 0;
256  unsigned NumEventImports = 0;
257  uint32_t SectionCount = 0;
258
259  // TargetObjectWriter wrappers.
260  bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
261  bool isEmscripten() const { return TargetObjectWriter->isEmscripten(); }
262
263  void startSection(SectionBookkeeping &Section, unsigned SectionId);
264  void startCustomSection(SectionBookkeeping &Section, StringRef Name);
265  void endSection(SectionBookkeeping &Section);
266
267public:
268  WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
269                   raw_pwrite_stream &OS)
270      : W(OS, support::little), TargetObjectWriter(std::move(MOTW)) {}
271
272private:
273  void reset() override {
274    CodeRelocations.clear();
275    DataRelocations.clear();
276    TypeIndices.clear();
277    WasmIndices.clear();
278    GOTIndices.clear();
279    TableIndices.clear();
280    DataLocations.clear();
281    CustomSections.clear();
282    ProducersSection.reset();
283    TargetFeaturesSection.reset();
284    CustomSectionsRelocations.clear();
285    SignatureIndices.clear();
286    Signatures.clear();
287    DataSegments.clear();
288    SectionFunctions.clear();
289    NumFunctionImports = 0;
290    NumGlobalImports = 0;
291    MCObjectWriter::reset();
292  }
293
294  void writeHeader(const MCAssembler &Asm);
295
296  void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
297                        const MCFragment *Fragment, const MCFixup &Fixup,
298                        MCValue Target, uint64_t &FixedValue) override;
299
300  void executePostLayoutBinding(MCAssembler &Asm,
301                                const MCAsmLayout &Layout) override;
302
303  uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
304
305  void writeString(const StringRef Str) {
306    encodeULEB128(Str.size(), W.OS);
307    W.OS << Str;
308  }
309
310  void writeValueType(wasm::ValType Ty) { W.OS << static_cast<char>(Ty); }
311
312  void writeTypeSection(ArrayRef<WasmSignature> Signatures);
313  void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint32_t DataSize,
314                          uint32_t NumElements);
315  void writeFunctionSection(ArrayRef<WasmFunction> Functions);
316  void writeExportSection(ArrayRef<wasm::WasmExport> Exports);
317  void writeElemSection(ArrayRef<uint32_t> TableElems);
318  void writeDataCountSection();
319  void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
320                        ArrayRef<WasmFunction> Functions);
321  void writeDataSection();
322  void writeEventSection(ArrayRef<wasm::WasmEventType> Events);
323  void writeRelocSection(uint32_t SectionIndex, StringRef Name,
324                         std::vector<WasmRelocationEntry> &Relocations);
325  void writeLinkingMetaDataSection(
326      ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
327      ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
328      const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats);
329  void writeCustomSection(WasmCustomSection &CustomSection,
330                          const MCAssembler &Asm, const MCAsmLayout &Layout);
331  void writeCustomRelocSections();
332  void
333  updateCustomSectionRelocations(const SmallVector<WasmFunction, 4> &Functions,
334                                 const MCAsmLayout &Layout);
335
336  uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
337  void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
338                        uint64_t ContentsOffset);
339
340  uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
341  uint32_t getFunctionType(const MCSymbolWasm &Symbol);
342  uint32_t getEventType(const MCSymbolWasm &Symbol);
343  void registerFunctionType(const MCSymbolWasm &Symbol);
344  void registerEventType(const MCSymbolWasm &Symbol);
345};
346
347} // end anonymous namespace
348
349// Write out a section header and a patchable section size field.
350void WasmObjectWriter::startSection(SectionBookkeeping &Section,
351                                    unsigned SectionId) {
352  LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n");
353  W.OS << char(SectionId);
354
355  Section.SizeOffset = W.OS.tell();
356
357  // The section size. We don't know the size yet, so reserve enough space
358  // for any 32-bit value; we'll patch it later.
359  encodeULEB128(0, W.OS, 5);
360
361  // The position where the section starts, for measuring its size.
362  Section.ContentsOffset = W.OS.tell();
363  Section.PayloadOffset = W.OS.tell();
364  Section.Index = SectionCount++;
365}
366
367void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
368                                          StringRef Name) {
369  LLVM_DEBUG(dbgs() << "startCustomSection " << Name << "\n");
370  startSection(Section, wasm::WASM_SEC_CUSTOM);
371
372  // The position where the section header ends, for measuring its size.
373  Section.PayloadOffset = W.OS.tell();
374
375  // Custom sections in wasm also have a string identifier.
376  writeString(Name);
377
378  // The position where the custom section starts.
379  Section.ContentsOffset = W.OS.tell();
380}
381
382// Now that the section is complete and we know how big it is, patch up the
383// section size field at the start of the section.
384void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
385  uint64_t Size = W.OS.tell();
386  // /dev/null doesn't support seek/tell and can report offset of 0.
387  // Simply skip this patching in that case.
388  if (!Size)
389    return;
390
391  Size -= Section.PayloadOffset;
392  if (uint32_t(Size) != Size)
393    report_fatal_error("section size does not fit in a uint32_t");
394
395  LLVM_DEBUG(dbgs() << "endSection size=" << Size << "\n");
396
397  // Write the final section size to the payload_len field, which follows
398  // the section id byte.
399  writePatchableLEB(static_cast<raw_pwrite_stream &>(W.OS), Size,
400                    Section.SizeOffset);
401}
402
403// Emit the Wasm header.
404void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
405  W.OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic));
406  W.write<uint32_t>(wasm::WasmVersion);
407}
408
409void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
410                                                const MCAsmLayout &Layout) {
411  // Build a map of sections to the function that defines them, for use
412  // in recordRelocation.
413  for (const MCSymbol &S : Asm.symbols()) {
414    const auto &WS = static_cast<const MCSymbolWasm &>(S);
415    if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {
416      const auto &Sec = static_cast<const MCSectionWasm &>(S.getSection());
417      auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));
418      if (!Pair.second)
419        report_fatal_error("section already has a defining function: " +
420                           Sec.getSectionName());
421    }
422  }
423}
424
425void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
426                                        const MCAsmLayout &Layout,
427                                        const MCFragment *Fragment,
428                                        const MCFixup &Fixup, MCValue Target,
429                                        uint64_t &FixedValue) {
430  // The WebAssembly backend should never generate FKF_IsPCRel fixups
431  assert(!(Asm.getBackend().getFixupKindInfo(Fixup.getKind()).Flags &
432           MCFixupKindInfo::FKF_IsPCRel));
433
434  const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
435  uint64_t C = Target.getConstant();
436  uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
437  MCContext &Ctx = Asm.getContext();
438
439  // The .init_array isn't translated as data, so don't do relocations in it.
440  if (FixupSection.getSectionName().startswith(".init_array"))
441    return;
442
443  if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
444    // To get here the A - B expression must have failed evaluateAsRelocatable.
445    // This means either A or B must be undefined and in WebAssembly we can't
446    // support either of those cases.
447    const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
448    Ctx.reportError(
449        Fixup.getLoc(),
450        Twine("symbol '") + SymB.getName() +
451            "': unsupported subtraction expression used in relocation.");
452    return;
453  }
454
455  // We either rejected the fixup or folded B into C at this point.
456  const MCSymbolRefExpr *RefA = Target.getSymA();
457  const auto *SymA = cast<MCSymbolWasm>(&RefA->getSymbol());
458
459  if (SymA->isVariable()) {
460    const MCExpr *Expr = SymA->getVariableValue();
461    const auto *Inner = cast<MCSymbolRefExpr>(Expr);
462    if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
463      llvm_unreachable("weakref used in reloc not yet implemented");
464  }
465
466  // Put any constant offset in an addend. Offsets can be negative, and
467  // LLVM expects wrapping, in contrast to wasm's immediates which can't
468  // be negative and don't wrap.
469  FixedValue = 0;
470
471  unsigned Type = TargetObjectWriter->getRelocType(Target, Fixup);
472
473  // Absolute offset within a section or a function.
474  // Currently only supported for for metadata sections.
475  // See: test/MC/WebAssembly/blockaddress.ll
476  if (Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
477      Type == wasm::R_WASM_SECTION_OFFSET_I32) {
478    if (!FixupSection.getKind().isMetadata())
479      report_fatal_error("relocations for function or section offsets are "
480                         "only supported in metadata sections");
481
482    const MCSymbol *SectionSymbol = nullptr;
483    const MCSection &SecA = SymA->getSection();
484    if (SecA.getKind().isText())
485      SectionSymbol = SectionFunctions.find(&SecA)->second;
486    else
487      SectionSymbol = SecA.getBeginSymbol();
488    if (!SectionSymbol)
489      report_fatal_error("section symbol is required for relocation");
490
491    C += Layout.getSymbolOffset(*SymA);
492    SymA = cast<MCSymbolWasm>(SectionSymbol);
493  }
494
495  // Relocation other than R_WASM_TYPE_INDEX_LEB are required to be
496  // against a named symbol.
497  if (Type != wasm::R_WASM_TYPE_INDEX_LEB) {
498    if (SymA->getName().empty())
499      report_fatal_error("relocations against un-named temporaries are not yet "
500                         "supported by wasm");
501
502    SymA->setUsedInReloc();
503  }
504
505  if (RefA->getKind() == MCSymbolRefExpr::VK_GOT)
506    SymA->setUsedInGOT();
507
508  WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
509  LLVM_DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
510
511  if (FixupSection.isWasmData()) {
512    DataRelocations.push_back(Rec);
513  } else if (FixupSection.getKind().isText()) {
514    CodeRelocations.push_back(Rec);
515  } else if (FixupSection.getKind().isMetadata()) {
516    CustomSectionsRelocations[&FixupSection].push_back(Rec);
517  } else {
518    llvm_unreachable("unexpected section type");
519  }
520}
521
522static const MCSymbolWasm *resolveSymbol(const MCSymbolWasm &Symbol) {
523  const MCSymbolWasm* Ret = &Symbol;
524  while (Ret->isVariable()) {
525    const MCExpr *Expr = Ret->getVariableValue();
526    auto *Inner = cast<MCSymbolRefExpr>(Expr);
527    Ret = cast<MCSymbolWasm>(&Inner->getSymbol());
528  }
529  return Ret;
530}
531
532// Compute a value to write into the code at the location covered
533// by RelEntry. This value isn't used by the static linker; it just serves
534// to make the object format more readable and more likely to be directly
535// useable.
536uint32_t
537WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
538  if (RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB && !RelEntry.Symbol->isGlobal()) {
539    assert(GOTIndices.count(RelEntry.Symbol) > 0 && "symbol not found in GOT index space");
540    return GOTIndices[RelEntry.Symbol];
541  }
542
543  switch (RelEntry.Type) {
544  case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
545  case wasm::R_WASM_TABLE_INDEX_SLEB:
546  case wasm::R_WASM_TABLE_INDEX_I32: {
547    // Provisional value is table address of the resolved symbol itself
548    const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol);
549    assert(Sym->isFunction());
550    return TableIndices[Sym];
551  }
552  case wasm::R_WASM_TYPE_INDEX_LEB:
553    // Provisional value is same as the index
554    return getRelocationIndexValue(RelEntry);
555  case wasm::R_WASM_FUNCTION_INDEX_LEB:
556  case wasm::R_WASM_GLOBAL_INDEX_LEB:
557  case wasm::R_WASM_EVENT_INDEX_LEB:
558    // Provisional value is function/global/event Wasm index
559    assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space");
560    return WasmIndices[RelEntry.Symbol];
561  case wasm::R_WASM_FUNCTION_OFFSET_I32:
562  case wasm::R_WASM_SECTION_OFFSET_I32: {
563    const auto &Section =
564        static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection());
565    return Section.getSectionOffset() + RelEntry.Addend;
566  }
567  case wasm::R_WASM_MEMORY_ADDR_LEB:
568  case wasm::R_WASM_MEMORY_ADDR_I32:
569  case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
570  case wasm::R_WASM_MEMORY_ADDR_SLEB: {
571    // Provisional value is address of the global
572    const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol);
573    // For undefined symbols, use zero
574    if (!Sym->isDefined())
575      return 0;
576    const wasm::WasmDataReference &Ref = DataLocations[Sym];
577    const WasmDataSegment &Segment = DataSegments[Ref.Segment];
578    // Ignore overflow. LLVM allows address arithmetic to silently wrap.
579    return Segment.Offset + Ref.Offset + RelEntry.Addend;
580  }
581  default:
582    llvm_unreachable("invalid relocation type");
583  }
584}
585
586static void addData(SmallVectorImpl<char> &DataBytes,
587                    MCSectionWasm &DataSection) {
588  LLVM_DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n");
589
590  DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
591
592  for (const MCFragment &Frag : DataSection) {
593    if (Frag.hasInstructions())
594      report_fatal_error("only data supported in data sections");
595
596    if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
597      if (Align->getValueSize() != 1)
598        report_fatal_error("only byte values supported for alignment");
599      // If nops are requested, use zeros, as this is the data section.
600      uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
601      uint64_t Size =
602          std::min<uint64_t>(alignTo(DataBytes.size(), Align->getAlignment()),
603                             DataBytes.size() + Align->getMaxBytesToEmit());
604      DataBytes.resize(Size, Value);
605    } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
606      int64_t NumValues;
607      if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
608        llvm_unreachable("The fill should be an assembler constant");
609      DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues,
610                       Fill->getValue());
611    } else if (auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) {
612      const SmallVectorImpl<char> &Contents = LEB->getContents();
613      DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
614    } else {
615      const auto &DataFrag = cast<MCDataFragment>(Frag);
616      const SmallVectorImpl<char> &Contents = DataFrag.getContents();
617      DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
618    }
619  }
620
621  LLVM_DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
622}
623
624uint32_t
625WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {
626  if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {
627    if (!TypeIndices.count(RelEntry.Symbol))
628      report_fatal_error("symbol not found in type index space: " +
629                         RelEntry.Symbol->getName());
630    return TypeIndices[RelEntry.Symbol];
631  }
632
633  return RelEntry.Symbol->getIndex();
634}
635
636// Apply the portions of the relocation records that we can handle ourselves
637// directly.
638void WasmObjectWriter::applyRelocations(
639    ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset) {
640  auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);
641  for (const WasmRelocationEntry &RelEntry : Relocations) {
642    uint64_t Offset = ContentsOffset +
643                      RelEntry.FixupSection->getSectionOffset() +
644                      RelEntry.Offset;
645
646    LLVM_DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
647    uint32_t Value = getProvisionalValue(RelEntry);
648
649    switch (RelEntry.Type) {
650    case wasm::R_WASM_FUNCTION_INDEX_LEB:
651    case wasm::R_WASM_TYPE_INDEX_LEB:
652    case wasm::R_WASM_GLOBAL_INDEX_LEB:
653    case wasm::R_WASM_MEMORY_ADDR_LEB:
654    case wasm::R_WASM_EVENT_INDEX_LEB:
655      writePatchableLEB(Stream, Value, Offset);
656      break;
657    case wasm::R_WASM_TABLE_INDEX_I32:
658    case wasm::R_WASM_MEMORY_ADDR_I32:
659    case wasm::R_WASM_FUNCTION_OFFSET_I32:
660    case wasm::R_WASM_SECTION_OFFSET_I32:
661      writeI32(Stream, Value, Offset);
662      break;
663    case wasm::R_WASM_TABLE_INDEX_SLEB:
664    case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
665    case wasm::R_WASM_MEMORY_ADDR_SLEB:
666    case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
667      writePatchableSLEB(Stream, Value, Offset);
668      break;
669    default:
670      llvm_unreachable("invalid relocation type");
671    }
672  }
673}
674
675void WasmObjectWriter::writeTypeSection(ArrayRef<WasmSignature> Signatures) {
676  if (Signatures.empty())
677    return;
678
679  SectionBookkeeping Section;
680  startSection(Section, wasm::WASM_SEC_TYPE);
681
682  encodeULEB128(Signatures.size(), W.OS);
683
684  for (const WasmSignature &Sig : Signatures) {
685    W.OS << char(wasm::WASM_TYPE_FUNC);
686    encodeULEB128(Sig.Params.size(), W.OS);
687    for (wasm::ValType Ty : Sig.Params)
688      writeValueType(Ty);
689    encodeULEB128(Sig.Returns.size(), W.OS);
690    for (wasm::ValType Ty : Sig.Returns)
691      writeValueType(Ty);
692  }
693
694  endSection(Section);
695}
696
697void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
698                                          uint32_t DataSize,
699                                          uint32_t NumElements) {
700  if (Imports.empty())
701    return;
702
703  uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
704
705  SectionBookkeeping Section;
706  startSection(Section, wasm::WASM_SEC_IMPORT);
707
708  encodeULEB128(Imports.size(), W.OS);
709  for (const wasm::WasmImport &Import : Imports) {
710    writeString(Import.Module);
711    writeString(Import.Field);
712    W.OS << char(Import.Kind);
713
714    switch (Import.Kind) {
715    case wasm::WASM_EXTERNAL_FUNCTION:
716      encodeULEB128(Import.SigIndex, W.OS);
717      break;
718    case wasm::WASM_EXTERNAL_GLOBAL:
719      W.OS << char(Import.Global.Type);
720      W.OS << char(Import.Global.Mutable ? 1 : 0);
721      break;
722    case wasm::WASM_EXTERNAL_MEMORY:
723      encodeULEB128(0, W.OS);        // flags
724      encodeULEB128(NumPages, W.OS); // initial
725      break;
726    case wasm::WASM_EXTERNAL_TABLE:
727      W.OS << char(Import.Table.ElemType);
728      encodeULEB128(0, W.OS);           // flags
729      encodeULEB128(NumElements, W.OS); // initial
730      break;
731    case wasm::WASM_EXTERNAL_EVENT:
732      encodeULEB128(Import.Event.Attribute, W.OS);
733      encodeULEB128(Import.Event.SigIndex, W.OS);
734      break;
735    default:
736      llvm_unreachable("unsupported import kind");
737    }
738  }
739
740  endSection(Section);
741}
742
743void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
744  if (Functions.empty())
745    return;
746
747  SectionBookkeeping Section;
748  startSection(Section, wasm::WASM_SEC_FUNCTION);
749
750  encodeULEB128(Functions.size(), W.OS);
751  for (const WasmFunction &Func : Functions)
752    encodeULEB128(Func.SigIndex, W.OS);
753
754  endSection(Section);
755}
756
757void WasmObjectWriter::writeEventSection(ArrayRef<wasm::WasmEventType> Events) {
758  if (Events.empty())
759    return;
760
761  SectionBookkeeping Section;
762  startSection(Section, wasm::WASM_SEC_EVENT);
763
764  encodeULEB128(Events.size(), W.OS);
765  for (const wasm::WasmEventType &Event : Events) {
766    encodeULEB128(Event.Attribute, W.OS);
767    encodeULEB128(Event.SigIndex, W.OS);
768  }
769
770  endSection(Section);
771}
772
773void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) {
774  if (Exports.empty())
775    return;
776
777  SectionBookkeeping Section;
778  startSection(Section, wasm::WASM_SEC_EXPORT);
779
780  encodeULEB128(Exports.size(), W.OS);
781  for (const wasm::WasmExport &Export : Exports) {
782    writeString(Export.Name);
783    W.OS << char(Export.Kind);
784    encodeULEB128(Export.Index, W.OS);
785  }
786
787  endSection(Section);
788}
789
790void WasmObjectWriter::writeElemSection(ArrayRef<uint32_t> TableElems) {
791  if (TableElems.empty())
792    return;
793
794  SectionBookkeeping Section;
795  startSection(Section, wasm::WASM_SEC_ELEM);
796
797  encodeULEB128(1, W.OS); // number of "segments"
798  encodeULEB128(0, W.OS); // the table index
799
800  // init expr for starting offset
801  W.OS << char(wasm::WASM_OPCODE_I32_CONST);
802  encodeSLEB128(InitialTableOffset, W.OS);
803  W.OS << char(wasm::WASM_OPCODE_END);
804
805  encodeULEB128(TableElems.size(), W.OS);
806  for (uint32_t Elem : TableElems)
807    encodeULEB128(Elem, W.OS);
808
809  endSection(Section);
810}
811
812void WasmObjectWriter::writeDataCountSection() {
813  if (DataSegments.empty())
814    return;
815
816  SectionBookkeeping Section;
817  startSection(Section, wasm::WASM_SEC_DATACOUNT);
818  encodeULEB128(DataSegments.size(), W.OS);
819  endSection(Section);
820}
821
822void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
823                                        const MCAsmLayout &Layout,
824                                        ArrayRef<WasmFunction> Functions) {
825  if (Functions.empty())
826    return;
827
828  SectionBookkeeping Section;
829  startSection(Section, wasm::WASM_SEC_CODE);
830  CodeSectionIndex = Section.Index;
831
832  encodeULEB128(Functions.size(), W.OS);
833
834  for (const WasmFunction &Func : Functions) {
835    auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection());
836
837    int64_t Size = 0;
838    if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
839      report_fatal_error(".size expression must be evaluatable");
840
841    encodeULEB128(Size, W.OS);
842    FuncSection.setSectionOffset(W.OS.tell() - Section.ContentsOffset);
843    Asm.writeSectionData(W.OS, &FuncSection, Layout);
844  }
845
846  // Apply fixups.
847  applyRelocations(CodeRelocations, Section.ContentsOffset);
848
849  endSection(Section);
850}
851
852void WasmObjectWriter::writeDataSection() {
853  if (DataSegments.empty())
854    return;
855
856  SectionBookkeeping Section;
857  startSection(Section, wasm::WASM_SEC_DATA);
858  DataSectionIndex = Section.Index;
859
860  encodeULEB128(DataSegments.size(), W.OS); // count
861
862  for (const WasmDataSegment &Segment : DataSegments) {
863    encodeULEB128(Segment.InitFlags, W.OS); // flags
864    if (Segment.InitFlags & wasm::WASM_SEGMENT_HAS_MEMINDEX)
865      encodeULEB128(0, W.OS); // memory index
866    if ((Segment.InitFlags & wasm::WASM_SEGMENT_IS_PASSIVE) == 0) {
867      W.OS << char(wasm::WASM_OPCODE_I32_CONST);
868      encodeSLEB128(Segment.Offset, W.OS); // offset
869      W.OS << char(wasm::WASM_OPCODE_END);
870    }
871    encodeULEB128(Segment.Data.size(), W.OS); // size
872    Segment.Section->setSectionOffset(W.OS.tell() - Section.ContentsOffset);
873    W.OS << Segment.Data; // data
874  }
875
876  // Apply fixups.
877  applyRelocations(DataRelocations, Section.ContentsOffset);
878
879  endSection(Section);
880}
881
882void WasmObjectWriter::writeRelocSection(
883    uint32_t SectionIndex, StringRef Name,
884    std::vector<WasmRelocationEntry> &Relocs) {
885  // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
886  // for descriptions of the reloc sections.
887
888  if (Relocs.empty())
889    return;
890
891  // First, ensure the relocations are sorted in offset order.  In general they
892  // should already be sorted since `recordRelocation` is called in offset
893  // order, but for the code section we combine many MC sections into single
894  // wasm section, and this order is determined by the order of Asm.Symbols()
895  // not the sections order.
896  llvm::stable_sort(
897      Relocs, [](const WasmRelocationEntry &A, const WasmRelocationEntry &B) {
898        return (A.Offset + A.FixupSection->getSectionOffset()) <
899               (B.Offset + B.FixupSection->getSectionOffset());
900      });
901
902  SectionBookkeeping Section;
903  startCustomSection(Section, std::string("reloc.") + Name.str());
904
905  encodeULEB128(SectionIndex, W.OS);
906  encodeULEB128(Relocs.size(), W.OS);
907  for (const WasmRelocationEntry &RelEntry : Relocs) {
908    uint64_t Offset =
909        RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
910    uint32_t Index = getRelocationIndexValue(RelEntry);
911
912    W.OS << char(RelEntry.Type);
913    encodeULEB128(Offset, W.OS);
914    encodeULEB128(Index, W.OS);
915    if (RelEntry.hasAddend())
916      encodeSLEB128(RelEntry.Addend, W.OS);
917  }
918
919  endSection(Section);
920}
921
922void WasmObjectWriter::writeCustomRelocSections() {
923  for (const auto &Sec : CustomSections) {
924    auto &Relocations = CustomSectionsRelocations[Sec.Section];
925    writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
926  }
927}
928
929void WasmObjectWriter::writeLinkingMetaDataSection(
930    ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
931    ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
932    const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) {
933  SectionBookkeeping Section;
934  startCustomSection(Section, "linking");
935  encodeULEB128(wasm::WasmMetadataVersion, W.OS);
936
937  SectionBookkeeping SubSection;
938  if (SymbolInfos.size() != 0) {
939    startSection(SubSection, wasm::WASM_SYMBOL_TABLE);
940    encodeULEB128(SymbolInfos.size(), W.OS);
941    for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) {
942      encodeULEB128(Sym.Kind, W.OS);
943      encodeULEB128(Sym.Flags, W.OS);
944      switch (Sym.Kind) {
945      case wasm::WASM_SYMBOL_TYPE_FUNCTION:
946      case wasm::WASM_SYMBOL_TYPE_GLOBAL:
947      case wasm::WASM_SYMBOL_TYPE_EVENT:
948        encodeULEB128(Sym.ElementIndex, W.OS);
949        if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
950            (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
951          writeString(Sym.Name);
952        break;
953      case wasm::WASM_SYMBOL_TYPE_DATA:
954        writeString(Sym.Name);
955        if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
956          encodeULEB128(Sym.DataRef.Segment, W.OS);
957          encodeULEB128(Sym.DataRef.Offset, W.OS);
958          encodeULEB128(Sym.DataRef.Size, W.OS);
959        }
960        break;
961      case wasm::WASM_SYMBOL_TYPE_SECTION: {
962        const uint32_t SectionIndex =
963            CustomSections[Sym.ElementIndex].OutputIndex;
964        encodeULEB128(SectionIndex, W.OS);
965        break;
966      }
967      default:
968        llvm_unreachable("unexpected kind");
969      }
970    }
971    endSection(SubSection);
972  }
973
974  if (DataSegments.size()) {
975    startSection(SubSection, wasm::WASM_SEGMENT_INFO);
976    encodeULEB128(DataSegments.size(), W.OS);
977    for (const WasmDataSegment &Segment : DataSegments) {
978      writeString(Segment.Name);
979      encodeULEB128(Segment.Alignment, W.OS);
980      encodeULEB128(Segment.LinkerFlags, W.OS);
981    }
982    endSection(SubSection);
983  }
984
985  if (!InitFuncs.empty()) {
986    startSection(SubSection, wasm::WASM_INIT_FUNCS);
987    encodeULEB128(InitFuncs.size(), W.OS);
988    for (auto &StartFunc : InitFuncs) {
989      encodeULEB128(StartFunc.first, W.OS);  // priority
990      encodeULEB128(StartFunc.second, W.OS); // function index
991    }
992    endSection(SubSection);
993  }
994
995  if (Comdats.size()) {
996    startSection(SubSection, wasm::WASM_COMDAT_INFO);
997    encodeULEB128(Comdats.size(), W.OS);
998    for (const auto &C : Comdats) {
999      writeString(C.first);
1000      encodeULEB128(0, W.OS); // flags for future use
1001      encodeULEB128(C.second.size(), W.OS);
1002      for (const WasmComdatEntry &Entry : C.second) {
1003        encodeULEB128(Entry.Kind, W.OS);
1004        encodeULEB128(Entry.Index, W.OS);
1005      }
1006    }
1007    endSection(SubSection);
1008  }
1009
1010  endSection(Section);
1011}
1012
1013void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1014                                          const MCAssembler &Asm,
1015                                          const MCAsmLayout &Layout) {
1016  SectionBookkeeping Section;
1017  auto *Sec = CustomSection.Section;
1018  startCustomSection(Section, CustomSection.Name);
1019
1020  Sec->setSectionOffset(W.OS.tell() - Section.ContentsOffset);
1021  Asm.writeSectionData(W.OS, Sec, Layout);
1022
1023  CustomSection.OutputContentsOffset = Section.ContentsOffset;
1024  CustomSection.OutputIndex = Section.Index;
1025
1026  endSection(Section);
1027
1028  // Apply fixups.
1029  auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1030  applyRelocations(Relocations, CustomSection.OutputContentsOffset);
1031}
1032
1033uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {
1034  assert(Symbol.isFunction());
1035  assert(TypeIndices.count(&Symbol));
1036  return TypeIndices[&Symbol];
1037}
1038
1039uint32_t WasmObjectWriter::getEventType(const MCSymbolWasm &Symbol) {
1040  assert(Symbol.isEvent());
1041  assert(TypeIndices.count(&Symbol));
1042  return TypeIndices[&Symbol];
1043}
1044
1045void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
1046  assert(Symbol.isFunction());
1047
1048  WasmSignature S;
1049  const MCSymbolWasm *ResolvedSym = resolveSymbol(Symbol);
1050  if (auto *Sig = ResolvedSym->getSignature()) {
1051    S.Returns = Sig->Returns;
1052    S.Params = Sig->Params;
1053  }
1054
1055  auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
1056  if (Pair.second)
1057    Signatures.push_back(S);
1058  TypeIndices[&Symbol] = Pair.first->second;
1059
1060  LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol
1061                    << " new:" << Pair.second << "\n");
1062  LLVM_DEBUG(dbgs() << "  -> type index: " << Pair.first->second << "\n");
1063}
1064
1065void WasmObjectWriter::registerEventType(const MCSymbolWasm &Symbol) {
1066  assert(Symbol.isEvent());
1067
1068  // TODO Currently we don't generate imported exceptions, but if we do, we
1069  // should have a way of infering types of imported exceptions.
1070  WasmSignature S;
1071  if (auto *Sig = Symbol.getSignature()) {
1072    S.Returns = Sig->Returns;
1073    S.Params = Sig->Params;
1074  }
1075
1076  auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
1077  if (Pair.second)
1078    Signatures.push_back(S);
1079  TypeIndices[&Symbol] = Pair.first->second;
1080
1081  LLVM_DEBUG(dbgs() << "registerEventType: " << Symbol << " new:" << Pair.second
1082                    << "\n");
1083  LLVM_DEBUG(dbgs() << "  -> type index: " << Pair.first->second << "\n");
1084}
1085
1086static bool isInSymtab(const MCSymbolWasm &Sym) {
1087  if (Sym.isUsedInReloc())
1088    return true;
1089
1090  if (Sym.isComdat() && !Sym.isDefined())
1091    return false;
1092
1093  if (Sym.isTemporary() && Sym.getName().empty())
1094    return false;
1095
1096  if (Sym.isTemporary() && Sym.isData() && !Sym.getSize())
1097    return false;
1098
1099  if (Sym.isSection())
1100    return false;
1101
1102  return true;
1103}
1104
1105uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
1106                                       const MCAsmLayout &Layout) {
1107  uint64_t StartOffset = W.OS.tell();
1108
1109  LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
1110
1111  // Collect information from the available symbols.
1112  SmallVector<WasmFunction, 4> Functions;
1113  SmallVector<uint32_t, 4> TableElems;
1114  SmallVector<wasm::WasmImport, 4> Imports;
1115  SmallVector<wasm::WasmExport, 4> Exports;
1116  SmallVector<wasm::WasmEventType, 1> Events;
1117  SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
1118  SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
1119  std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1120  uint32_t DataSize = 0;
1121
1122  // For now, always emit the memory import, since loads and stores are not
1123  // valid without it. In the future, we could perhaps be more clever and omit
1124  // it if there are no loads or stores.
1125  wasm::WasmImport MemImport;
1126  MemImport.Module = "env";
1127  MemImport.Field = "__linear_memory";
1128  MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
1129  Imports.push_back(MemImport);
1130
1131  // For now, always emit the table section, since indirect calls are not
1132  // valid without it. In the future, we could perhaps be more clever and omit
1133  // it if there are no indirect calls.
1134  wasm::WasmImport TableImport;
1135  TableImport.Module = "env";
1136  TableImport.Field = "__indirect_function_table";
1137  TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
1138  TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF;
1139  Imports.push_back(TableImport);
1140
1141  // Populate SignatureIndices, and Imports and WasmIndices for undefined
1142  // symbols.  This must be done before populating WasmIndices for defined
1143  // symbols.
1144  for (const MCSymbol &S : Asm.symbols()) {
1145    const auto &WS = static_cast<const MCSymbolWasm &>(S);
1146
1147    // Register types for all functions, including those with private linkage
1148    // (because wasm always needs a type signature).
1149    if (WS.isFunction())
1150      registerFunctionType(WS);
1151
1152    if (WS.isEvent())
1153      registerEventType(WS);
1154
1155    if (WS.isTemporary())
1156      continue;
1157
1158    // If the symbol is not defined in this translation unit, import it.
1159    if (!WS.isDefined() && !WS.isComdat()) {
1160      if (WS.isFunction()) {
1161        wasm::WasmImport Import;
1162        Import.Module = WS.getImportModule();
1163        Import.Field = WS.getImportName();
1164        Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
1165        Import.SigIndex = getFunctionType(WS);
1166        Imports.push_back(Import);
1167        assert(WasmIndices.count(&WS) == 0);
1168        WasmIndices[&WS] = NumFunctionImports++;
1169      } else if (WS.isGlobal()) {
1170        if (WS.isWeak())
1171          report_fatal_error("undefined global symbol cannot be weak");
1172
1173        wasm::WasmImport Import;
1174        Import.Field = WS.getImportName();
1175        Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1176        Import.Module = WS.getImportModule();
1177        Import.Global = WS.getGlobalType();
1178        Imports.push_back(Import);
1179        assert(WasmIndices.count(&WS) == 0);
1180        WasmIndices[&WS] = NumGlobalImports++;
1181      } else if (WS.isEvent()) {
1182        if (WS.isWeak())
1183          report_fatal_error("undefined event symbol cannot be weak");
1184
1185        wasm::WasmImport Import;
1186        Import.Module = WS.getImportModule();
1187        Import.Field = WS.getImportName();
1188        Import.Kind = wasm::WASM_EXTERNAL_EVENT;
1189        Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
1190        Import.Event.SigIndex = getEventType(WS);
1191        Imports.push_back(Import);
1192        assert(WasmIndices.count(&WS) == 0);
1193        WasmIndices[&WS] = NumEventImports++;
1194      }
1195    }
1196  }
1197
1198  // Add imports for GOT globals
1199  for (const MCSymbol &S : Asm.symbols()) {
1200    const auto &WS = static_cast<const MCSymbolWasm &>(S);
1201    if (WS.isUsedInGOT()) {
1202      wasm::WasmImport Import;
1203      if (WS.isFunction())
1204        Import.Module = "GOT.func";
1205      else
1206        Import.Module = "GOT.mem";
1207      Import.Field = WS.getName();
1208      Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1209      Import.Global = {wasm::WASM_TYPE_I32, true};
1210      Imports.push_back(Import);
1211      assert(GOTIndices.count(&WS) == 0);
1212      GOTIndices[&WS] = NumGlobalImports++;
1213    }
1214  }
1215
1216  // Populate DataSegments and CustomSections, which must be done before
1217  // populating DataLocations.
1218  for (MCSection &Sec : Asm) {
1219    auto &Section = static_cast<MCSectionWasm &>(Sec);
1220    StringRef SectionName = Section.getSectionName();
1221
1222    // .init_array sections are handled specially elsewhere.
1223    if (SectionName.startswith(".init_array"))
1224      continue;
1225
1226    // Code is handled separately
1227    if (Section.getKind().isText())
1228      continue;
1229
1230    if (Section.isWasmData()) {
1231      uint32_t SegmentIndex = DataSegments.size();
1232      DataSize = alignTo(DataSize, Section.getAlignment());
1233      DataSegments.emplace_back();
1234      WasmDataSegment &Segment = DataSegments.back();
1235      Segment.Name = SectionName;
1236      Segment.InitFlags =
1237          Section.getPassive() ? (uint32_t)wasm::WASM_SEGMENT_IS_PASSIVE : 0;
1238      Segment.Offset = DataSize;
1239      Segment.Section = &Section;
1240      addData(Segment.Data, Section);
1241      Segment.Alignment = Log2_32(Section.getAlignment());
1242      Segment.LinkerFlags = 0;
1243      DataSize += Segment.Data.size();
1244      Section.setSegmentIndex(SegmentIndex);
1245
1246      if (const MCSymbolWasm *C = Section.getGroup()) {
1247        Comdats[C->getName()].emplace_back(
1248            WasmComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex});
1249      }
1250    } else {
1251      // Create custom sections
1252      assert(Sec.getKind().isMetadata());
1253
1254      StringRef Name = SectionName;
1255
1256      // For user-defined custom sections, strip the prefix
1257      if (Name.startswith(".custom_section."))
1258        Name = Name.substr(strlen(".custom_section."));
1259
1260      MCSymbol *Begin = Sec.getBeginSymbol();
1261      if (Begin) {
1262        WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1263        if (SectionName != Begin->getName())
1264          report_fatal_error("section name and begin symbol should match: " +
1265                             Twine(SectionName));
1266      }
1267
1268      // Separate out the producers and target features sections
1269      if (Name == "producers") {
1270        ProducersSection = std::make_unique<WasmCustomSection>(Name, &Section);
1271        continue;
1272      }
1273      if (Name == "target_features") {
1274        TargetFeaturesSection =
1275            std::make_unique<WasmCustomSection>(Name, &Section);
1276        continue;
1277      }
1278
1279      CustomSections.emplace_back(Name, &Section);
1280    }
1281  }
1282
1283  // Populate WasmIndices and DataLocations for defined symbols.
1284  for (const MCSymbol &S : Asm.symbols()) {
1285    // Ignore unnamed temporary symbols, which aren't ever exported, imported,
1286    // or used in relocations.
1287    if (S.isTemporary() && S.getName().empty())
1288      continue;
1289
1290    const auto &WS = static_cast<const MCSymbolWasm &>(S);
1291    LLVM_DEBUG(
1292        dbgs() << "MCSymbol: " << toString(WS.getType()) << " '" << S << "'"
1293               << " isDefined=" << S.isDefined() << " isExternal="
1294               << S.isExternal() << " isTemporary=" << S.isTemporary()
1295               << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden()
1296               << " isVariable=" << WS.isVariable() << "\n");
1297
1298    if (WS.isVariable())
1299      continue;
1300    if (WS.isComdat() && !WS.isDefined())
1301      continue;
1302
1303    if (WS.isFunction()) {
1304      unsigned Index;
1305      if (WS.isDefined()) {
1306        if (WS.getOffset() != 0)
1307          report_fatal_error(
1308              "function sections must contain one function each");
1309
1310        if (WS.getSize() == nullptr)
1311          report_fatal_error(
1312              "function symbols must have a size set with .size");
1313
1314        // A definition. Write out the function body.
1315        Index = NumFunctionImports + Functions.size();
1316        WasmFunction Func;
1317        Func.SigIndex = getFunctionType(WS);
1318        Func.Sym = &WS;
1319        WasmIndices[&WS] = Index;
1320        Functions.push_back(Func);
1321
1322        auto &Section = static_cast<MCSectionWasm &>(WS.getSection());
1323        if (const MCSymbolWasm *C = Section.getGroup()) {
1324          Comdats[C->getName()].emplace_back(
1325              WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index});
1326        }
1327
1328        if (WS.hasExportName()) {
1329          wasm::WasmExport Export;
1330          Export.Name = WS.getExportName();
1331          Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
1332          Export.Index = Index;
1333          Exports.push_back(Export);
1334        }
1335      } else {
1336        // An import; the index was assigned above.
1337        Index = WasmIndices.find(&WS)->second;
1338      }
1339
1340      LLVM_DEBUG(dbgs() << "  -> function index: " << Index << "\n");
1341
1342    } else if (WS.isData()) {
1343      if (!isInSymtab(WS))
1344        continue;
1345
1346      if (!WS.isDefined()) {
1347        LLVM_DEBUG(dbgs() << "  -> segment index: -1"
1348                          << "\n");
1349        continue;
1350      }
1351
1352      if (!WS.getSize())
1353        report_fatal_error("data symbols must have a size set with .size: " +
1354                           WS.getName());
1355
1356      int64_t Size = 0;
1357      if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
1358        report_fatal_error(".size expression must be evaluatable");
1359
1360      auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
1361      if (!DataSection.isWasmData())
1362        report_fatal_error("data symbols must live in a data section: " +
1363                           WS.getName());
1364
1365      // For each data symbol, export it in the symtab as a reference to the
1366      // corresponding Wasm data segment.
1367      wasm::WasmDataReference Ref = wasm::WasmDataReference{
1368          DataSection.getSegmentIndex(),
1369          static_cast<uint32_t>(Layout.getSymbolOffset(WS)),
1370          static_cast<uint32_t>(Size)};
1371      DataLocations[&WS] = Ref;
1372      LLVM_DEBUG(dbgs() << "  -> segment index: " << Ref.Segment << "\n");
1373
1374    } else if (WS.isGlobal()) {
1375      // A "true" Wasm global (currently just __stack_pointer)
1376      if (WS.isDefined())
1377        report_fatal_error("don't yet support defined globals");
1378
1379      // An import; the index was assigned above
1380      LLVM_DEBUG(dbgs() << "  -> global index: "
1381                        << WasmIndices.find(&WS)->second << "\n");
1382
1383    } else if (WS.isEvent()) {
1384      // C++ exception symbol (__cpp_exception)
1385      unsigned Index;
1386      if (WS.isDefined()) {
1387        Index = NumEventImports + Events.size();
1388        wasm::WasmEventType Event;
1389        Event.SigIndex = getEventType(WS);
1390        Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION;
1391        assert(WasmIndices.count(&WS) == 0);
1392        WasmIndices[&WS] = Index;
1393        Events.push_back(Event);
1394      } else {
1395        // An import; the index was assigned above.
1396        assert(WasmIndices.count(&WS) > 0);
1397      }
1398      LLVM_DEBUG(dbgs() << "  -> event index: " << WasmIndices.find(&WS)->second
1399                        << "\n");
1400
1401    } else {
1402      assert(WS.isSection());
1403    }
1404  }
1405
1406  // Populate WasmIndices and DataLocations for aliased symbols.  We need to
1407  // process these in a separate pass because we need to have processed the
1408  // target of the alias before the alias itself and the symbols are not
1409  // necessarily ordered in this way.
1410  for (const MCSymbol &S : Asm.symbols()) {
1411    if (!S.isVariable())
1412      continue;
1413
1414    assert(S.isDefined());
1415
1416    // Find the target symbol of this weak alias and export that index
1417    const auto &WS = static_cast<const MCSymbolWasm &>(S);
1418    const MCSymbolWasm *ResolvedSym = resolveSymbol(WS);
1419    LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym
1420                      << "'\n");
1421
1422    if (ResolvedSym->isFunction()) {
1423      assert(WasmIndices.count(ResolvedSym) > 0);
1424      uint32_t WasmIndex = WasmIndices.find(ResolvedSym)->second;
1425      assert(WasmIndices.count(&WS) == 0);
1426      WasmIndices[&WS] = WasmIndex;
1427      LLVM_DEBUG(dbgs() << "  -> index:" << WasmIndex << "\n");
1428    } else if (ResolvedSym->isData()) {
1429      assert(DataLocations.count(ResolvedSym) > 0);
1430      const wasm::WasmDataReference &Ref =
1431          DataLocations.find(ResolvedSym)->second;
1432      DataLocations[&WS] = Ref;
1433      LLVM_DEBUG(dbgs() << "  -> index:" << Ref.Segment << "\n");
1434    } else {
1435      report_fatal_error("don't yet support global/event aliases");
1436    }
1437  }
1438
1439  // Finally, populate the symbol table itself, in its "natural" order.
1440  for (const MCSymbol &S : Asm.symbols()) {
1441    const auto &WS = static_cast<const MCSymbolWasm &>(S);
1442    if (!isInSymtab(WS)) {
1443      WS.setIndex(InvalidIndex);
1444      continue;
1445    }
1446    LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n");
1447
1448    uint32_t Flags = 0;
1449    if (WS.isWeak())
1450      Flags |= wasm::WASM_SYMBOL_BINDING_WEAK;
1451    if (WS.isHidden())
1452      Flags |= wasm::WASM_SYMBOL_VISIBILITY_HIDDEN;
1453    if (!WS.isExternal() && WS.isDefined())
1454      Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL;
1455    if (WS.isUndefined())
1456      Flags |= wasm::WASM_SYMBOL_UNDEFINED;
1457    if (WS.isNoStrip()) {
1458      Flags |= wasm::WASM_SYMBOL_NO_STRIP;
1459      if (isEmscripten()) {
1460        Flags |= wasm::WASM_SYMBOL_EXPORTED;
1461      }
1462    }
1463    if (WS.hasImportName())
1464      Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME;
1465    if (WS.hasExportName())
1466      Flags |= wasm::WASM_SYMBOL_EXPORTED;
1467
1468    wasm::WasmSymbolInfo Info;
1469    Info.Name = WS.getName();
1470    Info.Kind = WS.getType();
1471    Info.Flags = Flags;
1472    if (!WS.isData()) {
1473      assert(WasmIndices.count(&WS) > 0);
1474      Info.ElementIndex = WasmIndices.find(&WS)->second;
1475    } else if (WS.isDefined()) {
1476      assert(DataLocations.count(&WS) > 0);
1477      Info.DataRef = DataLocations.find(&WS)->second;
1478    }
1479    WS.setIndex(SymbolInfos.size());
1480    SymbolInfos.emplace_back(Info);
1481  }
1482
1483  {
1484    auto HandleReloc = [&](const WasmRelocationEntry &Rel) {
1485      // Functions referenced by a relocation need to put in the table.  This is
1486      // purely to make the object file's provisional values readable, and is
1487      // ignored by the linker, which re-calculates the relocations itself.
1488      if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1489          Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB)
1490        return;
1491      assert(Rel.Symbol->isFunction());
1492      const MCSymbolWasm &WS = *resolveSymbol(*Rel.Symbol);
1493      uint32_t FunctionIndex = WasmIndices.find(&WS)->second;
1494      uint32_t TableIndex = TableElems.size() + InitialTableOffset;
1495      if (TableIndices.try_emplace(&WS, TableIndex).second) {
1496        LLVM_DEBUG(dbgs() << "  -> adding " << WS.getName()
1497                          << " to table: " << TableIndex << "\n");
1498        TableElems.push_back(FunctionIndex);
1499        registerFunctionType(WS);
1500      }
1501    };
1502
1503    for (const WasmRelocationEntry &RelEntry : CodeRelocations)
1504      HandleReloc(RelEntry);
1505    for (const WasmRelocationEntry &RelEntry : DataRelocations)
1506      HandleReloc(RelEntry);
1507  }
1508
1509  // Translate .init_array section contents into start functions.
1510  for (const MCSection &S : Asm) {
1511    const auto &WS = static_cast<const MCSectionWasm &>(S);
1512    if (WS.getSectionName().startswith(".fini_array"))
1513      report_fatal_error(".fini_array sections are unsupported");
1514    if (!WS.getSectionName().startswith(".init_array"))
1515      continue;
1516    if (WS.getFragmentList().empty())
1517      continue;
1518
1519    // init_array is expected to contain a single non-empty data fragment
1520    if (WS.getFragmentList().size() != 3)
1521      report_fatal_error("only one .init_array section fragment supported");
1522
1523    auto IT = WS.begin();
1524    const MCFragment &EmptyFrag = *IT;
1525    if (EmptyFrag.getKind() != MCFragment::FT_Data)
1526      report_fatal_error(".init_array section should be aligned");
1527
1528    IT = std::next(IT);
1529    const MCFragment &AlignFrag = *IT;
1530    if (AlignFrag.getKind() != MCFragment::FT_Align)
1531      report_fatal_error(".init_array section should be aligned");
1532    if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (is64Bit() ? 8 : 4))
1533      report_fatal_error(".init_array section should be aligned for pointers");
1534
1535    const MCFragment &Frag = *std::next(IT);
1536    if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
1537      report_fatal_error("only data supported in .init_array section");
1538
1539    uint16_t Priority = UINT16_MAX;
1540    unsigned PrefixLength = strlen(".init_array");
1541    if (WS.getSectionName().size() > PrefixLength) {
1542      if (WS.getSectionName()[PrefixLength] != '.')
1543        report_fatal_error(
1544            ".init_array section priority should start with '.'");
1545      if (WS.getSectionName()
1546              .substr(PrefixLength + 1)
1547              .getAsInteger(10, Priority))
1548        report_fatal_error("invalid .init_array section priority");
1549    }
1550    const auto &DataFrag = cast<MCDataFragment>(Frag);
1551    const SmallVectorImpl<char> &Contents = DataFrag.getContents();
1552    for (const uint8_t *
1553             P = (const uint8_t *)Contents.data(),
1554            *End = (const uint8_t *)Contents.data() + Contents.size();
1555         P != End; ++P) {
1556      if (*P != 0)
1557        report_fatal_error("non-symbolic data in .init_array section");
1558    }
1559    for (const MCFixup &Fixup : DataFrag.getFixups()) {
1560      assert(Fixup.getKind() ==
1561             MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
1562      const MCExpr *Expr = Fixup.getValue();
1563      auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1564      if (!SymRef)
1565        report_fatal_error("fixups in .init_array should be symbol references");
1566      const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1567      if (TargetSym.getIndex() == InvalidIndex)
1568        report_fatal_error("symbols in .init_array should exist in symbtab");
1569      if (!TargetSym.isFunction())
1570        report_fatal_error("symbols in .init_array should be for functions");
1571      InitFuncs.push_back(
1572          std::make_pair(Priority, TargetSym.getIndex()));
1573    }
1574  }
1575
1576  // Write out the Wasm header.
1577  writeHeader(Asm);
1578
1579  writeTypeSection(Signatures);
1580  writeImportSection(Imports, DataSize, TableElems.size());
1581  writeFunctionSection(Functions);
1582  // Skip the "table" section; we import the table instead.
1583  // Skip the "memory" section; we import the memory instead.
1584  writeEventSection(Events);
1585  writeExportSection(Exports);
1586  writeElemSection(TableElems);
1587  writeDataCountSection();
1588  writeCodeSection(Asm, Layout, Functions);
1589  writeDataSection();
1590  for (auto &CustomSection : CustomSections)
1591    writeCustomSection(CustomSection, Asm, Layout);
1592  writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1593  writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);
1594  writeRelocSection(DataSectionIndex, "DATA", DataRelocations);
1595  writeCustomRelocSections();
1596  if (ProducersSection)
1597    writeCustomSection(*ProducersSection, Asm, Layout);
1598  if (TargetFeaturesSection)
1599    writeCustomSection(*TargetFeaturesSection, Asm, Layout);
1600
1601  // TODO: Translate the .comment section to the output.
1602  return W.OS.tell() - StartOffset;
1603}
1604
1605std::unique_ptr<MCObjectWriter>
1606llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
1607                             raw_pwrite_stream &OS) {
1608  return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
1609}
1610