diff options
| -rw-r--r-- | llvm/include/llvm/MC/MCWasmObjectWriter.h | 1 | ||||
| -rw-r--r-- | llvm/lib/MC/WasmObjectWriter.cpp | 245 | ||||
| -rw-r--r-- | llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp | 7 | ||||
| -rw-r--r-- | llvm/test/MC/WebAssembly/reloc-code.ll | 20 |
4 files changed, 112 insertions, 161 deletions
diff --git a/llvm/include/llvm/MC/MCWasmObjectWriter.h b/llvm/include/llvm/MC/MCWasmObjectWriter.h index 25d8c1486d8..004e4b78165 100644 --- a/llvm/include/llvm/MC/MCWasmObjectWriter.h +++ b/llvm/include/llvm/MC/MCWasmObjectWriter.h @@ -14,6 +14,7 @@ #include "llvm/MC/MCValue.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/Wasm.h" #include <vector> namespace llvm { diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index ee5957a8079..5f36a9ecce9 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -31,7 +31,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/StringSaver.h" -#include "llvm/Support/Wasm.h" #include <vector> using namespace llvm; @@ -141,6 +140,17 @@ struct WasmRelocationEntry { : Offset(Offset), Symbol(Symbol), Addend(Addend), Type(Type), FixupSection(FixupSection) {} + bool hasAddend() const { + switch (Type) { + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: + return true; + default: + return false; + } + } + void print(raw_ostream &Out) const { Out << "Off=" << Offset << ", Sym=" << Symbol << ", Addend=" << Addend << ", Type=" << Type << ", FixupSection=" << FixupSection; @@ -167,11 +177,14 @@ class WasmObjectWriter : public MCObjectWriter { // Relocations for fixing up references in the data section. std::vector<WasmRelocationEntry> DataRelocations; - // Fixups for call_indirect type indices. - std::vector<WasmRelocationEntry> TypeIndexFixups; - // Index values to use for fixing up call_indirect type indices. - std::vector<uint32_t> TypeIndexFixupTypes; + // Maps function symbols to the index of the type of the function + DenseMap<const MCSymbolWasm *, uint32_t> TypeIndices; + + DenseMap<const MCSymbolWasm *, uint32_t> SymbolIndices; + + DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo> + FunctionTypeIndices; // TargetObjectWriter wrappers. bool is64Bit() const { return TargetObjectWriter->is64Bit(); } @@ -191,6 +204,15 @@ public: private: ~WasmObjectWriter() override; + void reset() override { + CodeRelocations.clear(); + DataRelocations.clear(); + TypeIndices.clear(); + SymbolIndices.clear(); + FunctionTypeIndices.clear(); + MCObjectWriter::reset(); + } + void writeHeader(const MCAssembler &Asm); void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, @@ -216,21 +238,23 @@ private: void writeExportSection(const SmallVector<WasmExport, 4> &Exports); void writeElemSection(const SmallVector<uint32_t, 4> &TableElems); void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout, - DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices, const SmallVector<WasmFunction, 4> &Functions); uint64_t - writeDataSection(const SmallVector<char, 0> &DataBytes, - DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices); + writeDataSection(const SmallVector<char, 0> &DataBytes); void writeNameSection(const SmallVector<WasmFunction, 4> &Functions, const SmallVector<WasmImport, 4> &Imports, uint32_t NumFuncImports); - void writeCodeRelocSection( - DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices); - void writeDataRelocSection( - DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices, - uint64_t DataSectionHeaderSize); + void writeCodeRelocSection(); + void writeDataRelocSection(uint64_t DataSectionHeaderSize); void writeLinkingMetaDataSection(bool HasStackPointer, uint32_t StackPointerGlobal); + + void applyRelocations(ArrayRef<WasmRelocationEntry> Relocations, + uint64_t ContentsOffset); + + void writeRelocations(ArrayRef<WasmRelocationEntry> Relocations, + uint64_t HeaderSize); + uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry); }; } // end anonymous namespace @@ -377,19 +401,7 @@ void WasmObjectWriter::recordRelocation(MCAssembler &Asm, SymA->setUsedInReloc(); } - if (RefA) { - if (RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX) { - assert(C == 0); - WasmRelocationEntry Rec(FixupOffset, SymA, C, - wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB, - &FixupSection); - TypeIndexFixups.push_back(Rec); - return; - } - } - unsigned Type = getRelocType(Ctx, Target, Fixup, IsPCRel); - WasmRelocationEntry Rec(FixupOffset, SymA, C, Type, &FixupSection); if (FixupSection.hasInstructions()) @@ -448,124 +460,85 @@ static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) { return Value; } +uint32_t WasmObjectWriter::getRelocationIndexValue( + const WasmRelocationEntry &RelEntry) { + switch (RelEntry.Type) { + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: + case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: + assert(SymbolIndices.count(RelEntry.Symbol)); + return SymbolIndices[RelEntry.Symbol]; + case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: + assert(TypeIndices.count(RelEntry.Symbol)); + return TypeIndices[RelEntry.Symbol]; + default: + llvm_unreachable("invalid relocation type"); + } +} + // Apply the portions of the relocation records that we can handle ourselves // directly. -static void ApplyRelocations( - ArrayRef<WasmRelocationEntry> Relocations, - raw_pwrite_stream &Stream, - DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices, - uint64_t ContentsOffset) -{ +void WasmObjectWriter::applyRelocations( + ArrayRef<WasmRelocationEntry> Relocations, uint64_t ContentsOffset) { + raw_pwrite_stream &Stream = getStream(); for (const WasmRelocationEntry &RelEntry : Relocations) { uint64_t Offset = ContentsOffset + RelEntry.FixupSection->getSectionOffset() + RelEntry.Offset; - switch (RelEntry.Type) { - case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: { - assert(SymbolIndices.count(RelEntry.Symbol)); - uint32_t Index = SymbolIndices[RelEntry.Symbol]; - assert(RelEntry.Addend == 0); - WritePatchableLEB(Stream, Index, Offset); + switch (RelEntry.Type) { + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: { + uint32_t Index = getRelocationIndexValue(RelEntry); + WritePatchableSLEB(Stream, Index, Offset); break; } - case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: { - assert(SymbolIndices.count(RelEntry.Symbol)); - uint32_t Index = SymbolIndices[RelEntry.Symbol]; - assert(RelEntry.Addend == 0); - - WritePatchableSLEB(Stream, Index, Offset); + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: { + uint32_t Index = getRelocationIndexValue(RelEntry); + WriteI32(Stream, Index, Offset); break; } case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: { uint32_t Value = ProvisionalValue(RelEntry); - WritePatchableSLEB(Stream, Value, Offset); break; } case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: { uint32_t Value = ProvisionalValue(RelEntry); - WritePatchableLEB(Stream, Value, Offset); break; } - case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: { - assert(SymbolIndices.count(RelEntry.Symbol)); - uint32_t Index = SymbolIndices[RelEntry.Symbol]; - assert(RelEntry.Addend == 0); - - WriteI32(Stream, Index, Offset); - break; - } case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: { uint32_t Value = ProvisionalValue(RelEntry); - WriteI32(Stream, Value, Offset); break; } default: - break; + llvm_unreachable("unsupported relocation type"); } } } // Write out the portions of the relocation records that the linker will // need to handle. -static void -WriteRelocations(ArrayRef<WasmRelocationEntry> Relocations, - raw_pwrite_stream &Stream, - DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices, - uint64_t HeaderSize) { - for (const WasmRelocationEntry RelEntry : Relocations) { - encodeULEB128(RelEntry.Type, Stream); +void WasmObjectWriter::writeRelocations( + ArrayRef<WasmRelocationEntry> Relocations, uint64_t HeaderSize) { + raw_pwrite_stream &Stream = getStream(); + for (const WasmRelocationEntry& RelEntry : Relocations) { uint64_t Offset = RelEntry.Offset + RelEntry.FixupSection->getSectionOffset() + HeaderSize; - assert(SymbolIndices.count(RelEntry.Symbol)); - uint32_t Index = SymbolIndices[RelEntry.Symbol]; - int64_t Addend = RelEntry.Addend; - - switch (RelEntry.Type) { - case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: - case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: - encodeULEB128(Offset, Stream); - encodeULEB128(Index, Stream); - assert(Addend == 0 && "addends not supported for functions"); - break; - case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: - case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: - case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: - encodeULEB128(Offset, Stream); - encodeULEB128(Index, Stream); - encodeSLEB128(Addend, Stream); - break; - default: - llvm_unreachable("unsupported relocation type"); - } - } -} + uint32_t Index = getRelocationIndexValue(RelEntry); -// Write out the the type relocation records that the linker will -// need to handle. -static void WriteTypeRelocations( - ArrayRef<WasmRelocationEntry> TypeIndexFixups, - ArrayRef<uint32_t> TypeIndexFixupTypes, - raw_pwrite_stream &Stream) -{ - for (size_t i = 0, e = TypeIndexFixups.size(); i < e; ++i) { - const WasmRelocationEntry &Fixup = TypeIndexFixups[i]; - uint32_t Type = TypeIndexFixupTypes[i]; - - assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB); - assert(Fixup.Addend == 0); - - uint64_t Offset = Fixup.Offset + - Fixup.FixupSection->getSectionOffset(); - - encodeULEB128(Fixup.Type, Stream); + encodeULEB128(RelEntry.Type, Stream); encodeULEB128(Offset, Stream); - encodeULEB128(Type, Stream); + encodeULEB128(Index, Stream); + if (RelEntry.hasAddend()) + encodeSLEB128(RelEntry.Addend, Stream); } } @@ -754,7 +727,6 @@ void WasmObjectWriter::writeElemSection( void WasmObjectWriter::writeCodeSection( const MCAssembler &Asm, const MCAsmLayout &Layout, - DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices, const SmallVector<WasmFunction, 4> &Functions) { if (Functions.empty()) return; @@ -789,34 +761,14 @@ void WasmObjectWriter::writeCodeSection( Asm.writeSectionData(&FuncSection, Layout); } - // Apply the type index fixups for call_indirect etc. instructions. - for (size_t i = 0, e = TypeIndexFixups.size(); i < e; ++i) { - uint32_t Type = TypeIndexFixupTypes[i]; - unsigned Padding = PaddingFor5ByteULEB128(Type); - - const WasmRelocationEntry &Fixup = TypeIndexFixups[i]; - assert(Fixup.Addend == 0); - assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB); - uint64_t Offset = Fixup.Offset + - Fixup.FixupSection->getSectionOffset(); - - uint8_t Buffer[16]; - unsigned SizeLen = encodeULEB128(Type, Buffer, Padding); - assert(SizeLen == 5); - getStream().pwrite((char *)Buffer, SizeLen, - Section.ContentsOffset + Offset); - } - // Apply fixups. - ApplyRelocations(CodeRelocations, getStream(), SymbolIndices, - Section.ContentsOffset); + applyRelocations(CodeRelocations, Section.ContentsOffset); endSection(Section); } uint64_t WasmObjectWriter::writeDataSection( - const SmallVector<char, 0> &DataBytes, - DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices) { + const SmallVector<char, 0> &DataBytes) { if (DataBytes.empty()) return 0; @@ -833,8 +785,7 @@ uint64_t WasmObjectWriter::writeDataSection( writeBytes(DataBytes); // data // Apply fixups. - ApplyRelocations(DataRelocations, getStream(), SymbolIndices, - Section.ContentsOffset + HeaderSize); + applyRelocations(DataRelocations, Section.ContentsOffset + HeaderSize); endSection(Section); return HeaderSize; @@ -874,8 +825,7 @@ void WasmObjectWriter::writeNameSection( endSection(Section); } -void WasmObjectWriter::writeCodeRelocSection( - DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices) { +void WasmObjectWriter::writeCodeRelocSection() { // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md // for descriptions of the reloc sections. @@ -886,17 +836,14 @@ void WasmObjectWriter::writeCodeRelocSection( startSection(Section, wasm::WASM_SEC_CUSTOM, "reloc.CODE"); encodeULEB128(wasm::WASM_SEC_CODE, getStream()); - encodeULEB128(CodeRelocations.size() + TypeIndexFixups.size(), getStream()); + encodeULEB128(CodeRelocations.size(), getStream()); - WriteRelocations(CodeRelocations, getStream(), SymbolIndices, 0); - WriteTypeRelocations(TypeIndexFixups, TypeIndexFixupTypes, getStream()); + writeRelocations(CodeRelocations, 0); endSection(Section); } -void WasmObjectWriter::writeDataRelocSection( - DenseMap<const MCSymbolWasm *, uint32_t> &SymbolIndices, - uint64_t DataSectionHeaderSize) { +void WasmObjectWriter::writeDataRelocSection(uint64_t DataSectionHeaderSize) { // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md // for descriptions of the reloc sections. @@ -909,8 +856,7 @@ void WasmObjectWriter::writeDataRelocSection( encodeULEB128(wasm::WASM_SEC_DATA, getStream()); encodeULEB128(DataRelocations.size(), getStream()); - WriteRelocations(DataRelocations, getStream(), SymbolIndices, - DataSectionHeaderSize); + writeRelocations(DataRelocations, DataSectionHeaderSize); endSection(Section); } @@ -936,15 +882,12 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32; // Collect information from the available symbols. - DenseMap<WasmFunctionType, int32_t, WasmFunctionTypeDenseMapInfo> - FunctionTypeIndices; SmallVector<WasmFunctionType, 4> FunctionTypes; SmallVector<WasmFunction, 4> Functions; SmallVector<uint32_t, 4> TableElems; SmallVector<WasmGlobal, 4> Globals; SmallVector<WasmImport, 4> Imports; SmallVector<WasmExport, 4> Exports; - DenseMap<const MCSymbolWasm *, uint32_t> SymbolIndices; SmallPtrSet<const MCSymbolWasm *, 4> IsAddressTaken; unsigned NumFuncImports = 0; unsigned NumGlobalImports = 0; @@ -1215,9 +1158,9 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, } // Add types for indirect function calls. - for (const WasmRelocationEntry &Fixup : TypeIndexFixups) { - assert(Fixup.Addend == 0); - assert(Fixup.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB); + for (const WasmRelocationEntry &Fixup : CodeRelocations) { + if (Fixup.Type != wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) + continue; WasmFunctionType F; F.Returns = Fixup.Symbol->getReturns(); @@ -1227,7 +1170,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, if (Pair.second) FunctionTypes.push_back(F); - TypeIndexFixupTypes.push_back(Pair.first->second); + TypeIndices[Fixup.Symbol] = Pair.first->second; } // Write out the Wasm header. @@ -1242,11 +1185,11 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, writeExportSection(Exports); // TODO: Start Section writeElemSection(TableElems); - writeCodeSection(Asm, Layout, SymbolIndices, Functions); - uint64_t DataSectionHeaderSize = writeDataSection(DataBytes, SymbolIndices); + writeCodeSection(Asm, Layout, Functions); + uint64_t DataSectionHeaderSize = writeDataSection(DataBytes); writeNameSection(Functions, Imports, NumFuncImports); - writeCodeRelocSection(SymbolIndices); - writeDataRelocSection(SymbolIndices, DataSectionHeaderSize); + writeCodeRelocSection(); + writeDataRelocSection(DataSectionHeaderSize); writeLinkingMetaDataSection(HasStackPointer, StackPointerGlobal); // TODO: Translate the .comment section to the output. diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp index 00d7fc71c49..c773e57402e 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp @@ -54,6 +54,11 @@ static bool IsFunctionExpr(const MCExpr *Expr) { return false; } +static bool IsFunctionType(const MCValue &Target) { + const MCSymbolRefExpr *RefA = Target.getSymA(); + return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX; +} + unsigned WebAssemblyWasmObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, @@ -71,6 +76,8 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(MCContext &Ctx, case WebAssembly::fixup_code_sleb128_i64: llvm_unreachable("fixup_sleb128_i64 not implemented yet"); case WebAssembly::fixup_code_uleb128_i32: + if (IsFunctionType(Target)) + return wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB; if (IsFunction) return wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB; return wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB; diff --git a/llvm/test/MC/WebAssembly/reloc-code.ll b/llvm/test/MC/WebAssembly/reloc-code.ll index 5c794400fa0..5fcd9b40381 100644 --- a/llvm/test/MC/WebAssembly/reloc-code.ll +++ b/llvm/test/MC/WebAssembly/reloc-code.ll @@ -36,16 +36,6 @@ entry: ; CHECK-NEXT: Addend: 0 ; CHECK-NEXT: } ; CHECK-NEXT: Relocation { -; CHECK-NEXT: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0) -; CHECK-NEXT: Offset: 0x2D -; CHECK-NEXT: Index: 0x0 -; CHECK-NEXT: } -; CHECK-NEXT: Relocation { -; CHECK-NEXT: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0) -; CHECK-NEXT: Offset: 0x34 -; CHECK-NEXT: Index: 0x1 -; CHECK-NEXT: } -; CHECK-NEXT: Relocation { ; CHECK-NEXT: Type: R_WEBASSEMBLY_TYPE_INDEX_LEB (6) ; CHECK-NEXT: Offset: 0x1A ; CHECK-NEXT: Index: 0x1 @@ -55,5 +45,15 @@ entry: ; CHECK-NEXT: Offset: 0x24 ; CHECK-NEXT: Index: 0x0 ; CHECK-NEXT: } +; CHECK-NEXT: Relocation { +; CHECK-NEXT: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0) +; CHECK-NEXT: Offset: 0x2D +; CHECK-NEXT: Index: 0x0 +; CHECK-NEXT: } +; CHECK-NEXT: Relocation { +; CHECK-NEXT: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0) +; CHECK-NEXT: Offset: 0x34 +; CHECK-NEXT: Index: 0x1 +; CHECK-NEXT: } ; CHECK-NEXT: } ; CHECK-NEXT: ] |

