From 187d771d27ed9059675b53e92e8fb8aeee9c43d8 Mon Sep 17 00:00:00 2001 From: Derek Schuff Date: Fri, 15 Jan 2021 15:50:41 -0800 Subject: [PATCH] Revert "[WebAssembly] Add support for table linking to wasm-ld" This reverts commit 38dfce706f796dc109ea495dd69a8cb4c8fa819d. CI discovered a bug where the table is exported twice: see D91870 --- lld/test/wasm/alias.s | 8 +++ lld/test/wasm/init-fini.ll | 18 +++--- lld/test/wasm/local-symbols.ll | 8 +++ lld/test/wasm/locals-duplicate.test | 55 ++++++++--------- lld/test/wasm/pie.ll | 16 ++--- lld/test/wasm/section-symbol-relocs.yaml | 4 +- lld/test/wasm/shared.ll | 16 ++--- lld/test/wasm/signature-mismatch.ll | 9 +-- lld/test/wasm/stack-pointer.ll | 8 +++ lld/test/wasm/weak-alias.ll | 5 -- lld/wasm/Driver.cpp | 59 ------------------- lld/wasm/InputFiles.cpp | 75 ------------------------ lld/wasm/InputFiles.h | 1 - lld/wasm/MarkLive.cpp | 3 - lld/wasm/SymbolTable.cpp | 12 ---- lld/wasm/SymbolTable.h | 3 - lld/wasm/Symbols.cpp | 1 - lld/wasm/Symbols.h | 5 -- lld/wasm/SyntheticSections.cpp | 39 +++++++++++- lld/wasm/SyntheticSections.h | 13 +++- lld/wasm/Writer.cpp | 18 ------ 21 files changed, 127 insertions(+), 249 deletions(-) diff --git a/lld/test/wasm/alias.s b/lld/test/wasm/alias.s index b2ab45e98d95..6c99f69da8b8 100644 --- a/lld/test/wasm/alias.s +++ b/lld/test/wasm/alias.s @@ -22,6 +22,14 @@ _start: # CHECK-NEXT: ReturnTypes: [] # CHECK-NEXT: - Type: FUNCTION # CHECK-NEXT: FunctionTypes: [ 0 ] +# CHECK-NEXT: - Type: TABLE +# CHECK-NEXT: Tables: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: ElemType: FUNCREF +# CHECK-NEXT: Limits: +# CHECK-NEXT: Flags: [ HAS_MAX ] +# CHECK-NEXT: Initial: 0x1 +# CHECK-NEXT: Maximum: 0x1 # CHECK-NEXT: - Type: MEMORY # CHECK-NEXT: Memories: # CHECK-NEXT: - Initial: 0x2 diff --git a/lld/test/wasm/init-fini.ll b/lld/test/wasm/init-fini.ll index 5631d58d68e5..1e7644bc6d35 100644 --- a/lld/test/wasm/init-fini.ll +++ b/lld/test/wasm/init-fini.ll @@ -139,15 +139,15 @@ entry: ; RELOC-NEXT: InitFunctions [ ; RELOC-NEXT: 0 (priority=101) ; RELOC-NEXT: 1 (priority=101) -; RELOC-NEXT: 15 (priority=101) -; RELOC-NEXT: 11 (priority=101) -; RELOC-NEXT: 21 (priority=101) -; RELOC-NEXT: 11 (priority=202) -; RELOC-NEXT: 23 (priority=202) +; RELOC-NEXT: 14 (priority=101) +; RELOC-NEXT: 10 (priority=101) +; RELOC-NEXT: 20 (priority=101) +; RELOC-NEXT: 10 (priority=202) +; RELOC-NEXT: 22 (priority=202) ; RELOC-NEXT: 0 (priority=1001) -; RELOC-NEXT: 17 (priority=1001) -; RELOC-NEXT: 11 (priority=2002) -; RELOC-NEXT: 25 (priority=2002) +; RELOC-NEXT: 16 (priority=1001) +; RELOC-NEXT: 10 (priority=2002) +; RELOC-NEXT: 24 (priority=2002) ; RELOC-NEXT: 9 (priority=4000) -; RELOC-NEXT: 19 (priority=4000) +; RELOC-NEXT: 18 (priority=4000) ; RELOC-NEXT: ] diff --git a/lld/test/wasm/local-symbols.ll b/lld/test/wasm/local-symbols.ll index 216aced9cf07..13c200d648e9 100644 --- a/lld/test/wasm/local-symbols.ll +++ b/lld/test/wasm/local-symbols.ll @@ -35,6 +35,14 @@ entry: ; CHECK-NEXT: ReturnTypes: [] ; CHECK-NEXT: - Type: FUNCTION ; CHECK-NEXT: FunctionTypes: [ 0, 1 ] +; CHECK-NEXT: - Type: TABLE +; CHECK-NEXT: Tables: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: ElemType: FUNCREF +; CHECK-NEXT: Limits: +; CHECK-NEXT: Flags: [ HAS_MAX ] +; CHECK-NEXT: Initial: 0x1 +; CHECK-NEXT: Maximum: 0x1 ; CHECK-NEXT: - Type: MEMORY ; CHECK-NEXT: Memories: ; CHECK-NEXT: - Initial: 0x2 diff --git a/lld/test/wasm/locals-duplicate.test b/lld/test/wasm/locals-duplicate.test index cf9a148d4ab7..07abb7485381 100644 --- a/lld/test/wasm/locals-duplicate.test +++ b/lld/test/wasm/locals-duplicate.test @@ -254,40 +254,40 @@ ; RELOC-NEXT: - Type: CODE ; RELOC-NEXT: Relocations: ; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 19 +; RELOC-NEXT: Index: 18 ; RELOC-NEXT: Offset: 0x13 ; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB ; RELOC-NEXT: Index: 3 ; RELOC-NEXT: Offset: 0x1C ; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 20 +; RELOC-NEXT: Index: 19 ; RELOC-NEXT: Offset: 0x25 ; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 17 +; RELOC-NEXT: Index: 16 ; RELOC-NEXT: Offset: 0x2E ; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB ; RELOC-NEXT: Index: 0 ; RELOC-NEXT: Offset: 0x37 ; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 18 +; RELOC-NEXT: Index: 17 ; RELOC-NEXT: Offset: 0x40 ; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 11 +; RELOC-NEXT: Index: 10 ; RELOC-NEXT: Offset: 0x58 ; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 23 +; RELOC-NEXT: Index: 22 ; RELOC-NEXT: Offset: 0x61 ; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB -; RELOC-NEXT: Index: 24 +; RELOC-NEXT: Index: 23 ; RELOC-NEXT: Offset: 0x6A ; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 9 +; RELOC-NEXT: Index: 8 ; RELOC-NEXT: Offset: 0x73 ; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 21 +; RELOC-NEXT: Index: 20 ; RELOC-NEXT: Offset: 0x7C ; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB -; RELOC-NEXT: Index: 22 +; RELOC-NEXT: Index: 21 ; RELOC-NEXT: Offset: 0x85 ; RELOC-NEXT: Functions: ; RELOC-NEXT: - Index: 0 @@ -410,92 +410,87 @@ ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 8 ; RELOC-NEXT: - Index: 8 -; RELOC-NEXT: Kind: TABLE -; RELOC-NEXT: Name: __indirect_function_table -; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: Table: 0 -; RELOC-NEXT: - Index: 9 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: colliding_func1 ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 9 -; RELOC-NEXT: - Index: 10 +; RELOC-NEXT: - Index: 9 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_global1B ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 12 -; RELOC-NEXT: - Index: 11 +; RELOC-NEXT: - Index: 10 ; RELOC-NEXT: Kind: DATA ; RELOC-NEXT: Name: colliding_global1 ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Segment: 0 ; RELOC-NEXT: Offset: 4 ; RELOC-NEXT: Size: 4 -; RELOC-NEXT: - Index: 12 +; RELOC-NEXT: - Index: 11 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_global2B ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 13 -; RELOC-NEXT: - Index: 13 +; RELOC-NEXT: - Index: 12 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_global3B ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 14 -; RELOC-NEXT: - Index: 14 +; RELOC-NEXT: - Index: 13 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_func1B ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 15 -; RELOC-NEXT: - Index: 15 +; RELOC-NEXT: - Index: 14 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_func2B ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 16 -; RELOC-NEXT: - Index: 16 +; RELOC-NEXT: - Index: 15 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: get_func3B ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 17 -; RELOC-NEXT: - Index: 17 +; RELOC-NEXT: - Index: 16 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: colliding_func1 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Function: 0 -; RELOC-NEXT: - Index: 18 +; RELOC-NEXT: - Index: 17 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: colliding_func3 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Function: 2 -; RELOC-NEXT: - Index: 19 +; RELOC-NEXT: - Index: 18 ; RELOC-NEXT: Kind: DATA ; RELOC-NEXT: Name: colliding_global1 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Segment: 0 ; RELOC-NEXT: Size: 4 -; RELOC-NEXT: - Index: 20 +; RELOC-NEXT: - Index: 19 ; RELOC-NEXT: Kind: DATA ; RELOC-NEXT: Name: colliding_global3 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Segment: 2 ; RELOC-NEXT: Size: 4 -; RELOC-NEXT: - Index: 21 +; RELOC-NEXT: - Index: 20 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: colliding_func2 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Function: 10 -; RELOC-NEXT: - Index: 22 +; RELOC-NEXT: - Index: 21 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: colliding_func3 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Function: 11 -; RELOC-NEXT: - Index: 23 +; RELOC-NEXT: - Index: 22 ; RELOC-NEXT: Kind: DATA ; RELOC-NEXT: Name: colliding_global2 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] ; RELOC-NEXT: Segment: 1 ; RELOC-NEXT: Offset: 4 ; RELOC-NEXT: Size: 4 -; RELOC-NEXT: - Index: 24 +; RELOC-NEXT: - Index: 23 ; RELOC-NEXT: Kind: DATA ; RELOC-NEXT: Name: colliding_global3 ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] diff --git a/lld/test/wasm/pie.ll b/lld/test/wasm/pie.ll index 1aca4df3a594..84555a08f19d 100644 --- a/lld/test/wasm/pie.ll +++ b/lld/test/wasm/pie.ll @@ -41,6 +41,14 @@ define void @_start() { ; CHECK: - Type: IMPORT ; CHECK-NEXT: Imports: ; CHECK-NEXT: - Module: env +; CHECK-NEXT: Field: __indirect_function_table +; CHECK-NEXT: Kind: TABLE +; CHECK-NEXT: Table: +; CHECK-NEXT: Index: 0 +; CHECK-NEXT: ElemType: FUNCREF +; CHECK-NEXT: Limits: +; CHECK-NEXT: Initial: 0x1 +; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: __stack_pointer ; CHECK-NEXT: Kind: GLOBAL ; CHECK-NEXT: GlobalType: I32 @@ -55,14 +63,6 @@ define void @_start() { ; CHECK-NEXT: Kind: GLOBAL ; CHECK-NEXT: GlobalType: I32 ; CHECK-NEXT: GlobalMutable: false -; CHECK-NEXT: - Module: env -; CHECK-NEXT: Field: __indirect_function_table -; CHECK-NEXT: Kind: TABLE -; CHECK-NEXT: Table: -; CHECK-NEXT: Index: 0 -; CHECK-NEXT: ElemType: FUNCREF -; CHECK-NEXT: Limits: -; CHECK-NEXT: Initial: 0x1 ; CHECK: - Type: START ; CHECK-NEXT: StartFunction: 2 diff --git a/lld/test/wasm/section-symbol-relocs.yaml b/lld/test/wasm/section-symbol-relocs.yaml index 34126cbf1252..3248ed62521a 100644 --- a/lld/test/wasm/section-symbol-relocs.yaml +++ b/lld/test/wasm/section-symbol-relocs.yaml @@ -54,8 +54,8 @@ Sections: # RELOC-NEXT: - Index: 0 # RELOC-NEXT: Kind: SECTION # RELOC-NEXT: Flags: [ BINDING_LOCAL ] -# RELOC-NEXT: Section: 1 +# RELOC-NEXT: Section: 2 # RELOC-NEXT: - Index: 1 # RELOC-NEXT: Kind: SECTION # RELOC-NEXT: Flags: [ BINDING_LOCAL ] -# RELOC-NEXT: Section: 2 +# RELOC-NEXT: Section: 3 diff --git a/lld/test/wasm/shared.ll b/lld/test/wasm/shared.ll index 61337fcc6a3a..98751adda489 100644 --- a/lld/test/wasm/shared.ll +++ b/lld/test/wasm/shared.ll @@ -69,6 +69,14 @@ declare void @func_external() ; CHECK-NEXT: Memory: ; CHECK-NEXT: Initial: 0x1 ; CHECK-NEXT: - Module: env +; CHECK-NEXT: Field: __indirect_function_table +; CHECK-NEXT: Kind: TABLE +; CHECK-NEXT: Table: +; CHECK-NEXT: Index: 0 +; CHECK-NEXT: ElemType: FUNCREF +; CHECK-NEXT: Limits: +; CHECK-NEXT: Initial: 0x2 +; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: __stack_pointer ; CHECK-NEXT: Kind: GLOBAL ; CHECK-NEXT: GlobalType: I32 @@ -87,14 +95,6 @@ declare void @func_external() ; CHECK-NEXT: Field: func_external ; CHECK-NEXT: Kind: FUNCTION ; CHECK-NEXT: SigIndex: 1 -; CHECK-NEXT: - Module: env -; CHECK-NEXT: Field: __indirect_function_table -; CHECK-NEXT: Kind: TABLE -; CHECK-NEXT: Table: -; CHECK-NEXT: Index: 0 -; CHECK-NEXT: ElemType: FUNCREF -; CHECK-NEXT: Limits: -; CHECK-NEXT: Initial: 0x2 ; CHECK-NEXT: - Module: GOT.mem ; CHECK-NEXT: Field: indirect_func ; CHECK-NEXT: Kind: GLOBAL diff --git a/lld/test/wasm/signature-mismatch.ll b/lld/test/wasm/signature-mismatch.ll index 65ce73910ffa..d5f95b0073c0 100644 --- a/lld/test/wasm/signature-mismatch.ll +++ b/lld/test/wasm/signature-mismatch.ll @@ -80,22 +80,17 @@ declare i32 @ret32(i32, i64, i32) local_unnamed_addr ; RELOC-NEXT: Segment: 0 ; RELOC-NEXT: Size: 4 ; RELOC-NEXT: - Index: 3 -; RELOC-NEXT: Kind: TABLE -; RELOC-NEXT: Name: __indirect_function_table -; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: Table: 0 -; RELOC-NEXT: - Index: 4 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: call_ret32 ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 3 -; RELOC-NEXT: - Index: 5 +; RELOC-NEXT: - Index: 4 ; RELOC-NEXT: Kind: DATA ; RELOC-NEXT: Name: ret32_address ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Segment: 1 ; RELOC-NEXT: Size: 4 -; RELOC-NEXT: - Index: 6 +; RELOC-NEXT: - Index: 5 ; RELOC-NEXT: Kind: FUNCTION ; RELOC-NEXT: Name: 'signature_mismatch:ret32' ; RELOC-NEXT: Flags: [ BINDING_LOCAL ] diff --git a/lld/test/wasm/stack-pointer.ll b/lld/test/wasm/stack-pointer.ll index 11ab62fab1ae..8efb2aae1ee5 100644 --- a/lld/test/wasm/stack-pointer.ll +++ b/lld/test/wasm/stack-pointer.ll @@ -30,6 +30,14 @@ entry: ; CHECK-NEXT: GlobalMutable: true ; CHECK-NEXT: - Type: FUNCTION ; CHECK-NEXT: FunctionTypes: [ 0 ] +; CHECK-NEXT: - Type: TABLE +; CHECK-NEXT: Tables: +; CHECK-NEXT: - Index: 0 +; CHECK-NEXT: ElemType: FUNCREF +; CHECK-NEXT: Limits: +; CHECK-NEXT: Flags: [ HAS_MAX ] +; CHECK-NEXT: Initial: 0x1 +; CHECK-NEXT: Maximum: 0x1 ; CHECK-NEXT: - Type: MEMORY ; CHECK-NEXT: Memories: ; CHECK-NEXT: - Initial: 0x0 diff --git a/lld/test/wasm/weak-alias.ll b/lld/test/wasm/weak-alias.ll index 387501963d4b..9d903f73dd32 100644 --- a/lld/test/wasm/weak-alias.ll +++ b/lld/test/wasm/weak-alias.ll @@ -276,11 +276,6 @@ entry: ; RELOC-NEXT: Name: call_direct_ptr ; RELOC-NEXT: Flags: [ ] ; RELOC-NEXT: Function: 5 -; RELOC-NEXT: - Index: 8 -; RELOC-NEXT: Kind: TABLE -; RELOC-NEXT: Name: __indirect_function_table -; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; RELOC-NEXT: Table: 0 ; RELOC-NEXT: - Type: CUSTOM ; RELOC-NEXT: Name: name ; RELOC-NEXT: FunctionNames: diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index d349a6abf5e6..84fdb77aea2c 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -10,7 +10,6 @@ #include "Config.h" #include "InputChunks.h" #include "InputGlobal.h" -#include "InputTable.h" #include "MarkLive.h" #include "SymbolTable.h" #include "Writer.h" @@ -788,58 +787,6 @@ static void wrapSymbols(ArrayRef wrapped) { symtab->wrap(w.sym, w.real, w.wrap); } -static TableSymbol *createDefinedIndirectFunctionTable(StringRef name) { - const uint32_t invalidIndex = -1; - WasmLimits limits{0, 0, 0}; // Set by the writer. - WasmTableType type{uint8_t(ValType::FUNCREF), limits}; - WasmTable desc{invalidIndex, type, name}; - InputTable *table = make(desc, nullptr); - uint32_t flags = config->exportTable ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN; - TableSymbol *sym = symtab->addSyntheticTable(name, flags, table); - sym->markLive(); - sym->forceExport = config->exportTable; - return sym; -} - -static TableSymbol *createUndefinedIndirectFunctionTable(StringRef name) { - WasmLimits limits{0, 0, 0}; // Set by the writer. - WasmTableType *type = make(); - type->ElemType = uint8_t(ValType::FUNCREF); - type->Limits = limits; - StringRef module(defaultModule); - uint32_t flags = config->exportTable ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN; - flags |= WASM_SYMBOL_UNDEFINED; - Symbol *sym = - symtab->addUndefinedTable(name, name, module, flags, nullptr, type); - sym->markLive(); - sym->forceExport = config->exportTable; - return cast(sym); -} - -static TableSymbol *resolveIndirectFunctionTable() { - // Even though we may not need a table, if the user explicitly specified - // --import-table or --export-table, ensure a table is residualized. - if (config->importTable) - return createUndefinedIndirectFunctionTable(functionTableName); - if (config->exportTable) - return createDefinedIndirectFunctionTable(functionTableName); - - // Otherwise, check to the symtab to find the indirect function table. - if (Symbol *sym = symtab->find(functionTableName)) { - if (sym->isLive()) { - if (auto *t = dyn_cast(sym)) { - return t->isDefined() - ? t - : createDefinedIndirectFunctionTable(functionTableName); - } - } - } - - // An indirect function table will only be present in the symbol table if - // needed by a reloc; if we get here, we don't need one. - return nullptr; -} - void LinkerDriver::linkerMain(ArrayRef argsArr) { WasmOptTable parser; opt::InputArgList args = parser.parse(argsArr.slice(1)); @@ -1029,12 +976,6 @@ void LinkerDriver::linkerMain(ArrayRef argsArr) { // Do size optimizations: garbage collection markLive(); - // Provide the indirect funciton table if needed. - WasmSym::indirectFunctionTable = resolveIndirectFunctionTable(); - - if (errorCount()) - return; - // Write the result to the file. writeResult(); } diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp index 1101cfb1a210..1d0f016f325a 100644 --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -310,71 +310,6 @@ static void setRelocs(const std::vector &chunks, } } -// Since LLVM 12, we expect that if an input file defines or uses a table, it -// declares the tables using symbols and records each use with a relocation. -// This way when the linker combines inputs, it can collate the tables used by -// the inputs, assigning them distinct table numbers, and renumber all the uses -// as appropriate. At the same time, the linker has special logic to build the -// indirect function table if it is needed. -// -// However, object files produced by LLVM 11 and earlier neither write table -// symbols nor record relocations, and yet still use tables via call_indirect, -// and via function pointer bitcasts. We can detect these object files, as they -// declare tables as imports or define them locally, but don't have table -// symbols. synthesizeTableSymbols serves as a shim when loading these older -// input files, defining the missing symbols to allow the indirect function -// table to be built. -// -// Table uses in these older files won't be relocated, as they have no -// relocations. In practice this isn't a problem, as these object files -// typically just declare a single table named __indirect_function_table and -// having table number 0, so relocation would be idempotent anyway. -void ObjFile::synthesizeTableSymbols() { - uint32_t tableNumber = 0; - const WasmGlobalType *globalType = nullptr; - const WasmEventType *eventType = nullptr; - const WasmSignature *signature = nullptr; - if (wasmObj->getNumImportedTables()) { - for (const auto &import : wasmObj->imports()) { - if (import.Kind == WASM_EXTERNAL_TABLE) { - auto *info = make(); - info->Name = import.Field; - info->Kind = WASM_SYMBOL_TYPE_TABLE; - info->ImportModule = import.Module; - info->ImportName = import.Field; - info->Flags = WASM_SYMBOL_UNDEFINED; - info->Flags |= WASM_SYMBOL_NO_STRIP; - info->ElementIndex = tableNumber++; - LLVM_DEBUG(dbgs() << "Synthesizing symbol for table import: " - << info->Name << "\n"); - auto *wasmSym = make(*info, globalType, &import.Table, - eventType, signature); - symbols.push_back(createUndefined(*wasmSym, false)); - // Because there are no TABLE_NUMBER relocs in this case, we can't - // compute accurate liveness info; instead, just mark the symbol as - // always live. - symbols.back()->markLive(); - } - } - } - for (const auto &table : tables) { - auto *info = make(); - // Empty name. - info->Kind = WASM_SYMBOL_TYPE_TABLE; - info->Flags = WASM_SYMBOL_BINDING_LOCAL; - info->Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN; - info->Flags |= WASM_SYMBOL_NO_STRIP; - info->ElementIndex = tableNumber++; - LLVM_DEBUG(dbgs() << "Synthesizing symbol for table definition: " - << info->Name << "\n"); - auto *wasmSym = make(*info, globalType, &table->getType(), - eventType, signature); - symbols.push_back(createDefined(*wasmSym)); - // Mark live, for the same reasons as for imported tables. - symbols.back()->markLive(); - } -} - void ObjFile::parse(bool ignoreComdats) { // Parse a memory buffer as a wasm file. LLVM_DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n"); @@ -489,11 +424,8 @@ void ObjFile::parse(bool ignoreComdats) { // Populate `Symbols` based on the symbols in the object. symbols.reserve(wasmObj->getNumberOfSymbols()); - bool haveTableSymbol = false; for (const SymbolRef &sym : wasmObj->symbols()) { const WasmSymbol &wasmSym = wasmObj->getWasmSymbol(sym.getRawDataRefImpl()); - if (wasmSym.isTypeTable()) - haveTableSymbol = true; if (wasmSym.isDefined()) { // createDefined may fail if the symbol is comdat excluded in which case // we fall back to creating an undefined symbol @@ -505,13 +437,6 @@ void ObjFile::parse(bool ignoreComdats) { size_t idx = symbols.size(); symbols.push_back(createUndefined(wasmSym, isCalledDirectly[idx])); } - - // As a stopgap measure while implementing table support, if the object file - // has table definitions or imports but no table symbols, synthesize symbols - // for those tables. Mark as NO_STRIP to ensure they reach the output file, - // even if there are no TABLE_NUMBER relocs against them. - if (!haveTableSymbol) - synthesizeTableSymbols(); } bool ObjFile::isExcludedByComdat(InputChunk *chunk) const { diff --git a/lld/wasm/InputFiles.h b/lld/wasm/InputFiles.h index 8a471389e7d1..4243a4447a92 100644 --- a/lld/wasm/InputFiles.h +++ b/lld/wasm/InputFiles.h @@ -157,7 +157,6 @@ private: Symbol *createUndefined(const WasmSymbol &sym, bool isCalledDirectly); bool isExcludedByComdat(InputChunk *chunk) const; - void synthesizeTableSymbols(); std::unique_ptr wasmObj; }; diff --git a/lld/wasm/MarkLive.cpp b/lld/wasm/MarkLive.cpp index f21774b0eec1..c47e0953bfaa 100644 --- a/lld/wasm/MarkLive.cpp +++ b/lld/wasm/MarkLive.cpp @@ -177,9 +177,6 @@ void markLive() { for (InputGlobal *g : symtab->syntheticGlobals) if (!g->live) message("removing unused section " + toString(g)); - for (InputTable *t : symtab->syntheticTables) - if (!t->live) - message("removing unused section " + toString(t)); } } diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp index d93b2a14dc5a..c5af5cafa8bd 100644 --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -270,18 +270,6 @@ DefinedGlobal *SymbolTable::addOptionalGlobalSymbols(StringRef name, return replaceSymbol(s, name, flags, nullptr, global); } -DefinedTable *SymbolTable::addSyntheticTable(StringRef name, uint32_t flags, - InputTable *table) { - LLVM_DEBUG(dbgs() << "addSyntheticTable: " << name << " -> " << table - << "\n"); - Symbol *s = find(name); - assert(!s || s->isUndefined()); - if (!s) - s = insertName(name).first; - syntheticTables.emplace_back(table); - return replaceSymbol(s, name, flags, nullptr, table); -} - static bool shouldReplace(const Symbol *existing, InputFile *newFile, uint32_t newFlags) { // If existing symbol is undefined, replace it. diff --git a/lld/wasm/SymbolTable.h b/lld/wasm/SymbolTable.h index ce7219c3ba4f..921a6edaa516 100644 --- a/lld/wasm/SymbolTable.h +++ b/lld/wasm/SymbolTable.h @@ -93,8 +93,6 @@ public: DefinedData *addOptionalDataSymbol(StringRef name, uint64_t value = 0); DefinedGlobal *addOptionalGlobalSymbols(StringRef name, uint32_t flags, InputGlobal *global); - DefinedTable *addSyntheticTable(StringRef name, uint32_t flags, - InputTable *global); void handleSymbolVariants(); void handleWeakUndefines(); @@ -105,7 +103,6 @@ public: std::vector bitcodeFiles; std::vector syntheticFunctions; std::vector syntheticGlobals; - std::vector syntheticTables; private: std::pair insert(StringRef name, const InputFile *file); diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp index 173ad3131509..a403a47dcdd5 100644 --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -91,7 +91,6 @@ UndefinedGlobal *WasmSym::tableBase; DefinedData *WasmSym::definedTableBase; UndefinedGlobal *WasmSym::memoryBase; DefinedData *WasmSym::definedMemoryBase; -TableSymbol *WasmSym::indirectFunctionTable; WasmSymbolType Symbol::getWasmType() const { if (isa(this)) diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h index c8ee0e144881..8434f82539b9 100644 --- a/lld/wasm/Symbols.h +++ b/lld/wasm/Symbols.h @@ -568,11 +568,6 @@ struct WasmSym { // Used in PIC code for offset of global data static UndefinedGlobal *memoryBase; static DefinedData *definedMemoryBase; - - // __indirect_function_table - // Used as an address space for function pointers, with each function that is - // used as a function pointer being allocated a slot. - static TableSymbol *indirectFunctionTable; }; // A buffer class that is large enough to hold any Symbol-derived diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp index 6044601c4e6a..967c2e240924 100644 --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -92,11 +92,20 @@ void TypeSection::writeBody() { writeSig(bodyOutputStream, *sig); } +ImportSection::ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT) { + // FIXME: Remove when we treat __indirect_function_table as any other symbol. + if (config->importTable) { + numImportedTables++; + } +} + uint32_t ImportSection::getNumImports() const { assert(isSealed); uint32_t numImports = importedSymbols.size() + gotSymbols.size(); if (config->importMemory) ++numImports; + if (config->importTable) + ++numImports; return numImports; } @@ -145,6 +154,17 @@ void ImportSection::writeBody() { writeImport(os, import); } + if (config->importTable) { + uint32_t tableSize = config->tableBase + out.elemSec->numEntries(); + WasmImport import; + import.Module = defaultModule; + import.Field = functionTableName; + import.Kind = WASM_EXTERNAL_TABLE; + import.Table.ElemType = WASM_TYPE_FUNCREF; + import.Table.Limits = {0, tableSize, 0}; + writeImport(os, import); + } + for (const Symbol *sym : importedSymbols) { WasmImport import; if (auto *f = dyn_cast(sym)) { @@ -210,9 +230,26 @@ void FunctionSection::addFunction(InputFunction *func) { } void TableSection::writeBody() { + bool hasIndirectFunctionTable = !config->importTable; + + uint32_t tableCount = inputTables.size(); + if (hasIndirectFunctionTable) + tableCount++; + raw_ostream &os = bodyOutputStream; - writeUleb128(os, inputTables.size(), "table count"); + writeUleb128(os, tableCount, "table count"); + + if (hasIndirectFunctionTable) { + uint32_t tableSize = config->tableBase + out.elemSec->numEntries(); + WasmLimits limits; + if (config->growableTable) + limits = {0, tableSize, 0}; + else + limits = {WASM_LIMITS_FLAG_HAS_MAX, tableSize, tableSize}; + writeTableType(os, WasmTableType{WASM_TYPE_FUNCREF, limits}); + } + for (const InputTable *table : inputTables) writeTableType(os, table->getType()); } diff --git a/lld/wasm/SyntheticSections.h b/lld/wasm/SyntheticSections.h index 3795b38228d0..7af931b4adc7 100644 --- a/lld/wasm/SyntheticSections.h +++ b/lld/wasm/SyntheticSections.h @@ -98,7 +98,7 @@ protected: class ImportSection : public SyntheticSection { public: - ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT) {} + ImportSection(); bool isNeeded() const override { return getNumImports() > 0; } void writeBody() override; void addImport(Symbol *sym); @@ -150,7 +150,16 @@ class TableSection : public SyntheticSection { public: TableSection() : SyntheticSection(llvm::wasm::WASM_SEC_TABLE) {} - bool isNeeded() const override { return inputTables.size() > 0; }; + bool isNeeded() const override { + // The linker currently always writes an indirect function table to the + // output, so unless the indirect function table is imported, we need a + // table section. FIXME: Treat __indirect_function_table as a normal + // symbol, and only residualize a table section as needed. + if (!config->importTable) + return true; + return inputTables.size() > 0; + } + void writeBody() override; void addTable(InputTable *table); diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 763fce5a1f30..99cf48c08c52 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -745,19 +745,6 @@ void Writer::createCommandExportWrappers() { } } -static void finalizeIndirectFunctionTable() { - if (!WasmSym::indirectFunctionTable) - return; - - uint32_t tableSize = config->tableBase + out.elemSec->numEntries(); - WasmLimits limits = {0, tableSize, 0}; - if (WasmSym::indirectFunctionTable->isDefined() && !config->growableTable) { - limits.Flags |= WASM_LIMITS_FLAG_HAS_MAX; - limits.Maximum = limits.Initial; - } - WasmSym::indirectFunctionTable->setLimits(limits); -} - static void scanRelocations() { for (ObjFile *file : symtab->objectFiles) { LLVM_DEBUG(dbgs() << "scanRelocations: " << file->getName() << "\n"); @@ -805,9 +792,6 @@ void Writer::assignIndexes() { out.tableSec->addTable(table); } - for (InputTable *table : symtab->syntheticTables) - out.tableSec->addTable(table); - out.globalSec->assignIndexes(); } @@ -1357,8 +1341,6 @@ void Writer::run() { log("-- scanRelocations"); scanRelocations(); - log("-- finalizeIndirectFunctionTable"); - finalizeIndirectFunctionTable(); log("-- createSyntheticInitFunctions"); createSyntheticInitFunctions(); log("-- assignIndexes");