Skip to content

Commit

Permalink
[lld][WebAssembly] Fix for --import-table when combined with referenc…
Browse files Browse the repository at this point in the history
…e 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
WebAssembly/tool-conventions#158
  • Loading branch information
sbc100 authored Jul 2, 2024
1 parent 5f1743c commit 0fb3351
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 11 deletions.
26 changes: 26 additions & 0 deletions lld/test/wasm/import-table-explicit.s
Original file line number Diff line number Diff line change
@@ -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
16 changes: 8 additions & 8 deletions lld/test/wasm/import-table.test → lld/test/wasm/import-table.s
Original file line number Diff line number Diff line change
@@ -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

Expand Down
9 changes: 6 additions & 3 deletions lld/wasm/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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 ||
Expand Down

0 comments on commit 0fb3351

Please sign in to comment.