Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -215,11 +215,11 @@ // Index values to use for fixing up call_indirect type indices. // Maps function symbols to the index of the type of the function DenseMap TypeIndices; - // Maps function symbols to the table element index space. Used - // for TABLE_INDEX relocation types (i.e. address taken functions). - DenseMap IndirectSymbolIndices; // Maps function/global symbols to the function/global index space. DenseMap SymbolIndices; + // Maps function symbol indices to the table element index space. Used + // for TABLE_INDEX relocation types (i.e. address taken functions). + SmallVector TableIndices; DenseMap FunctionTypeIndices; @@ -252,7 +252,7 @@ DataRelocations.clear(); TypeIndices.clear(); SymbolIndices.clear(); - IndirectSymbolIndices.clear(); + TableIndices.clear(); FunctionTypeIndices.clear(); FunctionTypes.clear(); Globals.clear(); @@ -504,24 +504,27 @@ // useable. uint32_t WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) { - switch (RelEntry.Type) { case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: - case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: - // Provitional value is the indirect symbol index - if (!IndirectSymbolIndices.count(RelEntry.Symbol)) - report_fatal_error("symbol not found in table index space: " + - RelEntry.Symbol->getName()); - return IndirectSymbolIndices[RelEntry.Symbol]; + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: { + // Provisional value is table address of the resolved symbol itself + const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol); + assert(Sym->isFunction()); + assert(SymbolIndices.count(Sym)); + uint32_t SymbolIndex = SymbolIndices[Sym]; + int32_t TableIndex = TableIndices[SymbolIndex]; + assert(TableIndex >= 0); + return TableIndex; + } case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: - // Provitional value is function/type/global index itself + // Provisional value is function/type/global index itself return getRelocationIndexValue(RelEntry); case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: { - // Provitional value is address of the global + // Provisional value is address of the global const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol); // For undefined symbols, use zero if (!Sym->isDefined()) @@ -1313,26 +1316,21 @@ } { + TableIndices.resize(NumFunctionImports + Functions.size(), -1); auto HandleReloc = [&](const WasmRelocationEntry &Rel) { - // Functions referenced by a relocation need to prepared to be called - // indirectly. - const MCSymbolWasm& WS = *Rel.Symbol; - if (WS.isFunction() && IndirectSymbolIndices.count(&WS) == 0) { - switch (Rel.Type) { - case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: - case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: { - uint32_t Index = SymbolIndices.find(&WS)->second; - IndirectSymbolIndices[&WS] = TableElems.size() + kInitialTableOffset; - DEBUG(dbgs() << " -> adding to table: " << TableElems.size() << "\n"); - TableElems.push_back(Index); - registerFunctionType(WS); - break; - } - default: - break; - } + // Functions referenced by a relocation need to put in the table. This is + // 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_WEBASSEMBLY_TABLE_INDEX_I32 && + Rel.Type != wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB) + return; + assert(Rel.Symbol->isFunction()); + const MCSymbolWasm* WS = ResolveSymbol(*Rel.Symbol); + uint32_t SymbolIndex = SymbolIndices[WS]; + if (TableIndices[SymbolIndex] == -1) { + TableIndices[SymbolIndex] = TableElems.size() + kInitialTableOffset; + DEBUG(dbgs() << " -> adding to table: " << TableElems.size() << "\n"); + TableElems.push_back(SymbolIndex); } }; Index: test/MC/WebAssembly/weak-alias.ll =================================================================== --- test/MC/WebAssembly/weak-alias.ll +++ test/MC/WebAssembly/weak-alias.ll @@ -62,7 +62,7 @@ ; CHECK-NEXT: Table: ; CHECK-NEXT: ElemType: ANYFUNC ; CHECK-NEXT: Limits: -; CHECK-NEXT: Initial: 0x00000002 +; CHECK-NEXT: Initial: 0x00000001 ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: foo_alias ; CHECK-NEXT: Kind: FUNCTION @@ -131,7 +131,7 @@ ; CHECK-NEXT: - Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1 -; CHECK-NEXT: Functions: [ 1, 0 ] +; CHECK-NEXT: Functions: [ 1 ] ; CHECK-NEXT: - Type: CODE ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB @@ -189,8 +189,13 @@ ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 8 ; CHECK-NEXT: Content: '01000000' - -; CHECK: - Type: CUSTOM +; CHECK-NEXT: - SectionOffset: 24 +; CHECK-NEXT: MemoryIndex: 0 +; CHECK-NEXT: Offset: +; CHECK-NEXT: Opcode: I32_CONST +; CHECK-NEXT: Value: 16 +; CHECK-NEXT: Content: '01000000' +; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: name ; CHECK-NEXT: FunctionNames: ; CHECK-NEXT: - Index: 0