[llvm] [MC][WebAssembly] Fix importing tables with limits (PR #172992)

via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 21 18:46:20 PST 2025


https://github.com/daxpedda updated https://github.com/llvm/llvm-project/pull/172992

>From 158f4f47551394c2fd0f0b241ac77d66f2d904bf Mon Sep 17 00:00:00 2001
From: daxpedda <daxpedda at gmail.com>
Date: Fri, 19 Dec 2025 20:48:31 +0100
Subject: [PATCH 1/2] [WebAssembly] fix importing tables with limits

---
 llvm/lib/MC/WasmObjectWriter.cpp  | 13 +++---
 llvm/test/MC/WebAssembly/tables.s | 75 ++++++++++++++++++++++---------
 2 files changed, 62 insertions(+), 26 deletions(-)

diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index 15590b31fd07f..f0ad3bf97a2b4 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -323,8 +323,8 @@ class WasmObjectWriter : public MCObjectWriter {
   void writeValueType(wasm::ValType Ty) { W->OS << static_cast<char>(Ty); }
 
   void writeTypeSection(ArrayRef<wasm::WasmSignature> Signatures);
-  void writeImportSection(ArrayRef<wasm::WasmImport> Imports, uint64_t DataSize,
-                          uint32_t NumElements);
+  void writeImportSection(ArrayRef<wasm::WasmImport> Imports,
+                          uint64_t DataSize);
   void writeFunctionSection(ArrayRef<WasmFunction> Functions);
   void writeExportSection(ArrayRef<wasm::WasmExport> Exports);
   void writeElemSection(const MCSymbolWasm *IndirectFunctionTable,
@@ -823,8 +823,7 @@ void WasmObjectWriter::writeTypeSection(
 }
 
 void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
-                                          uint64_t DataSize,
-                                          uint32_t NumElements) {
+                                          uint64_t DataSize) {
   if (Imports.empty())
     return;
 
@@ -855,7 +854,9 @@ void WasmObjectWriter::writeImportSection(ArrayRef<wasm::WasmImport> Imports,
     case wasm::WASM_EXTERNAL_TABLE:
       W->OS << char(Import.Table.ElemType);
       encodeULEB128(Import.Table.Limits.Flags, W->OS);
-      encodeULEB128(NumElements, W->OS); // initial
+      encodeULEB128(Import.Table.Limits.Minimum, W->OS);
+      if (Import.Table.Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
+        encodeULEB128(Import.Table.Limits.Maximum, W->OS);
       break;
     case wasm::WASM_EXTERNAL_TAG:
       W->OS << char(0); // Reserved 'attribute' field
@@ -1901,7 +1902,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
   uint32_t CodeSectionIndex, DataSectionIndex;
   if (Mode != DwoMode::DwoOnly) {
     writeTypeSection(Signatures);
-    writeImportSection(Imports, DataSize, TableElems.size());
+    writeImportSection(Imports, DataSize);
     writeFunctionSection(Functions);
     writeTableSection(Tables);
     // Skip the "memory" section; we import the memory instead.
diff --git a/llvm/test/MC/WebAssembly/tables.s b/llvm/test/MC/WebAssembly/tables.s
index 8239432eed88d..16d4a2a59bb53 100644
--- a/llvm/test/MC/WebAssembly/tables.s
+++ b/llvm/test/MC/WebAssembly/tables.s
@@ -20,6 +20,10 @@ table1:
 table2:
     .tabletype table2, funcref, 42, 100
 
+.import_module table3, env
+.import_name table3, table3
+.tabletype table3, funcref, 42, 100
+
 # Table instructions
 
 #      CHECK: copy_tables:
@@ -28,6 +32,8 @@ table2:
 # CHECK-NEXT:	local.get	1
 #      CHECK:	table.size	table1
 #      CHECK:	table.copy	table1, table2
+#      CHECK:	table.size	table2
+#      CHECK:	table.copy	table2, table3
 # CHECK-NEXT:	end_function
 copy_tables:
     .functype copy_tables (i32, i32) -> ()
@@ -39,6 +45,11 @@ copy_tables:
 
     # ENC: table.copy	table1, table2          # encoding: [0xfc,0x0e,0x80'A',0x80'A',0x80'A',0x80'A',A,0x80'B',0x80'B',0x80'B',0x80'B',B]
     table.copy table1, table2
+
+    local.get 0
+    local.get 1
+    table.size table2
+    table.copy table2, table3
     end_function
 
 #      CHECK: table_get:
@@ -109,21 +120,31 @@ table_fill:
     table.fill table1
     end_function
 
+# BIN:    Field:           table3
+# BIN-NEXT:    Kind:            TABLE
+# BIN-NEXT:    Table:
+# BIN-NEXT:      Index: 0
+# BIN-NEXT:      ElemType:        FUNCREF
+# BIN-NEXT:      Limits:
+# BIN-NEXT:        Flags:           [ HAS_MAX ]
+# BIN-NEXT:        Minimum:         0x2A
+# BIN-NEXT:        Maximum:         0x64
+
 #      BIN:  - Type:            TABLE
 # BIN-NEXT:    Tables:
-# BIN-NEXT:      - Index:           0
+# BIN-NEXT:      - Index:           1
 # BIN-NEXT:        ElemType:        EXTERNREF
 # BIN-NEXT:        Limits:
 # BIN-NEXT:          Minimum:         0x0
-# BIN-NEXT:      - Index:           1
+# BIN-NEXT:      - Index:           2
 # BIN-NEXT:        ElemType:        FUNCREF
 # BIN-NEXT:        Limits:
 # BIN-NEXT:          Minimum:         0x0
-# BIN-NEXT:      - Index:           2
+# BIN-NEXT:      - Index:           3
 # BIN-NEXT:        ElemType:        FUNCREF
 # BIN-NEXT:        Limits:
 # BIN-NEXT:          Minimum:         0x2A
-# BIN-NEXT:      - Index:           3
+# BIN-NEXT:      - Index:           4
 # BIN-NEXT:        ElemType:        FUNCREF
 # BIN-NEXT:        Limits:
 # BIN-NEXT:          Flags:           [ HAS_MAX ]
@@ -142,39 +163,48 @@ table_fill:
 # BIN-NEXT:        Index:           3
 # BIN-NEXT:        Offset:          0x15
 # BIN-NEXT:      - Type:            R_WASM_TABLE_NUMBER_LEB
-# BIN-NEXT:        Index:           0
+# BIN-NEXT:        Index:           3
 # BIN-NEXT:        Offset:          0x20
 # BIN-NEXT:      - Type:            R_WASM_TABLE_NUMBER_LEB
+# BIN-NEXT:        Index:           3
+# BIN-NEXT:        Offset:          0x27
+# BIN-NEXT:      - Type:            R_WASM_TABLE_NUMBER_LEB
+# BIN-NEXT:        Index:           5
+# BIN-NEXT:        Offset:          0x2C
+# BIN-NEXT:      - Type:            R_WASM_TABLE_NUMBER_LEB
+# BIN-NEXT:        Index:           0
+# BIN-NEXT:        Offset:          0x37
+# BIN-NEXT:      - Type:            R_WASM_TABLE_NUMBER_LEB
 # BIN-NEXT:        Index:           0
-# BIN-NEXT:        Offset:          0x2D
+# BIN-NEXT:        Offset:          0x44
 # BIN-NEXT:      - Type:            R_WASM_TABLE_NUMBER_LEB
 # BIN-NEXT:        Index:           0
-# BIN-NEXT:        Offset:          0x38
+# BIN-NEXT:        Offset:          0x4F
 # BIN-NEXT:      - Type:            R_WASM_TABLE_NUMBER_LEB
 # BIN-NEXT:        Index:           0
-# BIN-NEXT:        Offset:          0x41
+# BIN-NEXT:        Offset:          0x58
 # BIN-NEXT:      - Type:            R_WASM_TABLE_NUMBER_LEB
 # BIN-NEXT:        Index:           2
-# BIN-NEXT:        Offset:          0x51
+# BIN-NEXT:        Offset:          0x68
 # BIN-NEXT:      - Type:            R_WASM_TABLE_NUMBER_LEB
 # BIN-NEXT:        Index:           2
-# BIN-NEXT:        Offset:          0x5A
+# BIN-NEXT:        Offset:          0x71
 # BIN-NEXT:    Functions:
 # BIN-NEXT:      - Index:           0
 # BIN-NEXT:        Locals:          []
-# BIN-NEXT:        Body:            20002001FC108280808000FC0E828080800083808080000B
+# BIN-NEXT:        Body:            20002001FC108380808000FC0E8380808000848080800020002001FC108480808000FC0E848080800080808080000B
 # BIN-NEXT:      - Index:           1
 # BIN-NEXT:        Locals:          []
-# BIN-NEXT:        Body:            20002580808080000B
+# BIN-NEXT:        Body:            20002581808080000B
 # BIN-NEXT:      - Index:           2
 # BIN-NEXT:        Locals:          []
-# BIN-NEXT:        Body:            200020012680808080000B
+# BIN-NEXT:        Body:            200020012681808080000B
 # BIN-NEXT:      - Index:           3
 # BIN-NEXT:        Locals:          []
-# BIN-NEXT:        Body:            41002580808080002000FC0F808080800020006A0B
+# BIN-NEXT:        Body:            41002581808080002000FC0F818080800020006A0B
 # BIN-NEXT:      - Index:           4
 # BIN-NEXT:        Locals:          []
-# BIN-NEXT:        Body:            200041002582808080002001FC1182808080000B
+# BIN-NEXT:        Body:            200041002583808080002001FC1183808080000B
 
 #      BIN:  - Type:            CUSTOM
 # BIN-NEXT:    Name:            linking
@@ -184,20 +214,25 @@ table_fill:
 # BIN-NEXT:        Kind:            TABLE
 # BIN-NEXT:        Name:            foo
 # BIN-NEXT:        Flags:           [ BINDING_LOCAL ]
-# BIN-NEXT:        Table:           0
+# BIN-NEXT:        Table:           1
 # BIN-NEXT:      - Index:           1
 # BIN-NEXT:        Kind:            TABLE
 # BIN-NEXT:        Name:            bar
 # BIN-NEXT:        Flags:           [ BINDING_LOCAL ]
-# BIN-NEXT:        Table:           1
+# BIN-NEXT:        Table:           2
 # BIN-NEXT:      - Index:           2
 # BIN-NEXT:        Kind:            TABLE
 # BIN-NEXT:        Name:            table1
 # BIN-NEXT:        Flags:           [ BINDING_LOCAL ]
-# BIN-NEXT:        Table:           2
+# BIN-NEXT:        Table:           3
 # BIN-NEXT:      - Index:           3
 # BIN-NEXT:        Kind:            TABLE
 # BIN-NEXT:        Name:            table2
 # BIN-NEXT:        Flags:           [ BINDING_LOCAL ]
-# BIN-NEXT:        Table:           3
-# BIN-NEXT:      - Index:           4
+# BIN-NEXT:        Table:           4
+#      BIN:      - Index:           5
+# BIN-NEXT:        Kind:            TABLE
+# BIN-NEXT:        Name:            table3
+# BIN-NEXT:        Flags:           [ UNDEFINED, EXPLICIT_NAME ]
+# BIN-NEXT:        Table:           0
+# BIN-NEXT:      - Index:           6

>From 390205316fa45e65bcdbdaf51579bc01a626e3dc Mon Sep 17 00:00:00 2001
From: daxpedda <daxpedda at gmail.com>
Date: Sun, 21 Dec 2025 07:27:49 +0100
Subject: [PATCH 2/2] Fix minimum size of `__indirect_function_table`

---
 llvm/lib/MC/WasmObjectWriter.cpp | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index f0ad3bf97a2b4..bdcc5aa2b05aa 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -1850,6 +1850,15 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
       HandleReloc(RelEntry);
     for (const WasmRelocationEntry &RelEntry : DataRelocations)
       HandleReloc(RelEntry);
+
+    // Update minimum size of `__indirect_function_table` table.
+    auto It = llvm::find_if(Imports, [](const wasm::WasmImport &I) {
+      return I.Field == "__indirect_function_table";
+    });
+
+    if (It != Imports.end()) {
+      It->Table.Limits.Minimum = TableElems.size();
+    }
   }
 
   // Translate .init_array section contents into start functions.



More information about the llvm-commits mailing list