[lld] [lld][WebAssembly] Fix for --import-table when combined with reference types (PR #97451)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 2 10:44:57 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld-wasm

Author: Sam Clegg (sbc100)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/97451.diff


3 Files Affected:

- (added) lld/test/wasm/import-table-explicit.s (+26) 
- (renamed) lld/test/wasm/import-table.s (+8-8) 
- (modified) lld/wasm/SymbolTable.cpp (+5-3) 


``````````diff
diff --git a/lld/test/wasm/import-table-explicit.s b/lld/test/wasm/import-table-explicit.s
new file mode 100644
index 0000000000000..1dc21beba0629
--- /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
similarity index 63%
rename from lld/test/wasm/import-table.test
rename to lld/test/wasm/import-table.s
index 73dc7189bbf28..7a0c94d130276 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 00c347ea3ef24..09c463299b05c 100644
--- a/lld/wasm/SymbolTable.cpp
+++ b/lld/wasm/SymbolTable.cpp
@@ -681,10 +681,9 @@ 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 +723,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 ||

``````````

</details>


https://github.com/llvm/llvm-project/pull/97451


More information about the llvm-commits mailing list