Index: lib/MC/WasmObjectWriter.cpp =================================================================== --- lib/MC/WasmObjectWriter.cpp +++ lib/MC/WasmObjectWriter.cpp @@ -152,8 +152,8 @@ } void print(raw_ostream &Out) const { - Out << "Off=" << Offset << ", Sym=" << Symbol << ", Addend=" << Addend - << ", Type=" << Type << ", FixupSection=" << FixupSection; + Out << "Off=" << Offset << ", Sym=" << Symbol->getName() << ", Addend=" << Addend + << ", Type=" << Type << ", FixupSection=" << FixupSection << "\n"; } void dump() const { print(errs()); } }; @@ -180,8 +180,8 @@ // 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; - DenseMap SymbolIndices; + DenseMap IndirectSymbolIndices; DenseMap FunctionTypeIndices; @@ -209,6 +209,7 @@ DataRelocations.clear(); TypeIndices.clear(); SymbolIndices.clear(); + IndirectSymbolIndices.clear(); FunctionTypeIndices.clear(); MCObjectWriter::reset(); } @@ -232,7 +233,7 @@ void writeTypeSection(const SmallVector &FunctionTypes); void writeImportSection(const SmallVector &Imports); void writeFunctionSection(const SmallVector &Functions); - void writeTableSection(const SmallVector &TableElems); + void writeTableSection(uint32_t NumElements); void writeMemorySection(const SmallVector &DataBytes); void writeGlobalSection(const SmallVector &Globals); void writeExportSection(const SmallVector &Exports); @@ -463,9 +464,11 @@ 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: + assert(IndirectSymbolIndices.count(RelEntry.Symbol)); + return IndirectSymbolIndices[RelEntry.Symbol]; + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: @@ -616,11 +619,10 @@ endSection(Section); } -void WasmObjectWriter::writeTableSection( - const SmallVector &TableElems) { - // For now, always emit the table section, since indirect calls are not - // valid without it. In the future, we could perhaps be more clever and omit - // it if there are no indirect calls. +void WasmObjectWriter::writeTableSection(uint32_t NumElements) { + if (NumElements == 0) + return; + SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_TABLE); @@ -630,7 +632,7 @@ encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); encodeULEB128(0, getStream()); // flags - encodeULEB128(TableElems.size(), getStream()); // initial + encodeULEB128(NumElements, getStream()); // initial endSection(Section); } @@ -1071,8 +1073,10 @@ } // If needed, prepare the function to be called indirectly. - if (IsAddressTaken.count(&WS)) + if (IsAddressTaken.count(&WS)) { + IndirectSymbolIndices[&WS] = TableElems.size(); TableElems.push_back(Index); + } } else { if (WS.isTemporary() && !WS.getSize()) continue; @@ -1179,7 +1183,7 @@ writeTypeSection(FunctionTypes); writeImportSection(Imports); writeFunctionSection(Functions); - writeTableSection(TableElems); + writeTableSection(TableElems.size()); writeMemorySection(DataBytes); writeGlobalSection(Globals); writeExportSection(Exports); Index: test/MC/WebAssembly/func-address.ll =================================================================== --- /dev/null +++ test/MC/WebAssembly/func-address.ll @@ -0,0 +1,44 @@ +; RUN: llc -mtriple wasm32-unknown-unknown-wasm -O2 -filetype=obj %s -o - | llvm-readobj -r -expand-relocs | FileCheck %s + +declare i32 @import1() +declare i32 @import2() +declare i32 @import3() + +; call the imports to make sure they are included in the imports section +define hidden void @call_imports() #0 { +entry: + %call = call i32 @import1() + %call1 = call i32 @import2() + ret void +} + +; take the address of the third import. This should generate a TABLE_INDEX +; relocation with index of 0 since its the first and only address taken +; function. +define hidden void @call_indirect() #0 { +entry: + %adr = alloca i32 ()*, align 4 + store i32 ()* @import3, i32 ()** %adr, align 4 + ret void +} + +; CHECK: Format: WASM +; CHECK: Relocations [ +; CHECK: Section (9) CODE { +; CHECK: Relocation { +; CHECK: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0) +; CHECK: Offset: 0x4 +; CHECK: Index: 0x0 +; CHECK: } +; CHECK: Relocation { +; CHECK: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0) +; CHECK: Offset: 0xB +; CHECK: Index: 0x1 +; CHECK: } +; CHECK: Relocation { +; CHECK: Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB (1) +; CHECK: Offset: 0x1A +; CHECK: Index: 0x0 +; CHECK: } +; CHECK: } + Index: test/MC/WebAssembly/reloc-code.ll =================================================================== --- test/MC/WebAssembly/reloc-code.ll +++ test/MC/WebAssembly/reloc-code.ll @@ -22,7 +22,7 @@ ; CHECK: Format: WASM ; CHECK: Relocations [ -; CHECK-NEXT: Section (8) CODE { +; CHECK-NEXT: Section (7) CODE { ; CHECK-NEXT: Relocation { ; CHECK-NEXT: Type: R_WEBASSEMBLY_GLOBAL_ADDR_LEB (3) ; CHECK-NEXT: Offset: 0x9 Index: test/MC/WebAssembly/reloc-data.ll =================================================================== --- test/MC/WebAssembly/reloc-data.ll +++ test/MC/WebAssembly/reloc-data.ll @@ -9,7 +9,7 @@ ; CHECK: Format: WASM ; CHECK: Relocations [ -; CHECK: Section (6) DATA { +; CHECK: Section (5) DATA { ; CHECK: Relocation { ; CHECK: Type: R_WEBASSEMBLY_GLOBAL_ADDR_I32 (5) ; CHECK: Offset: 0xE Index: test/MC/WebAssembly/sections.ll =================================================================== --- test/MC/WebAssembly/sections.ll +++ test/MC/WebAssembly/sections.ll @@ -28,9 +28,6 @@ ; CHECK: Type: FUNCTION (0x3) ; CHECK: } ; CHECK: Section { -; CHECK: Type: TABLE (0x4) -; CHECK: } -; CHECK: Section { ; CHECK: Type: MEMORY (0x5) ; CHECK: Memories [ ; CHECK: Memory {