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