1//===- lib/MC/WasmObjectWriter.cpp - Wasm File Writer ---------------------===//
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
7//===----------------------------------------------------------------------===//
9// This file implements Wasm object file writer information.
11//===----------------------------------------------------------------------===//
16#include "llvm/Config/llvm-config.h"
35 #define DEBUG_TYPE "mc"
39// When we create the indirect function table we start at 1, so that there is
40// and empty slot at 0 and therefore calling a null function pointer will trap.
41static const uint32_t InitialTableOffset = 1;
43// For patching purposes, we need to remember where each section starts, both
44// for patching up the section size field, and for patching up references to
45// locations within the section.
46struct SectionBookkeeping {
47 // Where the size of the section is written.
49 // Where the section header ends (without custom section name).
51 // Where the contents of the section starts.
56// A wasm data segment. A wasm binary contains only a single data section
57// but that can contain many segments, each with their own virtual location
58// in memory. Each MCSection data created by llvm is modeled as its own
60struct WasmDataSegment {
70// A wasm function to be written into the function section.
76// A wasm global to be written into the global section.
82// Information about a single item which is part of a COMDAT. For each data
83// segment or function which is in the COMDAT, there is a corresponding
85struct WasmComdatEntry {
90// Information about a single relocation.
91struct WasmRelocationEntry {
93 const MCSymbolWasm *Symbol;
// The symbol to relocate with.
94 int64_t Addend;
// A value to add to the symbol.
95 unsigned Type;
// The type of the relocation.
96 const MCSectionWasm *FixupSection;
// The section the relocation is targeting.
99 int64_t Addend,
unsigned Type,
102 FixupSection(FixupSection) {}
108 <<
", Sym=" << *Symbol <<
", Addend=" << Addend
109 <<
", FixupSection=" << FixupSection->
getName();
112#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
119struct WasmCustomSection {
128 : Name(Name), Section(Section) {}
138// Write Value as an (unsigned) LEB value at offset Offset in Stream, padded
140template <
typename T,
int W>
148// Write Value as an signed LEB value at offset Offset in Stream, padded
150template <
typename T,
int W>
160 writePatchableULEB<uint32_t, 5>(Stream,
Value,
Offset);
165 writePatchableSLEB<int32_t, 5>(Stream,
Value,
Offset);
170 writePatchableSLEB<uint64_t, 10>(Stream,
Value,
Offset);
175 writePatchableSLEB<int64_t, 10>(Stream,
Value,
Offset);
178// Write Value as a plain integer value at offset Offset in Stream.
200 /// The target specific Wasm writer instance.
201 std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter;
203 // Relocations for fixing up references in the code section.
204 std::vector<WasmRelocationEntry> CodeRelocations;
205 // Relocations for fixing up references in the data section.
206 std::vector<WasmRelocationEntry> DataRelocations;
208 // Index values to use for fixing up call_indirect type indices.
209 // Maps function symbols to the index of the type of the function
211 // Maps function symbols to the table element index space. Used
212 // for TABLE_INDEX relocation types (i.e. address taken functions).
214 // Maps function/global/table symbols to the
215 // function/global/table/tag/section index space.
218 // Maps data symbols to the Wasm segment and offset/size with the segment.
221 // Stores output data (index, relocations, content offset) for custom
223 std::vector<WasmCustomSection> CustomSections;
224 std::unique_ptr<WasmCustomSection> ProducersSection;
225 std::unique_ptr<WasmCustomSection> TargetFeaturesSection;
226 // Relocations for fixing up references in the custom sections.
228 CustomSectionsRelocations;
230 // Map from section to defining function symbol.
236 unsigned NumFunctionImports = 0;
237 unsigned NumGlobalImports = 0;
238 unsigned NumTableImports = 0;
239 unsigned NumTagImports = 0;
247 bool IsSplitDwarf =
false;
251 // TargetObjectWriter wranppers.
252 bool is64Bit()
const {
return TargetObjectWriter->is64Bit(); }
253 bool isEmscripten()
const {
return TargetObjectWriter->isEmscripten(); }
255 void startSection(SectionBookkeeping &Section,
unsigned SectionId);
256 void startCustomSection(SectionBookkeeping &Section,
StringRef Name);
257 void endSection(SectionBookkeeping &Section);
260 WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
262 : TargetObjectWriter(std::move(MOTW)), OS(&OS_) {}
264 WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW,
266 : TargetObjectWriter(std::move(MOTW)), IsSplitDwarf(
true), OS(&OS_),
270 void reset()
override {
271 CodeRelocations.clear();
272 DataRelocations.clear();
276 TableIndices.
clear();
277 DataLocations.
clear();
278 CustomSections.clear();
279 ProducersSection.reset();
280 TargetFeaturesSection.reset();
281 CustomSectionsRelocations.
clear();
282 SignatureIndices.
clear();
284 DataSegments.
clear();
285 SectionFunctions.
clear();
286 NumFunctionImports = 0;
287 NumGlobalImports = 0;
297 void executePostLayoutBinding()
override;
309 void writeStringWithAlignment(
const StringRef Str,
unsigned Alignment);
311 void writeI32(int32_t val) {
314 W->OS.write(Buffer,
sizeof(Buffer));
317 void writeI64(int64_t val) {
320 W->OS.write(Buffer,
sizeof(Buffer));
323 void writeValueType(
wasm::ValType Ty) { W->OS <<
static_cast<char>(Ty); }
330 void writeElemSection(
const MCSymbolWasm *IndirectFunctionTable,
332 void writeDataCountSection();
340 std::vector<WasmRelocationEntry> &Relocations);
341 void writeLinkingMetaDataSection(
343 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
344 const std::map<
StringRef, std::vector<WasmComdatEntry>> &Comdats);
345 void writeCustomSection(WasmCustomSection &CustomSection,
347 void writeCustomRelocSections();
350 const WasmRelocationEntry &RelEntry);
354 uint32_t getRelocationIndexValue(
const WasmRelocationEntry &RelEntry);
361}
// end anonymous namespace
363// Write out a section header and a patchable section size field.
364void WasmObjectWriter::startSection(SectionBookkeeping &Section,
365 unsigned SectionId) {
367 W->
OS << char(SectionId);
371 // The section size. We don't know the size yet, so reserve enough space
372 // for any 32-bit value; we'll patch it later.
375 // The position where the section starts, for measuring its size.
378 Section.Index = SectionCount++;
381// Write a string with extra paddings for trailing alignment
382// TODO: support alignment at asm and llvm level?
383void WasmObjectWriter::writeStringWithAlignment(
const StringRef Str,
384 unsigned Alignment) {
386 // Calculate the encoded size of str length and add pads based on it and
388 raw_null_ostream NullOS;
390 uint64_t
Offset = W->
OS.
tell() + StrSizeLength + Str.size();
394 // LEB128 greater than 5 bytes is invalid
395 assert((StrSizeLength + Paddings) <= 5 &&
"too long string to align");
403void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section,
408 // The position where the section header ends, for measuring its size.
411 // Custom sections in wasm also have a string identifier.
412 if (Name !=
"__clangast") {
415 // The on-disk hashtable in clangast needs to be aligned by 4 bytes.
416 writeStringWithAlignment(Name, 4);
419 // The position where the custom section starts.
423// Now that the section is complete and we know how big it is, patch up the
424// section size field at the start of the section.
425void WasmObjectWriter::endSection(SectionBookkeeping &Section) {
427 // /dev/null doesn't support seek/tell and can report offset of 0.
428 // Simply skip this patching in that case.
438 // Write the final section size to the payload_len field, which follows
439 // the section id byte.
440 writePatchableU32(
static_cast<raw_pwrite_stream &
>(W->
OS),
Size,
444// Emit the Wasm header.
445void WasmObjectWriter::writeHeader(
const MCAssembler &Asm) {
450void WasmObjectWriter::executePostLayoutBinding() {
451 // Some compilation units require the indirect function table to be present
452 // but don't explicitly reference it. This is the case for call_indirect
453 // without the reference-types feature, and also function bitcasts in all
454 // cases. In those cases the __indirect_function_table has the
455 // WASM_SYMBOL_NO_STRIP attribute. Here we make sure this symbol makes it to
456 // the assembler, if needed.
457 if (
auto *Sym =
Asm->getContext().lookupSymbol(
"__indirect_function_table")) {
458 const auto *WasmSym =
static_cast<const MCSymbolWasm *
>(Sym);
459 if (WasmSym->isNoStrip())
460 Asm->registerSymbol(*Sym);
463 // Build a map of sections to the function that defines them, for use
464 // in recordRelocation.
465 for (
const MCSymbol &S :
Asm->symbols()) {
466 const auto &WS =
static_cast<const MCSymbolWasm &
>(S);
467 if (WS.isDefined() && WS.isFunction() && !WS.isVariable()) {
468 const auto &Sec =
static_cast<const MCSectionWasm &
>(S.getSection());
469 auto Pair = SectionFunctions.insert(std::make_pair(&Sec, &S));
477void WasmObjectWriter::recordRelocation(
const MCFragment &
F,
478 const MCFixup &
Fixup, MCValue Target,
479 uint64_t &FixedValue) {
480 // The WebAssembly backend should never generate FKF_IsPCRel fixups
483 const auto &FixupSection =
static_cast<MCSectionWasm &
>(*
F.getParent());
484 uint64_t
C =
Target.getConstant();
485 uint64_t FixupOffset =
Asm->getFragmentOffset(
F) +
Fixup.getOffset();
487 bool IsLocRel =
false;
489 if (
const auto *RefB =
Target.getSubSym()) {
490 auto &SymB =
static_cast<const MCSymbolWasm &
>(*RefB);
492 if (FixupSection.isText()) {
494 Twine(
"symbol '") + SymB.getName() +
495 "' unsupported subtraction expression used in "
496 "relocation in code section.");
500 if (SymB.isUndefined()) {
502 Twine(
"symbol '") + SymB.getName() +
503 "' can not be undefined in a subtraction expression");
506 const MCSection &SecB = SymB.getSection();
507 if (&SecB != &FixupSection) {
509 Twine(
"symbol '") + SymB.getName() +
510 "' can not be placed in a different section");
514 C += FixupOffset -
Asm->getSymbolOffset(SymB);
517 // We either rejected the fixup or folded B into C at this point.
518 auto *SymA =
static_cast<const MCSymbolWasm *
>(
Target.getAddSym());
520 // The .init_array isn't translated as data, so don't do relocations in it.
521 if (FixupSection.getName().starts_with(
".init_array")) {
522 SymA->setUsedInInitArray();
526 // Put any constant offset in an addend. Offsets can be negative, and
527 // LLVM expects wrapping, in contrast to wasm's immediates which can't
528 // be negative and don't wrap.
536 TargetObjectWriter->getRelocType(Target,
Fixup, FixupSection, IsLocRel);
538 // Absolute offset within a section or a function.
539 // Currently only supported for metadata sections.
540 // See: test/MC/WebAssembly/blockaddress.ll
541 if ((
Type == wasm::R_WASM_FUNCTION_OFFSET_I32 ||
542 Type == wasm::R_WASM_FUNCTION_OFFSET_I64 ||
543 Type == wasm::R_WASM_SECTION_OFFSET_I32) &&
545 // SymA can be a temp data symbol that represents a function (in which case
546 // it needs to be replaced by the section symbol), [XXX and it apparently
547 // later gets changed again to a func symbol?] or it can be a real
548 // function symbol, in which case it can be left as-is.
550 if (!FixupSection.isMetadata())
552 "only supported in metadata sections");
554 const MCSymbol *SectionSymbol =
nullptr;
555 const MCSection &SecA = SymA->getSection();
557 auto SecSymIt = SectionFunctions.find(&SecA);
558 if (SecSymIt == SectionFunctions.end())
560 SectionSymbol = SecSymIt->second;
567 C +=
Asm->getSymbolOffset(*SymA);
568 SymA =
static_cast<const MCSymbolWasm *
>(SectionSymbol);
571 if (
Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
572 Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64 ||
573 Type == wasm::R_WASM_TABLE_INDEX_SLEB ||
574 Type == wasm::R_WASM_TABLE_INDEX_SLEB64 ||
575 Type == wasm::R_WASM_TABLE_INDEX_I32 ||
576 Type == wasm::R_WASM_TABLE_INDEX_I64) {
577 // TABLE_INDEX relocs implicitly use the default indirect function table.
578 // We require the function table to have already been defined.
579 auto TableName =
"__indirect_function_table";
580 auto *Sym =
static_cast<MCSymbolWasm *
>(Ctx.
lookupSymbol(TableName));
584 if (!Sym->isFunctionTable())
586 // Ensure that __indirect_function_table reaches the output.
588 Asm->registerSymbol(*Sym);
592 // Relocation other than R_WASM_TYPE_INDEX_LEB are required to be
593 // against a named symbol.
594 if (
Type != wasm::R_WASM_TYPE_INDEX_LEB) {
595 if (SymA->getName().empty())
597 "supported by wasm");
599 SymA->setUsedInReloc();
602 WasmRelocationEntry Rec(FixupOffset, SymA,
C,
Type, &FixupSection);
605 if (FixupSection.isWasmData()) {
606 DataRelocations.push_back(Rec);
607 }
else if (FixupSection.isText()) {
608 CodeRelocations.push_back(Rec);
609 }
else if (FixupSection.isMetadata()) {
610 CustomSectionsRelocations[&FixupSection].push_back(Rec);
616// Compute a value to write into the code at the location covered
617// by RelEntry. This value isn't used by the static linker; it just serves
618// to make the object format more readable and more likely to be directly
621WasmObjectWriter::getProvisionalValue(
const MCAssembler &Asm,
622 const WasmRelocationEntry &RelEntry) {
623 if ((RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_LEB ||
624 RelEntry.Type == wasm::R_WASM_GLOBAL_INDEX_I32) &&
626 assert(GOTIndices.count(RelEntry.Symbol) > 0 &&
"symbol not found in GOT index space");
627 return GOTIndices[RelEntry.Symbol];
630 switch (RelEntry.Type) {
631 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
632 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
633 case wasm::R_WASM_TABLE_INDEX_SLEB:
634 case wasm::R_WASM_TABLE_INDEX_SLEB64:
635 case wasm::R_WASM_TABLE_INDEX_I32:
636 case wasm::R_WASM_TABLE_INDEX_I64: {
637 // Provisional value is table address of the resolved symbol itself
639 static_cast<const MCSymbolWasm *
>(
Asm.getBaseSymbol(*RelEntry.Symbol));
641 if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB ||
642 RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
643 return TableIndices[
Base] - InitialTableOffset;
645 return TableIndices[
Base];
647 case wasm::R_WASM_TYPE_INDEX_LEB:
648 // Provisional value is same as the index
649 return getRelocationIndexValue(RelEntry);
650 case wasm::R_WASM_FUNCTION_INDEX_LEB:
651 case wasm::R_WASM_FUNCTION_INDEX_I32:
652 case wasm::R_WASM_GLOBAL_INDEX_LEB:
653 case wasm::R_WASM_GLOBAL_INDEX_I32:
654 case wasm::R_WASM_TAG_INDEX_LEB:
655 case wasm::R_WASM_TABLE_NUMBER_LEB:
656 // Provisional value is function/global/tag Wasm index
657 assert(WasmIndices.count(RelEntry.Symbol) > 0 &&
"symbol not found in wasm index space");
658 return WasmIndices[RelEntry.Symbol];
659 case wasm::R_WASM_FUNCTION_OFFSET_I32:
660 case wasm::R_WASM_FUNCTION_OFFSET_I64:
661 case wasm::R_WASM_SECTION_OFFSET_I32: {
665 static_cast<const MCSectionWasm &
>(RelEntry.Symbol->
getSection());
666 return Section.getSectionOffset() + RelEntry.Addend;
668 case wasm::R_WASM_MEMORY_ADDR_LEB:
669 case wasm::R_WASM_MEMORY_ADDR_LEB64:
670 case wasm::R_WASM_MEMORY_ADDR_SLEB:
671 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
672 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
673 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
674 case wasm::R_WASM_MEMORY_ADDR_I32:
675 case wasm::R_WASM_MEMORY_ADDR_I64:
676 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
677 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
678 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32: {
679 // Provisional value is address of the global plus the offset
680 // For undefined symbols, use zero
683 const wasm::WasmDataReference &SymRef = DataLocations[RelEntry.Symbol];
684 const WasmDataSegment &Segment = DataSegments[SymRef.
Segment];
685 // Ignore overflow. LLVM allows address arithmetic to silently wrap.
686 return Segment.Offset + SymRef.
Offset + RelEntry.Addend;
700 if (Frag.hasInstructions())
705 if (Frag.getAlignFillLen() != 1)
707 // If nops are requested, use zeros, as this is the data section.
708 uint8_t Value = Frag.hasAlignEmitNops() ? 0 : Frag.getAlignFill();
710 std::min<uint64_t>(
alignTo(DataBytes.
size(), Frag.getAlignment()),
711 DataBytes.
size() + Frag.getAlignMaxBytesToEmit());
715 if (!Fill->getNumValues().evaluateAsAbsolute(NumValues))
717 DataBytes.
insert(DataBytes.
end(), Fill->getValueSize() * NumValues,
730WasmObjectWriter::getRelocationIndexValue(
const WasmRelocationEntry &RelEntry) {
731 if (RelEntry.Type == wasm::R_WASM_TYPE_INDEX_LEB) {
732 auto It = TypeIndices.find(RelEntry.Symbol);
733 if (It == TypeIndices.end())
742// Apply the portions of the relocation records that we can handle ourselves
744void WasmObjectWriter::applyRelocations(
746 const MCAssembler &Asm) {
747 auto &Stream =
static_cast<raw_pwrite_stream &
>(W->
OS);
748 for (
const WasmRelocationEntry &RelEntry : Relocations) {
749 uint64_t
Offset = ContentsOffset +
754 uint64_t
Value = getProvisionalValue(Asm, RelEntry);
756 switch (RelEntry.Type) {
757 case wasm::R_WASM_FUNCTION_INDEX_LEB:
758 case wasm::R_WASM_TYPE_INDEX_LEB:
759 case wasm::R_WASM_GLOBAL_INDEX_LEB:
760 case wasm::R_WASM_MEMORY_ADDR_LEB:
761 case wasm::R_WASM_TAG_INDEX_LEB:
762 case wasm::R_WASM_TABLE_NUMBER_LEB:
765 case wasm::R_WASM_MEMORY_ADDR_LEB64:
768 case wasm::R_WASM_TABLE_INDEX_I32:
769 case wasm::R_WASM_MEMORY_ADDR_I32:
770 case wasm::R_WASM_FUNCTION_OFFSET_I32:
771 case wasm::R_WASM_FUNCTION_INDEX_I32:
772 case wasm::R_WASM_SECTION_OFFSET_I32:
773 case wasm::R_WASM_GLOBAL_INDEX_I32:
774 case wasm::R_WASM_MEMORY_ADDR_LOCREL_I32:
777 case wasm::R_WASM_TABLE_INDEX_I64:
778 case wasm::R_WASM_MEMORY_ADDR_I64:
779 case wasm::R_WASM_FUNCTION_OFFSET_I64:
782 case wasm::R_WASM_TABLE_INDEX_SLEB:
783 case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
784 case wasm::R_WASM_MEMORY_ADDR_SLEB:
785 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
786 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
789 case wasm::R_WASM_TABLE_INDEX_SLEB64:
790 case wasm::R_WASM_TABLE_INDEX_REL_SLEB64:
791 case wasm::R_WASM_MEMORY_ADDR_SLEB64:
792 case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
793 case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB64:
802void WasmObjectWriter::writeTypeSection(
812 for (
const wasm::WasmSignature &Sig :
Signatures) {
827 uint32_t NumElements) {
838 for (
const wasm::WasmImport &
Import : Imports) {
839 writeString(
Import.Module);
840 writeString(
Import.Field);
849 W->
OS << char(
Import.Global.Mutable ? 1 : 0);
856 W->
OS << char(
Import.Table.ElemType);
861 W->
OS << char(0);
// Reserved 'attribute' field
873 if (Functions.
empty())
880 for (
const WasmFunction &Func : Functions)
886void WasmObjectWriter::writeTagSection(ArrayRef<uint32_t> TagTypes) {
887 if (TagTypes.
empty())
894 for (uint32_t Index : TagTypes) {
895 W->
OS << char(0);
// Reserved 'attribute' field
910 for (
const wasm::WasmGlobal &
Global : Globals) {
913 if (
Global.InitExpr.Extended) {
916 W->
OS << char(
Global.InitExpr.Inst.Opcode);
917 switch (
Global.Type.Type) {
931 writeValueType(wasm::ValType::EXTERNREF);
951 for (
const wasm::WasmTable &Table : Tables) {
952 assert(Table.Type.ElemType != wasm::ValType::OTHERREF &&
953 "Cannot encode general ref-typed tables");
971 for (
const wasm::WasmExport &
Export : Exports) {
980void WasmObjectWriter::writeElemSection(
981 const MCSymbolWasm *IndirectFunctionTable, ArrayRef<uint32_t> TableElems) {
982 if (TableElems.
empty())
985 assert(IndirectFunctionTable);
992 assert(WasmIndices.count(IndirectFunctionTable));
993 uint32_t TableNumber = WasmIndices.find(IndirectFunctionTable)->second;
1001 // init expr for starting offset
1008 // We only write active function table initializers, for which the elem kind
1009 // is specified to be written as 0x00 and interpreted to mean "funcref".
1010 const uint8_t ElemKind = 0;
1015 for (uint32_t Elem : TableElems)
1018 endSection(Section);
1021void WasmObjectWriter::writeDataCountSection() {
1022 if (DataSegments.empty())
1028 endSection(Section);
1031uint32_t WasmObjectWriter::writeCodeSection(
const MCAssembler &Asm,
1033 if (Functions.
empty())
1041 for (
const WasmFunction &Func : Functions) {
1042 auto *FuncSection =
static_cast<MCSectionWasm *
>(
Func.Section);
1044 int64_t
Size =
Asm.getSectionAddressSize(*FuncSection);
1046 FuncSection->setSectionOffset(W->
OS.
tell() -
Section.ContentsOffset);
1047 Asm.writeSectionData(W->
OS, FuncSection);
1051 applyRelocations(CodeRelocations,
Section.ContentsOffset, Asm);
1053 endSection(Section);
1057uint32_t WasmObjectWriter::writeDataSection(
const MCAssembler &Asm) {
1058 if (DataSegments.empty())
1066 for (
const WasmDataSegment &Segment : DataSegments) {
1077 Segment.Section->setSectionOffset(W->
OS.
tell() -
Section.ContentsOffset);
1078 W->
OS << Segment.Data;
// data
1082 applyRelocations(DataRelocations,
Section.ContentsOffset, Asm);
1084 endSection(Section);
1088void WasmObjectWriter::writeRelocSection(
1089 uint32_t SectionIndex, StringRef Name,
1090 std::vector<WasmRelocationEntry> &Relocs) {
1091 // See: https://github.com/WebAssembly/tool-conventions/blob/main/Linking.md
1092 // for descriptions of the reloc sections.
1097 // First, ensure the relocations are sorted in offset order. In general they
1098 // should already be sorted since `recordRelocation` is called in offset
1099 // order, but for the code section we combine many MC sections into single
1100 // wasm section, and this order is determined by the order of Asm.Symbols()
1101 // not the sections order.
1103 Relocs, [](
const WasmRelocationEntry &
A,
const WasmRelocationEntry &
B) {
1104 return (
A.Offset +
A.FixupSection->getSectionOffset()) <
1105 (
B.Offset +
B.FixupSection->getSectionOffset());
1109 startCustomSection(Section, std::string(
"reloc.") +
Name.str());
1113 for (
const WasmRelocationEntry &RelEntry : Relocs) {
1116 uint32_t
Index = getRelocationIndexValue(RelEntry);
1118 W->
OS << char(RelEntry.Type);
1121 if (RelEntry.hasAddend())
1125 endSection(Section);
1128void WasmObjectWriter::writeCustomRelocSections() {
1129 for (
const auto &Sec : CustomSections) {
1130 auto &Relocations = CustomSectionsRelocations[Sec.Section];
1131 writeRelocSection(Sec.OutputIndex, Sec.Name, Relocations);
1135void WasmObjectWriter::writeLinkingMetaDataSection(
1137 ArrayRef<std::pair<uint16_t, uint32_t>> InitFuncs,
1138 const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) {
1140 startCustomSection(Section,
"linking");
1143 SectionBookkeeping SubSection;
1144 if (SymbolInfos.
size() != 0) {
1147 for (
const wasm::WasmSymbolInfo &Sym : SymbolInfos) {
1158 writeString(Sym.Name);
1161 writeString(Sym.Name);
1169 const uint32_t SectionIndex =
1170 CustomSections[Sym.ElementIndex].OutputIndex;
1178 endSection(SubSection);
1181 if (DataSegments.size()) {
1184 for (
const WasmDataSegment &Segment : DataSegments) {
1185 writeString(Segment.Name);
1189 endSection(SubSection);
1192 if (!InitFuncs.empty()) {
1195 for (
auto &StartFunc : InitFuncs) {
1199 endSection(SubSection);
1202 if (Comdats.size()) {
1205 for (
const auto &
C : Comdats) {
1206 writeString(
C.first);
1209 for (
const WasmComdatEntry &Entry :
C.second) {
1214 endSection(SubSection);
1217 endSection(Section);
1220void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection,
1221 const MCAssembler &Asm) {
1223 auto *Sec = CustomSection.Section;
1224 startCustomSection(Section, CustomSection.Name);
1226 Sec->setSectionOffset(W->
OS.
tell() -
Section.ContentsOffset);
1227 Asm.writeSectionData(W->
OS, Sec);
1229 CustomSection.OutputContentsOffset =
Section.ContentsOffset;
1230 CustomSection.OutputIndex =
Section.Index;
1232 endSection(Section);
1235 auto &Relocations = CustomSectionsRelocations[CustomSection.Section];
1236 applyRelocations(Relocations, CustomSection.OutputContentsOffset, Asm);
1239uint32_t WasmObjectWriter::getFunctionType(
const MCSymbolWasm &Symbol) {
1241 assert(TypeIndices.count(&Symbol));
1242 return TypeIndices[&
Symbol];
1245uint32_t WasmObjectWriter::getTagType(
const MCSymbolWasm &Symbol) {
1247 assert(TypeIndices.count(&Symbol));
1248 return TypeIndices[&
Symbol];
1251void WasmObjectWriter::registerFunctionType(
const MCSymbolWasm &Symbol) {
1254 wasm::WasmSignature S;
1256 if (
auto *Sig =
Symbol.getSignature()) {
1261 auto Pair = SignatureIndices.insert(std::make_pair(S,
Signatures.size()));
1264 TypeIndices[&
Symbol] = Pair.first->second;
1267 <<
" new:" << Pair.second <<
"\n");
1268 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1271void WasmObjectWriter::registerTagType(
const MCSymbolWasm &Symbol) {
1274 // TODO Currently we don't generate imported exceptions, but if we do, we
1275 // should have a way of infering types of imported exceptions.
1276 wasm::WasmSignature S;
1277 if (
auto *Sig =
Symbol.getSignature()) {
1282 auto Pair = SignatureIndices.insert(std::make_pair(S,
Signatures.size()));
1285 TypeIndices[&
Symbol] = Pair.first->second;
1287 LLVM_DEBUG(
dbgs() <<
"registerTagType: " << Symbol <<
" new:" << Pair.second
1289 LLVM_DEBUG(
dbgs() <<
" -> type index: " << Pair.first->second <<
"\n");
1314 for (
const MCSymbol &S : Asm.symbols()) {
1316 if (WS.isData() && WS.isInSection()) {
1317 auto &RefSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1327void WasmObjectWriter::prepareImports(
1328 SmallVectorImpl<wasm::WasmImport> &Imports, MCAssembler &Asm) {
1329 // For now, always emit the memory import, since loads and stores are not
1330 // valid without it. In the future, we could perhaps be more clever and omit
1331 // it if there are no loads or stores.
1332 wasm::WasmImport MemImport;
1333 MemImport.
Module =
"env";
1334 MemImport.
Field =
"__linear_memory";
1340 // Populate SignatureIndices, and Imports and WasmIndices for undefined
1341 // symbols. This must be done before populating WasmIndices for defined
1343 for (
const MCSymbol &S :
Asm.symbols()) {
1344 const auto &WS =
static_cast<const MCSymbolWasm &
>(S);
1346 // Register types for all functions, including those with private linkage
1347 // (because wasm always needs a type signature).
1348 if (WS.isFunction()) {
1349 auto *BS =
static_cast<const MCSymbolWasm *
>(
Asm.getBaseSymbol(S));
1352 ": absolute addressing not supported!");
1353 registerFunctionType(*BS);
1357 registerTagType(WS);
1359 if (WS.isTemporary())
1362 // If the symbol is not defined in this translation unit, import it.
1363 if (!WS.isDefined() && !WS.isComdat()) {
1364 if (WS.isFunction()) {
1366 Import.Module = WS.getImportModule();
1367 Import.Field = WS.getImportName();
1369 Import.SigIndex = getFunctionType(WS);
1371 assert(WasmIndices.count(&WS) == 0);
1372 WasmIndices[&WS] = NumFunctionImports++;
1373 }
else if (WS.isGlobal()) {
1378 Import.Field = WS.getImportName();
1380 Import.Module = WS.getImportModule();
1381 Import.Global = WS.getGlobalType();
1383 assert(WasmIndices.count(&WS) == 0);
1384 WasmIndices[&WS] = NumGlobalImports++;
1385 }
else if (WS.isTag()) {
1390 Import.Module = WS.getImportModule();
1391 Import.Field = WS.getImportName();
1393 Import.SigIndex = getTagType(WS);
1395 assert(WasmIndices.count(&WS) == 0);
1396 WasmIndices[&WS] = NumTagImports++;
1397 }
else if (WS.isTable()) {
1402 Import.Module = WS.getImportModule();
1403 Import.Field = WS.getImportName();
1405 Import.Table = WS.getTableType();
1407 assert(WasmIndices.count(&WS) == 0);
1408 WasmIndices[&WS] = NumTableImports++;
1413 // Add imports for GOT globals
1414 for (
const MCSymbol &S :
Asm.symbols()) {
1415 const auto &WS =
static_cast<const MCSymbolWasm &
>(S);
1416 if (WS.isUsedInGOT()) {
1418 if (WS.isFunction())
1419 Import.Module =
"GOT.func";
1421 Import.Module =
"GOT.mem";
1422 Import.Field = WS.getName();
1426 assert(GOTIndices.count(&WS) == 0);
1427 GOTIndices[&WS] = NumGlobalImports++;
1432uint64_t WasmObjectWriter::writeObject() {
1436 uint64_t TotalSize = writeOneObject(*Asm, DwoMode::NonDwoOnly);
1440 return TotalSize + writeOneObject(*Asm, DwoMode::DwoOnly);
1442 return writeOneObject(*Asm, DwoMode::AllSections);
1446uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
1448 uint64_t StartOffset = W->
OS.
tell();
1450 CustomSections.clear();
1454 // Collect information from the available symbols.
1456 SmallVector<uint32_t, 4> TableElems;
1464 std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
1466 if (
Mode != DwoMode::DwoOnly)
1467 prepareImports(Imports, Asm);
1469 // Populate DataSegments and CustomSections, which must be done before
1470 // populating DataLocations.
1471 for (MCSection &Sec : Asm) {
1472 auto &
Section =
static_cast<MCSectionWasm &
>(Sec);
1480 LLVM_DEBUG(
dbgs() <<
"Processing Section " << SectionName <<
" group "
1481 <<
Section.getGroup() <<
"\n";);
1483 // .init_array sections are handled specially elsewhere, include them in
1484 // data segments if and only if referenced by a symbol.
1489 // Code is handled separately
1494 uint32_t SegmentIndex = DataSegments.size();
1496 DataSegments.emplace_back();
1497 WasmDataSegment &Segment = DataSegments.back();
1499 Segment.InitFlags =
Section.getPassive()
1504 addData(Segment.Data, Section);
1506 Segment.LinkingFlags =
Section.getSegmentFlags();
1508 Section.setSegmentIndex(SegmentIndex);
1510 if (
const MCSymbolWasm *
C =
Section.getGroup()) {
1511 Comdats[
C->getName()].emplace_back(
1515 // Create custom sections
1520 // For user-defined custom sections, strip the prefix
1521 Name.consume_front(
".custom_section.");
1523 auto *Begin =
static_cast<MCSymbolWasm *
>(Sec.getBeginSymbol());
1525 assert(WasmIndices.count(Begin) == 0);
1526 WasmIndices[Begin] = CustomSections.size();
1529 // Separate out the producers and target features sections
1530 if (Name ==
"producers") {
1531 ProducersSection = std::make_unique<WasmCustomSection>(Name, &Section);
1534 if (Name ==
"target_features") {
1535 TargetFeaturesSection =
1536 std::make_unique<WasmCustomSection>(Name, &Section);
1540 // Custom sections can also belong to COMDAT groups. In this case the
1541 // decriptor's "index" field is the section index (in the final object
1542 // file), but that is not known until after layout, so it must be fixed up
1544 if (
const MCSymbolWasm *
C =
Section.getGroup()) {
1545 Comdats[
C->getName()].emplace_back(
1547 static_cast<uint32_t
>(CustomSections.size())});
1550 CustomSections.emplace_back(Name, &Section);
1554 if (
Mode != DwoMode::DwoOnly) {
1555 // Populate WasmIndices and DataLocations for defined symbols.
1556 for (
const MCSymbol &S :
Asm.symbols()) {
1557 // Ignore unnamed temporary symbols, which aren't ever exported, imported,
1558 // or used in relocations.
1559 if (S.isTemporary() && S.getName().empty())
1562 const auto &WS =
static_cast<const MCSymbolWasm &
>(S);
1564 dbgs() <<
"MCSymbol: "
1567 <<
" isDefined=" << S.isDefined() <<
" isExternal="
1568 << WS.isExternal() <<
" isTemporary=" << S.isTemporary()
1569 <<
" isWeak=" << WS.isWeak() <<
" isHidden=" << WS.isHidden()
1570 <<
" isVariable=" << WS.isVariable() <<
"\n");
1572 if (WS.isVariable())
1574 if (WS.isComdat() && !WS.isDefined())
1577 if (WS.isFunction()) {
1579 if (WS.isDefined()) {
1580 if (WS.getOffset() != 0)
1582 "function sections must contain one function each");
1584 // A definition. Write out the function body.
1585 Index = NumFunctionImports + Functions.
size();
1587 Func.SigIndex = getFunctionType(WS);
1588 Func.Section = &WS.getSection();
1589 assert(WasmIndices.count(&WS) == 0);
1590 WasmIndices[&WS] =
Index;
1593 auto &
Section =
static_cast<MCSectionWasm &
>(WS.getSection());
1594 if (
const MCSymbolWasm *
C =
Section.getGroup()) {
1595 Comdats[
C->getName()].emplace_back(
1599 if (WS.hasExportName()) {
1601 Export.Name = WS.getExportName();
1607 // An import; the index was assigned above.
1608 Index = WasmIndices.find(&WS)->second;
1613 }
else if (WS.isData()) {
1617 if (!WS.isDefined()) {
1628 if (!WS.getSize()->evaluateAsAbsolute(
Size, Asm))
1631 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1632 if (!DataSection.isWasmData())
1636 // For each data symbol, export it in the symtab as a reference to the
1637 // corresponding Wasm data segment.
1638 wasm::WasmDataReference
Ref = wasm::WasmDataReference{
1639 DataSection.getSegmentIndex(),
Asm.getSymbolOffset(WS),
1640 static_cast<uint64_t
>(
Size)};
1641 assert(DataLocations.count(&WS) == 0);
1642 DataLocations[&WS] =
Ref;
1645 }
else if (WS.isGlobal()) {
1646 // A "true" Wasm global (currently just __stack_pointer)
1647 if (WS.isDefined()) {
1649 Global.Type = WS.getGlobalType();
1650 Global.Index = NumGlobalImports + Globals.
size();
1651 Global.InitExpr.Extended =
false;
1652 switch (
Global.Type.Type) {
1671 assert(WasmIndices.count(&WS) == 0);
1672 WasmIndices[&WS] =
Global.Index;
1675 // An import; the index was assigned above
1677 << WasmIndices.find(&WS)->second <<
"\n");
1679 }
else if (WS.isTable()) {
1680 if (WS.isDefined()) {
1681 wasm::WasmTable Table;
1682 Table.
Index = NumTableImports + Tables.
size();
1683 Table.
Type = WS.getTableType();
1684 assert(WasmIndices.count(&WS) == 0);
1685 WasmIndices[&WS] = Table.
Index;
1689 << WasmIndices.find(&WS)->second <<
"\n");
1690 }
else if (WS.isTag()) {
1691 // C++ exception symbol (__cpp_exception) or longjmp symbol
1694 if (WS.isDefined()) {
1695 Index = NumTagImports + TagTypes.
size();
1696 uint32_t SigIndex = getTagType(WS);
1697 assert(WasmIndices.count(&WS) == 0);
1698 WasmIndices[&WS] =
Index;
1701 // An import; the index was assigned above.
1702 assert(WasmIndices.count(&WS) > 0);
1704 LLVM_DEBUG(
dbgs() <<
" -> tag index: " << WasmIndices.find(&WS)->second
1712 // Populate WasmIndices and DataLocations for aliased symbols. We need to
1713 // process these in a separate pass because we need to have processed the
1714 // target of the alias before the alias itself and the symbols are not
1715 // necessarily ordered in this way.
1716 for (
const MCSymbol &S :
Asm.symbols()) {
1717 if (!S.isVariable())
1722 const auto *BS =
Asm.getBaseSymbol(S);
1725 ": absolute addressing not supported!");
1726 const MCSymbolWasm *
Base =
static_cast<const MCSymbolWasm *
>(BS);
1728 // Find the target symbol of this weak alias and export that index
1729 const auto &WS =
static_cast<const MCSymbolWasm &
>(S);
1733 if (
Base->isFunction()) {
1735 uint32_t WasmIndex = WasmIndices.find(
Base)->second;
1736 assert(WasmIndices.count(&WS) == 0);
1737 WasmIndices[&WS] = WasmIndex;
1739 }
else if (
Base->isData()) {
1740 auto &DataSection =
static_cast<MCSectionWasm &
>(WS.getSection());
1741 uint64_t
Offset =
Asm.getSymbolOffset(S);
1743 // For data symbol alias we use the size of the base symbol as the
1744 // size of the alias. When an offset from the base is involved this
1745 // can result in a offset + size goes past the end of the data section
1746 // which out object format doesn't support. So we must clamp it.
1747 if (!
Base->getSize()->evaluateAsAbsolute(
Size, Asm))
1749 const WasmDataSegment &Segment =
1750 DataSegments[DataSection.getSegmentIndex()];
1752 std::min(
static_cast<uint64_t
>(
Size), Segment.Data.size() -
Offset);
1753 wasm::WasmDataReference
Ref = wasm::WasmDataReference{
1754 DataSection.getSegmentIndex(),
1755 static_cast<uint32_t
>(
Asm.getSymbolOffset(S)),
1756 static_cast<uint32_t
>(
Size)};
1757 DataLocations[&WS] =
Ref;
1765 // Finally, populate the symbol table itself, in its "natural" order.
1766 for (
const MCSymbol &S :
Asm.symbols()) {
1767 const auto &WS =
static_cast<const MCSymbolWasm &
>(S);
1772 // In bitcode generated by split-LTO-unit mode in ThinLTO, these lines can
1774 // module asm ".lto_set_conditional symbolA,symbolA.[moduleId]"
1776 // (Here [moduleId] will be replaced by a real module hash ID)
1778 // Here the original symbol (symbolA here) has been renamed to the new name
1779 // created by attaching its module ID, so the original symbol does not
1780 // appear in the bitcode anymore, and thus not in DataLocations. We should
1782 if (WS.isData() && WS.isDefined() && !DataLocations.count(&WS))
1791 if (!WS.isExternal() && WS.isDefined())
1793 if (WS.isUndefined())
1795 if (WS.isNoStrip()) {
1797 if (isEmscripten()) {
1801 if (WS.hasImportName())
1803 if (WS.hasExportName())
1808 wasm::WasmSymbolInfo
Info;
1809 Info.Name = WS.getName();
1813 assert(WasmIndices.count(&WS) > 0);
1814 Info.ElementIndex = WasmIndices.find(&WS)->second;
1815 }
else if (WS.isDefined()) {
1816 assert(DataLocations.count(&WS) > 0);
1817 Info.DataRef = DataLocations.find(&WS)->second;
1819 WS.setIndex(SymbolInfos.
size());
1824 auto HandleReloc = [&](
const WasmRelocationEntry &Rel) {
1825 // Functions referenced by a relocation need to put in the table. This is
1826 // purely to make the object file's provisional values readable, and is
1827 // ignored by the linker, which re-calculates the relocations itself.
1828 if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
1829 Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 &&
1830 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
1831 Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 &&
1832 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB &&
1833 Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB64)
1835 assert(Rel.Symbol->isFunction());
1837 static_cast<const MCSymbolWasm *
>(
Asm.getBaseSymbol(*Rel.Symbol));
1838 uint32_t FunctionIndex = WasmIndices.find(
Base)->second;
1839 uint32_t TableIndex = TableElems.
size() + InitialTableOffset;
1840 if (TableIndices.try_emplace(
Base, TableIndex).second) {
1842 <<
" to table: " << TableIndex <<
"\n");
1844 registerFunctionType(*
Base);
1848 for (
const WasmRelocationEntry &RelEntry : CodeRelocations)
1849 HandleReloc(RelEntry);
1850 for (
const WasmRelocationEntry &RelEntry : DataRelocations)
1851 HandleReloc(RelEntry);
1854 // Translate .init_array section contents into start functions.
1855 for (
const MCSection &S : Asm) {
1856 const auto &WS =
static_cast<const MCSectionWasm &
>(S);
1857 if (WS.getName().starts_with(
".fini_array"))
1859 if (!WS.getName().starts_with(
".init_array"))
1861 auto IT = WS.begin();
1864 for (
auto *Frag = &*
IT; Frag; Frag = Frag->getNext()) {
1869 uint16_t Priority = UINT16_MAX;
1870 unsigned PrefixLength = strlen(
".init_array");
1871 if (WS.getName().size() > PrefixLength) {
1872 if (WS.getName()[PrefixLength] !=
'.')
1874 ".init_array section priority should start with '.'");
1875 if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
1879 for (
const MCFixup &
Fixup : Frag->getFixups()) {
1882 const MCExpr *Expr =
Fixup.getValue();
1886 "fixups in .init_array should be symbol references");
1888 static_cast<const MCSymbolWasm &
>(SymRef->getSymbol());
1891 if (!TargetSym.isFunction())
1893 InitFuncs.
push_back(std::make_pair(Priority, TargetSym.getIndex()));
1898 // Write out the Wasm header.
1901 uint32_t CodeSectionIndex, DataSectionIndex;
1902 if (
Mode != DwoMode::DwoOnly) {
1904 writeImportSection(Imports,
DataSize, TableElems.
size());
1905 writeFunctionSection(Functions);
1906 writeTableSection(Tables);
1907 // Skip the "memory" section; we import the memory instead.
1908 writeTagSection(TagTypes);
1909 writeGlobalSection(Globals);
1910 writeExportSection(Exports);
1911 const MCSymbol *IndirectFunctionTable =
1912 getContext().lookupSymbol(
"__indirect_function_table");
1913 writeElemSection(
static_cast<const MCSymbolWasm *
>(IndirectFunctionTable),
1915 writeDataCountSection();
1917 CodeSectionIndex = writeCodeSection(Asm, Functions);
1918 DataSectionIndex = writeDataSection(Asm);
1921 // The Sections in the COMDAT list have placeholder indices (their index among
1922 // custom sections, rather than among all sections). Fix them up here.
1923 for (
auto &Group : Comdats) {
1924 for (
auto &Entry : Group.second) {
1926 Entry.Index += SectionCount;
1930 for (
auto &CustomSection : CustomSections)
1931 writeCustomSection(CustomSection, Asm);
1933 if (
Mode != DwoMode::DwoOnly) {
1934 writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats);
1936 writeRelocSection(CodeSectionIndex,
"CODE", CodeRelocations);
1937 writeRelocSection(DataSectionIndex,
"DATA", DataRelocations);
1939 writeCustomRelocSections();
1940 if (ProducersSection)
1941 writeCustomSection(*ProducersSection, Asm);
1942 if (TargetFeaturesSection)
1943 writeCustomSection(*TargetFeaturesSection, Asm);
1945 // TODO: Translate the .comment section to the output.
1946 return W->
OS.
tell() - StartOffset;
1949std::unique_ptr<MCObjectWriter>
1952 return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS);
1955std::unique_ptr<MCObjectWriter>
1959 return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS, DwoOS);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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")))
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
PowerPC TLS Dynamic Call Fixup
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static const FuncProtoTy Signatures[]
static const unsigned InvalidIndex
static bool isSectionReferenced(MCAssembler &Asm, MCSectionWasm &Section)
static void addData(SmallVectorImpl< char > &DataBytes, MCSectionWasm &DataSection)
static bool isInSymtab(const MCSymbolWasm &Sym)
static bool isDwoSection(const MCSection &Sec)
static bool is64Bit(const char *name)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
LLVM_ABI MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
static MCFixupKind getDataKindForSize(unsigned Size)
Return the generic fixup kind for a value with the given size.
Defines the object file and target independent interfaces used by the assembler backend to write nati...
virtual void reset()
lifetime management
This represents a section on wasm.
uint64_t getSectionOffset() const
Instances of this class represent a uniqued identifier for a section in the current translation unit.
StringRef getName() const
MCSymbol * getBeginSymbol()
bool omitFromLinkingSection() const
bool isUsedInInitArray() const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
bool isDefined() const
isDefined - Check if this symbol is defined (i.e., it has an address).
StringRef getName() const
getName - Get the symbol name.
uint32_t getIndex() const
Get the (implementation defined) index.
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
bool isUsedInReloc() const
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
This class implements an extremely fast bulk output stream that can only output to a stream.
uint64_t tell() const
tell - Return the current offset with the file.
raw_ostream & write(unsigned char C)
An abstract base class for streams implementations that also support a pwrite operation.
void pwrite(const char *Ptr, size_t Size, uint64_t Offset)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ C
The default llvm calling convention, compatible with C.
bool isRelocRelocation(MCFixupKind FixupKind)
NodeAddr< FuncNode * > Func
Context & getContext() const
void write64le(void *P, uint64_t V)
void write32le(void *P, uint32_t V)
const unsigned WASM_SYMBOL_UNDEFINED
const unsigned WASM_SYMBOL_NO_STRIP
const unsigned WASM_SYMBOL_TLS
const uint32_t WasmMetadataVersion
const unsigned WASM_SYMBOL_BINDING_WEAK
const unsigned WASM_SYMBOL_BINDING_LOCAL
@ WASM_LIMITS_FLAG_HAS_MAX
@ WASM_DATA_SEGMENT_IS_PASSIVE
@ WASM_DATA_SEGMENT_HAS_MEMINDEX
@ WASM_SYMBOL_TYPE_GLOBAL
@ WASM_SYMBOL_TYPE_SECTION
@ WASM_SYMBOL_TYPE_FUNCTION
const uint32_t WasmVersion
const unsigned WASM_SYMBOL_EXPORTED
@ WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER
LLVM_ABI bool relocTypeHasAddend(uint32_t type)
const uint32_t WasmDefaultPageSize
const unsigned WASM_SYMBOL_EXPLICIT_NAME
const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN
const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC
LLVM_ABI llvm::StringRef relocTypetoString(uint32_t type)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
FunctionAddr VTableAddr Value
void stable_sort(R &&Range)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Export
Export information to summary.
@ Import
Import information from summary.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
FunctionAddr VTableAddr uintptr_t uintptr_t DataSize
std::unique_ptr< MCObjectWriter > createWasmObjectWriter(std::unique_ptr< MCWasmObjectTargetWriter > MOTW, raw_pwrite_stream &OS)
Construct a new Wasm writer instance.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Global
Append to llvm.global_dtors.
@ Ref
The access may reference the value stored in memory.
@ FirstLiteralRelocationKind
FunctionAddr VTableAddr uintptr_t uintptr_t Data
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
ArrayRef(const T &OneElt) -> ArrayRef< T >
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
unsigned encodeSLEB128(int64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a SLEB128 value to an output stream.
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
unsigned Log2(Align A)
Returns the log2 of the alignment.
std::unique_ptr< MCObjectWriter > createWasmDwoObjectWriter(std::unique_ptr< MCWasmObjectTargetWriter > MOTW, raw_pwrite_stream &OS, raw_pwrite_stream &DwoOS)
Adapter to write values to a stream in a particular byte order.
void write(ArrayRef< value_type > Val)
SmallVector< ValType, 1 > Returns
SmallVector< ValType, 4 > Params