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