[lld][WebAssembly] Fix resolveIndirectFunctionTable for relocatable output
authorAndy Wingo <wingo@igalia.com>
Tue, 16 Feb 2021 12:28:44 +0000 (13:28 +0100)
committerAndy Wingo <wingo@igalia.com>
Thu, 18 Feb 2021 08:33:54 +0000 (09:33 +0100)
For relocatable output that needs the indirect function table, identify
the well-known function table.  This allows us to properly fix the
limits on the imported table, and in a followup will allow the element
section to reference the indirect function table even if it's not
assigned to table number 0.  Adapt tests for import reordering.

Differential Revision: https://reviews.llvm.org/D96770

lld/test/wasm/locals-duplicate.test
lld/test/wasm/relocatable-options.test [new file with mode: 0644]
lld/test/wasm/relocatable.ll
lld/test/wasm/weak-alias.ll
lld/wasm/Driver.cpp

index 1d704ec..df76d2f 100644 (file)
 ; RELOC-NEXT:          Index:           0
 ; RELOC-NEXT:          ElemType:        FUNCREF
 ; RELOC-NEXT:          Limits:
-; RELOC-NEXT:            Initial:         0x3
+; RELOC-NEXT:            Initial:         0x7
 ; RELOC-NEXT:   - Type:            FUNCTION
 ; RELOC-NEXT:     FunctionTypes:   [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 ; RELOC-NEXT:                        0, 0 ]
diff --git a/lld/test/wasm/relocatable-options.test b/lld/test/wasm/relocatable-options.test
new file mode 100644 (file)
index 0000000..03beb76
--- /dev/null
@@ -0,0 +1,6 @@
+; RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/start.s -o %t.o
+; RUN: not wasm-ld -o %t.wasm --relocatable --export-table %t.o 2>&1 | FileCheck %s --check-prefix=EXPORT
+; RUN: not wasm-ld -o %t.wasm --relocatable --growable-table %t.o 2>&1 | FileCheck %s --check-prefix=GROWABLE
+
+; EXPORT: error: --relocatable is incompatible with --export-table
+; GROWABLE: error: --relocatable is incompatible with --growable-table
index 7de51a3..b011813 100644 (file)
@@ -60,6 +60,14 @@ define void @_start() {
 ; CHECK-NEXT:   - 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:             Initial:         0x4
+; CHECK-NEXT:       - Module:          env
 ; CHECK-NEXT:         Field:           puts
 ; CHECK-NEXT:         Kind:            FUNCTION
 ; CHECK-NEXT:         SigIndex:        0
@@ -71,14 +79,6 @@ define void @_start() {
 ; CHECK-NEXT:         Field:           bar_import
 ; CHECK-NEXT:         Kind:            FUNCTION
 ; CHECK-NEXT:         SigIndex:        1
-; 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:             Initial:         0x3
 ; CHECK-NEXT:   - Type:            FUNCTION
 ; CHECK-NEXT:     FunctionTypes:   [ 2, 1, 1, 2 ]
 ; CHECK-NEXT:   - Type:            MEMORY
index 90531fa..8bdeda0 100644 (file)
@@ -145,18 +145,18 @@ entry:
 ; RELOC-NEXT:   - Type:            IMPORT
 ; RELOC-NEXT:     Imports:
 ; RELOC-NEXT:       - Module:          env
-; RELOC-NEXT:         Field:           __stack_pointer
-; RELOC-NEXT:         Kind:            GLOBAL
-; RELOC-NEXT:         GlobalType:      I32
-; RELOC-NEXT:         GlobalMutable:   true
-; RELOC-NEXT:       - Module:          env
 ; RELOC-NEXT:         Field:           __indirect_function_table
 ; RELOC-NEXT:         Kind:            TABLE
 ; RELOC-NEXT:         Table:
 ; RELOC-NEXT:           Index:           0
 ; RELOC-NEXT:           ElemType:        FUNCREF
 ; RELOC-NEXT:           Limits:
-; RELOC-NEXT:             Initial:         0x1
+; RELOC-NEXT:             Initial:         0x2
+; RELOC-NEXT:       - Module:          env
+; RELOC-NEXT:         Field:           __stack_pointer
+; RELOC-NEXT:         Kind:            GLOBAL
+; RELOC-NEXT:         GlobalType:      I32
+; RELOC-NEXT:         GlobalMutable:   true
 ; RELOC-NEXT:   - Type:            FUNCTION
 ; RELOC-NEXT:     FunctionTypes:   [ 0, 1, 1, 1, 1, 1 ]
 ; RELOC-NEXT:   - Type:            MEMORY
index 7e647cb..7216e0a 100644 (file)
@@ -470,6 +470,15 @@ static void setConfigs() {
     config->importTable = true;
   }
 
+  if (config->relocatable) {
+    if (config->exportTable)
+      error("--relocatable is incompatible with --export-table");
+    if (config->growableTable)
+      error("--relocatable is incompatible with --growable-table");
+    // Ignore any --import-table, as it's redundant.
+    config->importTable = true;
+  }
+
   if (config->shared) {
     config->importMemory = true;
     config->unresolvedSymbols = UnresolvedPolicy::ImportFuncs;
@@ -1012,13 +1021,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
   // Do size optimizations: garbage collection
   markLive();
 
-  if (!config->relocatable) {
-    // Provide the indirect funciton table if needed.
-    WasmSym::indirectFunctionTable = resolveIndirectFunctionTable();
+  // Provide the indirect funciton table if needed.
+  WasmSym::indirectFunctionTable = resolveIndirectFunctionTable();
 
-    if (errorCount())
-      return;
-  }
+  if (errorCount())
+    return;
 
   // Write the result to the file.
   writeResult();