aboutsummaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
authorSam Clegg <sbc@chromium.org>2024-07-02 11:23:15 -0700
committerGitHub <noreply@github.com>2024-07-02 11:23:15 -0700
commit0fb3351524acd48c62c06c57ed28cc423db4e99e (patch)
treecdbc39971f0c58eb1b805664a25f7a5501f190ed /lld
parent5f1743cd074cc7d45744d1acc8db379513b4501c (diff)
downloadllvm-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.s26
-rw-r--r--lld/test/wasm/import-table.s (renamed from lld/test/wasm/import-table.test)16
-rw-r--r--lld/wasm/SymbolTable.cpp9
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 ||