Index: test/wasm/locals-duplicate.test =================================================================== --- test/wasm/locals-duplicate.test +++ test/wasm/locals-duplicate.test @@ -385,13 +385,13 @@ ; RELOC-NEXT: Index: 5 ; RELOC-NEXT: Offset: 0x0000006A ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 3 +; RELOC-NEXT: Index: 9 ; RELOC-NEXT: Offset: 0x00000073 ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 4 +; RELOC-NEXT: Index: 10 ; RELOC-NEXT: Offset: 0x0000007C ; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 5 +; RELOC-NEXT: Index: 11 ; RELOC-NEXT: Offset: 0x00000085 ; RELOC-NEXT: Functions: ; RELOC-NEXT: - Index: 0 Index: test/wasm/relocatable.ll =================================================================== --- test/wasm/relocatable.ll +++ test/wasm/relocatable.ll @@ -177,7 +177,7 @@ ; CHECK-NEXT: - Type: DATA ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 0 +; CHECK-NEXT: Index: 4 ; CHECK-NEXT: Offset: 0x00000012 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 ; CHECK-NEXT: Index: 1 Index: wasm/InputChunks.h =================================================================== --- wasm/InputChunks.h +++ wasm/InputChunks.h @@ -46,6 +46,7 @@ } uint32_t getOutputOffset() const { return OutputOffset; } + ArrayRef getRelocations() const { return Relocations; } virtual StringRef getComdat() const = 0; Index: wasm/InputChunks.cpp =================================================================== --- wasm/InputChunks.cpp +++ wasm/InputChunks.cpp @@ -59,12 +59,6 @@ encodeULEB128(Reloc.Value, Buf, 5); break; case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - ExistingValue = decodeSLEB128(Buf); - if (ExistingValue != Reloc.Reloc.Index) { - DEBUG(dbgs() << "existing value: " << decodeSLEB128(Buf) << "\n"); - assert(decodeSLEB128(Buf) == Reloc.Reloc.Index); - } - LLVM_FALLTHROUGH; case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: encodeSLEB128(static_cast(Reloc.Value), Buf, 5); break; @@ -110,17 +104,7 @@ if (Config->EmitRelocs) NewReloc.NewIndex = File->calcNewIndex(Reloc); - - switch (Reloc.Type) { - case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - case R_WEBASSEMBLY_MEMORY_ADDR_I32: - case R_WEBASSEMBLY_MEMORY_ADDR_LEB: - NewReloc.Value = File->getRelocatedAddress(Reloc.Index) + Reloc.Addend; - break; - default: - NewReloc.Value = File->calcNewIndex(Reloc); - break; - } + NewReloc.Value = File->calcNewValue(Reloc); OutRelocations.emplace_back(NewReloc); } Index: wasm/InputFiles.h =================================================================== --- wasm/InputFiles.h +++ wasm/InputFiles.h @@ -94,8 +94,8 @@ void dumpInfo() const; uint32_t relocateFunctionIndex(uint32_t Original) const; - uint32_t getRelocatedAddress(uint32_t Index) const; uint32_t calcNewIndex(const WasmRelocation &Reloc) const; + uint32_t calcNewValue(const WasmRelocation &Reloc) const; const WasmSection *CodeSection = nullptr; const WasmSection *DataSection = nullptr; @@ -104,10 +104,11 @@ std::vector Segments; std::vector Functions; - ArrayRef getSymbols() { return Symbols; } - ArrayRef getTableSymbols() { return TableSymbols; } + ArrayRef getSymbols() const { return Symbols; } + ArrayRef getFunctionSymbols() const { return FunctionSymbols; } private: + uint32_t relocateVirtualAddress(uint32_t Index) const; uint32_t relocateTypeIndex(uint32_t Original) const; uint32_t relocateGlobalIndex(uint32_t Original) const; uint32_t relocateTableIndex(uint32_t Original) const; @@ -134,9 +135,6 @@ // List of all global symbols indexed by the global index space std::vector GlobalSymbols; - // List of all indirect symbols indexed by table index space. - std::vector TableSymbols; - uint32_t NumGlobalImports = 0; uint32_t NumFunctionImports = 0; std::unique_ptr WasmObj; Index: wasm/InputFiles.cpp =================================================================== --- wasm/InputFiles.cpp +++ wasm/InputFiles.cpp @@ -47,11 +47,10 @@ " Total Functions : " + Twine(FunctionSymbols.size()) + "\n" + " Total Globals : " + Twine(GlobalSymbols.size()) + "\n" + " Function Imports : " + Twine(NumFunctionImports) + "\n" + - " Global Imports : " + Twine(NumGlobalImports) + "\n" + - " Table Entries : " + Twine(TableSymbols.size()) + "\n"); + " Global Imports : " + Twine(NumGlobalImports) + "\n"); } -uint32_t ObjFile::getRelocatedAddress(uint32_t GlobalIndex) const { +uint32_t ObjFile::relocateVirtualAddress(uint32_t GlobalIndex) const { return GlobalSymbols[GlobalIndex]->getVirtualAddress(); } @@ -68,7 +67,7 @@ } uint32_t ObjFile::relocateTableIndex(uint32_t Original) const { - Symbol *Sym = TableSymbols[Original]; + Symbol *Sym = FunctionSymbols[Original]; uint32_t Index = Sym->hasTableIndex() ? Sym->getTableIndex() : 0; DEBUG(dbgs() << "relocateTableIndex: " << toString(*Sym) << ": " << Original << " -> " << Index << "\n"); @@ -92,10 +91,9 @@ case R_WEBASSEMBLY_TYPE_INDEX_LEB: return relocateTypeIndex(Reloc.Index); case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - return relocateFunctionIndex(Reloc.Index); case R_WEBASSEMBLY_TABLE_INDEX_I32: case R_WEBASSEMBLY_TABLE_INDEX_SLEB: - return relocateTableIndex(Reloc.Index); + return relocateFunctionIndex(Reloc.Index); case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: case R_WEBASSEMBLY_MEMORY_ADDR_LEB: case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: @@ -106,6 +104,27 @@ } } +// Translate from the relocation's index into the final linked output value. +uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const { + switch (Reloc.Type) { + case R_WEBASSEMBLY_TABLE_INDEX_I32: + case R_WEBASSEMBLY_TABLE_INDEX_SLEB: + return relocateTableIndex(Reloc.Index); + case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: + case R_WEBASSEMBLY_MEMORY_ADDR_I32: + case R_WEBASSEMBLY_MEMORY_ADDR_LEB: + return relocateVirtualAddress(Reloc.Index) + Reloc.Addend; + case R_WEBASSEMBLY_TYPE_INDEX_LEB: + return relocateTypeIndex(Reloc.Index); + case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + return relocateFunctionIndex(Reloc.Index); + case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: + return relocateGlobalIndex(Reloc.Index); + default: + llvm_unreachable("unknown relocation type"); + } +} + void ObjFile::parse() { // Parse a memory buffer as a wasm file. DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n"); @@ -271,24 +290,6 @@ for (size_t I = 0; I < GlobalSymbols.size(); ++I) assert(GlobalSymbols[I] != nullptr);); - // Populate `TableSymbols` with all symbols that are called indirectly - uint32_t SegmentCount = WasmObj->elements().size(); - if (SegmentCount) { - if (SegmentCount > 1) - fatal(getName() + ": contains more than one element segment"); - const WasmElemSegment &Segment = WasmObj->elements()[0]; - if (Segment.Offset.Opcode != WASM_OPCODE_I32_CONST) - fatal(getName() + ": unsupported element segment"); - if (Segment.TableIndex != 0) - fatal(getName() + ": unsupported table index in elem segment"); - uint32_t Offset = Segment.Offset.Value.Int32; - TableSymbols.resize(Offset); - TableSymbols.reserve(Offset + Segment.Functions.size()); - for (uint64_t FunctionIndex : Segment.Functions) - TableSymbols.push_back(FunctionSymbols[FunctionIndex]); - } - - DEBUG(dbgs() << "TableSymbols: " << TableSymbols.size() << "\n"); DEBUG(dbgs() << "Functions : " << FunctionSymbols.size() << "\n"); DEBUG(dbgs() << "Globals : " << GlobalSymbols.size() << "\n"); } Index: wasm/Writer.cpp =================================================================== --- wasm/Writer.cpp +++ wasm/Writer.cpp @@ -754,12 +754,24 @@ for (ObjFile *File : Symtab->ObjectFiles) { DEBUG(dbgs() << "Table Indexes: " << File->getName() << "\n"); - for (Symbol *Sym : File->getTableSymbols()) { - if (!Sym || Sym->hasTableIndex() || !Sym->hasOutputIndex()) - continue; - Sym->setTableIndex(TableIndex++); - IndirectFunctions.emplace_back(Sym); - } + auto HandleTableRelocs = [&](InputChunk *Chunk) { + if (Chunk->Discarded) + return; + for (const WasmRelocation& Reloc : Chunk->getRelocations()) { + if (Reloc.Type != R_WEBASSEMBLY_TABLE_INDEX_I32 && + Reloc.Type != R_WEBASSEMBLY_TABLE_INDEX_SLEB) + continue; + Symbol *Sym = File->getFunctionSymbols()[Reloc.Index]; + if (Sym->hasTableIndex() || !Sym->hasOutputIndex()) + continue; + Sym->setTableIndex(TableIndex++); + IndirectFunctions.emplace_back(Sym); + } + }; + for (InputFunction* Function : File->Functions) + HandleTableRelocs(Function); + for (InputSegment* Segment : File->Segments) + HandleTableRelocs(Segment); } }