LLVM  16.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;
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;
64  StringRef Name;
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  MCSection *Section;
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;
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.getAlign()));
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(
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.Section);
1062 
1063  int64_t Size = Layout.getSectionAddressSize(FuncSection);
1064  encodeULEB128(Size, W->OS);
1065  FuncSection->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
1066  Asm.writeSectionData(W->OS, FuncSection, Layout);
1067  }
1068 
1069  // Apply fixups.
1070  applyRelocations(CodeRelocations, Section.ContentsOffset, Layout);
1071 
1072  endSection(Section);
1073  return Section.Index;
1074 }
1075 
1076 uint32_t WasmObjectWriter::writeDataSection(const MCAsmLayout &Layout) {
1077  if (DataSegments.empty())
1078  return 0;
1079 
1080  SectionBookkeeping Section;
1081  startSection(Section, wasm::WASM_SEC_DATA);
1082 
1083  encodeULEB128(DataSegments.size(), W->OS); // count
1084 
1085  for (const WasmDataSegment &Segment : DataSegments) {
1086  encodeULEB128(Segment.InitFlags, W->OS); // flags
1087  if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX)
1088  encodeULEB128(0, W->OS); // memory index
1089  if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) {
1090  W->OS << char(is64Bit() ? wasm::WASM_OPCODE_I64_CONST
1092  encodeSLEB128(Segment.Offset, W->OS); // offset
1093  W->OS << char(wasm::WASM_OPCODE_END);
1094  }
1095  encodeULEB128(Segment.Data.size(), W->OS); // size
1096  Segment.Section->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
1097  W->OS << Segment.Data; // data
1098  }
1099 
1100  // Apply fixups.
1101  applyRelocations(DataRelocations, Section.ContentsOffset, Layout);
1102 
1103  endSection(Section);
1104  return Section.Index;
1105 }
1106 
1107 void WasmObjectWriter::writeRelocSection(
1108  uint32_t SectionIndex, StringRef Name,
1109  std::vector<WasmRelocationEntry> &Relocs) {
1110  // See: https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md
1111  // for descriptions of the reloc sections.
1112 
1113  if (Relocs.empty())
1114  return;
1115 
1116  // First, ensure the relocations are sorted in offset order. In general they
1117  // should already be sorted since `recordRelocation` is called in offset
1118  // order, but for the code section we combine many MC sections into single
1119  // wasm section, and this order is determined by the order of Asm.Symbols()
1120  // not the sections order.
1122  Relocs, [](const WasmRelocationEntry &A, const WasmRelocationEntry &B) {
1123  return (A.Offset + A.FixupSection->getSectionOffset()) <
1124  (B.Offset + B.FixupSection->getSectionOffset());
1125  });
1126 
1127  SectionBookkeeping Section;
1128  startCustomSection(Section, std::string("reloc.") + Name.str());
1129 
1130  encodeULEB128(SectionIndex, W->OS);
1131  encodeULEB128(Relocs.size(), W->OS);
1132  for (const WasmRelocationEntry &RelEntry : Relocs) {
1133  uint64_t Offset =
1134  RelEntry.Offset + RelEntry.FixupSection->getSectionOffset();
1135  uint32_t Index = getRelocationIndexValue(RelEntry);
1136 
1137  W->OS << char(RelEntry.Type);
1138  encodeULEB128(Offset, W->OS);
1139  encodeULEB128(Index, W->OS);
1140  if (RelEntry.hasAddend())
1141  encodeSLEB128(RelEntry.Addend, W->OS);
1142  }
1143 
1144  endSection(Section);
1145 }
1146 
1147 void WasmObjectWriter::writeCustomRelocSections() {
1148  for (const auto &Sec : CustomSections) {
1149  auto &Relocations = CustomSectionsRelocations[Sec.Section];
1150  writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1151  }
1152 }
1153 
1154 void WasmObjectWriter::writeLinkingMetaDataSection(
1155  ArrayRef<wasm::WasmSymbolInfo> SymbolInfos,
1156  ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1157  const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) {
1158  SectionBookkeeping Section;
1159  startCustomSection(Section, "linking");
1161 
1162  SectionBookkeeping SubSection;
1163  if (SymbolInfos.size() != 0) {
1164  startSection(SubSection, wasm::WASM_SYMBOL_TABLE);
1165  encodeULEB128(SymbolInfos.size(), W->OS);
1166  for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) {
1167  encodeULEB128(Sym.Kind, W->OS);
1168  encodeULEB128(Sym.Flags, W->OS);
1169  switch (Sym.Kind) {
1174  encodeULEB128(Sym.ElementIndex, W->OS);
1175  if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
1177  writeString(Sym.Name);
1178  break;
1180  writeString(Sym.Name);
1181  if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) {
1182  encodeULEB128(Sym.DataRef.Segment, W->OS);
1183  encodeULEB128(Sym.DataRef.Offset, W->OS);
1184  encodeULEB128(Sym.DataRef.Size, W->OS);
1185  }
1186  break;
1188  const uint32_t SectionIndex =
1189  CustomSections[Sym.ElementIndex].OutputIndex;
1190  encodeULEB128(SectionIndex, W->OS);
1191  break;
1192  }
1193  default:
1194  llvm_unreachable("unexpected kind");
1195  }
1196  }
1197  endSection(SubSection);
1198  }
1199 
1200  if (DataSegments.size()) {
1201  startSection(SubSection, wasm::WASM_SEGMENT_INFO);
1202  encodeULEB128(DataSegments.size(), W->OS);
1203  for (const WasmDataSegment &Segment : DataSegments) {
1204  writeString(Segment.Name);
1205  encodeULEB128(Segment.Alignment, W->OS);
1206  encodeULEB128(Segment.LinkingFlags, W->OS);
1207  }
1208  endSection(SubSection);
1209  }
1210 
1211  if (!InitFuncs.empty()) {
1212  startSection(SubSection, wasm::WASM_INIT_FUNCS);
1213  encodeULEB128(InitFuncs.size(), W->OS);
1214  for (auto &StartFunc : InitFuncs) {
1215  encodeULEB128(StartFunc.first, W->OS); // priority
1216  encodeULEB128(StartFunc.second, W->OS); // function index
1217  }
1218  endSection(SubSection);
1219  }
1220 
1221  if (Comdats.size()) {
1222  startSection(SubSection, wasm::WASM_COMDAT_INFO);
1223  encodeULEB128(Comdats.size(), W->OS);
1224  for (const auto &C : Comdats) {
1225  writeString(C.first);
1226  encodeULEB128(0, W->OS); // flags for future use
1227  encodeULEB128(C.second.size(), W->OS);
1228  for (const WasmComdatEntry &Entry : C.second) {
1229  encodeULEB128(Entry.Kind, W->OS);
1230  encodeULEB128(Entry.Index, W->OS);
1231  }
1232  }
1233  endSection(SubSection);
1234  }
1235 
1236  endSection(Section);
1237 }
1238 
1239 void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1240  const MCAssembler &Asm,
1241  const MCAsmLayout &Layout) {
1242  SectionBookkeeping Section;
1243  auto *Sec = CustomSection.Section;
1244  startCustomSection(Section, CustomSection.Name);
1245 
1246  Sec->setSectionOffset(W->OS.tell() - Section.ContentsOffset);
1247  Asm.writeSectionData(W->OS, Sec, Layout);
1248 
1249  CustomSection.OutputContentsOffset = Section.ContentsOffset;
1250  CustomSection.OutputIndex = Section.Index;
1251 
1252  endSection(Section);
1253 
1254  // Apply fixups.
1255  auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1256  applyRelocations(Relocations, CustomSection.OutputContentsOffset, Layout);
1257 }
1258 
1259 uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm &Symbol) {
1260  assert(Symbol.isFunction());
1261  assert(TypeIndices.count(&Symbol));
1262  return TypeIndices[&Symbol];
1263 }
1264 
1265 uint32_t WasmObjectWriter::getTagType(const MCSymbolWasm &Symbol) {
1266  assert(Symbol.isTag());
1267  assert(TypeIndices.count(&Symbol));
1268  return TypeIndices[&Symbol];
1269 }
1270 
1271 void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) {
1272  assert(Symbol.isFunction());
1273 
1275 
1276  if (auto *Sig = Symbol.getSignature()) {
1277  S.Returns = Sig->Returns;
1278  S.Params = Sig->Params;
1279  }
1280 
1281  auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
1282  if (Pair.second)
1283  Signatures.push_back(S);
1284  TypeIndices[&Symbol] = Pair.first->second;
1285 
1286  LLVM_DEBUG(dbgs() << "registerFunctionType: " << Symbol
1287  << " new:" << Pair.second << "\n");
1288  LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
1289 }
1290 
1291 void WasmObjectWriter::registerTagType(const MCSymbolWasm &Symbol) {
1292  assert(Symbol.isTag());
1293 
1294  // TODO Currently we don't generate imported exceptions, but if we do, we
1295  // should have a way of infering types of imported exceptions.
1297  if (auto *Sig = Symbol.getSignature()) {
1298  S.Returns = Sig->Returns;
1299  S.Params = Sig->Params;
1300  }
1301 
1302  auto Pair = SignatureIndices.insert(std::make_pair(S, Signatures.size()));
1303  if (Pair.second)
1304  Signatures.push_back(S);
1305  TypeIndices[&Symbol] = Pair.first->second;
1306 
1307  LLVM_DEBUG(dbgs() << "registerTagType: " << Symbol << " new:" << Pair.second
1308  << "\n");
1309  LLVM_DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
1310 }
1311 
1312 static bool isInSymtab(const MCSymbolWasm &Sym) {
1313  if (Sym.isUsedInReloc() || Sym.isUsedInInitArray())
1314  return true;
1315 
1316  if (Sym.isComdat() && !Sym.isDefined())
1317  return false;
1318 
1319  if (Sym.isTemporary())
1320  return false;
1321 
1322  if (Sym.isSection())
1323  return false;
1324 
1325  if (Sym.omitFromLinkingSection())
1326  return false;
1327 
1328  return true;
1329 }
1330 
1331 void WasmObjectWriter::prepareImports(
1333  const MCAsmLayout &Layout) {
1334  // For now, always emit the memory import, since loads and stores are not
1335  // valid without it. In the future, we could perhaps be more clever and omit
1336  // it if there are no loads or stores.
1337  wasm::WasmImport MemImport;
1338  MemImport.Module = "env";
1339  MemImport.Field = "__linear_memory";
1340  MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
1343  Imports.push_back(MemImport);
1344 
1345  // Populate SignatureIndices, and Imports and WasmIndices for undefined
1346  // symbols. This must be done before populating WasmIndices for defined
1347  // symbols.
1348  for (const MCSymbol &S : Asm.symbols()) {
1349  const auto &WS = static_cast<const MCSymbolWasm &>(S);
1350 
1351  // Register types for all functions, including those with private linkage
1352  // (because wasm always needs a type signature).
1353  if (WS.isFunction()) {
1354  const auto *BS = Layout.getBaseSymbol(S);
1355  if (!BS)
1356  report_fatal_error(Twine(S.getName()) +
1357  ": absolute addressing not supported!");
1358  registerFunctionType(*cast<MCSymbolWasm>(BS));
1359  }
1360 
1361  if (WS.isTag())
1362  registerTagType(WS);
1363 
1364  if (WS.isTemporary())
1365  continue;
1366 
1367  // If the symbol is not defined in this translation unit, import it.
1368  if (!WS.isDefined() && !WS.isComdat()) {
1369  if (WS.isFunction()) {
1371  Import.Module = WS.getImportModule();
1372  Import.Field = WS.getImportName();
1374  Import.SigIndex = getFunctionType(WS);
1375  Imports.push_back(Import);
1376  assert(WasmIndices.count(&WS) == 0);
1377  WasmIndices[&WS] = NumFunctionImports++;
1378  } else if (WS.isGlobal()) {
1379  if (WS.isWeak())
1380  report_fatal_error("undefined global symbol cannot be weak");
1381 
1383  Import.Field = WS.getImportName();
1385  Import.Module = WS.getImportModule();
1386  Import.Global = WS.getGlobalType();
1387  Imports.push_back(Import);
1388  assert(WasmIndices.count(&WS) == 0);
1389  WasmIndices[&WS] = NumGlobalImports++;
1390  } else if (WS.isTag()) {
1391  if (WS.isWeak())
1392  report_fatal_error("undefined tag symbol cannot be weak");
1393 
1395  Import.Module = WS.getImportModule();
1396  Import.Field = WS.getImportName();
1398  Import.SigIndex = getTagType(WS);
1399  Imports.push_back(Import);
1400  assert(WasmIndices.count(&WS) == 0);
1401  WasmIndices[&WS] = NumTagImports++;
1402  } else if (WS.isTable()) {
1403  if (WS.isWeak())
1404  report_fatal_error("undefined table symbol cannot be weak");
1405 
1407  Import.Module = WS.getImportModule();
1408  Import.Field = WS.getImportName();
1410  Import.Table = WS.getTableType();
1411  Imports.push_back(Import);
1412  assert(WasmIndices.count(&WS) == 0);
1413  WasmIndices[&WS] = NumTableImports++;
1414  }
1415  }
1416  }
1417 
1418  // Add imports for GOT globals
1419  for (const MCSymbol &S : Asm.symbols()) {
1420  const auto &WS = static_cast<const MCSymbolWasm &>(S);
1421  if (WS.isUsedInGOT()) {
1423  if (WS.isFunction())
1424  Import.Module = "GOT.func";
1425  else
1426  Import.Module = "GOT.mem";
1427  Import.Field = WS.getName();
1429  Import.Global = {wasm::WASM_TYPE_I32, true};
1430  Imports.push_back(Import);
1431  assert(GOTIndices.count(&WS) == 0);
1432  GOTIndices[&WS] = NumGlobalImports++;
1433  }
1434  }
1435 }
1436 
1437 uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
1438  const MCAsmLayout &Layout) {
1439  support::endian::Writer MainWriter(*OS, support::little);
1440  W = &MainWriter;
1441  if (IsSplitDwarf) {
1442  uint64_t TotalSize = writeOneObject(Asm, Layout, DwoMode::NonDwoOnly);
1443  assert(DwoOS);
1444  support::endian::Writer DwoWriter(*DwoOS, support::little);
1445  W = &DwoWriter;
1446  return TotalSize + writeOneObject(Asm, Layout, DwoMode::DwoOnly);
1447  } else {
1448  return writeOneObject(Asm, Layout, DwoMode::AllSections);
1449  }
1450 }
1451 
1452 uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
1453  const MCAsmLayout &Layout,
1454  DwoMode Mode) {
1455  uint64_t StartOffset = W->OS.tell();
1456  SectionCount = 0;
1457  CustomSections.clear();
1458 
1459  LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
1460 
1461  // Collect information from the available symbols.
1462  SmallVector<WasmFunction, 4> Functions;
1463  SmallVector<uint32_t, 4> TableElems;
1466  SmallVector<uint32_t, 2> TagTypes;
1471  std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1472  uint64_t DataSize = 0;
1473  if (Mode != DwoMode::DwoOnly) {
1474  prepareImports(Imports, Asm, Layout);
1475  }
1476 
1477  // Populate DataSegments and CustomSections, which must be done before
1478  // populating DataLocations.
1479  for (MCSection &Sec : Asm) {
1480  auto &Section = static_cast<MCSectionWasm &>(Sec);
1481  StringRef SectionName = Section.getName();
1482 
1483  if (Mode == DwoMode::NonDwoOnly && isDwoSection(Sec))
1484  continue;
1485  if (Mode == DwoMode::DwoOnly && !isDwoSection(Sec))
1486  continue;
1487 
1488  LLVM_DEBUG(dbgs() << "Processing Section " << SectionName << " group "
1489  << Section.getGroup() << "\n";);
1490 
1491  // .init_array sections are handled specially elsewhere.
1492  if (SectionName.startswith(".init_array"))
1493  continue;
1494 
1495  // Code is handled separately
1496  if (Section.getKind().isText())
1497  continue;
1498 
1499  if (Section.isWasmData()) {
1500  uint32_t SegmentIndex = DataSegments.size();
1501  DataSize = alignTo(DataSize, Section.getAlign());
1502  DataSegments.emplace_back();
1503  WasmDataSegment &Segment = DataSegments.back();
1504  Segment.Name = SectionName;
1505  Segment.InitFlags = Section.getPassive()
1507  : 0;
1508  Segment.Offset = DataSize;
1509  Segment.Section = &Section;
1510  addData(Segment.Data, Section);
1511  Segment.Alignment = Log2(Section.getAlign());
1512  Segment.LinkingFlags = Section.getSegmentFlags();
1513  DataSize += Segment.Data.size();
1514  Section.setSegmentIndex(SegmentIndex);
1515 
1516  if (const MCSymbolWasm *C = Section.getGroup()) {
1517  Comdats[C->getName()].emplace_back(
1518  WasmComdatEntry{wasm::WASM_COMDAT_DATA, SegmentIndex});
1519  }
1520  } else {
1521  // Create custom sections
1522  assert(Sec.getKind().isMetadata());
1523 
1525 
1526  // For user-defined custom sections, strip the prefix
1527  if (Name.startswith(".custom_section."))
1528  Name = Name.substr(strlen(".custom_section."));
1529 
1530  MCSymbol *Begin = Sec.getBeginSymbol();
1531  if (Begin) {
1532  assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0);
1533  WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size();
1534  }
1535 
1536  // Separate out the producers and target features sections
1537  if (Name == "producers") {
1538  ProducersSection = std::make_unique<WasmCustomSection>(Name, &Section);
1539  continue;
1540  }
1541  if (Name == "target_features") {
1542  TargetFeaturesSection =
1543  std::make_unique<WasmCustomSection>(Name, &Section);
1544  continue;
1545  }
1546 
1547  // Custom sections can also belong to COMDAT groups. In this case the
1548  // decriptor's "index" field is the section index (in the final object
1549  // file), but that is not known until after layout, so it must be fixed up
1550  // later
1551  if (const MCSymbolWasm *C = Section.getGroup()) {
1552  Comdats[C->getName()].emplace_back(
1553  WasmComdatEntry{wasm::WASM_COMDAT_SECTION,
1554  static_cast<uint32_t>(CustomSections.size())});
1555  }
1556 
1557  CustomSections.emplace_back(Name, &Section);
1558  }
1559  }
1560 
1561  if (Mode != DwoMode::DwoOnly) {
1562  // Populate WasmIndices and DataLocations for defined symbols.
1563  for (const MCSymbol &S : Asm.symbols()) {
1564  // Ignore unnamed temporary symbols, which aren't ever exported, imported,
1565  // or used in relocations.
1566  if (S.isTemporary() && S.getName().empty())
1567  continue;
1568 
1569  const auto &WS = static_cast<const MCSymbolWasm &>(S);
1570  LLVM_DEBUG(
1571  dbgs() << "MCSymbol: "
1572  << toString(WS.getType().value_or(wasm::WASM_SYMBOL_TYPE_DATA))
1573  << " '" << S << "'"
1574  << " isDefined=" << S.isDefined() << " isExternal="
1575  << S.isExternal() << " isTemporary=" << S.isTemporary()
1576  << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden()
1577  << " isVariable=" << WS.isVariable() << "\n");
1578 
1579  if (WS.isVariable())
1580  continue;
1581  if (WS.isComdat() && !WS.isDefined())
1582  continue;
1583 
1584  if (WS.isFunction()) {
1585  unsigned Index;
1586  if (WS.isDefined()) {
1587  if (WS.getOffset() != 0)
1589  "function sections must contain one function each");
1590 
1591  // A definition. Write out the function body.
1592  Index = NumFunctionImports + Functions.size();
1593  WasmFunction Func;
1594  Func.SigIndex = getFunctionType(WS);
1595  Func.Section = &WS.getSection();
1596  assert(WasmIndices.count(&WS) == 0);
1597  WasmIndices[&WS] = Index;
1598  Functions.push_back(Func);
1599 
1600  auto &Section = static_cast<MCSectionWasm &>(WS.getSection());
1601  if (const MCSymbolWasm *C = Section.getGroup()) {
1602  Comdats[C->getName()].emplace_back(
1603  WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index});
1604  }
1605 
1606  if (WS.hasExportName()) {
1608  Export.Name = WS.getExportName();
1610  Export.Index = Index;
1611  Exports.push_back(Export);
1612  }
1613  } else {
1614  // An import; the index was assigned above.
1615  Index = WasmIndices.find(&WS)->second;
1616  }
1617 
1618  LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n");
1619 
1620  } else if (WS.isData()) {
1621  if (!isInSymtab(WS))
1622  continue;
1623 
1624  if (!WS.isDefined()) {
1625  LLVM_DEBUG(dbgs() << " -> segment index: -1"
1626  << "\n");
1627  continue;
1628  }
1629 
1630  if (!WS.getSize())
1631  report_fatal_error("data symbols must have a size set with .size: " +
1632  WS.getName());
1633 
1634  int64_t Size = 0;
1635  if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
1636  report_fatal_error(".size expression must be evaluatable");
1637 
1638  auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
1639  if (!DataSection.isWasmData())
1640  report_fatal_error("data symbols must live in a data section: " +
1641  WS.getName());
1642 
1643  // For each data symbol, export it in the symtab as a reference to the
1644  // corresponding Wasm data segment.
1646  DataSection.getSegmentIndex(), Layout.getSymbolOffset(WS),
1647  static_cast<uint64_t>(Size)};
1648  assert(DataLocations.count(&WS) == 0);
1649  DataLocations[&WS] = Ref;
1650  LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n");
1651 
1652  } else if (WS.isGlobal()) {
1653  // A "true" Wasm global (currently just __stack_pointer)
1654  if (WS.isDefined()) {
1656  Global.Type = WS.getGlobalType();
1657  Global.Index = NumGlobalImports + Globals.size();
1658  Global.InitExpr.Extended = false;
1659  switch (Global.Type.Type) {
1660  case wasm::WASM_TYPE_I32:
1661  Global.InitExpr.Inst.Opcode = wasm::WASM_OPCODE_I32_CONST;
1662  break;
1663  case wasm::WASM_TYPE_I64:
1664  Global.InitExpr.Inst.Opcode = wasm::WASM_OPCODE_I64_CONST;
1665  break;
1666  case wasm::WASM_TYPE_F32:
1667  Global.InitExpr.Inst.Opcode = wasm::WASM_OPCODE_F32_CONST;
1668  break;
1669  case wasm::WASM_TYPE_F64:
1670  Global.InitExpr.Inst.Opcode = wasm::WASM_OPCODE_F64_CONST;
1671  break;
1673  Global.InitExpr.Inst.Opcode = wasm::WASM_OPCODE_REF_NULL;
1674  break;
1675  default:
1676  llvm_unreachable("unexpected type");
1677  }
1678  assert(WasmIndices.count(&WS) == 0);
1679  WasmIndices[&WS] = Global.Index;
1680  Globals.push_back(Global);
1681  } else {
1682  // An import; the index was assigned above
1683  LLVM_DEBUG(dbgs() << " -> global index: "
1684  << WasmIndices.find(&WS)->second << "\n");
1685  }
1686  } else if (WS.isTable()) {
1687  if (WS.isDefined()) {
1688  wasm::WasmTable Table;
1689  Table.Index = NumTableImports + Tables.size();
1690  Table.Type = WS.getTableType();
1691  assert(WasmIndices.count(&WS) == 0);
1692  WasmIndices[&WS] = Table.Index;
1693  Tables.push_back(Table);
1694  }
1695  LLVM_DEBUG(dbgs() << " -> table index: "
1696  << WasmIndices.find(&WS)->second << "\n");
1697  } else if (WS.isTag()) {
1698  // C++ exception symbol (__cpp_exception) or longjmp symbol
1699  // (__c_longjmp)
1700  unsigned Index;
1701  if (WS.isDefined()) {
1702  Index = NumTagImports + TagTypes.size();
1703  uint32_t SigIndex = getTagType(WS);
1704  assert(WasmIndices.count(&WS) == 0);
1705  WasmIndices[&WS] = Index;
1706  TagTypes.push_back(SigIndex);
1707  } else {
1708  // An import; the index was assigned above.
1709  assert(WasmIndices.count(&WS) > 0);
1710  }
1711  LLVM_DEBUG(dbgs() << " -> tag index: " << WasmIndices.find(&WS)->second
1712  << "\n");
1713 
1714  } else {
1715  assert(WS.isSection());
1716  }
1717  }
1718 
1719  // Populate WasmIndices and DataLocations for aliased symbols. We need to
1720  // process these in a separate pass because we need to have processed the
1721  // target of the alias before the alias itself and the symbols are not
1722  // necessarily ordered in this way.
1723  for (const MCSymbol &S : Asm.symbols()) {
1724  if (!S.isVariable())
1725  continue;
1726 
1727  assert(S.isDefined());
1728 
1729  const auto *BS = Layout.getBaseSymbol(S);
1730  if (!BS)
1731  report_fatal_error(Twine(S.getName()) +
1732  ": absolute addressing not supported!");
1733  const MCSymbolWasm *Base = cast<MCSymbolWasm>(BS);
1734 
1735  // Find the target symbol of this weak alias and export that index
1736  const auto &WS = static_cast<const MCSymbolWasm &>(S);
1737  LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *Base
1738  << "'\n");
1739 
1740  if (Base->isFunction()) {
1741  assert(WasmIndices.count(Base) > 0);
1742  uint32_t WasmIndex = WasmIndices.find(Base)->second;
1743  assert(WasmIndices.count(&WS) == 0);
1744  WasmIndices[&WS] = WasmIndex;
1745  LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n");
1746  } else if (Base->isData()) {
1747  auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
1748  uint64_t Offset = Layout.getSymbolOffset(S);
1749  int64_t Size = 0;
1750  // For data symbol alias we use the size of the base symbol as the
1751  // size of the alias. When an offset from the base is involved this
1752  // can result in a offset + size goes past the end of the data section
1753  // which out object format doesn't support. So we must clamp it.
1754  if (!Base->getSize()->evaluateAsAbsolute(Size, Layout))
1755  report_fatal_error(".size expression must be evaluatable");
1756  const WasmDataSegment &Segment =
1757  DataSegments[DataSection.getSegmentIndex()];
1758  Size =
1759  std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset);
1761  DataSection.getSegmentIndex(),
1762  static_cast<uint32_t>(Layout.getSymbolOffset(S)),
1763  static_cast<uint32_t>(Size)};
1764  DataLocations[&WS] = Ref;
1765  LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n");
1766  } else {
1767  report_fatal_error("don't yet support global/tag aliases");
1768  }
1769  }
1770  }
1771 
1772  // Finally, populate the symbol table itself, in its "natural" order.
1773  for (const MCSymbol &S : Asm.symbols()) {
1774  const auto &WS = static_cast<const MCSymbolWasm &>(S);
1775  if (!isInSymtab(WS)) {
1776  WS.setIndex(InvalidIndex);
1777  continue;
1778  }
1779  LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n");
1780 
1781  uint32_t Flags = 0;
1782  if (WS.isWeak())
1784  if (WS.isHidden())
1786  if (!WS.isExternal() && WS.isDefined())
1788  if (WS.isUndefined())
1790  if (WS.isNoStrip()) {
1792  if (isEmscripten()) {
1794  }
1795  }
1796  if (WS.hasImportName())
1798  if (WS.hasExportName())
1800  if (WS.isTLS())
1802 
1804  Info.Name = WS.getName();
1805  Info.Kind = WS.getType().value_or(wasm::WASM_SYMBOL_TYPE_DATA);
1806  Info.Flags = Flags;
1807  if (!WS.isData()) {
1808  assert(WasmIndices.count(&WS) > 0);
1809  Info.ElementIndex = WasmIndices.find(&WS)->second;
1810  } else if (WS.isDefined()) {
1811  assert(DataLocations.count(&WS) > 0);
1812  Info.DataRef = DataLocations.find(&WS)->second;
1813  }
1814  WS.setIndex(SymbolInfos.size());
1815  SymbolInfos.emplace_back(Info);
1816  }
1817 
1818  {
1819  auto HandleReloc = [&](const WasmRelocationEntry &Rel) {
1820  // Functions referenced by a relocation need to put in the table. This is
1821  // purely to make the object file's provisional values readable, and is
1822  // ignored by the linker, which re-calculates the relocations itself.
1823  if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1824  Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1825  Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1826  Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1827  Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1828  Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1829  return;
1830  assert(Rel.Symbol->isFunction());
1831  const MCSymbolWasm *Base =
1832  cast<MCSymbolWasm>(Layout.getBaseSymbol(*Rel.Symbol));
1833  uint32_t FunctionIndex = WasmIndices.find(Base)->second;
1834  uint32_t TableIndex = TableElems.size() + InitialTableOffset;
1835  if (TableIndices.try_emplace(Base, TableIndex).second) {
1836  LLVM_DEBUG(dbgs() << " -> adding " << Base->getName()
1837  << " to table: " << TableIndex << "\n");
1838  TableElems.push_back(FunctionIndex);
1839  registerFunctionType(*Base);
1840  }
1841  };
1842 
1843  for (const WasmRelocationEntry &RelEntry : CodeRelocations)
1844  HandleReloc(RelEntry);
1845  for (const WasmRelocationEntry &RelEntry : DataRelocations)
1846  HandleReloc(RelEntry);
1847  }
1848 
1849  // Translate .init_array section contents into start functions.
1850  for (const MCSection &S : Asm) {
1851  const auto &WS = static_cast<const MCSectionWasm &>(S);
1852  if (WS.getName().startswith(".fini_array"))
1853  report_fatal_error(".fini_array sections are unsupported");
1854  if (!WS.getName().startswith(".init_array"))
1855  continue;
1856  if (WS.getFragmentList().empty())
1857  continue;
1858 
1859  // init_array is expected to contain a single non-empty data fragment
1860  if (WS.getFragmentList().size() != 3)
1861  report_fatal_error("only one .init_array section fragment supported");
1862 
1863  auto IT = WS.begin();
1864  const MCFragment &EmptyFrag = *IT;
1865  if (EmptyFrag.getKind() != MCFragment::FT_Data)
1866  report_fatal_error(".init_array section should be aligned");
1867 
1868  IT = std::next(IT);
1869  const MCFragment &AlignFrag = *IT;
1870  if (AlignFrag.getKind() != MCFragment::FT_Align)
1871  report_fatal_error(".init_array section should be aligned");
1872  if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
1873  Align(is64Bit() ? 8 : 4))
1874  report_fatal_error(".init_array section should be aligned for pointers");
1875 
1876  const MCFragment &Frag = *std::next(IT);
1877  if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
1878  report_fatal_error("only data supported in .init_array section");
1879 
1880  uint16_t Priority = UINT16_MAX;
1881  unsigned PrefixLength = strlen(".init_array");
1882  if (WS.getName().size() > PrefixLength) {
1883  if (WS.getName()[PrefixLength] != '.')
1885  ".init_array section priority should start with '.'");
1886  if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1887  report_fatal_error("invalid .init_array section priority");
1888  }
1889  const auto &DataFrag = cast<MCDataFragment>(Frag);
1890  const SmallVectorImpl<char> &Contents = DataFrag.getContents();
1891  for (const uint8_t *
1892  P = (const uint8_t *)Contents.data(),
1893  *End = (const uint8_t *)Contents.data() + Contents.size();
1894  P != End; ++P) {
1895  if (*P != 0)
1896  report_fatal_error("non-symbolic data in .init_array section");
1897  }
1898  for (const MCFixup &Fixup : DataFrag.getFixups()) {
1899  assert(Fixup.getKind() ==
1900  MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
1901  const MCExpr *Expr = Fixup.getValue();
1902  auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
1903  if (!SymRef)
1904  report_fatal_error("fixups in .init_array should be symbol references");
1905  const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
1906  if (TargetSym.getIndex() == InvalidIndex)
1907  report_fatal_error("symbols in .init_array should exist in symtab");
1908  if (!TargetSym.isFunction())
1909  report_fatal_error("symbols in .init_array should be for functions");
1910  InitFuncs.push_back(
1911  std::make_pair(Priority, TargetSym.getIndex()));
1912  }
1913  }
1914 
1915  // Write out the Wasm header.
1916  writeHeader(Asm);
1917 
1918  uint32_t CodeSectionIndex, DataSectionIndex;
1919  if (Mode != DwoMode::DwoOnly) {
1920  writeTypeSection(Signatures);
1921  writeImportSection(Imports, DataSize, TableElems.size());
1922  writeFunctionSection(Functions);
1923  writeTableSection(Tables);
1924  // Skip the "memory" section; we import the memory instead.
1925  writeTagSection(TagTypes);
1926  writeGlobalSection(Globals);
1927  writeExportSection(Exports);
1928  const MCSymbol *IndirectFunctionTable =
1929  Asm.getContext().lookupSymbol("__indirect_function_table");
1930  writeElemSection(cast_or_null<const MCSymbolWasm>(IndirectFunctionTable),
1931  TableElems);
1932  writeDataCountSection();
1933 
1934  CodeSectionIndex = writeCodeSection(Asm, Layout, Functions);
1935  DataSectionIndex = writeDataSection(Layout);
1936  }
1937 
1938  // The Sections in the COMDAT list have placeholder indices (their index among
1939  // custom sections, rather than among all sections). Fix them up here.
1940  for (auto &Group : Comdats) {
1941  for (auto &Entry : Group.second) {
1942  if (Entry.Kind == wasm::WASM_COMDAT_SECTION) {
1943  Entry.Index += SectionCount;
1944  }
1945  }
1946  }
1947  for (auto &CustomSection : CustomSections)
1948  writeCustomSection(CustomSection, Asm, Layout);
1949 
1950  if (Mode != DwoMode::DwoOnly) {
1951  writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1952 
1953  writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations);
1954  writeRelocSection(DataSectionIndex, "DATA", DataRelocations);
1955  }
1956  writeCustomRelocSections();
1957  if (ProducersSection)
1958  writeCustomSection(*ProducersSection, Asm, Layout);
1959  if (TargetFeaturesSection)
1960  writeCustomSection(*TargetFeaturesSection, Asm, Layout);
1961 
1962  // TODO: Translate the .comment section to the output.
1963  return W->OS.tell() - StartOffset;
1964 }
1965 
1966 std::unique_ptr<MCObjectWriter>
1967 llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
1968  raw_pwrite_stream &OS) {
1969  return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
1970 }
1971 
1972 std::unique_ptr<MCObjectWriter>
1973 llvm::createWasmDwoObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
1974  raw_pwrite_stream &OS,
1975  raw_pwrite_stream &DwoOS) {
1976  return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS, DwoOS);
1977 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:77
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:156
llvm::wasm::WASM_EXTERNAL_TABLE
@ WASM_EXTERNAL_TABLE
Definition: Wasm.h:275
llvm::wasm::WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_SECTION
Definition: Wasm.h:386
getAlignment
static uint32_t getAlignment(const MCSectionCOFF &Sec)
Definition: WinCOFFObjectWriter.cpp:269
llvm::wasm::WASM_SYMBOL_EXPORTED
const unsigned WASM_SYMBOL_EXPORTED
Definition: Wasm.h:410
llvm::wasm::WASM_TYPE_EXTERNREF
@ WASM_TYPE_EXTERNREF
Definition: Wasm.h:267
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:492
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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::wasm::WASM_OPCODE_END
@ WASM_OPCODE_END
Definition: Wasm.h:283
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:340
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:77
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:1967
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:1018
llvm::wasm::WasmVersion
const uint32_t WasmVersion
Definition: Wasm.h:28
llvm::Target
Target - Wrapper for Target specific information.
Definition: TargetRegistry.h:150
llvm::MCSection::getBeginSymbol
MCSymbol * getBeginSymbol()
Definition: MCSection.h:129
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::RISCVFenceField::W
@ W
Definition: RISCVBaseInfo.h:266
llvm::support::endian::write32le
void write32le(void *P, uint32_t V)
Definition: Endian.h:416
llvm::wasm::WASM_LIMITS_FLAG_IS_64
@ WASM_LIMITS_FLAG_IS_64
Definition: Wasm.h:327
ErrorHandling.h
llvm::wasm::WASM_SYMBOL_NO_STRIP
const unsigned WASM_SYMBOL_NO_STRIP
Definition: Wasm.h:412
llvm::wasm::WASM_EXTERNAL_FUNCTION
@ WASM_EXTERNAL_FUNCTION
Definition: Wasm.h:274
llvm::wasm::WASM_SEC_FUNCTION
@ WASM_SEC_FUNCTION
Definition: Wasm.h:245
llvm::wasm::WASM_SYMBOL_BINDING_LOCAL
const unsigned WASM_SYMBOL_BINDING_LOCAL
Definition: Wasm.h:406
llvm::wasm::WASM_SYMBOL_TYPE_TABLE
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:388
llvm::wasm::relocTypetoString
llvm::StringRef relocTypetoString(uint32_t type)
Definition: Wasm.cpp:29
llvm::wasm::WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_GLOBAL
Definition: Wasm.h:385
MCAssembler.h
IT
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
llvm::wasm::WASM_SEC_DATACOUNT
@ WASM_SEC_DATACOUNT
Definition: Wasm.h:254
llvm::wasm::WASM_SEC_TABLE
@ WASM_SEC_TABLE
Definition: Wasm.h:246
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
MCWasmObjectWriter.h
llvm::MCSymbol::isDefined
bool isDefined() const
isDefined - Check if this symbol is defined (i.e., it has an address).
Definition: MCSymbol.h:243
llvm::MCFragment::getParent
MCSection * getParent() const
Definition: MCFragment.h:95
MCFixupKindInfo.h
llvm::wasm::WASM_SYMBOL_UNDEFINED
const unsigned WASM_SYMBOL_UNDEFINED
Definition: Wasm.h:409
llvm::wasm::WASM_SEC_TAG
@ WASM_SEC_TAG
Definition: Wasm.h:255
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:891
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:61
llvm::wasm::WasmDataReference::Offset
uint64_t Offset
Definition: Wasm.h:187
llvm::wasm::WASM_SEC_CODE
@ WASM_SEC_CODE
Definition: Wasm.h:252
llvm::support::endian::Writer
Adapter to write values to a stream in a particular byte order.
Definition: EndianStream.h:52
llvm::wasm::WASM_SEC_IMPORT
@ WASM_SEC_IMPORT
Definition: Wasm.h:244
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:359
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::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:405
llvm::wasm::WASM_OPCODE_I64_CONST
@ WASM_OPCODE_I64_CONST
Definition: Wasm.h:293
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:408
llvm::Log2
unsigned Log2(Align A)
Returns the log2 of the alignment.
Definition: Alignment.h:209
MCContext.h
llvm::wasm::WASM_LIMITS_FLAG_NONE
@ WASM_LIMITS_FLAG_NONE
Definition: Wasm.h:324
llvm::wasm::WASM_LIMITS_FLAG_HAS_MAX
@ WASM_LIMITS_FLAG_HAS_MAX
Definition: Wasm.h:325
llvm::wasm::WASM_SYMBOL_TLS
const unsigned WASM_SYMBOL_TLS
Definition: Wasm.h:413
addData
static void addData(SmallVectorImpl< char > &DataBytes, MCSectionWasm &DataSection)
Definition: WasmObjectWriter.cpp:715
llvm::wasm::WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_IS_PASSIVE
Definition: Wasm.h:331
llvm::wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
Definition: Wasm.h:332
llvm::wasm::WasmGlobalType
Definition: Wasm.h:112
llvm::dwarf::Index
Index
Definition: Dwarf.h:472
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::wasm::WASM_EXTERNAL_TAG
@ WASM_EXTERNAL_TAG
Definition: Wasm.h:278
llvm::MCSection::getAlign
Align getAlign() const
Definition: MCSection.h:140
llvm::wasm::WASM_OPCODE_F32_CONST
@ WASM_OPCODE_F32_CONST
Definition: Wasm.h:294
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:145
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
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:642
llvm::operator<<
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Definition: APFixedPoint.h:292
llvm::wasm::WASM_SYMBOL_TYPE_FUNCTION
@ WASM_SYMBOL_TYPE_FUNCTION
Definition: Wasm.h:383
llvm::wasm::WasmMetadataVersion
const uint32_t WasmMetadataVersion
Definition: Wasm.h:30
llvm::wasm::ValType
ValType
Definition: Wasm.h:424
llvm::wasm::WasmTable::Index
uint32_t Index
Definition: Wasm.h:89
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
Signatures
static const FuncProtoTy Signatures[]
Definition: TargetLibraryInfo.cpp:68
Align
uint64_t Align
Definition: ELFObjHandler.cpp:82
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::wasm::WASM_SEC_EXPORT
@ WASM_SEC_EXPORT
Definition: Wasm.h:249
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::PassSummaryAction::Import
@ Import
Import information from summary.
llvm::wasm::WASM_OPCODE_F64_CONST
@ WASM_OPCODE_F64_CONST
Definition: Wasm.h:295
llvm::logicalview::LVElementKind::Global
@ Global
llvm::wasm::WasmLimits::Flags
uint8_t Flags
Definition: Wasm.h:78
llvm::wasm::WASM_TYPE_FUNC
@ WASM_TYPE_FUNC
Definition: Wasm.h:268
llvm::wasm::WASM_SYMBOL_TABLE
@ WASM_SYMBOL_TABLE
Definition: Wasm.h:362
llvm::wasm::WASM_EXTERNAL_MEMORY
@ WASM_EXTERNAL_MEMORY
Definition: Wasm.h:276
val
The initial backend is deliberately restricted to z10 We should add support for later architectures at some point If an asm ties an i32 r result to an i64 the input will be treated as an leaving the upper bits uninitialised For i64 store i32 val
Definition: README.txt:15
llvm::wasm::WASM_OPCODE_I32_CONST
@ WASM_OPCODE_I32_CONST
Definition: Wasm.h:292
llvm::MCAssembler
Definition: MCAssembler.h:73
llvm::wasm::WASM_SEC_GLOBAL
@ WASM_SEC_GLOBAL
Definition: Wasm.h:248
llvm::AMDGPU::Hwreg::Offset
Offset
Definition: SIDefines.h:419
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:110
Index
uint32_t Index
Definition: ELFObjHandler.cpp:83
uint64_t
llvm::raw_pwrite_stream
An abstract base class for streams implementations that also support a pwrite operation.
Definition: raw_ostream.h:414
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_COMDAT_FUNCTION
@ WASM_COMDAT_FUNCTION
Definition: Wasm.h:376
llvm::wasm::ValType::EXTERNREF
@ EXTERNREF
llvm::wasm::WASM_SYMBOL_EXPLICIT_NAME
const unsigned WASM_SYMBOL_EXPLICIT_NAME
Definition: Wasm.h:411
llvm::MCSymbolWasm
Definition: MCSymbolWasm.h:16
LEB128.h
llvm::wasm::WASM_SEC_CUSTOM
@ WASM_SEC_CUSTOM
Definition: Wasm.h:242
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::MCFixupKindInfo::FKF_IsPCRel
@ FKF_IsPCRel
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...
Definition: MCFixupKindInfo.h:19
llvm::DenseMap
Definition: DenseMap.h:714
llvm::MCSymbolWasm::isUsedInInitArray
bool isUsedInInitArray() const
Definition: MCSymbolWasm.h:126
llvm::wasm::WasmImport
Definition: Wasm.h:130
llvm::wasm::WASM_SYMBOL_TYPE_TAG
@ WASM_SYMBOL_TYPE_TAG
Definition: Wasm.h:387
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::wasm::WASM_TYPE_F64
@ WASM_TYPE_F64
Definition: Wasm.h:264
llvm::MCSymbolWasm::omitFromLinkingSection
bool omitFromLinkingSection() const
Definition: MCSymbolWasm.h:86
llvm::wasm::WASM_OPCODE_REF_NULL
@ WASM_OPCODE_REF_NULL
Definition: Wasm.h:302
llvm::MCContext::reportError
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1055
Mode
SI Whole Quad Mode
Definition: SIWholeQuadMode.cpp:264
llvm::wasm::relocTypeHasAddend
bool relocTypeHasAddend(uint32_t type)
Definition: Wasm.cpp:66
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:691
llvm::print
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr)
Definition: GCNRegPressure.cpp:138
llvm::wasm::WASM_TYPE_F32
@ WASM_TYPE_F32
Definition: Wasm.h:263
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
Fixup
PowerPC TLS Dynamic Call Fixup
Definition: PPCTLSDynamicCall.cpp:215
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
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:2013
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::WASM_SEC_TYPE
@ WASM_SEC_TYPE
Definition: Wasm.h:243
llvm::wasm::WasmSymbolInfo
Definition: Wasm.h:203
llvm::ifs::IFSSymbolType::Func
@ Func
llvm::wasm::WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
Definition: Wasm.h:337
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:124
MCObjectWriter.h
llvm::wasm::WasmDataReference::Segment
uint32_t Segment
Definition: Wasm.h:186
llvm::wasm::WASM_TYPE_I64
@ WASM_TYPE_I64
Definition: Wasm.h:262
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
llvm::stable_sort
void stable_sort(R &&Range)
Definition: STLExtras.h:1947
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
llvm::MCSymbolWasm::isFunctionTable
bool isFunctionTable() const
Definition: MCSymbolWasm.h:113
EndianStream.h
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::WASM_COMDAT_SECTION
@ WASM_COMDAT_SECTION
Definition: Wasm.h:378
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:422
llvm::StringRef::endswith
bool endswith(StringRef Suffix) const
Definition: StringRef.h:276
llvm::wasm::WASM_TYPE_I32
@ WASM_TYPE_I32
Definition: Wasm.h:261
llvm::wasm::WASM_SEC_DATA
@ WASM_SEC_DATA
Definition: Wasm.h:253
Casting.h
isInSymtab
static bool isInSymtab(const MCSymbolWasm &Sym)
Definition: WasmObjectWriter.cpp:1312
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::SmallVectorImpl::clear
void clear()
Definition: SmallVector.h:614
Wasm.h
MCValue.h
llvm::wasm::WasmTable
Definition: Wasm.h:88
llvm::wasm::WASM_SEC_ELEM
@ WASM_SEC_ELEM
Definition: Wasm.h:251
llvm::ARMBuildAttrs::Symbol
@ Symbol
Definition: ARMBuildAttributes.h:83
llvm::MCSection::getKind
SectionKind getKind() const
Definition: MCSection.h:125
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:1973
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:164
llvm::wasm::WASM_INIT_FUNCS
@ WASM_INIT_FUNCS
Definition: Wasm.h:360
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::HexStyle::Asm
@ Asm
0ffh
Definition: MCInstPrinter.h:34
llvm::MCValue
This represents an "assembler immediate".
Definition: MCValue.h:36
llvm::omp::RTLDependInfoFields::Flags
@ Flags
llvm::wasm::WasmImport::Kind
uint8_t Kind
Definition: Wasm.h:133
llvm::MCAsmLayout::getSectionAddressSize
uint64_t getSectionAddressSize(const MCSection *Sec) const
Get the address space size of the given section, as it effects layout.
Definition: MCFragment.cpp:198
llvm::wasm::WASM_COMDAT_DATA
@ WASM_COMDAT_DATA
Definition: Wasm.h:375
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_SEGMENT_INFO
@ WASM_SEGMENT_INFO
Definition: Wasm.h:359
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:198
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:384
llvm::wasm::WasmSignature
Definition: Wasm.h:434
llvm::sampleprof::Base
@ Base
Definition: Discriminator.h:58
llvm::wasm::WASM_EXTERNAL_GLOBAL
@ WASM_EXTERNAL_GLOBAL
Definition: Wasm.h:277
llvm::wasm::WASM_COMDAT_INFO
@ WASM_COMDAT_INFO
Definition: Wasm.h:361
MCSectionWasm.h
llvm::SmallVectorImpl::emplace_back
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:941
llvm::SmallVectorImpl::insert
iterator insert(iterator I, T &&Elt)
Definition: SmallVector.h:809
llvm::wasm::WasmPageSize
const uint32_t WasmPageSize
Definition: Wasm.h:32