diff options
author | Sam Clegg <sbc@chromium.org> | 2024-07-02 11:23:15 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-02 11:23:15 -0700 |
commit | 0fb3351524acd48c62c06c57ed28cc423db4e99e (patch) | |
tree | cdbc39971f0c58eb1b805664a25f7a5501f190ed /lld | |
parent | 5f1743cd074cc7d45744d1acc8db379513b4501c (diff) | |
download | llvm-0fb3351524acd48c62c06c57ed28cc423db4e99e.zip llvm-0fb3351524acd48c62c06c57ed28cc423db4e99e.tar.gz llvm-0fb3351524acd48c62c06c57ed28cc423db4e99e.tar.bz2 |
[lld][WebAssembly] Fix for --import-table when combined with reference types (#97451)
When reference types are enabled clang will generate call_indirect
instructions that explicitly reference the global
`__indirect_function_table` symbol.
In this case the resulting global symbol was not being correctly marked
with explicit import name/module, resulting in the linker reporting
errors when it was referenced.
This issue was reported in
https://github.com/WebAssembly/tool-conventions/issues/158
Diffstat (limited to 'lld')
-rw-r--r-- | lld/test/wasm/import-table-explicit.s | 26 | ||||
-rw-r--r-- | lld/test/wasm/import-table.s (renamed from lld/test/wasm/import-table.test) | 16 | ||||
-rw-r--r-- | lld/wasm/SymbolTable.cpp | 9 |
3 files changed, 40 insertions, 11 deletions
diff --git a/lld/test/wasm/import-table-explicit.s b/lld/test/wasm/import-table-explicit.s new file mode 100644 index 0000000..1dc21be --- /dev/null +++ b/lld/test/wasm/import-table-explicit.s @@ -0,0 +1,26 @@ +# RUN: llvm-mc -mattr=+reference-types -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o +# RUN: wasm-ld --import-table -o %t.wasm %t.o +# RUN: obj2yaml %t.wasm | FileCheck %s + +.globl __indirect_function_table +.tabletype __indirect_function_table, funcref + +.globl _start +_start: + .functype _start () -> () + i32.const 1 + call_indirect __indirect_function_table, () -> () + end_function + +# Verify the --import-table flag creates a table import + +# 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: Minimum: 0x1 diff --git a/lld/test/wasm/import-table.test b/lld/test/wasm/import-table.s index 73dc718..7a0c94d 100644 --- a/lld/test/wasm/import-table.test +++ b/lld/test/wasm/import-table.s @@ -1,14 +1,14 @@ -# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/start.s -o %t.start.o # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o -# RUN: wasm-ld --export-all --import-table -o %t.wasm %t.start.o %t.o +# RUN: wasm-ld --export-all --import-table -o %t.wasm %t.o # RUN: obj2yaml %t.wasm | FileCheck %s -.globl require_function_table -require_function_table: -.functype require_function_table () -> () - i32.const 1 - call_indirect () -> () - end_function +.globl _start +_start: + .functype _start () -> () + i32.const 1 + # call_indirect instruction implicitly references the function table + call_indirect () -> () + end_function # Verify the --import-table flag creates a table import diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp index 00c347e..081f811 100644 --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -681,10 +681,10 @@ TableSymbol *SymbolTable::createUndefinedIndirectFunctionTable(StringRef name) { WasmTableType *type = make<WasmTableType>(); type->ElemType = ValType::FUNCREF; type->Limits = limits; - StringRef module(defaultModule); uint32_t flags = config->exportTable ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN; flags |= WASM_SYMBOL_UNDEFINED; - Symbol *sym = addUndefinedTable(name, name, module, flags, nullptr, type); + Symbol *sym = + addUndefinedTable(name, name, defaultModule, flags, nullptr, type); sym->markLive(); sym->forceExport = config->exportTable; return cast<TableSymbol>(sym); @@ -724,8 +724,11 @@ TableSymbol *SymbolTable::resolveIndirectFunctionTable(bool required) { } if (config->importTable) { - if (existing) + if (existing) { + existing->importModule = defaultModule; + existing->importName = functionTableName; return cast<TableSymbol>(existing); + } if (required) return createUndefinedIndirectFunctionTable(functionTableName); } else if ((existing && existing->isLive()) || config->exportTable || |