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