Skip to content

Commit b195e27

Browse files
committed
[lld][WebAssembly] Fix for --import-table when combined with reference types
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 WebAssembly/tool-conventions#158
1 parent ffca4ef commit b195e27

File tree

3 files changed

+40
-11
lines changed

3 files changed

+40
-11
lines changed

lld/test/wasm/import-table-explicit.s

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# RUN: llvm-mc -mattr=+reference-types -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o
2+
# RUN: wasm-ld --import-table -o %t.wasm %t.o
3+
# RUN: obj2yaml %t.wasm | FileCheck %s
4+
5+
.globl __indirect_function_table
6+
.tabletype __indirect_function_table, funcref
7+
8+
.globl _start
9+
_start:
10+
.functype _start () -> ()
11+
i32.const 1
12+
call_indirect __indirect_function_table, () -> ()
13+
end_function
14+
15+
# Verify the --import-table flag creates a table import
16+
17+
# CHECK: - Type: IMPORT
18+
# CHECK-NEXT: Imports:
19+
# CHECK-NEXT: - Module: env
20+
# CHECK-NEXT: Field: __indirect_function_table
21+
# CHECK-NEXT: Kind: TABLE
22+
# CHECK-NEXT: Table:
23+
# CHECK-NEXT: Index: 0
24+
# CHECK-NEXT: ElemType: FUNCREF
25+
# CHECK-NEXT: Limits:
26+
# CHECK-NEXT: Minimum: 0x1

lld/test/wasm/import-table.test lld/test/wasm/import-table.s

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/start.s -o %t.start.o
21
# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o
3-
# RUN: wasm-ld --export-all --import-table -o %t.wasm %t.start.o %t.o
2+
# RUN: wasm-ld --export-all --import-table -o %t.wasm %t.o
43
# RUN: obj2yaml %t.wasm | FileCheck %s
54

6-
.globl require_function_table
7-
require_function_table:
8-
.functype require_function_table () -> ()
9-
i32.const 1
10-
call_indirect () -> ()
11-
end_function
5+
.globl _start
6+
_start:
7+
.functype _start () -> ()
8+
i32.const 1
9+
# call_indirect instruction implicitly references the function table
10+
call_indirect () -> ()
11+
end_function
1212

1313
# Verify the --import-table flag creates a table import
1414

lld/wasm/SymbolTable.cpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -681,10 +681,10 @@ TableSymbol *SymbolTable::createUndefinedIndirectFunctionTable(StringRef name) {
681681
WasmTableType *type = make<WasmTableType>();
682682
type->ElemType = ValType::FUNCREF;
683683
type->Limits = limits;
684-
StringRef module(defaultModule);
685684
uint32_t flags = config->exportTable ? 0 : WASM_SYMBOL_VISIBILITY_HIDDEN;
686685
flags |= WASM_SYMBOL_UNDEFINED;
687-
Symbol *sym = addUndefinedTable(name, name, module, flags, nullptr, type);
686+
Symbol *sym =
687+
addUndefinedTable(name, name, defaultModule, flags, nullptr, type);
688688
sym->markLive();
689689
sym->forceExport = config->exportTable;
690690
return cast<TableSymbol>(sym);
@@ -724,8 +724,11 @@ TableSymbol *SymbolTable::resolveIndirectFunctionTable(bool required) {
724724
}
725725

726726
if (config->importTable) {
727-
if (existing)
727+
if (existing) {
728+
existing->importModule = defaultModule;
729+
existing->importName = functionTableName;
728730
return cast<TableSymbol>(existing);
731+
}
729732
if (required)
730733
return createUndefinedIndirectFunctionTable(functionTableName);
731734
} else if ((existing && existing->isLive()) || config->exportTable ||

0 commit comments

Comments
 (0)