Index: include/llvm/MC/MCWasmObjectWriter.h =================================================================== --- include/llvm/MC/MCWasmObjectWriter.h +++ 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 namespace llvm { @@ -42,6 +43,17 @@ : 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; Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ 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 using namespace llvm; @@ -146,11 +145,14 @@ // Relocations for fixing up references in the data section. std::vector DataRelocations; - // Fixups for call_indirect type indices. - std::vector TypeIndexFixups; - // Index values to use for fixing up call_indirect type indices. - std::vector TypeIndexFixupTypes; + // Maps function symbols to the index of the type of the function + DenseMap TypeIndices; + + DenseMap SymbolIndices; + + DenseMap + FunctionTypeIndices; // TargetObjectWriter wrappers. bool is64Bit() const { return TargetObjectWriter->is64Bit(); } @@ -170,6 +172,15 @@ 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, @@ -195,21 +206,23 @@ void writeExportSection(const SmallVector &Exports); void writeElemSection(const SmallVector &TableElems); void writeCodeSection(const MCAssembler &Asm, const MCAsmLayout &Layout, - DenseMap &SymbolIndices, const SmallVector &Functions); uint64_t - writeDataSection(const SmallVector &DataBytes, - DenseMap &SymbolIndices); + writeDataSection(const SmallVector &DataBytes); void writeNameSection(const SmallVector &Functions, const SmallVector &Imports, uint32_t NumFuncImports); - void writeCodeRelocSection( - DenseMap &SymbolIndices); - void writeDataRelocSection( - DenseMap &SymbolIndices, - uint64_t DataSectionHeaderSize); + void writeCodeRelocSection(); + void writeDataRelocSection(uint64_t DataSectionHeaderSize); void writeLinkingMetaDataSection(bool HasStackPointer, uint32_t StackPointerGlobal); + + void applyRelocations(ArrayRef Relocations, + uint64_t ContentsOffset); + + void writeRelocations(ArrayRef Relocations, + uint64_t HeaderSize); + uint32_t getRelocationIndexValue(const WasmRelocationEntry &RelEntry); }; } // end anonymous namespace @@ -356,19 +369,7 @@ 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()) @@ -427,124 +428,85 @@ 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 Relocations, - raw_pwrite_stream &Stream, - DenseMap &SymbolIndices, - uint64_t ContentsOffset) -{ +void WasmObjectWriter::applyRelocations( + ArrayRef 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 Relocations, - raw_pwrite_stream &Stream, - DenseMap &SymbolIndices, - uint64_t HeaderSize) { - for (const WasmRelocationEntry RelEntry : Relocations) { - encodeULEB128(RelEntry.Type, Stream); +void WasmObjectWriter::writeRelocations( + ArrayRef 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 TypeIndexFixups, - ArrayRef 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); } } @@ -733,7 +695,6 @@ void WasmObjectWriter::writeCodeSection( const MCAssembler &Asm, const MCAsmLayout &Layout, - DenseMap &SymbolIndices, const SmallVector &Functions) { if (Functions.empty()) return; @@ -768,34 +729,14 @@ 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 &DataBytes, - DenseMap &SymbolIndices) { + const SmallVector &DataBytes) { if (DataBytes.empty()) return 0; @@ -812,8 +753,7 @@ writeBytes(DataBytes); // data // Apply fixups. - ApplyRelocations(DataRelocations, getStream(), SymbolIndices, - Section.ContentsOffset + HeaderSize); + applyRelocations(DataRelocations, Section.ContentsOffset + HeaderSize); endSection(Section); return HeaderSize; @@ -853,8 +793,7 @@ endSection(Section); } -void WasmObjectWriter::writeCodeRelocSection( - DenseMap &SymbolIndices) { +void WasmObjectWriter::writeCodeRelocSection() { // See: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md // for descriptions of the reloc sections. @@ -865,17 +804,14 @@ 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 &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. @@ -888,8 +824,7 @@ encodeULEB128(wasm::WASM_SEC_DATA, getStream()); encodeULEB128(DataRelocations.size(), getStream()); - WriteRelocations(DataRelocations, getStream(), SymbolIndices, - DataSectionHeaderSize); + writeRelocations(DataRelocations, DataSectionHeaderSize); endSection(Section); } @@ -915,15 +850,12 @@ wasm::ValType PtrType = is64Bit() ? wasm::ValType::I64 : wasm::ValType::I32; // Collect information from the available symbols. - DenseMap - FunctionTypeIndices; SmallVector FunctionTypes; SmallVector Functions; SmallVector TableElems; SmallVector Globals; SmallVector Imports; SmallVector Exports; - DenseMap SymbolIndices; SmallPtrSet IsAddressTaken; unsigned NumFuncImports = 0; unsigned NumGlobalImports = 0; @@ -1194,9 +1126,9 @@ } // 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(); @@ -1206,7 +1138,7 @@ if (Pair.second) FunctionTypes.push_back(F); - TypeIndexFixupTypes.push_back(Pair.first->second); + TypeIndices[Fixup.Symbol] = Pair.first->second; } // Write out the Wasm header. @@ -1221,11 +1153,11 @@ 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. Index: lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp =================================================================== --- lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp +++ lib/Target/WebAssembly/MCTargetDesc/WebAssemblyWasmObjectWriter.cpp @@ -54,6 +54,11 @@ 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 @@ 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; Index: test/MC/WebAssembly/reloc-code.ll =================================================================== --- test/MC/WebAssembly/reloc-code.ll +++ test/MC/WebAssembly/reloc-code.ll @@ -36,16 +36,6 @@ ; 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 @@ ; 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: ]