Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Jul 2, 2024

Conversation

sbc100
Copy link
Collaborator

@sbc100 sbc100 commented Jul 2, 2024

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

@sbc100 sbc100 requested a review from dschuff July 2, 2024 17:44
@sbc100 sbc100 requested a review from aheejin July 2, 2024 17:44
@llvmbot
Copy link
Member

llvmbot commented Jul 2, 2024

@llvm/pr-subscribers-lld

Author: Sam Clegg (sbc100)

Changes

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


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 --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 ||

@llvmbot
Copy link
Member

llvmbot commented Jul 2, 2024

@llvm/pr-subscribers-lld-wasm

Author: Sam Clegg (sbc100)

Changes

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


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 --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 ||

Copy link

github-actions bot commented Jul 2, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

…e 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
@@ -724,8 +724,11 @@ TableSymbol *SymbolTable::resolveIndirectFunctionTable(bool required) {
}

if (config->importTable) {
if (existing)
if (existing) {
existing->importModule = defaultModule;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to import a table from a non-default module? If so, how do we do it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, before this PR, what was this importModule set to?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function only deal with one very particular table (__indirect_function_table). This table is implicitly generated by the linker and we don't support defining it explicitly anywhere. The import name is also fixed. It should not be possible to attach any kind of custom import name to it.

@sbc100 sbc100 merged commit 0fb3351 into llvm:main Jul 2, 2024
5 of 6 checks passed
@sbc100 sbc100 deleted the import_table branch July 2, 2024 18:23
lravenclaw pushed a commit to lravenclaw/llvm-project that referenced this pull request Jul 3, 2024
…e types (llvm#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
kbluck pushed a commit to kbluck/llvm-project that referenced this pull request Jul 6, 2024
…e types (llvm#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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants