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(); @@ -521,14 +521,23 @@ return Value; } -// Get a provisional table index. This isn't used by the linker at all; -// for now we'll write out the same value that we always have. TODO make neater +// Get a provisional table index. For table relocations, the relocation +// entry contains the actual function symbol index, and that's all that's +// used by the linker. However, as a nice touch so that the object files +// "work", we create provisional table and table indexes just for show. uint32_t WasmObjectWriter::getProvisionalTableIndex( - const WasmRelocationEntry &RelEntry) { - if (!IndirectSymbolIndices.count(RelEntry.Symbol)) - report_fatal_error("symbol not found in table index space: " + + const WasmRelocationEntry &RelEntry) { + const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol); + assert(Sym->isFunction()); + if (!SymbolIndices.count(Sym)) + report_fatal_error("symbol not found in function/global index space: " + RelEntry.Symbol->getName()); - return IndirectSymbolIndices[RelEntry.Symbol]; + uint32_t SymbolIndex = SymbolIndices[Sym]; + int32_t TableIndex = TableIndices[SymbolIndex]; + if (TableIndex < 0) + report_fatal_error("symbol not found in table index space: " + + Sym->getName()); + return TableIndex; } static void addData(SmallVectorImpl &DataBytes, @@ -1321,26 +1330,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