diff --git a/lld/wasm/InputFiles.h b/lld/wasm/InputFiles.h --- a/lld/wasm/InputFiles.h +++ b/lld/wasm/InputFiles.h @@ -118,6 +118,7 @@ std::vector typeIsUsed; // Maps function indices to table indices std::vector tableEntries; + std::vector tableEntriesRel; std::vector keptComdats; std::vector segments; std::vector functions; diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -122,11 +122,14 @@ uint32_t ObjFile::calcExpectedValue(const WasmRelocation &reloc) const { switch (reloc.Type) { case R_WASM_TABLE_INDEX_I32: - case R_WASM_TABLE_INDEX_SLEB: - case R_WASM_TABLE_INDEX_REL_SLEB: { + case R_WASM_TABLE_INDEX_SLEB: { const WasmSymbol &sym = wasmObj->syms()[reloc.Index]; return tableEntries[sym.Info.ElementIndex]; } + case R_WASM_TABLE_INDEX_REL_SLEB: { + const WasmSymbol &sym = wasmObj->syms()[reloc.Index]; + return tableEntriesRel[sym.Info.ElementIndex]; + } case R_WASM_MEMORY_ADDR_SLEB: case R_WASM_MEMORY_ADDR_I32: case R_WASM_MEMORY_ADDR_LEB: @@ -266,6 +269,7 @@ // verifying the existing table index relocations uint32_t totalFunctions = wasmObj->getNumImportedFunctions() + wasmObj->functions().size(); + tableEntriesRel.resize(totalFunctions); tableEntries.resize(totalFunctions); for (const WasmElemSegment &seg : wasmObj->elements()) { if (seg.Offset.Opcode != WASM_OPCODE_I32_CONST) @@ -274,6 +278,7 @@ for (uint32_t index = 0; index < seg.Functions.size(); index++) { uint32_t functionIndex = seg.Functions[index]; + tableEntriesRel[functionIndex] = index; tableEntries[functionIndex] = offset + index; } } diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -565,7 +565,10 @@ // Provisional value is table address of the resolved symbol itself const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol); assert(Sym->isFunction()); - return TableIndices[Sym]; + if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB) + return TableIndices[Sym] - InitialTableOffset; + else + return TableIndices[Sym]; } case wasm::R_WASM_TYPE_INDEX_LEB: // Provisional value is same as the index @@ -1559,7 +1562,8 @@ // 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_SLEB) + Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB && + Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB) return; assert(Rel.Symbol->isFunction()); const MCSymbolWasm &WS = *resolveSymbol(*Rel.Symbol); diff --git a/llvm/test/MC/WebAssembly/reloc-pic.s b/llvm/test/MC/WebAssembly/reloc-pic.s --- a/llvm/test/MC/WebAssembly/reloc-pic.s +++ b/llvm/test/MC/WebAssembly/reloc-pic.s @@ -68,7 +68,7 @@ # CHECK-NEXT: Table: # CHECK-NEXT: ElemType: FUNCREF # CHECK-NEXT: Limits: -# CHECK-NEXT: Initial: 0x00000000 +# CHECK-NEXT: Initial: 0x00000001 # CHECK-NEXT: - Module: env # CHECK-NEXT: Field: default_func # CHECK-NEXT: Kind: FUNCTION @@ -85,6 +85,12 @@ # CHECK-NEXT: GlobalMutable: true # CHECK-NEXT: - Type: FUNCTION # CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0 ] +# CHECK-NEXT: - Type: ELEM +# CHECK-NEXT: Segments: +# CHECK-NEXT: Offset: +# CHECK-NEXT: Opcode: I32_CONST +# CHECK-NEXT: Value: 1 +# CHECK-NEXT: Functions: [ 5 ] # CHECK-NEXT: - Type: DATACOUNT # CHECK-NEXT: Count: 1 # CHECK-NEXT: - Type: CODE