From 0fb3351524acd48c62c06c57ed28cc423db4e99e Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 2 Jul 2024 11:23:15 -0700 Subject: [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 --- lld/test/wasm/import-table-explicit.s | 26 ++++++++++++++++++++++++++ lld/test/wasm/import-table.s | 25 +++++++++++++++++++++++++ lld/test/wasm/import-table.test | 25 ------------------------- lld/wasm/SymbolTable.cpp | 9 ++++++--- 4 files changed, 57 insertions(+), 28 deletions(-) create mode 100644 lld/test/wasm/import-table-explicit.s create mode 100644 lld/test/wasm/import-table.s delete mode 100644 lld/test/wasm/import-table.test (limited to 'lld') 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.s b/lld/test/wasm/import-table.s new file mode 100644 index 0000000..7a0c94d --- /dev/null +++ b/lld/test/wasm/import-table.s @@ -0,0 +1,25 @@ +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o +# RUN: wasm-ld --export-all --import-table -o %t.wasm %t.o +# RUN: obj2yaml %t.wasm | FileCheck %s + +.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 + +# 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.test deleted file mode 100644 index 73dc718..0000000 --- a/lld/test/wasm/import-table.test +++ /dev/null @@ -1,25 +0,0 @@ -# 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: obj2yaml %t.wasm | FileCheck %s - -.globl require_function_table -require_function_table: -.functype require_function_table () -> () - i32.const 1 - call_indirect () -> () - 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/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(); 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(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(existing); + } if (required) return createUndefinedIndirectFunctionTable(functionTableName); } else if ((existing && existing->isLive()) || config->exportTable || -- cgit v1.1