LLVM  7.0.0svn
WasmObjectWriter.cpp
Go to the documentation of this file.
1 //===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements Wasm object file writer information.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/ADT/STLExtras.h"
15 #include "llvm/ADT/SmallPtrSet.h"
16 #include "llvm/BinaryFormat/Wasm.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"
31 #include "llvm/Support/LEB128.h"
33 #include <vector>
34 
35 using namespace llvm;
36 
37 #define DEBUG_TYPE "mc"
38 
39 namespace {
40 
41 // For patching purposes, we need to remember where each section starts, both
42 // for patching up the section size field, and for patching up references to
43 // locations within the section.
44 struct SectionBookkeeping {
45  // Where the size of the section is written.
46  uint64_t SizeOffset;
47  // Where the contents of the section starts (after the header).
48  uint64_t ContentsOffset;
49 };
50 
51 // The signature of a wasm function, in a struct capable of being used as a
52 // DenseMap key.
53 struct WasmFunctionType {
54  // Support empty and tombstone instances, needed by DenseMap.
55  enum { Plain, Empty, Tombstone } State;
56 
57  // The return types of the function.
59 
60  // The parameter types of the function.
62 
63  WasmFunctionType() : State(Plain) {}
64 
65  bool operator==(const WasmFunctionType &Other) const {
66  return State == Other.State && Returns == Other.Returns &&
67  Params == Other.Params;
68  }
69 };
70 
71 // Traits for using WasmFunctionType in a DenseMap.
72 struct WasmFunctionTypeDenseMapInfo {
73  static WasmFunctionType getEmptyKey() {
74  WasmFunctionType FuncTy;
75  FuncTy.State = WasmFunctionType::Empty;
76  return FuncTy;
77  }
78  static WasmFunctionType getTombstoneKey() {
79  WasmFunctionType FuncTy;
80  FuncTy.State = WasmFunctionType::Tombstone;
81  return FuncTy;
82  }
83  static unsigned getHashValue(const WasmFunctionType &FuncTy) {
84  uintptr_t Value = FuncTy.State;
85  for (wasm::ValType Ret : FuncTy.Returns)
86  Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Ret));
87  for (wasm::ValType Param : FuncTy.Params)
88  Value += DenseMapInfo<int32_t>::getHashValue(int32_t(Param));
89  return Value;
90  }
91  static bool isEqual(const WasmFunctionType &LHS,
92  const WasmFunctionType &RHS) {
93  return LHS == RHS;
94  }
95 };
96 
97 // A wasm data segment. A wasm binary contains only a single data section
98 // but that can contain many segments, each with their own virtual location
99 // in memory. Each MCSection data created by llvm is modeled as its own
100 // wasm data segment.
101 struct WasmDataSegment {
103  StringRef Name;
105  uint32_t Alignment;
106  uint32_t Flags;
108 };
109 
110 // A wasm import to be written into the import section.
111 struct WasmImport {
112  StringRef ModuleName;
113  StringRef FieldName;
114  unsigned Kind;
115  int32_t Type;
116  bool IsMutable;
117 };
118 
119 // A wasm function to be written into the function section.
120 struct WasmFunction {
121  int32_t Type;
122  const MCSymbolWasm *Sym;
123 };
124 
125 // A wasm export to be written into the export section.
126 struct WasmExport {
127  StringRef FieldName;
128  unsigned Kind;
129  uint32_t Index;
130 };
131 
132 // A wasm global to be written into the global section.
133 struct WasmGlobal {
135  bool IsMutable;
136  bool HasImport;
137  uint64_t InitialValue;
138  uint32_t ImportIndex;
139 };
140 
141 // Information about a single item which is part of a COMDAT. For each data
142 // segment or function which is in the COMDAT, there is a corresponding
143 // WasmComdatEntry.
144 struct WasmComdatEntry {
145  unsigned Kind;
146  uint32_t Index;
147 };
148 
149 // Information about a single relocation.
150 struct WasmRelocationEntry {
151  uint64_t Offset; // Where is the relocation.
152  const MCSymbolWasm *Symbol; // The symbol to relocate with.
153  int64_t Addend; // A value to add to the symbol.
154  unsigned Type; // The type of the relocation.
155  const MCSectionWasm *FixupSection;// The section the relocation is targeting.
156 
157  WasmRelocationEntry(uint64_t Offset, const MCSymbolWasm *Symbol,
158  int64_t Addend, unsigned Type,
159  const MCSectionWasm *FixupSection)
160  : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type),
161  FixupSection(FixupSection) {}
162 
163  bool hasAddend() const {
164  switch (Type) {
165  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
166  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
167  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
168  return true;
169  default:
170  return false;
171  }
172  }
173 
174  void print(raw_ostream &Out) const {
175  Out << "Off=" << Offset << ", Sym=" << *Symbol << ", Addend=" << Addend
176  << ", Type=" << Type
177  << ", FixupSection=" << FixupSection->getSectionName();
178  }
179 
180 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
181  LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
182 #endif
183 };
184 
185 #if !defined(NDEBUG)
186 raw_ostream &operator<<(raw_ostream &OS, const WasmRelocationEntry &Rel) {
187  Rel.print(OS);
188  return OS;
189 }
190 #endif
191 
192 class WasmObjectWriter : public MCObjectWriter {
193  /// Helper struct for containing some precomputed information on symbols.
194  struct WasmSymbolData {
195  const MCSymbolWasm *Symbol;
196  StringRef Name;
197 
198  // Support lexicographic sorting.
199  bool operator<(const WasmSymbolData &RHS) const { return Name < RHS.Name; }
200  };
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 
208  // Relocations for fixing up references in the data section.
209  std::vector<WasmRelocationEntry> DataRelocations;
210 
211  // Index values to use for fixing up call_indirect type indices.
212  // Maps function symbols to the index of the type of the function
214  // Maps function symbols to the table element index space. Used
215  // for TABLE_INDEX relocation types (i.e. address taken functions).
216  DenseMap<const MCSymbolWasm *, uint32_t> IndirectSymbolIndices;
217  // Maps function/global symbols to the function/global index space.
219 
221  FunctionTypeIndices;
222  SmallVector<WasmFunctionType, 4> FunctionTypes;
224  unsigned NumGlobalImports = 0;
225 
226  // TargetObjectWriter wrappers.
227  bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
228  unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup) const {
229  return TargetObjectWriter->getRelocType(Target, Fixup);
230  }
231 
232  void startSection(SectionBookkeeping &Section, unsigned SectionId,
233  const char *Name = nullptr);
234  void endSection(SectionBookkeeping &Section);
235 
236 public:
237  WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
238  raw_pwrite_stream &OS)
239  : MCObjectWriter(OS, /*IsLittleEndian=*/true),
240  TargetObjectWriter(std::move(MOTW)) {}
241 
242  ~WasmObjectWriter() override;
243 
244 private:
245  void reset() override {
246  CodeRelocations.clear();
247  DataRelocations.clear();
248  TypeIndices.clear();
249  SymbolIndices.clear();
250  IndirectSymbolIndices.clear();
251  FunctionTypeIndices.clear();
252  FunctionTypes.clear();
253  Globals.clear();
255  NumGlobalImports = 0;
256  }
257 
258  void writeHeader(const MCAssembler &Asm);
259 
260  void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout,
261  const MCFragment *Fragment, const MCFixup &Fixup,
262  MCValue Target, uint64_t &FixedValue) override;
263 
264  void executePostLayoutBinding(MCAssembler &Asm,
265  const MCAsmLayout &Layout) override;
266 
267  void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
268 
269  void writeString(const StringRef Str) {
270  encodeULEB128(Str.size(), getStream());
271  writeBytes(Str);
272  }
273 
274  void writeValueType(wasm::ValType Ty) {
275  encodeSLEB128(int32_t(Ty), getStream());
276  }
277 
278  void writeTypeSection(ArrayRef<WasmFunctionType> FunctionTypes);
279  void writeImportSection(ArrayRef<WasmImport> Imports, uint32_t DataSize,
280  uint32_t NumElements);
281  void writeFunctionSection(ArrayRef<WasmFunction> Functions);
282  void writeGlobalSection();
283  void writeExportSection(ArrayRef<WasmExport> Exports);
284  void writeElemSection(ArrayRef<uint32_t> TableElems);
285  void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
286  ArrayRef<WasmFunction> Functions);
287  void writeDataSection(ArrayRef<WasmDataSegment> Segments);
288  void writeNameSection(ArrayRef<WasmFunction> Functions,
289  ArrayRef<WasmImport> Imports,
290  uint32_t NumFuncImports);
291  void writeCodeRelocSection();
292  void writeDataRelocSection();
293  void writeLinkingMetaDataSection(
294  ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
295  ArrayRef<std::pair<StringRef, uint32_t>> SymbolFlags,
296  ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
297  const std::map<StringRef, std::vector<WasmComdatEntry>>& Comdats);
298 
299  uint32_t getProvisionalValue(const WasmRelocationEntry &RelEntry);
300  void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations,
301  uint64_t ContentsOffset);
302 
303  void writeRelocations(ArrayRef<WasmRelocationEntry> Relocations);
304  uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry);
305  uint32_t getFunctionType(const MCSymbolWasm& Symbol);
306  uint32_t registerFunctionType(const MCSymbolWasm& Symbol);
307 };
308 
309 } // end anonymous namespace
310 
311 WasmObjectWriter::~WasmObjectWriter() {}
312 
313 // Write out a section header and a patchable section size field.
314 void WasmObjectWriter::startSection(SectionBookkeeping &Section,
315  unsigned SectionId,
316  const char *Name) {
317  assert((Name != nullptr) == (SectionId == wasm::WASM_SEC_CUSTOM) &&
318  "Only custom sections can have names");
319 
320  DEBUG(dbgs() << "startSection " << SectionId << ": " << Name << "\n");
321  encodeULEB128(SectionId, getStream());
322 
323  Section.SizeOffset = getStream().tell();
324 
325  // The section size. We don't know the size yet, so reserve enough space
326  // for any 32-bit value; we'll patch it later.
327  encodeULEB128(UINT32_MAX, getStream());
328 
329  // The position where the section starts, for measuring its size.
330  Section.ContentsOffset = getStream().tell();
331 
332  // Custom sections in wasm also have a string identifier.
333  if (SectionId == wasm::WASM_SEC_CUSTOM) {
334  assert(Name);
335  writeString(StringRef(Name));
336  }
337 }
338 
339 // Now that the section is complete and we know how big it is, patch up the
340 // section size field at the start of the section.
341 void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
342  uint64_t Size = getStream().tell() - Section.ContentsOffset;
343  if (uint32_t(Size) != Size)
344  report_fatal_error("section size does not fit in a uint32_t");
345 
346  DEBUG(dbgs() << "endSection size=" << Size << "\n");
347 
348  // Write the final section size to the payload_len field, which follows
349  // the section id byte.
350  uint8_t Buffer[16];
351  unsigned SizeLen = encodeULEB128(Size, Buffer, 5);
352  assert(SizeLen == 5);
353  getStream().pwrite((char *)Buffer, SizeLen, Section.SizeOffset);
354 }
355 
356 // Emit the Wasm header.
357 void WasmObjectWriter::writeHeader(const MCAssembler &Asm) {
358  writeBytes(StringRef(wasm::WasmMagic, sizeof(wasm::WasmMagic)));
359  writeLE32(wasm::WasmVersion);
360 }
361 
362 void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
363  const MCAsmLayout &Layout) {
364 }
365 
366 void WasmObjectWriter::recordRelocation(MCAssembler &Asm,
367  const MCAsmLayout &Layout,
368  const MCFragment *Fragment,
369  const MCFixup &Fixup, MCValue Target,
370  uint64_t &FixedValue) {
371  MCAsmBackend &Backend = Asm.getBackend();
372  bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
374  const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
375  uint64_t C = Target.getConstant();
376  uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
377  MCContext &Ctx = Asm.getContext();
378 
379  // The .init_array isn't translated as data, so don't do relocations in it.
380  if (FixupSection.getSectionName().startswith(".init_array"))
381  return;
382 
383  if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
384  assert(RefB->getKind() == MCSymbolRefExpr::VK_None &&
385  "Should not have constructed this");
386 
387  // Let A, B and C being the components of Target and R be the location of
388  // the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
389  // If it is pcrel, we want to compute (A - B + C - R).
390 
391  // In general, Wasm has no relocations for -B. It can only represent (A + C)
392  // or (A + C - R). If B = R + K and the relocation is not pcrel, we can
393  // replace B to implement it: (A - R - K + C)
394  if (IsPCRel) {
395  Ctx.reportError(
396  Fixup.getLoc(),
397  "No relocation available to represent this relative expression");
398  return;
399  }
400 
401  const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
402 
403  if (SymB.isUndefined()) {
404  Ctx.reportError(Fixup.getLoc(),
405  Twine("symbol '") + SymB.getName() +
406  "' can not be undefined in a subtraction expression");
407  return;
408  }
409 
410  assert(!SymB.isAbsolute() && "Should have been folded");
411  const MCSection &SecB = SymB.getSection();
412  if (&SecB != &FixupSection) {
413  Ctx.reportError(Fixup.getLoc(),
414  "Cannot represent a difference across sections");
415  return;
416  }
417 
418  uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
419  uint64_t K = SymBOffset - FixupOffset;
420  IsPCRel = true;
421  C -= K;
422  }
423 
424  // We either rejected the fixup or folded B into C at this point.
425  const MCSymbolRefExpr *RefA = Target.getSymA();
426  const auto *SymA = RefA ? cast<MCSymbolWasm>(&RefA->getSymbol()) : nullptr;
427 
428  if (SymA && SymA->isVariable()) {
429  const MCExpr *Expr = SymA->getVariableValue();
430  const auto *Inner = cast<MCSymbolRefExpr>(Expr);
431  if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
432  llvm_unreachable("weakref used in reloc not yet implemented");
433  }
434 
435  // Put any constant offset in an addend. Offsets can be negative, and
436  // LLVM expects wrapping, in contrast to wasm's immediates which can't
437  // be negative and don't wrap.
438  FixedValue = 0;
439 
440  if (SymA)
441  SymA->setUsedInReloc();
442 
443  assert(!IsPCRel);
444  assert(SymA);
445 
446  unsigned Type = getRelocType(Target, Fixup);
447 
448  WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection);
449  DEBUG(dbgs() << "WasmReloc: " << Rec << "\n");
450 
451  if (FixupSection.isWasmData())
452  DataRelocations.push_back(Rec);
453  else if (FixupSection.getKind().isText())
454  CodeRelocations.push_back(Rec);
455  else if (!FixupSection.getKind().isMetadata())
456  // TODO(sbc): Add support for debug sections.
457  llvm_unreachable("unexpected section type");
458 }
459 
460 // Write X as an (unsigned) LEB value at offset Offset in Stream, padded
461 // to allow patching.
462 static void
464  uint8_t Buffer[5];
465  unsigned SizeLen = encodeULEB128(X, Buffer, 5);
466  assert(SizeLen == 5);
467  Stream.pwrite((char *)Buffer, SizeLen, Offset);
468 }
469 
470 // Write X as an signed LEB value at offset Offset in Stream, padded
471 // to allow patching.
472 static void
473 WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset) {
474  uint8_t Buffer[5];
475  unsigned SizeLen = encodeSLEB128(X, Buffer, 5);
476  assert(SizeLen == 5);
477  Stream.pwrite((char *)Buffer, SizeLen, Offset);
478 }
479 
480 // Write X as a plain integer value at offset Offset in Stream.
481 static void WriteI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset) {
482  uint8_t Buffer[4];
483  support::endian::write32le(Buffer, X);
484  Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset);
485 }
486 
488  if (Symbol.isVariable()) {
489  const MCExpr *Expr = Symbol.getVariableValue();
490  auto *Inner = cast<MCSymbolRefExpr>(Expr);
491  return cast<MCSymbolWasm>(&Inner->getSymbol());
492  }
493  return &Symbol;
494 }
495 
496 // Compute a value to write into the code at the location covered
497 // by RelEntry. This value isn't used by the static linker, since
498 // we have addends; it just serves to make the code more readable
499 // and to make standalone wasm modules directly usable.
500 uint32_t
501 WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
502  const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol);
503 
504  // For undefined symbols, use zero
505  if (!Sym->isDefined())
506  return 0;
507 
508  uint32_t GlobalIndex = SymbolIndices[Sym];
509  const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports];
510  uint64_t Address = Global.InitialValue + RelEntry.Addend;
511 
512  // Ignore overflow. LLVM allows address arithmetic to silently wrap.
514 
515  return Value;
516 }
517 
518 static void addData(SmallVectorImpl<char> &DataBytes,
519  MCSectionWasm &DataSection) {
520  DEBUG(errs() << "addData: " << DataSection.getSectionName() << "\n");
521 
522  DataBytes.resize(alignTo(DataBytes.size(), DataSection.getAlignment()));
523 
524  size_t LastFragmentSize = 0;
525  for (const MCFragment &Frag : DataSection) {
526  if (Frag.hasInstructions())
527  report_fatal_error("only data supported in data sections");
528 
529  if (auto *Align = dyn_cast<MCAlignFragment>(&Frag)) {
530  if (Align->getValueSize() != 1)
531  report_fatal_error("only byte values supported for alignment");
532  // If nops are requested, use zeros, as this is the data section.
533  uint8_t Value = Align->hasEmitNops() ? 0 : Align->getValue();
534  uint64_t Size = std::min<uint64_t>(alignTo(DataBytes.size(),
535  Align->getAlignment()),
536  DataBytes.size() +
537  Align->getMaxBytesToEmit());
538  DataBytes.resize(Size, Value);
539  } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) {
540  int64_t Size;
541  if (!Fill->getSize().evaluateAsAbsolute(Size))
542  llvm_unreachable("The fill should be an assembler constant");
543  DataBytes.insert(DataBytes.end(), Size, Fill->getValue());
544  } else {
545  const auto &DataFrag = cast<MCDataFragment>(Frag);
546  const SmallVectorImpl<char> &Contents = DataFrag.getContents();
547 
548  DataBytes.insert(DataBytes.end(), Contents.begin(), Contents.end());
549  LastFragmentSize = Contents.size();
550  }
551  }
552 
553  // Don't allow empty segments, or segments that end with zero-sized
554  // fragment, otherwise the linker cannot map symbols to a unique
555  // data segment. This can be triggered by zero-sized structs
556  // See: test/MC/WebAssembly/bss.ll
557  if (LastFragmentSize == 0)
558  DataBytes.resize(DataBytes.size() + 1);
559  DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
560 }
561 
562 uint32_t WasmObjectWriter::getRelocationIndexValue(
563  const WasmRelocationEntry &RelEntry) {
564  switch (RelEntry.Type) {
565  case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
566  case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
567  if (!IndirectSymbolIndices.count(RelEntry.Symbol))
568  report_fatal_error("symbol not found in table index space: " +
569  RelEntry.Symbol->getName());
570  return IndirectSymbolIndices[RelEntry.Symbol];
571  case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
572  case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
573  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
574  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
575  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
576  if (!SymbolIndices.count(RelEntry.Symbol))
577  report_fatal_error("symbol not found in function/global index space: " +
578  RelEntry.Symbol->getName());
579  return SymbolIndices[RelEntry.Symbol];
580  case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
581  if (!TypeIndices.count(RelEntry.Symbol))
582  report_fatal_error("symbol not found in type index space: " +
583  RelEntry.Symbol->getName());
584  return TypeIndices[RelEntry.Symbol];
585  default:
586  llvm_unreachable("invalid relocation type");
587  }
588 }
589 
590 // Apply the portions of the relocation records that we can handle ourselves
591 // directly.
592 void WasmObjectWriter::applyRelocations(
593  ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset) {
594  raw_pwrite_stream &Stream = getStream();
595  for (const WasmRelocationEntry &RelEntry : Relocations) {
596  uint64_t Offset = ContentsOffset +
597  RelEntry.FixupSection->getSectionOffset() +
598  RelEntry.Offset;
599 
600  DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
601  switch (RelEntry.Type) {
602  case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
603  case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
604  case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
605  case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: {
606  uint32_t Index = getRelocationIndexValue(RelEntry);
607  WritePatchableSLEB(Stream, Index, Offset);
608  break;
609  }
610  case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: {
611  uint32_t Index = getRelocationIndexValue(RelEntry);
612  WriteI32(Stream, Index, Offset);
613  break;
614  }
615  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
616  uint32_t Value = getProvisionalValue(RelEntry);
617  WritePatchableSLEB(Stream, Value, Offset);
618  break;
619  }
620  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: {
621  uint32_t Value = getProvisionalValue(RelEntry);
622  WritePatchableLEB(Stream, Value, Offset);
623  break;
624  }
625  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: {
626  uint32_t Value = getProvisionalValue(RelEntry);
627  WriteI32(Stream, Value, Offset);
628  break;
629  }
630  default:
631  llvm_unreachable("invalid relocation type");
632  }
633  }
634 }
635 
636 // Write out the portions of the relocation records that the linker will
637 // need to handle.
638 void WasmObjectWriter::writeRelocations(
639  ArrayRef<WasmRelocationEntry> Relocations) {
640  raw_pwrite_stream &Stream = getStream();
641  for (const WasmRelocationEntry& RelEntry : Relocations) {
642 
643  uint64_t Offset = RelEntry.Offset +
644  RelEntry.FixupSection->getSectionOffset();
645  uint32_t Index = getRelocationIndexValue(RelEntry);
646 
647  encodeULEB128(RelEntry.Type, Stream);
648  encodeULEB128(Offset, Stream);
649  encodeULEB128(Index, Stream);
650  if (RelEntry.hasAddend())
651  encodeSLEB128(RelEntry.Addend, Stream);
652  }
653 }
654 
655 void WasmObjectWriter::writeTypeSection(
656  ArrayRef<WasmFunctionType> FunctionTypes) {
657  if (FunctionTypes.empty())
658  return;
659 
660  SectionBookkeeping Section;
661  startSection(Section, wasm::WASM_SEC_TYPE);
662 
663  encodeULEB128(FunctionTypes.size(), getStream());
664 
665  for (const WasmFunctionType &FuncTy : FunctionTypes) {
666  encodeSLEB128(wasm::WASM_TYPE_FUNC, getStream());
667  encodeULEB128(FuncTy.Params.size(), getStream());
668  for (wasm::ValType Ty : FuncTy.Params)
669  writeValueType(Ty);
670  encodeULEB128(FuncTy.Returns.size(), getStream());
671  for (wasm::ValType Ty : FuncTy.Returns)
672  writeValueType(Ty);
673  }
674 
675  endSection(Section);
676 }
677 
678 void WasmObjectWriter::writeImportSection(ArrayRef<WasmImport> Imports,
679  uint32_t DataSize,
680  uint32_t NumElements) {
681  if (Imports.empty())
682  return;
683 
684  uint32_t NumPages = (DataSize + wasm::WasmPageSize - 1) / wasm::WasmPageSize;
685 
686  SectionBookkeeping Section;
687  startSection(Section, wasm::WASM_SEC_IMPORT);
688 
689  encodeULEB128(Imports.size(), getStream());
690  for (const WasmImport &Import : Imports) {
691  writeString(Import.ModuleName);
692  writeString(Import.FieldName);
693 
694  encodeULEB128(Import.Kind, getStream());
695 
696  switch (Import.Kind) {
698  encodeULEB128(Import.Type, getStream());
699  break;
701  encodeSLEB128(int32_t(Import.Type), getStream());
702  encodeULEB128(int32_t(Import.IsMutable), getStream());
703  break;
705  encodeULEB128(0, getStream()); // flags
706  encodeULEB128(NumPages, getStream()); // initial
707  break;
709  encodeSLEB128(int32_t(Import.Type), getStream());
710  encodeULEB128(0, getStream()); // flags
711  encodeULEB128(NumElements, getStream()); // initial
712  break;
713  default:
714  llvm_unreachable("unsupported import kind");
715  }
716  }
717 
718  endSection(Section);
719 }
720 
721 void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) {
722  if (Functions.empty())
723  return;
724 
725  SectionBookkeeping Section;
726  startSection(Section, wasm::WASM_SEC_FUNCTION);
727 
728  encodeULEB128(Functions.size(), getStream());
729  for (const WasmFunction &Func : Functions)
730  encodeULEB128(Func.Type, getStream());
731 
732  endSection(Section);
733 }
734 
735 void WasmObjectWriter::writeGlobalSection() {
736  if (Globals.empty())
737  return;
738 
739  SectionBookkeeping Section;
740  startSection(Section, wasm::WASM_SEC_GLOBAL);
741 
742  encodeULEB128(Globals.size(), getStream());
743  for (const WasmGlobal &Global : Globals) {
744  writeValueType(Global.Type);
745  write8(Global.IsMutable);
746 
747  if (Global.HasImport) {
748  assert(Global.InitialValue == 0);
750  encodeULEB128(Global.ImportIndex, getStream());
751  } else {
752  assert(Global.ImportIndex == 0);
754  encodeSLEB128(Global.InitialValue, getStream()); // offset
755  }
756  write8(wasm::WASM_OPCODE_END);
757  }
758 
759  endSection(Section);
760 }
761 
762 void WasmObjectWriter::writeExportSection(ArrayRef<WasmExport> Exports) {
763  if (Exports.empty())
764  return;
765 
766  SectionBookkeeping Section;
767  startSection(Section, wasm::WASM_SEC_EXPORT);
768 
769  encodeULEB128(Exports.size(), getStream());
770  for (const WasmExport &Export : Exports) {
771  writeString(Export.FieldName);
772  encodeSLEB128(Export.Kind, getStream());
773  encodeULEB128(Export.Index, getStream());
774  }
775 
776  endSection(Section);
777 }
778 
779 void WasmObjectWriter::writeElemSection(ArrayRef<uint32_t> TableElems) {
780  if (TableElems.empty())
781  return;
782 
783  SectionBookkeeping Section;
784  startSection(Section, wasm::WASM_SEC_ELEM);
785 
786  encodeULEB128(1, getStream()); // number of "segments"
787  encodeULEB128(0, getStream()); // the table index
788 
789  // init expr for starting offset
791  encodeSLEB128(0, getStream());
792  write8(wasm::WASM_OPCODE_END);
793 
794  encodeULEB128(TableElems.size(), getStream());
795  for (uint32_t Elem : TableElems)
796  encodeULEB128(Elem, getStream());
797 
798  endSection(Section);
799 }
800 
801 void WasmObjectWriter::writeCodeSection(const MCAssembler &Asm,
802  const MCAsmLayout &Layout,
803  ArrayRef<WasmFunction> Functions) {
804  if (Functions.empty())
805  return;
806 
807  SectionBookkeeping Section;
808  startSection(Section, wasm::WASM_SEC_CODE);
809 
810  encodeULEB128(Functions.size(), getStream());
811 
812  for (const WasmFunction &Func : Functions) {
813  auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection());
814 
815  int64_t Size = 0;
816  if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout))
817  report_fatal_error(".size expression must be evaluatable");
818 
819  encodeULEB128(Size, getStream());
820  FuncSection.setSectionOffset(getStream().tell() - Section.ContentsOffset);
821  Asm.writeSectionData(&FuncSection, Layout);
822  }
823 
824  // Apply fixups.
825  applyRelocations(CodeRelocations, Section.ContentsOffset);
826 
827  endSection(Section);
828 }
829 
830 void WasmObjectWriter::writeDataSection(ArrayRef<WasmDataSegment> Segments) {
831  if (Segments.empty())
832  return;
833 
834  SectionBookkeeping Section;
835  startSection(Section, wasm::WASM_SEC_DATA);
836 
837  encodeULEB128(Segments.size(), getStream()); // count
838 
839  for (const WasmDataSegment & Segment : Segments) {
840  encodeULEB128(0, getStream()); // memory index
842  encodeSLEB128(Segment.Offset, getStream()); // offset
843  write8(wasm::WASM_OPCODE_END);
844  encodeULEB128(Segment.Data.size(), getStream()); // size
845  Segment.Section->setSectionOffset(getStream().tell() - Section.ContentsOffset);
846  writeBytes(Segment.Data); // data
847  }
848 
849  // Apply fixups.
850  applyRelocations(DataRelocations, Section.ContentsOffset);
851 
852  endSection(Section);
853 }
854 
855 void WasmObjectWriter::writeNameSection(
856  ArrayRef<WasmFunction> Functions,
857  ArrayRef<WasmImport> Imports,
858  unsigned NumFuncImports) {
859  uint32_t TotalFunctions = NumFuncImports + Functions.size();
860  if (TotalFunctions == 0)
861  return;
862 
863  SectionBookkeeping Section;
864  startSection(Section, wasm::WASM_SEC_CUSTOM, "name");
865  SectionBookkeeping SubSection;
866  startSection(SubSection, wasm::WASM_NAMES_FUNCTION);
867 
868  encodeULEB128(TotalFunctions, getStream());
869  uint32_t Index = 0;
870  for (const WasmImport &Import : Imports) {
871  if (Import.Kind == wasm::WASM_EXTERNAL_FUNCTION) {
872  encodeULEB128(Index, getStream());
873  writeString(Import.FieldName);
874  ++Index;
875  }
876  }
877  for (const WasmFunction &Func : Functions) {
878  encodeULEB128(Index, getStream());
879  writeString(Func.Sym->getName());
880  ++Index;
881  }
882 
883  endSection(SubSection);
884  endSection(Section);
885 }
886 
887 void WasmObjectWriter::writeCodeRelocSection() {
888  // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
889  // for descriptions of the reloc sections.
890 
891  if (CodeRelocations.empty())
892  return;
893 
894  SectionBookkeeping Section;
895  startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.CODE");
896 
897  encodeULEB128(wasm::WASM_SEC_CODE, getStream());
898  encodeULEB128(CodeRelocations.size(), getStream());
899 
900  writeRelocations(CodeRelocations);
901 
902  endSection(Section);
903 }
904 
905 void WasmObjectWriter::writeDataRelocSection() {
906  // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
907  // for descriptions of the reloc sections.
908 
909  if (DataRelocations.empty())
910  return;
911 
912  SectionBookkeeping Section;
913  startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.DATA");
914 
915  encodeULEB128(wasm::WASM_SEC_DATA, getStream());
916  encodeULEB128(DataRelocations.size(), getStream());
917 
918  writeRelocations(DataRelocations);
919 
920  endSection(Section);
921 }
922 
923 void WasmObjectWriter::writeLinkingMetaDataSection(
924  ArrayRef<WasmDataSegment> Segments, uint32_t DataSize,
925  ArrayRef<std::pair<StringRef, uint32_t>> SymbolFlags,
926  ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
927  const std::map<StringRef, std::vector<WasmComdatEntry>>& Comdats) {
928  SectionBookkeeping Section;
929  startSection(Section, wasm::WASM_SEC_CUSTOM, "linking");
930  SectionBookkeeping SubSection;
931 
932  if (SymbolFlags.size() != 0) {
933  startSection(SubSection, wasm::WASM_SYMBOL_INFO);
934  encodeULEB128(SymbolFlags.size(), getStream());
935  for (auto Pair: SymbolFlags) {
936  writeString(Pair.first);
937  encodeULEB128(Pair.second, getStream());
938  }
939  endSection(SubSection);
940  }
941 
942  if (DataSize > 0) {
943  startSection(SubSection, wasm::WASM_DATA_SIZE);
944  encodeULEB128(DataSize, getStream());
945  endSection(SubSection);
946  }
947 
948  if (Segments.size()) {
949  startSection(SubSection, wasm::WASM_SEGMENT_INFO);
950  encodeULEB128(Segments.size(), getStream());
951  for (const WasmDataSegment &Segment : Segments) {
952  writeString(Segment.Name);
953  encodeULEB128(Segment.Alignment, getStream());
954  encodeULEB128(Segment.Flags, getStream());
955  }
956  endSection(SubSection);
957  }
958 
959  if (!InitFuncs.empty()) {
960  startSection(SubSection, wasm::WASM_INIT_FUNCS);
961  encodeULEB128(InitFuncs.size(), getStream());
962  for (auto &StartFunc : InitFuncs) {
963  encodeULEB128(StartFunc.first, getStream()); // priority
964  encodeULEB128(StartFunc.second, getStream()); // function index
965  }
966  endSection(SubSection);
967  }
968 
969  if (Comdats.size()) {
970  startSection(SubSection, wasm::WASM_COMDAT_INFO);
971  encodeULEB128(Comdats.size(), getStream());
972  for (const auto &C : Comdats) {
973  writeString(C.first);
974  encodeULEB128(0, getStream()); // flags for future use
975  encodeULEB128(C.second.size(), getStream());
976  for (const WasmComdatEntry &Entry : C.second) {
977  encodeULEB128(Entry.Kind, getStream());
978  encodeULEB128(Entry.Index, getStream());
979  }
980  }
981  endSection(SubSection);
982  }
983 
984  endSection(Section);
985 }
986 
987 uint32_t WasmObjectWriter::getFunctionType(const MCSymbolWasm& Symbol) {
988  assert(Symbol.isFunction());
989  assert(TypeIndices.count(&Symbol));
990  return TypeIndices[&Symbol];
991 }
992 
993 uint32_t WasmObjectWriter::registerFunctionType(const MCSymbolWasm& Symbol) {
994  assert(Symbol.isFunction());
995 
996  WasmFunctionType F;
997  const MCSymbolWasm* ResolvedSym = ResolveSymbol(Symbol);
998  F.Returns = ResolvedSym->getReturns();
999  F.Params = ResolvedSym->getParams();
1000 
1001  auto Pair =
1002  FunctionTypeIndices.insert(std::make_pair(F, FunctionTypes.size()));
1003  if (Pair.second)
1004  FunctionTypes.push_back(F);
1005  TypeIndices[&Symbol] = Pair.first->second;
1006 
1007  DEBUG(dbgs() << "registerFunctionType: " << Symbol << " new:" << Pair.second << "\n");
1008  DEBUG(dbgs() << " -> type index: " << Pair.first->second << "\n");
1009  return Pair.first->second;
1010 }
1011 
1012 void WasmObjectWriter::writeObject(MCAssembler &Asm,
1013  const MCAsmLayout &Layout) {
1014  DEBUG(dbgs() << "WasmObjectWriter::writeObject\n");
1015  MCContext &Ctx = Asm.getContext();
1017 
1018  // Collect information from the available symbols.
1019  SmallVector<WasmFunction, 4> Functions;
1020  SmallVector<uint32_t, 4> TableElems;
1025  std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1026  unsigned NumFuncImports = 0;
1027  SmallVector<WasmDataSegment, 4> DataSegments;
1028  uint32_t DataSize = 0;
1029 
1030  // In the special .global_variables section, we've encoded global
1031  // variables used by the function. Translate them into the Globals
1032  // list.
1033  MCSectionWasm *GlobalVars =
1034  Ctx.getWasmSection(".global_variables", SectionKind::getMetadata());
1035  if (!GlobalVars->getFragmentList().empty()) {
1036  if (GlobalVars->getFragmentList().size() != 1)
1037  report_fatal_error("only one .global_variables fragment supported");
1038  const MCFragment &Frag = *GlobalVars->begin();
1039  if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
1040  report_fatal_error("only data supported in .global_variables");
1041  const auto &DataFrag = cast<MCDataFragment>(Frag);
1042  if (!DataFrag.getFixups().empty())
1043  report_fatal_error("fixups not supported in .global_variables");
1044  const SmallVectorImpl<char> &Contents = DataFrag.getContents();
1045  for (const uint8_t *p = (const uint8_t *)Contents.data(),
1046  *end = (const uint8_t *)Contents.data() + Contents.size();
1047  p != end; ) {
1048  WasmGlobal G;
1049  if (end - p < 3)
1050  report_fatal_error("truncated global variable encoding");
1051  G.Type = wasm::ValType(int8_t(*p++));
1052  G.IsMutable = bool(*p++);
1053  G.HasImport = bool(*p++);
1054  if (G.HasImport) {
1055  G.InitialValue = 0;
1056 
1057  WasmImport Import;
1058  Import.ModuleName = (const char *)p;
1059  const uint8_t *nul = (const uint8_t *)memchr(p, '\0', end - p);
1060  if (!nul)
1061  report_fatal_error("global module name must be nul-terminated");
1062  p = nul + 1;
1063  nul = (const uint8_t *)memchr(p, '\0', end - p);
1064  if (!nul)
1065  report_fatal_error("global base name must be nul-terminated");
1066  Import.FieldName = (const char *)p;
1067  p = nul + 1;
1068 
1069  Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1070  Import.Type = int32_t(G.Type);
1071 
1072  G.ImportIndex = NumGlobalImports;
1073  ++NumGlobalImports;
1074 
1075  Imports.push_back(Import);
1076  } else {
1077  unsigned n;
1078  G.InitialValue = decodeSLEB128(p, &n);
1079  G.ImportIndex = 0;
1080  if ((ptrdiff_t)n > end - p)
1081  report_fatal_error("global initial value must be valid SLEB128");
1082  p += n;
1083  }
1084  Globals.push_back(G);
1085  }
1086  }
1087 
1088  // For now, always emit the memory import, since loads and stores are not
1089  // valid without it. In the future, we could perhaps be more clever and omit
1090  // it if there are no loads or stores.
1091  MCSymbolWasm *MemorySym =
1092  cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__linear_memory"));
1093  WasmImport MemImport;
1094  MemImport.ModuleName = MemorySym->getModuleName();
1095  MemImport.FieldName = MemorySym->getName();
1096  MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY;
1097  Imports.push_back(MemImport);
1098 
1099  // For now, always emit the table section, since indirect calls are not
1100  // valid without it. In the future, we could perhaps be more clever and omit
1101  // it if there are no indirect calls.
1102  MCSymbolWasm *TableSym =
1103  cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__indirect_function_table"));
1104  WasmImport TableImport;
1105  TableImport.ModuleName = TableSym->getModuleName();
1106  TableImport.FieldName = TableSym->getName();
1107  TableImport.Kind = wasm::WASM_EXTERNAL_TABLE;
1108  TableImport.Type = wasm::WASM_TYPE_ANYFUNC;
1109  Imports.push_back(TableImport);
1110 
1111  // Populate FunctionTypeIndices and Imports.
1112  for (const MCSymbol &S : Asm.symbols()) {
1113  const auto &WS = static_cast<const MCSymbolWasm &>(S);
1114 
1115  // Register types for all functions, including those with private linkage
1116  // (making them
1117  // because wasm always needs a type signature.
1118  if (WS.isFunction())
1119  registerFunctionType(WS);
1120 
1121  if (WS.isTemporary())
1122  continue;
1123 
1124  // If the symbol is not defined in this translation unit, import it.
1125  if ((!WS.isDefined() && !WS.isComdat()) ||
1126  WS.isVariable()) {
1127  WasmImport Import;
1128  Import.ModuleName = WS.getModuleName();
1129  Import.FieldName = WS.getName();
1130 
1131  if (WS.isFunction()) {
1132  Import.Kind = wasm::WASM_EXTERNAL_FUNCTION;
1133  Import.Type = getFunctionType(WS);
1134  SymbolIndices[&WS] = NumFuncImports;
1135  ++NumFuncImports;
1136  } else {
1137  Import.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1138  Import.Type = int32_t(PtrType);
1139  Import.IsMutable = false;
1140  SymbolIndices[&WS] = NumGlobalImports;
1141 
1142  // If this global is the stack pointer, make it mutable.
1143  if (WS.getName() == "__stack_pointer")
1144  Import.IsMutable = true;
1145 
1146  ++NumGlobalImports;
1147  }
1148 
1149  Imports.push_back(Import);
1150  }
1151  }
1152 
1153  for (MCSection &Sec : Asm) {
1154  auto &Section = static_cast<MCSectionWasm &>(Sec);
1155  if (!Section.isWasmData())
1156  continue;
1157 
1158  // .init_array sections are handled specially elsewhere.
1159  if (cast<MCSectionWasm>(Sec).getSectionName().startswith(".init_array"))
1160  continue;
1161 
1162  DataSize = alignTo(DataSize, Section.getAlignment());
1163  DataSegments.emplace_back();
1164  WasmDataSegment &Segment = DataSegments.back();
1165  Segment.Name = Section.getSectionName();
1166  Segment.Offset = DataSize;
1167  Segment.Section = &Section;
1168  addData(Segment.Data, Section);
1169  Segment.Alignment = Section.getAlignment();
1170  Segment.Flags = 0;
1171  DataSize += Segment.Data.size();
1172  Section.setMemoryOffset(Segment.Offset);
1173 
1174  if (const MCSymbolWasm *C = Section.getGroup()) {
1175  Comdats[C->getName()].emplace_back(
1176  WasmComdatEntry{wasm::WASM_COMDAT_DATA,
1177  static_cast<uint32_t>(DataSegments.size()) - 1});
1178  }
1179  }
1180 
1181  // Handle regular defined and undefined symbols.
1182  for (const MCSymbol &S : Asm.symbols()) {
1183  // Ignore unnamed temporary symbols, which aren't ever exported, imported,
1184  // or used in relocations.
1185  if (S.isTemporary() && S.getName().empty())
1186  continue;
1187 
1188  const auto &WS = static_cast<const MCSymbolWasm &>(S);
1189  DEBUG(dbgs() << "MCSymbol: '" << S << "'"
1190  << " isDefined=" << S.isDefined() << " isExternal="
1191  << S.isExternal() << " isTemporary=" << S.isTemporary()
1192  << " isFunction=" << WS.isFunction()
1193  << " isWeak=" << WS.isWeak()
1194  << " isHidden=" << WS.isHidden()
1195  << " isVariable=" << WS.isVariable() << "\n");
1196 
1197  if (WS.isWeak() || WS.isHidden()) {
1198  uint32_t Flags = (WS.isWeak() ? wasm::WASM_SYMBOL_BINDING_WEAK : 0) |
1199  (WS.isHidden() ? wasm::WASM_SYMBOL_VISIBILITY_HIDDEN : 0);
1200  SymbolFlags.emplace_back(WS.getName(), Flags);
1201  }
1202 
1203  if (WS.isVariable())
1204  continue;
1205 
1206  unsigned Index;
1207 
1208  if (WS.isFunction()) {
1209  if (WS.isDefined()) {
1210  if (WS.getOffset() != 0)
1212  "function sections must contain one function each");
1213 
1214  if (WS.getSize() == 0)
1216  "function symbols must have a size set with .size");
1217 
1218  // A definition. Take the next available index.
1219  Index = NumFuncImports + Functions.size();
1220 
1221  // Prepare the function.
1222  WasmFunction Func;
1223  Func.Type = getFunctionType(WS);
1224  Func.Sym = &WS;
1225  SymbolIndices[&WS] = Index;
1226  Functions.push_back(Func);
1227  } else {
1228  // An import; the index was assigned above.
1229  Index = SymbolIndices.find(&WS)->second;
1230  }
1231 
1232  DEBUG(dbgs() << " -> function index: " << Index << "\n");
1233  } else {
1234  if (WS.isTemporary() && !WS.getSize())
1235  continue;
1236 
1237  if (!WS.isDefined())
1238  continue;
1239 
1240  if (!WS.getSize())
1241  report_fatal_error("data symbols must have a size set with .size: " +
1242  WS.getName());
1243 
1244  int64_t Size = 0;
1245  if (!WS.getSize()->evaluateAsAbsolute(Size, Layout))
1246  report_fatal_error(".size expression must be evaluatable");
1247 
1248  // For each global, prepare a corresponding wasm global holding its
1249  // address. For externals these will also be named exports.
1250  Index = NumGlobalImports + Globals.size();
1251  auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection());
1252  assert(DataSection.isWasmData());
1253 
1254  WasmGlobal Global;
1255  Global.Type = PtrType;
1256  Global.IsMutable = false;
1257  Global.HasImport = false;
1258  Global.InitialValue = DataSection.getMemoryOffset() + Layout.getSymbolOffset(WS);
1259  Global.ImportIndex = 0;
1260  SymbolIndices[&WS] = Index;
1261  DEBUG(dbgs() << " -> global index: " << Index << "\n");
1262  Globals.push_back(Global);
1263  }
1264 
1265  // If the symbol is visible outside this translation unit, export it.
1266  if (WS.isDefined()) {
1267  WasmExport Export;
1268  Export.FieldName = WS.getName();
1269  Export.Index = Index;
1270  if (WS.isFunction())
1271  Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
1272  else
1273  Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1274  DEBUG(dbgs() << " -> export " << Exports.size() << "\n");
1275  Exports.push_back(Export);
1276 
1277  if (!WS.isExternal())
1278  SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
1279 
1280  if (WS.isFunction()) {
1281  auto &Section = static_cast<MCSectionWasm &>(WS.getSection());
1282  if (const MCSymbolWasm *C = Section.getGroup())
1283  Comdats[C->getName()].emplace_back(
1284  WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index});
1285  }
1286  }
1287  }
1288 
1289  // Handle weak aliases. We need to process these in a separate pass because
1290  // we need to have processed the target of the alias before the alias itself
1291  // and the symbols are not necessarily ordered in this way.
1292  for (const MCSymbol &S : Asm.symbols()) {
1293  if (!S.isVariable())
1294  continue;
1295 
1296  assert(S.isDefined());
1297 
1298  // Find the target symbol of this weak alias and export that index
1299  const auto &WS = static_cast<const MCSymbolWasm &>(S);
1300  const MCSymbolWasm *ResolvedSym = ResolveSymbol(WS);
1301  DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *ResolvedSym << "'\n");
1302  assert(SymbolIndices.count(ResolvedSym) > 0);
1303  uint32_t Index = SymbolIndices.find(ResolvedSym)->second;
1304  DEBUG(dbgs() << " -> index:" << Index << "\n");
1305 
1306  WasmExport Export;
1307  Export.FieldName = WS.getName();
1308  Export.Index = Index;
1309  if (WS.isFunction())
1310  Export.Kind = wasm::WASM_EXTERNAL_FUNCTION;
1311  else
1312  Export.Kind = wasm::WASM_EXTERNAL_GLOBAL;
1313  DEBUG(dbgs() << " -> export " << Exports.size() << "\n");
1314  Exports.push_back(Export);
1315 
1316  if (!WS.isExternal())
1317  SymbolFlags.emplace_back(WS.getName(), wasm::WASM_SYMBOL_BINDING_LOCAL);
1318  }
1319 
1320  {
1321  auto HandleReloc = [&](const WasmRelocationEntry &Rel) {
1322  // Functions referenced by a relocation need to prepared to be called
1323  // indirectly.
1324  const MCSymbolWasm& WS = *Rel.Symbol;
1325  if (WS.isFunction() && IndirectSymbolIndices.count(&WS) == 0) {
1326  switch (Rel.Type) {
1327  case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
1328  case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
1329  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
1330  case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: {
1331  uint32_t Index = SymbolIndices.find(&WS)->second;
1332  IndirectSymbolIndices[&WS] = TableElems.size();
1333  DEBUG(dbgs() << " -> adding to table: " << TableElems.size() << "\n");
1334  TableElems.push_back(Index);
1335  registerFunctionType(WS);
1336  break;
1337  }
1338  default:
1339  break;
1340  }
1341  }
1342  };
1343 
1344  for (const WasmRelocationEntry &RelEntry : CodeRelocations)
1345  HandleReloc(RelEntry);
1346  for (const WasmRelocationEntry &RelEntry : DataRelocations)
1347  HandleReloc(RelEntry);
1348  }
1349 
1350  // Translate .init_array section contents into start functions.
1351  for (const MCSection &S : Asm) {
1352  const auto &WS = static_cast<const MCSectionWasm &>(S);
1353  if (WS.getSectionName().startswith(".fini_array"))
1354  report_fatal_error(".fini_array sections are unsupported");
1355  if (!WS.getSectionName().startswith(".init_array"))
1356  continue;
1357  if (WS.getFragmentList().empty())
1358  continue;
1359  if (WS.getFragmentList().size() != 2)
1360  report_fatal_error("only one .init_array section fragment supported");
1361  const MCFragment &AlignFrag = *WS.begin();
1362  if (AlignFrag.getKind() != MCFragment::FT_Align)
1363  report_fatal_error(".init_array section should be aligned");
1364  if (cast<MCAlignFragment>(AlignFrag).getAlignment() != (is64Bit() ? 8 : 4))
1365  report_fatal_error(".init_array section should be aligned for pointers");
1366  const MCFragment &Frag = *std::next(WS.begin());
1367  if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
1368  report_fatal_error("only data supported in .init_array section");
1369  uint16_t Priority = UINT16_MAX;
1370  if (WS.getSectionName().size() != 11) {
1371  if (WS.getSectionName()[11] != '.')
1372  report_fatal_error(".init_array section priority should start with '.'");
1373  if (WS.getSectionName().substr(12).getAsInteger(10, Priority))
1374  report_fatal_error("invalid .init_array section priority");
1375  }
1376  const auto &DataFrag = cast<MCDataFragment>(Frag);
1377  const SmallVectorImpl<char> &Contents = DataFrag.getContents();
1378  for (const uint8_t *p = (const uint8_t *)Contents.data(),
1379  *end = (const uint8_t *)Contents.data() + Contents.size();
1380  p != end; ++p) {
1381  if (*p != 0)
1382  report_fatal_error("non-symbolic data in .init_array section");
1383  }
1384  for (const MCFixup &Fixup : DataFrag.getFixups()) {
1385  assert(Fixup.getKind() == MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
1386  const MCExpr *Expr = Fixup.getValue();
1387  auto *Sym = dyn_cast<MCSymbolRefExpr>(Expr);
1388  if (!Sym)
1389  report_fatal_error("fixups in .init_array should be symbol references");
1390  if (Sym->getKind() != MCSymbolRefExpr::VK_WebAssembly_FUNCTION)
1391  report_fatal_error("symbols in .init_array should be for functions");
1392  auto I = SymbolIndices.find(cast<MCSymbolWasm>(&Sym->getSymbol()));
1393  if (I == SymbolIndices.end())
1394  report_fatal_error("symbols in .init_array should be defined");
1395  uint32_t Index = I->second;
1396  InitFuncs.push_back(std::make_pair(Priority, Index));
1397  }
1398  }
1399 
1400  // Write out the Wasm header.
1401  writeHeader(Asm);
1402 
1403  writeTypeSection(FunctionTypes);
1404  writeImportSection(Imports, DataSize, TableElems.size());
1405  writeFunctionSection(Functions);
1406  // Skip the "table" section; we import the table instead.
1407  // Skip the "memory" section; we import the memory instead.
1408  writeGlobalSection();
1409  writeExportSection(Exports);
1410  writeElemSection(TableElems);
1411  writeCodeSection(Asm, Layout, Functions);
1412  writeDataSection(DataSegments);
1413  writeNameSection(Functions, Imports, NumFuncImports);
1414  writeCodeRelocSection();
1415  writeDataRelocSection();
1416  writeLinkingMetaDataSection(DataSegments, DataSize, SymbolFlags,
1417  InitFuncs, Comdats);
1418 
1419  // TODO: Translate the .comment section to the output.
1420  // TODO: Translate debug sections to the output.
1421 }
1422 
1423 std::unique_ptr<MCObjectWriter>
1424 llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
1425  raw_pwrite_stream &OS) {
1426  return llvm::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
1427 }
bool isFunction() const
Definition: MCSymbolWasm.h:44
uint64_t CallInst * C
Instances of this class represent a uniqued identifier for a section in the current translation unit...
Definition: MCSection.h:39
static const MCSymbolWasm * ResolveSymbol(const MCSymbolWasm &Symbol)
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:245
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:115
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
bool isVariable() const
isVariable - Check if this is a variable symbol.
Definition: MCSymbol.h:294
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds...
Definition: Compiler.h:449
This represents an "assembler immediate".
Definition: MCValue.h:40
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
static void WriteI32(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset)
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:136
const unsigned WASM_SYMBOL_BINDING_LOCAL
Definition: Wasm.h:216
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
const StringRef getModuleName() const
Definition: MCSymbolWasm.h:56
MCSectionWasm * getWasmSection(const Twine &Section, SectionKind K)
Definition: MCContext.h:445
StringRef getSectionName() const
Definition: MCSectionWasm.h:63
static MCFixupKind getKindForSize(unsigned Size, bool isPCRel)
Return the generic fixup kind for a value with the given size.
Definition: MCFixup.h:102
FragmentType getKind() const
Definition: MCFragment.h:102
void write32le(void *P, uint32_t V)
Definition: Endian.h:404
F(f)
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
Definition: MathExtras.h:677
Defines the object file and target independent interfaces used by the assembler backend to write nati...
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:66
unsigned getAlignment() const
Definition: MCSection.h:117
Export information to summary.
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...
MCContext & getContext() const
Definition: MCAssembler.h:273
static void WritePatchableSLEB(raw_pwrite_stream &Stream, int32_t X, uint64_t Offset)
int64_t getConstant() const
Definition: MCValue.h:47
const MCSymbolRefExpr * getSymB() const
Definition: MCValue.h:49
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:29
int64_t decodeSLEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a SLEB128 value.
Definition: LEB128.h:162
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:165
static unsigned getRelocType(const MCValue &Target, const MCFixupKind FixupKind, const bool IsPCRel)
Translates generic PPC fixup kind to Mach-O/PPC relocation type enum.
ELFYAML::ELF_STO Other
Definition: ELFYAML.cpp:736
const uint32_t WasmVersion
Definition: Wasm.h:26
void writeSectionData(const MCSection *Section, const MCAsmLayout &Layout) const
Emit the section contents using the given object writer.
Context object for machine code objects.
Definition: MCContext.h:60
static bool isEqual(const Function &Caller, const Function &Callee)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
Import information from summary.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN
Definition: Wasm.h:218
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:150
This represents a section on wasm.
Definition: MCSectionWasm.h:28
static bool is64Bit(const char *name)
virtual void reset()
lifetime management
const unsigned WASM_SYMBOL_BINDING_WEAK
Definition: Wasm.h:215
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:129
void pwrite(const char *Ptr, size_t Size, uint64_t Offset)
Definition: raw_ostream.h:343
std::unique_ptr< MCObjectWriter > createWasmObjectWriter(std::unique_ptr< MCWasmObjectTargetWriter > MOTW, raw_pwrite_stream &OS)
Construct a new Wasm writer instance.
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:48
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:573
const SmallVector< wasm::ValType, 1 > & getReturns() const
Definition: MCSymbolWasm.h:58
static void addData(SmallVectorImpl< char > &DataBytes, MCSectionWasm &DataSection)
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
uint32_t getOffset() const
Definition: MCFixup.h:95
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
uint64_t getFragmentOffset(const MCFragment *F) const
Get the offset of the given fragment inside its containing section.
Definition: MCFragment.cpp:77
PowerPC TLS Dynamic Call Fixup
const char WasmMagic[]
Definition: Wasm.h:24
SMLoc getLoc() const
Definition: MCFixup.h:112
MCAsmBackend & getBackend() const
Definition: MCAssembler.h:275
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:81
const MCSymbol & getSymbol() const
Definition: MCExpr.h:326
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:24
const DataFlowGraph & G
Definition: RDFGraph.cpp:211
static SectionKind getMetadata()
Definition: SectionKind.h:179
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
bool isDefined() const
isDefined - Check if this symbol is defined (i.e., it has an address).
Definition: MCSymbol.h:248
Target - Wrapper for Target specific information.
MCSection * getParent() const
Definition: MCFragment.h:104
bool hasInstructions() const
Does this fragment have instructions emitted into it? By default this is false, but specific fragment...
Definition: MCFragment.h:115
iterator insert(iterator I, T &&Elt)
Definition: SmallVector.h:480
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:120
pointer data()
Return a pointer to the vector&#39;s buffer, even if empty().
Definition: SmallVector.h:143
void emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:654
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:121
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:224
#define I(x, y, z)
Definition: MD5.cpp:58
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:323
symbol_range symbols()
Definition: MCAssembler.h:336
raw_ostream & operator<<(raw_ostream &OS, const APInt &I)
Definition: APInt.h:2018
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:203
An abstract base class for streams implementations that also support a pwrite operation.
Definition: raw_ostream.h:337
const SmallVector< wasm::ValType, 4 > & getParams() const
Definition: MCSymbolWasm.h:68
const unsigned Kind
static void WritePatchableLEB(raw_pwrite_stream &Stream, uint32_t X, uint64_t Offset)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
const MCExpr * getVariableValue(bool SetUsed=true) const
getVariableValue - Get the value for variable symbols.
Definition: MCSymbol.h:299
bool operator<(int64_t V1, const APSInt &V2)
Definition: APSInt.h:326
LLVM Value Representation.
Definition: Value.h:73
Generic interface to target specific assembler backends.
Definition: MCAsmBackend.h:40
constexpr char Size[]
Key for Kernel::Arg::Metadata::mSize.
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:44
#define DEBUG(X)
Definition: Debug.h:118
const MCExpr * getValue() const
Definition: MCFixup.h:98
const uint32_t WasmPageSize
Definition: Wasm.h:28
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
bool operator==(uint64_t V1, const APInt &V2)
Definition: APInt.h:1946
MCSection::FragmentListType & getFragmentList()
Definition: MCSection.h:143
MCFixupKind getKind() const
Definition: MCFixup.h:93
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:145
iterator begin()
Definition: MCSection.h:156
void resize(size_type N)
Definition: SmallVector.h:353