diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:30 +0300 |
commit | 2598ef1d0aee359b4b6d5fdd1758916d5907d04f (patch) | |
tree | 012bb94d777798f1f56ac1cec429509766d05181 /contrib/libs/llvm12/lib/MC/WasmObjectWriter.cpp | |
parent | 6751af0b0c1b952fede40b19b71da8025b5d8bcf (diff) | |
download | ydb-2598ef1d0aee359b4b6d5fdd1758916d5907d04f.tar.gz |
Restoring authorship annotation for <shadchin@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/llvm12/lib/MC/WasmObjectWriter.cpp')
-rw-r--r-- | contrib/libs/llvm12/lib/MC/WasmObjectWriter.cpp | 1106 |
1 files changed, 553 insertions, 553 deletions
diff --git a/contrib/libs/llvm12/lib/MC/WasmObjectWriter.cpp b/contrib/libs/llvm12/lib/MC/WasmObjectWriter.cpp index 930413e834..e99bcb980e 100644 --- a/contrib/libs/llvm12/lib/MC/WasmObjectWriter.cpp +++ b/contrib/libs/llvm12/lib/MC/WasmObjectWriter.cpp @@ -13,7 +13,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/BinaryFormat/Wasm.h" -#include "llvm/BinaryFormat/WasmTraits.h" +#include "llvm/BinaryFormat/WasmTraits.h" #include "llvm/Config/llvm-config.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmLayout.h" @@ -40,8 +40,8 @@ using namespace llvm; namespace { -// When we create the indirect function table we start at 1, so that there is -// and empty slot at 0 and therefore calling a null function pointer will trap. +// When we create the indirect function table we start at 1, so that there is +// and empty slot at 0 and therefore calling a null function pointer will trap. static const uint32_t InitialTableOffset = 1; // For patching purposes, we need to remember where each section starts, both @@ -173,12 +173,12 @@ static void patchI64(raw_pwrite_stream &Stream, uint64_t X, uint64_t Offset) { Stream.pwrite((char *)Buffer, sizeof(Buffer), Offset); } -bool isDwoSection(const MCSection &Sec) { - return Sec.getName().endswith(".dwo"); -} - +bool isDwoSection(const MCSection &Sec) { + return Sec.getName().endswith(".dwo"); +} + class WasmObjectWriter : public MCObjectWriter { - support::endian::Writer *W; + support::endian::Writer *W; /// The target specific Wasm writer instance. std::unique_ptr<MCWasmObjectTargetWriter> TargetObjectWriter; @@ -194,8 +194,8 @@ class WasmObjectWriter : public MCObjectWriter { // Maps function symbols to the table element index space. Used // for TABLE_INDEX relocation types (i.e. address taken functions). DenseMap<const MCSymbolWasm *, uint32_t> TableIndices; - // Maps function/global/table symbols to the - // function/global/table/event/section index space. + // Maps function/global/table symbols to the + // function/global/table/event/section index space. DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices; DenseMap<const MCSymbolWasm *, uint32_t> GOTIndices; // Maps data symbols to the Wasm segment and offset/size with the segment. @@ -213,25 +213,25 @@ class WasmObjectWriter : public MCObjectWriter { // Map from section to defining function symbol. DenseMap<const MCSection *, const MCSymbol *> SectionFunctions; - DenseMap<wasm::WasmSignature, uint32_t> SignatureIndices; - SmallVector<wasm::WasmSignature, 4> Signatures; + DenseMap<wasm::WasmSignature, uint32_t> SignatureIndices; + SmallVector<wasm::WasmSignature, 4> Signatures; SmallVector<WasmDataSegment, 4> DataSegments; unsigned NumFunctionImports = 0; unsigned NumGlobalImports = 0; - unsigned NumTableImports = 0; + unsigned NumTableImports = 0; unsigned NumEventImports = 0; uint32_t SectionCount = 0; - enum class DwoMode { - AllSections, - NonDwoOnly, - DwoOnly, - }; - bool IsSplitDwarf = false; - raw_pwrite_stream *OS = nullptr; - raw_pwrite_stream *DwoOS = nullptr; - - // TargetObjectWriter wranppers. + enum class DwoMode { + AllSections, + NonDwoOnly, + DwoOnly, + }; + bool IsSplitDwarf = false; + raw_pwrite_stream *OS = nullptr; + raw_pwrite_stream *DwoOS = nullptr; + + // TargetObjectWriter wranppers. bool is64Bit() const { return TargetObjectWriter->is64Bit(); } bool isEmscripten() const { return TargetObjectWriter->isEmscripten(); } @@ -241,14 +241,14 @@ class WasmObjectWriter : public MCObjectWriter { public: WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, - raw_pwrite_stream &OS_) - : TargetObjectWriter(std::move(MOTW)), OS(&OS_) {} - - WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, - raw_pwrite_stream &OS_, raw_pwrite_stream &DwoOS_) - : TargetObjectWriter(std::move(MOTW)), IsSplitDwarf(true), OS(&OS_), - DwoOS(&DwoOS_) {} - + raw_pwrite_stream &OS_) + : TargetObjectWriter(std::move(MOTW)), OS(&OS_) {} + + WasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, + raw_pwrite_stream &OS_, raw_pwrite_stream &DwoOS_) + : TargetObjectWriter(std::move(MOTW)), IsSplitDwarf(true), OS(&OS_), + DwoOS(&DwoOS_) {} + private: void reset() override { CodeRelocations.clear(); @@ -268,7 +268,7 @@ private: SectionFunctions.clear(); NumFunctionImports = 0; NumGlobalImports = 0; - NumTableImports = 0; + NumTableImports = 0; MCObjectWriter::reset(); } @@ -280,33 +280,33 @@ private: void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; - void prepareImports(SmallVectorImpl<wasm::WasmImport> &Imports, - MCAssembler &Asm, const MCAsmLayout &Layout); + void prepareImports(SmallVectorImpl<wasm::WasmImport> &Imports, + MCAssembler &Asm, const MCAsmLayout &Layout); uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; - uint64_t writeOneObject(MCAssembler &Asm, const MCAsmLayout &Layout, - DwoMode Mode); - + uint64_t writeOneObject(MCAssembler &Asm, const MCAsmLayout &Layout, + DwoMode Mode); + void writeString(const StringRef Str) { - encodeULEB128(Str.size(), W->OS); - W->OS << Str; + encodeULEB128(Str.size(), W->OS); + W->OS << Str; } void writeI32(int32_t val) { char Buffer[4]; support::endian::write32le(Buffer, val); - W->OS.write(Buffer, sizeof(Buffer)); + W->OS.write(Buffer, sizeof(Buffer)); } void writeI64(int64_t val) { char Buffer[8]; support::endian::write64le(Buffer, val); - W->OS.write(Buffer, sizeof(Buffer)); + W->OS.write(Buffer, sizeof(Buffer)); } - void writeValueType(wasm::ValType Ty) { W->OS << static_cast<char>(Ty); } + void writeValueType(wasm::ValType Ty) { W->OS << static_cast<char>(Ty); } - void writeTypeSection(ArrayRef<wasm::WasmSignature> Signatures); + void writeTypeSection(ArrayRef<wasm::WasmSignature> Signatures); void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint64_t DataSize, uint32_t NumElements); void writeFunctionSection(ArrayRef<WasmFunction> Functions); @@ -318,7 +318,7 @@ private: uint32_t writeDataSection(const MCAsmLayout &Layout); void writeEventSection(ArrayRef<wasm::WasmEventType> Events); void writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals); - void writeTableSection(ArrayRef<wasm::WasmTable> Tables); + void writeTableSection(ArrayRef<wasm::WasmTable> Tables); void writeRelocSection(uint32_t SectionIndex, StringRef Name, std::vector<WasmRelocationEntry> &Relocations); void writeLinkingMetaDataSection( @@ -347,17 +347,17 @@ private: void WasmObjectWriter::startSection(SectionBookkeeping &Section, unsigned SectionId) { LLVM_DEBUG(dbgs() << "startSection " << SectionId << "\n"); - W->OS << char(SectionId); + W->OS << char(SectionId); - Section.SizeOffset = W->OS.tell(); + Section.SizeOffset = W->OS.tell(); // The section size. We don't know the size yet, so reserve enough space // for any 32-bit value; we'll patch it later. - encodeULEB128(0, W->OS, 5); + encodeULEB128(0, W->OS, 5); // The position where the section starts, for measuring its size. - Section.ContentsOffset = W->OS.tell(); - Section.PayloadOffset = W->OS.tell(); + Section.ContentsOffset = W->OS.tell(); + Section.PayloadOffset = W->OS.tell(); Section.Index = SectionCount++; } @@ -367,19 +367,19 @@ void WasmObjectWriter::startCustomSection(SectionBookkeeping &Section, startSection(Section, wasm::WASM_SEC_CUSTOM); // The position where the section header ends, for measuring its size. - Section.PayloadOffset = W->OS.tell(); + Section.PayloadOffset = W->OS.tell(); // Custom sections in wasm also have a string identifier. writeString(Name); // The position where the custom section starts. - Section.ContentsOffset = W->OS.tell(); + Section.ContentsOffset = W->OS.tell(); } // Now that the section is complete and we know how big it is, patch up the // section size field at the start of the section. void WasmObjectWriter::endSection(SectionBookkeeping &Section) { - uint64_t Size = W->OS.tell(); + uint64_t Size = W->OS.tell(); // /dev/null doesn't support seek/tell and can report offset of 0. // Simply skip this patching in that case. if (!Size) @@ -393,25 +393,25 @@ void WasmObjectWriter::endSection(SectionBookkeeping &Section) { // Write the final section size to the payload_len field, which follows // the section id byte. - writePatchableLEB<5>(static_cast<raw_pwrite_stream &>(W->OS), Size, + writePatchableLEB<5>(static_cast<raw_pwrite_stream &>(W->OS), Size, Section.SizeOffset); } // Emit the Wasm header. void WasmObjectWriter::writeHeader(const MCAssembler &Asm) { - W->OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic)); - W->write<uint32_t>(wasm::WasmVersion); + W->OS.write(wasm::WasmMagic, sizeof(wasm::WasmMagic)); + W->write<uint32_t>(wasm::WasmVersion); } void WasmObjectWriter::executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) { - // As a stopgap measure until call_indirect instructions start explicitly - // referencing the indirect function table via TABLE_NUMBER relocs, ensure - // that the indirect function table import makes it to the output if anything - // in the compilation unit has caused it to be present. - if (auto *Sym = Asm.getContext().lookupSymbol("__indirect_function_table")) - Asm.registerSymbol(*Sym); - + // As a stopgap measure until call_indirect instructions start explicitly + // referencing the indirect function table via TABLE_NUMBER relocs, ensure + // that the indirect function table import makes it to the output if anything + // in the compilation unit has caused it to be present. + if (auto *Sym = Asm.getContext().lookupSymbol("__indirect_function_table")) + Asm.registerSymbol(*Sym); + // Build a map of sections to the function that defines them, for use // in recordRelocation. for (const MCSymbol &S : Asm.symbols()) { @@ -480,7 +480,7 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, // Currently only supported for for metadata sections. // See: test/MC/WebAssembly/blockaddress.ll if (Type == wasm::R_WASM_FUNCTION_OFFSET_I32 || - Type == wasm::R_WASM_FUNCTION_OFFSET_I64 || + Type == wasm::R_WASM_FUNCTION_OFFSET_I64 || Type == wasm::R_WASM_SECTION_OFFSET_I32) { if (!FixupSection.getKind().isMetadata()) report_fatal_error("relocations for function or section offsets are " @@ -499,29 +499,29 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, SymA = cast<MCSymbolWasm>(SectionSymbol); } - if (Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB || - Type == wasm::R_WASM_TABLE_INDEX_SLEB || - Type == wasm::R_WASM_TABLE_INDEX_SLEB64 || - Type == wasm::R_WASM_TABLE_INDEX_I32 || - Type == wasm::R_WASM_TABLE_INDEX_I64) { - // TABLE_INDEX relocs implicitly use the default indirect function table. - auto TableName = "__indirect_function_table"; - MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(TableName)); - if (Sym) { - if (!Sym->isFunctionTable()) - Ctx.reportError( - Fixup.getLoc(), - "symbol '__indirect_function_table' is not a function table"); - } else { - Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(TableName)); - Sym->setFunctionTable(); - // The default function table is synthesized by the linker. - Sym->setUndefined(); - } - Sym->setUsedInReloc(); - Asm.registerSymbol(*Sym); - } - + if (Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB || + Type == wasm::R_WASM_TABLE_INDEX_SLEB || + Type == wasm::R_WASM_TABLE_INDEX_SLEB64 || + Type == wasm::R_WASM_TABLE_INDEX_I32 || + Type == wasm::R_WASM_TABLE_INDEX_I64) { + // TABLE_INDEX relocs implicitly use the default indirect function table. + auto TableName = "__indirect_function_table"; + MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(TableName)); + if (Sym) { + if (!Sym->isFunctionTable()) + Ctx.reportError( + Fixup.getLoc(), + "symbol '__indirect_function_table' is not a function table"); + } else { + Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(TableName)); + Sym->setFunctionTable(); + // The default function table is synthesized by the linker. + Sym->setUndefined(); + } + Sym->setUsedInReloc(); + Asm.registerSymbol(*Sym); + } + // Relocation other than R_WASM_TYPE_INDEX_LEB are required to be // against a named symbol. if (Type != wasm::R_WASM_TYPE_INDEX_LEB) { @@ -566,9 +566,9 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry, switch (RelEntry.Type) { case wasm::R_WASM_TABLE_INDEX_REL_SLEB: case wasm::R_WASM_TABLE_INDEX_SLEB: - case wasm::R_WASM_TABLE_INDEX_SLEB64: - case wasm::R_WASM_TABLE_INDEX_I32: - case wasm::R_WASM_TABLE_INDEX_I64: { + case wasm::R_WASM_TABLE_INDEX_SLEB64: + case wasm::R_WASM_TABLE_INDEX_I32: + case wasm::R_WASM_TABLE_INDEX_I64: { // Provisional value is table address of the resolved symbol itself const MCSymbolWasm *Base = cast<MCSymbolWasm>(Layout.getBaseSymbol(*RelEntry.Symbol)); @@ -585,12 +585,12 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry, case wasm::R_WASM_GLOBAL_INDEX_LEB: case wasm::R_WASM_GLOBAL_INDEX_I32: case wasm::R_WASM_EVENT_INDEX_LEB: - case wasm::R_WASM_TABLE_NUMBER_LEB: + case wasm::R_WASM_TABLE_NUMBER_LEB: // Provisional value is function/global/event Wasm index assert(WasmIndices.count(RelEntry.Symbol) > 0 && "symbol not found in wasm index space"); return WasmIndices[RelEntry.Symbol]; case wasm::R_WASM_FUNCTION_OFFSET_I32: - case wasm::R_WASM_FUNCTION_OFFSET_I64: + case wasm::R_WASM_FUNCTION_OFFSET_I64: case wasm::R_WASM_SECTION_OFFSET_I32: { const auto &Section = static_cast<const MCSectionWasm &>(RelEntry.Symbol->getSection()); @@ -603,19 +603,19 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry, case wasm::R_WASM_MEMORY_ADDR_REL_SLEB: case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64: case wasm::R_WASM_MEMORY_ADDR_I32: - case wasm::R_WASM_MEMORY_ADDR_I64: - case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: { - // Provisional value is address of the global plus the offset + case wasm::R_WASM_MEMORY_ADDR_I64: + case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: { + // Provisional value is address of the global plus the offset const MCSymbolWasm *Base = cast<MCSymbolWasm>(Layout.getBaseSymbol(*RelEntry.Symbol)); // For undefined symbols, use zero if (!Base->isDefined()) return 0; - const wasm::WasmDataReference &BaseRef = DataLocations[Base], - &SymRef = DataLocations[RelEntry.Symbol]; - const WasmDataSegment &Segment = DataSegments[BaseRef.Segment]; + const wasm::WasmDataReference &BaseRef = DataLocations[Base], + &SymRef = DataLocations[RelEntry.Symbol]; + const WasmDataSegment &Segment = DataSegments[BaseRef.Segment]; // Ignore overflow. LLVM allows address arithmetic to silently wrap. - return Segment.Offset + BaseRef.Offset + SymRef.Offset + RelEntry.Addend; + return Segment.Offset + BaseRef.Offset + SymRef.Offset + RelEntry.Addend; } default: llvm_unreachable("invalid relocation type"); @@ -649,11 +649,11 @@ static void addData(SmallVectorImpl<char> &DataBytes, Fill->getValue()); } else if (auto *LEB = dyn_cast<MCLEBFragment>(&Frag)) { const SmallVectorImpl<char> &Contents = LEB->getContents(); - llvm::append_range(DataBytes, Contents); + llvm::append_range(DataBytes, Contents); } else { const auto &DataFrag = cast<MCDataFragment>(Frag); const SmallVectorImpl<char> &Contents = DataFrag.getContents(); - llvm::append_range(DataBytes, Contents); + llvm::append_range(DataBytes, Contents); } } @@ -677,7 +677,7 @@ WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) { void WasmObjectWriter::applyRelocations( ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset, const MCAsmLayout &Layout) { - auto &Stream = static_cast<raw_pwrite_stream &>(W->OS); + auto &Stream = static_cast<raw_pwrite_stream &>(W->OS); for (const WasmRelocationEntry &RelEntry : Relocations) { uint64_t Offset = ContentsOffset + RelEntry.FixupSection->getSectionOffset() + @@ -692,7 +692,7 @@ void WasmObjectWriter::applyRelocations( case wasm::R_WASM_GLOBAL_INDEX_LEB: case wasm::R_WASM_MEMORY_ADDR_LEB: case wasm::R_WASM_EVENT_INDEX_LEB: - case wasm::R_WASM_TABLE_NUMBER_LEB: + case wasm::R_WASM_TABLE_NUMBER_LEB: writePatchableLEB<5>(Stream, Value, Offset); break; case wasm::R_WASM_MEMORY_ADDR_LEB64: @@ -705,19 +705,19 @@ void WasmObjectWriter::applyRelocations( case wasm::R_WASM_GLOBAL_INDEX_I32: patchI32(Stream, Value, Offset); break; - case wasm::R_WASM_TABLE_INDEX_I64: + case wasm::R_WASM_TABLE_INDEX_I64: case wasm::R_WASM_MEMORY_ADDR_I64: - case wasm::R_WASM_FUNCTION_OFFSET_I64: + case wasm::R_WASM_FUNCTION_OFFSET_I64: patchI64(Stream, Value, Offset); break; case wasm::R_WASM_TABLE_INDEX_SLEB: case wasm::R_WASM_TABLE_INDEX_REL_SLEB: case wasm::R_WASM_MEMORY_ADDR_SLEB: case wasm::R_WASM_MEMORY_ADDR_REL_SLEB: - case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: + case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: writePatchableSLEB<5>(Stream, Value, Offset); break; - case wasm::R_WASM_TABLE_INDEX_SLEB64: + case wasm::R_WASM_TABLE_INDEX_SLEB64: case wasm::R_WASM_MEMORY_ADDR_SLEB64: case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64: writePatchableSLEB<10>(Stream, Value, Offset); @@ -728,22 +728,22 @@ void WasmObjectWriter::applyRelocations( } } -void WasmObjectWriter::writeTypeSection( - ArrayRef<wasm::WasmSignature> Signatures) { +void WasmObjectWriter::writeTypeSection( + ArrayRef<wasm::WasmSignature> Signatures) { if (Signatures.empty()) return; SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_TYPE); - encodeULEB128(Signatures.size(), W->OS); + encodeULEB128(Signatures.size(), W->OS); - for (const wasm::WasmSignature &Sig : Signatures) { - W->OS << char(wasm::WASM_TYPE_FUNC); - encodeULEB128(Sig.Params.size(), W->OS); + for (const wasm::WasmSignature &Sig : Signatures) { + W->OS << char(wasm::WASM_TYPE_FUNC); + encodeULEB128(Sig.Params.size(), W->OS); for (wasm::ValType Ty : Sig.Params) writeValueType(Ty); - encodeULEB128(Sig.Returns.size(), W->OS); + encodeULEB128(Sig.Returns.size(), W->OS); for (wasm::ValType Ty : Sig.Returns) writeValueType(Ty); } @@ -762,32 +762,32 @@ void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports, SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_IMPORT); - encodeULEB128(Imports.size(), W->OS); + encodeULEB128(Imports.size(), W->OS); for (const wasm::WasmImport &Import : Imports) { writeString(Import.Module); writeString(Import.Field); - W->OS << char(Import.Kind); + W->OS << char(Import.Kind); switch (Import.Kind) { case wasm::WASM_EXTERNAL_FUNCTION: - encodeULEB128(Import.SigIndex, W->OS); + encodeULEB128(Import.SigIndex, W->OS); break; case wasm::WASM_EXTERNAL_GLOBAL: - W->OS << char(Import.Global.Type); - W->OS << char(Import.Global.Mutable ? 1 : 0); + W->OS << char(Import.Global.Type); + W->OS << char(Import.Global.Mutable ? 1 : 0); break; case wasm::WASM_EXTERNAL_MEMORY: - encodeULEB128(Import.Memory.Flags, W->OS); - encodeULEB128(NumPages, W->OS); // initial + encodeULEB128(Import.Memory.Flags, W->OS); + encodeULEB128(NumPages, W->OS); // initial break; case wasm::WASM_EXTERNAL_TABLE: - W->OS << char(Import.Table.ElemType); - encodeULEB128(0, W->OS); // flags - encodeULEB128(NumElements, W->OS); // initial + W->OS << char(Import.Table.ElemType); + encodeULEB128(0, W->OS); // flags + encodeULEB128(NumElements, W->OS); // initial break; case wasm::WASM_EXTERNAL_EVENT: - encodeULEB128(Import.Event.Attribute, W->OS); - encodeULEB128(Import.Event.SigIndex, W->OS); + encodeULEB128(Import.Event.Attribute, W->OS); + encodeULEB128(Import.Event.SigIndex, W->OS); break; default: llvm_unreachable("unsupported import kind"); @@ -804,9 +804,9 @@ void WasmObjectWriter::writeFunctionSection(ArrayRef<WasmFunction> Functions) { SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_FUNCTION); - encodeULEB128(Functions.size(), W->OS); + encodeULEB128(Functions.size(), W->OS); for (const WasmFunction &Func : Functions) - encodeULEB128(Func.SigIndex, W->OS); + encodeULEB128(Func.SigIndex, W->OS); endSection(Section); } @@ -818,10 +818,10 @@ void WasmObjectWriter::writeEventSection(ArrayRef<wasm::WasmEventType> Events) { SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_EVENT); - encodeULEB128(Events.size(), W->OS); + encodeULEB128(Events.size(), W->OS); for (const wasm::WasmEventType &Event : Events) { - encodeULEB128(Event.Attribute, W->OS); - encodeULEB128(Event.SigIndex, W->OS); + encodeULEB128(Event.Attribute, W->OS); + encodeULEB128(Event.SigIndex, W->OS); } endSection(Section); @@ -834,17 +834,17 @@ void WasmObjectWriter::writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals) { SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_GLOBAL); - encodeULEB128(Globals.size(), W->OS); + encodeULEB128(Globals.size(), W->OS); for (const wasm::WasmGlobal &Global : Globals) { - encodeULEB128(Global.Type.Type, W->OS); - W->OS << char(Global.Type.Mutable); - W->OS << char(Global.InitExpr.Opcode); + encodeULEB128(Global.Type.Type, W->OS); + W->OS << char(Global.Type.Mutable); + W->OS << char(Global.InitExpr.Opcode); switch (Global.Type.Type) { case wasm::WASM_TYPE_I32: - encodeSLEB128(0, W->OS); + encodeSLEB128(0, W->OS); break; case wasm::WASM_TYPE_I64: - encodeSLEB128(0, W->OS); + encodeSLEB128(0, W->OS); break; case wasm::WASM_TYPE_F32: writeI32(0); @@ -858,30 +858,30 @@ void WasmObjectWriter::writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals) { default: llvm_unreachable("unexpected type"); } - W->OS << char(wasm::WASM_OPCODE_END); + W->OS << char(wasm::WASM_OPCODE_END); } endSection(Section); } -void WasmObjectWriter::writeTableSection(ArrayRef<wasm::WasmTable> Tables) { - if (Tables.empty()) - return; - - SectionBookkeeping Section; - startSection(Section, wasm::WASM_SEC_TABLE); - - encodeULEB128(Tables.size(), W->OS); - for (const wasm::WasmTable &Table : Tables) { - encodeULEB128(Table.Type.ElemType, W->OS); - encodeULEB128(Table.Type.Limits.Flags, W->OS); - encodeULEB128(Table.Type.Limits.Initial, W->OS); - if (Table.Type.Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) - encodeULEB128(Table.Type.Limits.Maximum, W->OS); - } - endSection(Section); -} - +void WasmObjectWriter::writeTableSection(ArrayRef<wasm::WasmTable> Tables) { + if (Tables.empty()) + return; + + SectionBookkeeping Section; + startSection(Section, wasm::WASM_SEC_TABLE); + + encodeULEB128(Tables.size(), W->OS); + for (const wasm::WasmTable &Table : Tables) { + encodeULEB128(Table.Type.ElemType, W->OS); + encodeULEB128(Table.Type.Limits.Flags, W->OS); + encodeULEB128(Table.Type.Limits.Initial, W->OS); + if (Table.Type.Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX) + encodeULEB128(Table.Type.Limits.Maximum, W->OS); + } + endSection(Section); +} + void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) { if (Exports.empty()) return; @@ -889,11 +889,11 @@ void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) { SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_EXPORT); - encodeULEB128(Exports.size(), W->OS); + encodeULEB128(Exports.size(), W->OS); for (const wasm::WasmExport &Export : Exports) { writeString(Export.Name); - W->OS << char(Export.Kind); - encodeULEB128(Export.Index, W->OS); + W->OS << char(Export.Kind); + encodeULEB128(Export.Index, W->OS); } endSection(Section); @@ -906,17 +906,17 @@ void WasmObjectWriter::writeElemSection(ArrayRef<uint32_t> TableElems) { SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_ELEM); - encodeULEB128(1, W->OS); // number of "segments" - encodeULEB128(0, W->OS); // the table index + encodeULEB128(1, W->OS); // number of "segments" + encodeULEB128(0, W->OS); // the table index // init expr for starting offset - W->OS << char(wasm::WASM_OPCODE_I32_CONST); - encodeSLEB128(InitialTableOffset, W->OS); - W->OS << char(wasm::WASM_OPCODE_END); + W->OS << char(wasm::WASM_OPCODE_I32_CONST); + encodeSLEB128(InitialTableOffset, W->OS); + W->OS << char(wasm::WASM_OPCODE_END); - encodeULEB128(TableElems.size(), W->OS); + encodeULEB128(TableElems.size(), W->OS); for (uint32_t Elem : TableElems) - encodeULEB128(Elem, W->OS); + encodeULEB128(Elem, W->OS); endSection(Section); } @@ -927,7 +927,7 @@ void WasmObjectWriter::writeDataCountSection() { SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_DATACOUNT); - encodeULEB128(DataSegments.size(), W->OS); + encodeULEB128(DataSegments.size(), W->OS); endSection(Section); } @@ -940,7 +940,7 @@ uint32_t WasmObjectWriter::writeCodeSection(const MCAssembler &Asm, SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_CODE); - encodeULEB128(Functions.size(), W->OS); + encodeULEB128(Functions.size(), W->OS); for (const WasmFunction &Func : Functions) { auto &FuncSection = static_cast<MCSectionWasm &>(Func.Sym->getSection()); @@ -949,9 +949,9 @@ uint32_t WasmObjectWriter::writeCodeSection(const MCAssembler &Asm, if (!Func.Sym->getSize()->evaluateAsAbsolute(Size, Layout)) report_fatal_error(".size expression must be evaluatable"); - encodeULEB128(Size, W->OS); - FuncSection.setSectionOffset(W->OS.tell() - Section.ContentsOffset); - Asm.writeSectionData(W->OS, &FuncSection, Layout); + encodeULEB128(Size, W->OS); + FuncSection.setSectionOffset(W->OS.tell() - Section.ContentsOffset); + Asm.writeSectionData(W->OS, &FuncSection, Layout); } // Apply fixups. @@ -968,21 +968,21 @@ uint32_t WasmObjectWriter::writeDataSection(const MCAsmLayout &Layout) { SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_DATA); - encodeULEB128(DataSegments.size(), W->OS); // count + encodeULEB128(DataSegments.size(), W->OS); // count for (const WasmDataSegment &Segment : DataSegments) { - encodeULEB128(Segment.InitFlags, W->OS); // flags - if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX) - encodeULEB128(0, W->OS); // memory index - if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) { - W->OS << char(Segment.Offset > INT32_MAX ? wasm::WASM_OPCODE_I64_CONST - : wasm::WASM_OPCODE_I32_CONST); - encodeSLEB128(Segment.Offset, W->OS); // offset - W->OS << char(wasm::WASM_OPCODE_END); + encodeULEB128(Segment.InitFlags, W->OS); // flags + if (Segment.InitFlags & wasm::WASM_DATA_SEGMENT_HAS_MEMINDEX) + encodeULEB128(0, W->OS); // memory index + if ((Segment.InitFlags & wasm::WASM_DATA_SEGMENT_IS_PASSIVE) == 0) { + W->OS << char(Segment.Offset > INT32_MAX ? wasm::WASM_OPCODE_I64_CONST + : wasm::WASM_OPCODE_I32_CONST); + encodeSLEB128(Segment.Offset, W->OS); // offset + W->OS << char(wasm::WASM_OPCODE_END); } - encodeULEB128(Segment.Data.size(), W->OS); // size - Segment.Section->setSectionOffset(W->OS.tell() - Section.ContentsOffset); - W->OS << Segment.Data; // data + encodeULEB128(Segment.Data.size(), W->OS); // size + Segment.Section->setSectionOffset(W->OS.tell() - Section.ContentsOffset); + W->OS << Segment.Data; // data } // Apply fixups. @@ -1015,18 +1015,18 @@ void WasmObjectWriter::writeRelocSection( SectionBookkeeping Section; startCustomSection(Section, std::string("reloc.") + Name.str()); - encodeULEB128(SectionIndex, W->OS); - encodeULEB128(Relocs.size(), W->OS); + encodeULEB128(SectionIndex, W->OS); + encodeULEB128(Relocs.size(), W->OS); for (const WasmRelocationEntry &RelEntry : Relocs) { uint64_t Offset = RelEntry.Offset + RelEntry.FixupSection->getSectionOffset(); uint32_t Index = getRelocationIndexValue(RelEntry); - W->OS << char(RelEntry.Type); - encodeULEB128(Offset, W->OS); - encodeULEB128(Index, W->OS); + W->OS << char(RelEntry.Type); + encodeULEB128(Offset, W->OS); + encodeULEB128(Index, W->OS); if (RelEntry.hasAddend()) - encodeSLEB128(RelEntry.Addend, W->OS); + encodeSLEB128(RelEntry.Addend, W->OS); } endSection(Section); @@ -1045,21 +1045,21 @@ void WasmObjectWriter::writeLinkingMetaDataSection( const std::map<StringRef, std::vector<WasmComdatEntry>> &Comdats) { SectionBookkeeping Section; startCustomSection(Section, "linking"); - encodeULEB128(wasm::WasmMetadataVersion, W->OS); + encodeULEB128(wasm::WasmMetadataVersion, W->OS); SectionBookkeeping SubSection; if (SymbolInfos.size() != 0) { startSection(SubSection, wasm::WASM_SYMBOL_TABLE); - encodeULEB128(SymbolInfos.size(), W->OS); + encodeULEB128(SymbolInfos.size(), W->OS); for (const wasm::WasmSymbolInfo &Sym : SymbolInfos) { - encodeULEB128(Sym.Kind, W->OS); - encodeULEB128(Sym.Flags, W->OS); + encodeULEB128(Sym.Kind, W->OS); + encodeULEB128(Sym.Flags, W->OS); switch (Sym.Kind) { case wasm::WASM_SYMBOL_TYPE_FUNCTION: case wasm::WASM_SYMBOL_TYPE_GLOBAL: case wasm::WASM_SYMBOL_TYPE_EVENT: - case wasm::WASM_SYMBOL_TYPE_TABLE: - encodeULEB128(Sym.ElementIndex, W->OS); + case wasm::WASM_SYMBOL_TYPE_TABLE: + encodeULEB128(Sym.ElementIndex, W->OS); if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 || (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) writeString(Sym.Name); @@ -1067,15 +1067,15 @@ void WasmObjectWriter::writeLinkingMetaDataSection( case wasm::WASM_SYMBOL_TYPE_DATA: writeString(Sym.Name); if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) { - encodeULEB128(Sym.DataRef.Segment, W->OS); - encodeULEB128(Sym.DataRef.Offset, W->OS); - encodeULEB128(Sym.DataRef.Size, W->OS); + encodeULEB128(Sym.DataRef.Segment, W->OS); + encodeULEB128(Sym.DataRef.Offset, W->OS); + encodeULEB128(Sym.DataRef.Size, W->OS); } break; case wasm::WASM_SYMBOL_TYPE_SECTION: { const uint32_t SectionIndex = CustomSections[Sym.ElementIndex].OutputIndex; - encodeULEB128(SectionIndex, W->OS); + encodeULEB128(SectionIndex, W->OS); break; } default: @@ -1087,35 +1087,35 @@ void WasmObjectWriter::writeLinkingMetaDataSection( if (DataSegments.size()) { startSection(SubSection, wasm::WASM_SEGMENT_INFO); - encodeULEB128(DataSegments.size(), W->OS); + encodeULEB128(DataSegments.size(), W->OS); for (const WasmDataSegment &Segment : DataSegments) { writeString(Segment.Name); - encodeULEB128(Segment.Alignment, W->OS); - encodeULEB128(Segment.LinkerFlags, W->OS); + encodeULEB128(Segment.Alignment, W->OS); + encodeULEB128(Segment.LinkerFlags, W->OS); } endSection(SubSection); } if (!InitFuncs.empty()) { startSection(SubSection, wasm::WASM_INIT_FUNCS); - encodeULEB128(InitFuncs.size(), W->OS); + encodeULEB128(InitFuncs.size(), W->OS); for (auto &StartFunc : InitFuncs) { - encodeULEB128(StartFunc.first, W->OS); // priority - encodeULEB128(StartFunc.second, W->OS); // function index + encodeULEB128(StartFunc.first, W->OS); // priority + encodeULEB128(StartFunc.second, W->OS); // function index } endSection(SubSection); } if (Comdats.size()) { startSection(SubSection, wasm::WASM_COMDAT_INFO); - encodeULEB128(Comdats.size(), W->OS); + encodeULEB128(Comdats.size(), W->OS); for (const auto &C : Comdats) { writeString(C.first); - encodeULEB128(0, W->OS); // flags for future use - encodeULEB128(C.second.size(), W->OS); + encodeULEB128(0, W->OS); // flags for future use + encodeULEB128(C.second.size(), W->OS); for (const WasmComdatEntry &Entry : C.second) { - encodeULEB128(Entry.Kind, W->OS); - encodeULEB128(Entry.Index, W->OS); + encodeULEB128(Entry.Kind, W->OS); + encodeULEB128(Entry.Index, W->OS); } } endSection(SubSection); @@ -1131,8 +1131,8 @@ void WasmObjectWriter::writeCustomSection(WasmCustomSection &CustomSection, auto *Sec = CustomSection.Section; startCustomSection(Section, CustomSection.Name); - Sec->setSectionOffset(W->OS.tell() - Section.ContentsOffset); - Asm.writeSectionData(W->OS, Sec, Layout); + Sec->setSectionOffset(W->OS.tell() - Section.ContentsOffset); + Asm.writeSectionData(W->OS, Sec, Layout); CustomSection.OutputContentsOffset = Section.ContentsOffset; CustomSection.OutputIndex = Section.Index; @@ -1159,7 +1159,7 @@ uint32_t WasmObjectWriter::getEventType(const MCSymbolWasm &Symbol) { void WasmObjectWriter::registerFunctionType(const MCSymbolWasm &Symbol) { assert(Symbol.isFunction()); - wasm::WasmSignature S; + wasm::WasmSignature S; if (auto *Sig = Symbol.getSignature()) { S.Returns = Sig->Returns; @@ -1181,7 +1181,7 @@ void WasmObjectWriter::registerEventType(const MCSymbolWasm &Symbol) { // TODO Currently we don't generate imported exceptions, but if we do, we // should have a way of infering types of imported exceptions. - wasm::WasmSignature S; + wasm::WasmSignature S; if (auto *Sig = Symbol.getSignature()) { S.Returns = Sig->Returns; S.Params = Sig->Params; @@ -1213,9 +1213,9 @@ static bool isInSymtab(const MCSymbolWasm &Sym) { return true; } -void WasmObjectWriter::prepareImports( - SmallVectorImpl<wasm::WasmImport> &Imports, MCAssembler &Asm, - const MCAsmLayout &Layout) { +void WasmObjectWriter::prepareImports( + SmallVectorImpl<wasm::WasmImport> &Imports, MCAssembler &Asm, + const MCAsmLayout &Layout) { // For now, always emit the memory import, since loads and stores are not // valid without it. In the future, we could perhaps be more clever and omit // it if there are no loads or stores. @@ -1236,11 +1236,11 @@ void WasmObjectWriter::prepareImports( // Register types for all functions, including those with private linkage // (because wasm always needs a type signature). if (WS.isFunction()) { - const auto *BS = Layout.getBaseSymbol(S); - if (!BS) - report_fatal_error(Twine(S.getName()) + - ": absolute addressing not supported!"); - registerFunctionType(*cast<MCSymbolWasm>(BS)); + const auto *BS = Layout.getBaseSymbol(S); + if (!BS) + report_fatal_error(Twine(S.getName()) + + ": absolute addressing not supported!"); + registerFunctionType(*cast<MCSymbolWasm>(BS)); } if (WS.isEvent()) @@ -1285,23 +1285,23 @@ void WasmObjectWriter::prepareImports( Imports.push_back(Import); assert(WasmIndices.count(&WS) == 0); WasmIndices[&WS] = NumEventImports++; - } else if (WS.isTable()) { - if (WS.isWeak()) - report_fatal_error("undefined table symbol cannot be weak"); - - wasm::WasmImport Import; - Import.Module = WS.getImportModule(); - Import.Field = WS.getImportName(); - Import.Kind = wasm::WASM_EXTERNAL_TABLE; - wasm::ValType ElemType = WS.getTableType(); - Import.Table.ElemType = uint8_t(ElemType); - // FIXME: Extend table type to include limits? For now we don't specify - // a min or max which does not place any restrictions on the size of the - // imported table. - Import.Table.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0}; - Imports.push_back(Import); - assert(WasmIndices.count(&WS) == 0); - WasmIndices[&WS] = NumTableImports++; + } else if (WS.isTable()) { + if (WS.isWeak()) + report_fatal_error("undefined table symbol cannot be weak"); + + wasm::WasmImport Import; + Import.Module = WS.getImportModule(); + Import.Field = WS.getImportName(); + Import.Kind = wasm::WASM_EXTERNAL_TABLE; + wasm::ValType ElemType = WS.getTableType(); + Import.Table.ElemType = uint8_t(ElemType); + // FIXME: Extend table type to include limits? For now we don't specify + // a min or max which does not place any restrictions on the size of the + // imported table. + Import.Table.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0}; + Imports.push_back(Import); + assert(WasmIndices.count(&WS) == 0); + WasmIndices[&WS] = NumTableImports++; } } } @@ -1323,62 +1323,62 @@ void WasmObjectWriter::prepareImports( GOTIndices[&WS] = NumGlobalImports++; } } -} - -uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, - const MCAsmLayout &Layout) { - support::endian::Writer MainWriter(*OS, support::little); - W = &MainWriter; - if (IsSplitDwarf) { - uint64_t TotalSize = writeOneObject(Asm, Layout, DwoMode::NonDwoOnly); - assert(DwoOS); - support::endian::Writer DwoWriter(*DwoOS, support::little); - W = &DwoWriter; - return TotalSize + writeOneObject(Asm, Layout, DwoMode::DwoOnly); - } else { - return writeOneObject(Asm, Layout, DwoMode::AllSections); - } -} - -uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, - const MCAsmLayout &Layout, - DwoMode Mode) { - uint64_t StartOffset = W->OS.tell(); - SectionCount = 0; - CustomSections.clear(); - - LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n"); - - // Collect information from the available symbols. - SmallVector<WasmFunction, 4> Functions; - SmallVector<uint32_t, 4> TableElems; - SmallVector<wasm::WasmImport, 4> Imports; - SmallVector<wasm::WasmExport, 4> Exports; - SmallVector<wasm::WasmEventType, 1> Events; - SmallVector<wasm::WasmGlobal, 1> Globals; - SmallVector<wasm::WasmTable, 1> Tables; - SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos; - SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs; - std::map<StringRef, std::vector<WasmComdatEntry>> Comdats; - uint64_t DataSize = 0; - if (Mode != DwoMode::DwoOnly) { - prepareImports(Imports, Asm, Layout); - } - +} + +uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, + const MCAsmLayout &Layout) { + support::endian::Writer MainWriter(*OS, support::little); + W = &MainWriter; + if (IsSplitDwarf) { + uint64_t TotalSize = writeOneObject(Asm, Layout, DwoMode::NonDwoOnly); + assert(DwoOS); + support::endian::Writer DwoWriter(*DwoOS, support::little); + W = &DwoWriter; + return TotalSize + writeOneObject(Asm, Layout, DwoMode::DwoOnly); + } else { + return writeOneObject(Asm, Layout, DwoMode::AllSections); + } +} + +uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, + const MCAsmLayout &Layout, + DwoMode Mode) { + uint64_t StartOffset = W->OS.tell(); + SectionCount = 0; + CustomSections.clear(); + + LLVM_DEBUG(dbgs() << "WasmObjectWriter::writeObject\n"); + + // Collect information from the available symbols. + SmallVector<WasmFunction, 4> Functions; + SmallVector<uint32_t, 4> TableElems; + SmallVector<wasm::WasmImport, 4> Imports; + SmallVector<wasm::WasmExport, 4> Exports; + SmallVector<wasm::WasmEventType, 1> Events; + SmallVector<wasm::WasmGlobal, 1> Globals; + SmallVector<wasm::WasmTable, 1> Tables; + SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos; + SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs; + std::map<StringRef, std::vector<WasmComdatEntry>> Comdats; + uint64_t DataSize = 0; + if (Mode != DwoMode::DwoOnly) { + prepareImports(Imports, Asm, Layout); + } + // Populate DataSegments and CustomSections, which must be done before // populating DataLocations. for (MCSection &Sec : Asm) { auto &Section = static_cast<MCSectionWasm &>(Sec); StringRef SectionName = Section.getName(); - if (Mode == DwoMode::NonDwoOnly && isDwoSection(Sec)) - continue; - if (Mode == DwoMode::DwoOnly && !isDwoSection(Sec)) - continue; - - LLVM_DEBUG(dbgs() << "Processing Section " << SectionName << " group " - << Section.getGroup() << "\n";); - + if (Mode == DwoMode::NonDwoOnly && isDwoSection(Sec)) + continue; + if (Mode == DwoMode::DwoOnly && !isDwoSection(Sec)) + continue; + + LLVM_DEBUG(dbgs() << "Processing Section " << SectionName << " group " + << Section.getGroup() << "\n";); + // .init_array sections are handled specially elsewhere. if (SectionName.startswith(".init_array")) continue; @@ -1393,9 +1393,9 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, DataSegments.emplace_back(); WasmDataSegment &Segment = DataSegments.back(); Segment.Name = SectionName; - Segment.InitFlags = Section.getPassive() - ? (uint32_t)wasm::WASM_DATA_SEGMENT_IS_PASSIVE - : 0; + Segment.InitFlags = Section.getPassive() + ? (uint32_t)wasm::WASM_DATA_SEGMENT_IS_PASSIVE + : 0; Segment.Offset = DataSize; Segment.Section = &Section; addData(Segment.Data, Section); @@ -1420,7 +1420,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, MCSymbol *Begin = Sec.getBeginSymbol(); if (Begin) { - assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0); + assert(WasmIndices.count(cast<MCSymbolWasm>(Begin)) == 0); WasmIndices[cast<MCSymbolWasm>(Begin)] = CustomSections.size(); } @@ -1435,232 +1435,232 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, continue; } - // Custom sections can also belong to COMDAT groups. In this case the - // decriptor's "index" field is the section index (in the final object - // file), but that is not known until after layout, so it must be fixed up - // later - if (const MCSymbolWasm *C = Section.getGroup()) { - Comdats[C->getName()].emplace_back( - WasmComdatEntry{wasm::WASM_COMDAT_SECTION, - static_cast<uint32_t>(CustomSections.size())}); - } - + // Custom sections can also belong to COMDAT groups. In this case the + // decriptor's "index" field is the section index (in the final object + // file), but that is not known until after layout, so it must be fixed up + // later + if (const MCSymbolWasm *C = Section.getGroup()) { + Comdats[C->getName()].emplace_back( + WasmComdatEntry{wasm::WASM_COMDAT_SECTION, + static_cast<uint32_t>(CustomSections.size())}); + } + CustomSections.emplace_back(Name, &Section); } } - if (Mode != DwoMode::DwoOnly) { - // Populate WasmIndices and DataLocations for defined symbols. - for (const MCSymbol &S : Asm.symbols()) { - // Ignore unnamed temporary symbols, which aren't ever exported, imported, - // or used in relocations. - if (S.isTemporary() && S.getName().empty()) - continue; - - const auto &WS = static_cast<const MCSymbolWasm &>(S); - LLVM_DEBUG( - dbgs() << "MCSymbol: " << toString(WS.getType()) << " '" << S << "'" - << " isDefined=" << S.isDefined() << " isExternal=" - << S.isExternal() << " isTemporary=" << S.isTemporary() - << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden() - << " isVariable=" << WS.isVariable() << "\n"); - - if (WS.isVariable()) - continue; - if (WS.isComdat() && !WS.isDefined()) - continue; - - if (WS.isFunction()) { - unsigned Index; - if (WS.isDefined()) { - if (WS.getOffset() != 0) - report_fatal_error( - "function sections must contain one function each"); - - if (WS.getSize() == nullptr) - report_fatal_error( - "function symbols must have a size set with .size"); - - // A definition. Write out the function body. - Index = NumFunctionImports + Functions.size(); - WasmFunction Func; - Func.SigIndex = getFunctionType(WS); - Func.Sym = &WS; - assert(WasmIndices.count(&WS) == 0); - WasmIndices[&WS] = Index; - Functions.push_back(Func); - - auto &Section = static_cast<MCSectionWasm &>(WS.getSection()); - if (const MCSymbolWasm *C = Section.getGroup()) { - Comdats[C->getName()].emplace_back( - WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index}); - } - - if (WS.hasExportName()) { - wasm::WasmExport Export; - Export.Name = WS.getExportName(); - Export.Kind = wasm::WASM_EXTERNAL_FUNCTION; - Export.Index = Index; - Exports.push_back(Export); - } - } else { - // An import; the index was assigned above. - Index = WasmIndices.find(&WS)->second; + if (Mode != DwoMode::DwoOnly) { + // Populate WasmIndices and DataLocations for defined symbols. + for (const MCSymbol &S : Asm.symbols()) { + // Ignore unnamed temporary symbols, which aren't ever exported, imported, + // or used in relocations. + if (S.isTemporary() && S.getName().empty()) + continue; + + const auto &WS = static_cast<const MCSymbolWasm &>(S); + LLVM_DEBUG( + dbgs() << "MCSymbol: " << toString(WS.getType()) << " '" << S << "'" + << " isDefined=" << S.isDefined() << " isExternal=" + << S.isExternal() << " isTemporary=" << S.isTemporary() + << " isWeak=" << WS.isWeak() << " isHidden=" << WS.isHidden() + << " isVariable=" << WS.isVariable() << "\n"); + + if (WS.isVariable()) + continue; + if (WS.isComdat() && !WS.isDefined()) + continue; + + if (WS.isFunction()) { + unsigned Index; + if (WS.isDefined()) { + if (WS.getOffset() != 0) + report_fatal_error( + "function sections must contain one function each"); + + if (WS.getSize() == nullptr) + report_fatal_error( + "function symbols must have a size set with .size"); + + // A definition. Write out the function body. + Index = NumFunctionImports + Functions.size(); + WasmFunction Func; + Func.SigIndex = getFunctionType(WS); + Func.Sym = &WS; + assert(WasmIndices.count(&WS) == 0); + WasmIndices[&WS] = Index; + Functions.push_back(Func); + + auto &Section = static_cast<MCSectionWasm &>(WS.getSection()); + if (const MCSymbolWasm *C = Section.getGroup()) { + Comdats[C->getName()].emplace_back( + WasmComdatEntry{wasm::WASM_COMDAT_FUNCTION, Index}); + } + + if (WS.hasExportName()) { + wasm::WasmExport Export; + Export.Name = WS.getExportName(); + Export.Kind = wasm::WASM_EXTERNAL_FUNCTION; + Export.Index = Index; + Exports.push_back(Export); + } + } else { + // An import; the index was assigned above. + Index = WasmIndices.find(&WS)->second; } - LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n"); - - } else if (WS.isData()) { - if (!isInSymtab(WS)) - continue; - - if (!WS.isDefined()) { - LLVM_DEBUG(dbgs() << " -> segment index: -1" - << "\n"); - continue; + LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n"); + + } else if (WS.isData()) { + if (!isInSymtab(WS)) + continue; + + if (!WS.isDefined()) { + LLVM_DEBUG(dbgs() << " -> segment index: -1" + << "\n"); + continue; + } + + if (!WS.getSize()) + report_fatal_error("data symbols must have a size set with .size: " + + WS.getName()); + + int64_t Size = 0; + if (!WS.getSize()->evaluateAsAbsolute(Size, Layout)) + report_fatal_error(".size expression must be evaluatable"); + + auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection()); + if (!DataSection.isWasmData()) + report_fatal_error("data symbols must live in a data section: " + + WS.getName()); + + // For each data symbol, export it in the symtab as a reference to the + // corresponding Wasm data segment. + wasm::WasmDataReference Ref = wasm::WasmDataReference{ + DataSection.getSegmentIndex(), Layout.getSymbolOffset(WS), + static_cast<uint64_t>(Size)}; + assert(DataLocations.count(&WS) == 0); + DataLocations[&WS] = Ref; + LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n"); + + } else if (WS.isGlobal()) { + // A "true" Wasm global (currently just __stack_pointer) + if (WS.isDefined()) { + wasm::WasmGlobal Global; + Global.Type = WS.getGlobalType(); + Global.Index = NumGlobalImports + Globals.size(); + switch (Global.Type.Type) { + case wasm::WASM_TYPE_I32: + Global.InitExpr.Opcode = wasm::WASM_OPCODE_I32_CONST; + break; + case wasm::WASM_TYPE_I64: + Global.InitExpr.Opcode = wasm::WASM_OPCODE_I64_CONST; + break; + case wasm::WASM_TYPE_F32: + Global.InitExpr.Opcode = wasm::WASM_OPCODE_F32_CONST; + break; + case wasm::WASM_TYPE_F64: + Global.InitExpr.Opcode = wasm::WASM_OPCODE_F64_CONST; + break; + case wasm::WASM_TYPE_EXTERNREF: + Global.InitExpr.Opcode = wasm::WASM_OPCODE_REF_NULL; + break; + default: + llvm_unreachable("unexpected type"); + } + assert(WasmIndices.count(&WS) == 0); + WasmIndices[&WS] = Global.Index; + Globals.push_back(Global); + } else { + // An import; the index was assigned above + LLVM_DEBUG(dbgs() << " -> global index: " + << WasmIndices.find(&WS)->second << "\n"); } - - if (!WS.getSize()) - report_fatal_error("data symbols must have a size set with .size: " + - WS.getName()); - - int64_t Size = 0; - if (!WS.getSize()->evaluateAsAbsolute(Size, Layout)) - report_fatal_error(".size expression must be evaluatable"); - - auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection()); - if (!DataSection.isWasmData()) - report_fatal_error("data symbols must live in a data section: " + - WS.getName()); - - // For each data symbol, export it in the symtab as a reference to the - // corresponding Wasm data segment. - wasm::WasmDataReference Ref = wasm::WasmDataReference{ - DataSection.getSegmentIndex(), Layout.getSymbolOffset(WS), - static_cast<uint64_t>(Size)}; - assert(DataLocations.count(&WS) == 0); - DataLocations[&WS] = Ref; - LLVM_DEBUG(dbgs() << " -> segment index: " << Ref.Segment << "\n"); - - } else if (WS.isGlobal()) { - // A "true" Wasm global (currently just __stack_pointer) - if (WS.isDefined()) { - wasm::WasmGlobal Global; - Global.Type = WS.getGlobalType(); - Global.Index = NumGlobalImports + Globals.size(); - switch (Global.Type.Type) { - case wasm::WASM_TYPE_I32: - Global.InitExpr.Opcode = wasm::WASM_OPCODE_I32_CONST; - break; - case wasm::WASM_TYPE_I64: - Global.InitExpr.Opcode = wasm::WASM_OPCODE_I64_CONST; - break; - case wasm::WASM_TYPE_F32: - Global.InitExpr.Opcode = wasm::WASM_OPCODE_F32_CONST; - break; - case wasm::WASM_TYPE_F64: - Global.InitExpr.Opcode = wasm::WASM_OPCODE_F64_CONST; - break; - case wasm::WASM_TYPE_EXTERNREF: - Global.InitExpr.Opcode = wasm::WASM_OPCODE_REF_NULL; - break; - default: - llvm_unreachable("unexpected type"); - } - assert(WasmIndices.count(&WS) == 0); - WasmIndices[&WS] = Global.Index; - Globals.push_back(Global); - } else { - // An import; the index was assigned above - LLVM_DEBUG(dbgs() << " -> global index: " - << WasmIndices.find(&WS)->second << "\n"); - } - } else if (WS.isTable()) { - if (WS.isDefined()) { - wasm::WasmTable Table; - Table.Index = NumTableImports + Tables.size(); - Table.Type.ElemType = static_cast<uint8_t>(WS.getTableType()); - // FIXME: Work on custom limits is ongoing - Table.Type.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0}; - assert(WasmIndices.count(&WS) == 0); - WasmIndices[&WS] = Table.Index; - Tables.push_back(Table); - } - LLVM_DEBUG(dbgs() << " -> table index: " + } else if (WS.isTable()) { + if (WS.isDefined()) { + wasm::WasmTable Table; + Table.Index = NumTableImports + Tables.size(); + Table.Type.ElemType = static_cast<uint8_t>(WS.getTableType()); + // FIXME: Work on custom limits is ongoing + Table.Type.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0}; + assert(WasmIndices.count(&WS) == 0); + WasmIndices[&WS] = Table.Index; + Tables.push_back(Table); + } + LLVM_DEBUG(dbgs() << " -> table index: " << WasmIndices.find(&WS)->second << "\n"); - } else if (WS.isEvent()) { - // C++ exception symbol (__cpp_exception) - unsigned Index; - if (WS.isDefined()) { - Index = NumEventImports + Events.size(); - wasm::WasmEventType Event; - Event.SigIndex = getEventType(WS); - Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION; - assert(WasmIndices.count(&WS) == 0); - WasmIndices[&WS] = Index; - Events.push_back(Event); - } else { - // An import; the index was assigned above. - assert(WasmIndices.count(&WS) > 0); - } - LLVM_DEBUG(dbgs() << " -> event index: " - << WasmIndices.find(&WS)->second << "\n"); - + } else if (WS.isEvent()) { + // C++ exception symbol (__cpp_exception) + unsigned Index; + if (WS.isDefined()) { + Index = NumEventImports + Events.size(); + wasm::WasmEventType Event; + Event.SigIndex = getEventType(WS); + Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION; + assert(WasmIndices.count(&WS) == 0); + WasmIndices[&WS] = Index; + Events.push_back(Event); + } else { + // An import; the index was assigned above. + assert(WasmIndices.count(&WS) > 0); + } + LLVM_DEBUG(dbgs() << " -> event index: " + << WasmIndices.find(&WS)->second << "\n"); + } else { - assert(WS.isSection()); + assert(WS.isSection()); } } - // Populate WasmIndices and DataLocations for aliased symbols. We need to - // process these in a separate pass because we need to have processed the - // target of the alias before the alias itself and the symbols are not - // necessarily ordered in this way. - for (const MCSymbol &S : Asm.symbols()) { - if (!S.isVariable()) - continue; - - assert(S.isDefined()); - - const auto *BS = Layout.getBaseSymbol(S); - if (!BS) - report_fatal_error(Twine(S.getName()) + - ": absolute addressing not supported!"); - const MCSymbolWasm *Base = cast<MCSymbolWasm>(BS); - - // Find the target symbol of this weak alias and export that index - const auto &WS = static_cast<const MCSymbolWasm &>(S); - LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *Base - << "'\n"); - - if (Base->isFunction()) { - assert(WasmIndices.count(Base) > 0); - uint32_t WasmIndex = WasmIndices.find(Base)->second; - assert(WasmIndices.count(&WS) == 0); - WasmIndices[&WS] = WasmIndex; - LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n"); - } else if (Base->isData()) { - auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection()); - uint64_t Offset = Layout.getSymbolOffset(S); - int64_t Size = 0; - // For data symbol alias we use the size of the base symbol as the - // size of the alias. When an offset from the base is involved this - // can result in a offset + size goes past the end of the data section - // which out object format doesn't support. So we must clamp it. - if (!Base->getSize()->evaluateAsAbsolute(Size, Layout)) - report_fatal_error(".size expression must be evaluatable"); - const WasmDataSegment &Segment = - DataSegments[DataSection.getSegmentIndex()]; - Size = - std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset); - wasm::WasmDataReference Ref = wasm::WasmDataReference{ - DataSection.getSegmentIndex(), - static_cast<uint32_t>(Layout.getSymbolOffset(S)), - static_cast<uint32_t>(Size)}; - DataLocations[&WS] = Ref; - LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n"); - } else { - report_fatal_error("don't yet support global/event aliases"); - } + // Populate WasmIndices and DataLocations for aliased symbols. We need to + // process these in a separate pass because we need to have processed the + // target of the alias before the alias itself and the symbols are not + // necessarily ordered in this way. + for (const MCSymbol &S : Asm.symbols()) { + if (!S.isVariable()) + continue; + + assert(S.isDefined()); + + const auto *BS = Layout.getBaseSymbol(S); + if (!BS) + report_fatal_error(Twine(S.getName()) + + ": absolute addressing not supported!"); + const MCSymbolWasm *Base = cast<MCSymbolWasm>(BS); + + // Find the target symbol of this weak alias and export that index + const auto &WS = static_cast<const MCSymbolWasm &>(S); + LLVM_DEBUG(dbgs() << WS.getName() << ": weak alias of '" << *Base + << "'\n"); + + if (Base->isFunction()) { + assert(WasmIndices.count(Base) > 0); + uint32_t WasmIndex = WasmIndices.find(Base)->second; + assert(WasmIndices.count(&WS) == 0); + WasmIndices[&WS] = WasmIndex; + LLVM_DEBUG(dbgs() << " -> index:" << WasmIndex << "\n"); + } else if (Base->isData()) { + auto &DataSection = static_cast<MCSectionWasm &>(WS.getSection()); + uint64_t Offset = Layout.getSymbolOffset(S); + int64_t Size = 0; + // For data symbol alias we use the size of the base symbol as the + // size of the alias. When an offset from the base is involved this + // can result in a offset + size goes past the end of the data section + // which out object format doesn't support. So we must clamp it. + if (!Base->getSize()->evaluateAsAbsolute(Size, Layout)) + report_fatal_error(".size expression must be evaluatable"); + const WasmDataSegment &Segment = + DataSegments[DataSection.getSegmentIndex()]; + Size = + std::min(static_cast<uint64_t>(Size), Segment.Data.size() - Offset); + wasm::WasmDataReference Ref = wasm::WasmDataReference{ + DataSection.getSegmentIndex(), + static_cast<uint32_t>(Layout.getSymbolOffset(S)), + static_cast<uint32_t>(Size)}; + DataLocations[&WS] = Ref; + LLVM_DEBUG(dbgs() << " -> index:" << Ref.Segment << "\n"); + } else { + report_fatal_error("don't yet support global/event aliases"); + } } } @@ -1671,10 +1671,10 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, WS.setIndex(InvalidIndex); continue; } - if (WS.isTable() && WS.getName() == "__indirect_function_table") { - // For the moment, don't emit table symbols -- wasm-ld can't handle them. - continue; - } + if (WS.isTable() && WS.getName() == "__indirect_function_table") { + // For the moment, don't emit table symbols -- wasm-ld can't handle them. + continue; + } LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n"); uint32_t Flags = 0; @@ -1718,9 +1718,9 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, // purely to make the object file's provisional values readable, and is // ignored by the linker, which re-calculates the relocations itself. if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 && - Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 && + Rel.Type != wasm::R_WASM_TABLE_INDEX_I64 && Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB && - Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 && + Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB64 && Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB) return; assert(Rel.Symbol->isFunction()); @@ -1810,41 +1810,41 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, // Write out the Wasm header. writeHeader(Asm); - uint32_t CodeSectionIndex, DataSectionIndex; - if (Mode != DwoMode::DwoOnly) { - writeTypeSection(Signatures); - writeImportSection(Imports, DataSize, TableElems.size()); - writeFunctionSection(Functions); - writeTableSection(Tables); - // Skip the "memory" section; we import the memory instead. - writeEventSection(Events); - writeGlobalSection(Globals); - writeExportSection(Exports); - writeElemSection(TableElems); - writeDataCountSection(); - - CodeSectionIndex = writeCodeSection(Asm, Layout, Functions); - DataSectionIndex = writeDataSection(Layout); - } - - // The Sections in the COMDAT list have placeholder indices (their index among - // custom sections, rather than among all sections). Fix them up here. - for (auto &Group : Comdats) { - for (auto &Entry : Group.second) { - if (Entry.Kind == wasm::WASM_COMDAT_SECTION) { - Entry.Index += SectionCount; - } - } - } + uint32_t CodeSectionIndex, DataSectionIndex; + if (Mode != DwoMode::DwoOnly) { + writeTypeSection(Signatures); + writeImportSection(Imports, DataSize, TableElems.size()); + writeFunctionSection(Functions); + writeTableSection(Tables); + // Skip the "memory" section; we import the memory instead. + writeEventSection(Events); + writeGlobalSection(Globals); + writeExportSection(Exports); + writeElemSection(TableElems); + writeDataCountSection(); + + CodeSectionIndex = writeCodeSection(Asm, Layout, Functions); + DataSectionIndex = writeDataSection(Layout); + } + + // The Sections in the COMDAT list have placeholder indices (their index among + // custom sections, rather than among all sections). Fix them up here. + for (auto &Group : Comdats) { + for (auto &Entry : Group.second) { + if (Entry.Kind == wasm::WASM_COMDAT_SECTION) { + Entry.Index += SectionCount; + } + } + } for (auto &CustomSection : CustomSections) writeCustomSection(CustomSection, Asm, Layout); - - if (Mode != DwoMode::DwoOnly) { - writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats); - - writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations); - writeRelocSection(DataSectionIndex, "DATA", DataRelocations); - } + + if (Mode != DwoMode::DwoOnly) { + writeLinkingMetaDataSection(SymbolInfos, InitFuncs, Comdats); + + writeRelocSection(CodeSectionIndex, "CODE", CodeRelocations); + writeRelocSection(DataSectionIndex, "DATA", DataRelocations); + } writeCustomRelocSections(); if (ProducersSection) writeCustomSection(*ProducersSection, Asm, Layout); @@ -1852,7 +1852,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm, writeCustomSection(*TargetFeaturesSection, Asm, Layout); // TODO: Translate the .comment section to the output. - return W->OS.tell() - StartOffset; + return W->OS.tell() - StartOffset; } std::unique_ptr<MCObjectWriter> @@ -1860,10 +1860,10 @@ llvm::createWasmObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, raw_pwrite_stream &OS) { return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS); } - -std::unique_ptr<MCObjectWriter> -llvm::createWasmDwoObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, - raw_pwrite_stream &OS, - raw_pwrite_stream &DwoOS) { - return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS, DwoOS); -} + +std::unique_ptr<MCObjectWriter> +llvm::createWasmDwoObjectWriter(std::unique_ptr<MCWasmObjectTargetWriter> MOTW, + raw_pwrite_stream &OS, + raw_pwrite_stream &DwoOS) { + return std::make_unique<WasmObjectWriter>(std::move(MOTW), OS, DwoOS); +} |