[llvm] [WebAssembly] Support multiple `.init_array` fragments when writing Wasm objects (PR #111008)

George Stagg via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 6 06:14:46 PST 2024


https://github.com/georgestagg updated https://github.com/llvm/llvm-project/pull/111008

>From 8266ca5900fe1b2013f108784fbdf94b001fd5cd Mon Sep 17 00:00:00 2001
From: George Stagg <george.stagg at posit.co>
Date: Thu, 3 Oct 2024 15:25:43 +0100
Subject: [PATCH 1/3] WasmObjectWriter: Support multiple .init_array section
 fragments

---
 llvm/lib/MC/WasmObjectWriter.cpp       | 94 ++++++++++++++------------
 llvm/test/MC/WebAssembly/init-array.ll | 56 +++++++++++++++
 2 files changed, 108 insertions(+), 42 deletions(-)
 create mode 100644 llvm/test/MC/WebAssembly/init-array.ll

diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index f25dc92fa235a2..034e058690744a 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -1769,6 +1769,11 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
       WS.setIndex(InvalidIndex);
       continue;
     }
+    // Contents of .init_array sections are handled elsewhere.
+    if (WS.isDefined() &&
+        WS.getSection().getName().starts_with(".init_array")) {
+      continue;
+    }
     LLVM_DEBUG(dbgs() << "adding to symtab: " << WS << "\n");
 
     uint32_t Flags = 0;
@@ -1853,49 +1858,54 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
     if (EmptyFrag.getKind() != MCFragment::FT_Data)
       report_fatal_error(".init_array section should be aligned");
 
-    const MCFragment &AlignFrag = *EmptyFrag.getNext();
-    if (AlignFrag.getKind() != MCFragment::FT_Align)
-      report_fatal_error(".init_array section should be aligned");
-    if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
-        Align(is64Bit() ? 8 : 4))
-      report_fatal_error(".init_array section should be aligned for pointers");
-
-    const MCFragment &Frag = *AlignFrag.getNext();
-    if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
-      report_fatal_error("only data supported in .init_array section");
-
-    uint16_t Priority = UINT16_MAX;
-    unsigned PrefixLength = strlen(".init_array");
-    if (WS.getName().size() > PrefixLength) {
-      if (WS.getName()[PrefixLength] != '.')
+    const MCFragment *nextFrag = EmptyFrag.getNext();
+    while (nextFrag != nullptr) {
+      const MCFragment &AlignFrag = *nextFrag;
+      if (AlignFrag.getKind() != MCFragment::FT_Align)
+        report_fatal_error(".init_array section should be aligned");
+      if (cast<MCAlignFragment>(AlignFrag).getAlignment() !=
+          Align(is64Bit() ? 8 : 4))
         report_fatal_error(
-            ".init_array section priority should start with '.'");
-      if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
-        report_fatal_error("invalid .init_array section priority");
-    }
-    const auto &DataFrag = cast<MCDataFragment>(Frag);
-    const SmallVectorImpl<char> &Contents = DataFrag.getContents();
-    for (const uint8_t *
-             P = (const uint8_t *)Contents.data(),
-            *End = (const uint8_t *)Contents.data() + Contents.size();
-         P != End; ++P) {
-      if (*P != 0)
-        report_fatal_error("non-symbolic data in .init_array section");
-    }
-    for (const MCFixup &Fixup : DataFrag.getFixups()) {
-      assert(Fixup.getKind() ==
-             MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
-      const MCExpr *Expr = Fixup.getValue();
-      auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
-      if (!SymRef)
-        report_fatal_error("fixups in .init_array should be symbol references");
-      const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
-      if (TargetSym.getIndex() == InvalidIndex)
-        report_fatal_error("symbols in .init_array should exist in symtab");
-      if (!TargetSym.isFunction())
-        report_fatal_error("symbols in .init_array should be for functions");
-      InitFuncs.push_back(
-          std::make_pair(Priority, TargetSym.getIndex()));
+            ".init_array section should be aligned for pointers");
+
+      const MCFragment &Frag = *AlignFrag.getNext();
+      nextFrag = Frag.getNext();
+      if (Frag.hasInstructions() || Frag.getKind() != MCFragment::FT_Data)
+        report_fatal_error("only data supported in .init_array section");
+
+      uint16_t Priority = UINT16_MAX;
+      unsigned PrefixLength = strlen(".init_array");
+      if (WS.getName().size() > PrefixLength) {
+        if (WS.getName()[PrefixLength] != '.')
+          report_fatal_error(
+              ".init_array section priority should start with '.'");
+        if (WS.getName().substr(PrefixLength + 1).getAsInteger(10, Priority))
+          report_fatal_error("invalid .init_array section priority");
+      }
+      const auto &DataFrag = cast<MCDataFragment>(Frag);
+      const SmallVectorImpl<char> &Contents = DataFrag.getContents();
+      for (const uint8_t *
+               P = (const uint8_t *)Contents.data(),
+              *End = (const uint8_t *)Contents.data() + Contents.size();
+           P != End; ++P) {
+        if (*P != 0)
+          report_fatal_error("non-symbolic data in .init_array section");
+      }
+      for (const MCFixup &Fixup : DataFrag.getFixups()) {
+        assert(Fixup.getKind() ==
+               MCFixup::getKindForSize(is64Bit() ? 8 : 4, false));
+        const MCExpr *Expr = Fixup.getValue();
+        auto *SymRef = dyn_cast<MCSymbolRefExpr>(Expr);
+        if (!SymRef)
+          report_fatal_error(
+              "fixups in .init_array should be symbol references");
+        const auto &TargetSym = cast<const MCSymbolWasm>(SymRef->getSymbol());
+        if (TargetSym.getIndex() == InvalidIndex)
+          report_fatal_error("symbols in .init_array should exist in symtab");
+        if (!TargetSym.isFunction())
+          report_fatal_error("symbols in .init_array should be for functions");
+        InitFuncs.push_back(std::make_pair(Priority, TargetSym.getIndex()));
+      }
     }
   }
 
diff --git a/llvm/test/MC/WebAssembly/init-array.ll b/llvm/test/MC/WebAssembly/init-array.ll
new file mode 100644
index 00000000000000..d19ddcf10d5d9c
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/init-array.ll
@@ -0,0 +1,56 @@
+; RUN: llc -mcpu=mvp -filetype=obj %s -o - | obj2yaml | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+ at p_init1 = hidden global ptr @init1, section ".init_array", align 4
+ at p_init2 = hidden global ptr @init2, section ".init_array", align 4
+
+define hidden void @init1() #0 { ret void }
+define hidden void @init2() #0 { ret void }
+
+
+; CHECK:        - Type:            IMPORT
+; CHECK-NEXT:     Imports:
+; CHECK-NEXT:       - Module:          env
+; CHECK-NEXT:         Field:           __linear_memory
+; CHECK-NEXT:         Kind:            MEMORY
+; CHECK-NEXT:         Memory:
+; CHECK-NEXT:           Minimum:         0x0
+; 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:         0x0
+; CHECK-NEXT:   - Type:            FUNCTION
+; CHECK-NEXT:     FunctionTypes:   [ 0, 0 ]
+; CHECK-NEXT:   - Type:            CODE
+; CHECK-NEXT:     Functions:
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         Locals:          []
+; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:       - Index:           1
+; CHECK-NEXT:         Locals:          []
+; CHECK-NEXT:         Body:            0B
+; CHECK-NEXT:    - Type:            CUSTOM
+; CHECK-NEXT:      Name:            linking
+; CHECK-NEXT:      Version:         2
+; CHECK-NEXT:      SymbolTable:
+; CHECK-NEXT:        - Index:           0
+; CHECK-NEXT:          Kind:            FUNCTION
+; CHECK-NEXT:          Name:            init1
+; CHECK-NEXT:          Flags:           [ VISIBILITY_HIDDEN ]
+; CHECK-NEXT:          Function:        0
+; CHECK-NEXT:        - Index:           1
+; CHECK-NEXT:          Kind:            FUNCTION
+; CHECK-NEXT:          Name:            init2
+; CHECK-NEXT:          Flags:           [ VISIBILITY_HIDDEN ]
+; CHECK-NEXT:          Function:        1
+; CHECK-NEXT:      InitFunctions:
+; CHECK-NEXT:        - Priority:        65535
+; CHECK-NEXT:          Symbol:          0
+; CHECK-NEXT:        - Priority:        65535
+; CHECK-NEXT:          Symbol:          1
+; CHECK-NEXT: ...

>From ffbc5e1bdfe7186ff4f64d436a8536bee494e26f Mon Sep 17 00:00:00 2001
From: George Stagg <george.stagg at posit.co>
Date: Wed, 6 Nov 2024 10:02:15 +0000
Subject: [PATCH 2/3] Switch init-array test to assembly format

---
 llvm/test/MC/WebAssembly/init-array.ll | 56 --------------------------
 llvm/test/MC/WebAssembly/init-array.s  | 49 ++++++++++++++++++++++
 2 files changed, 49 insertions(+), 56 deletions(-)
 delete mode 100644 llvm/test/MC/WebAssembly/init-array.ll
 create mode 100644 llvm/test/MC/WebAssembly/init-array.s

diff --git a/llvm/test/MC/WebAssembly/init-array.ll b/llvm/test/MC/WebAssembly/init-array.ll
deleted file mode 100644
index d19ddcf10d5d9c..00000000000000
--- a/llvm/test/MC/WebAssembly/init-array.ll
+++ /dev/null
@@ -1,56 +0,0 @@
-; RUN: llc -mcpu=mvp -filetype=obj %s -o - | obj2yaml | FileCheck %s
-
-target triple = "wasm32-unknown-unknown"
-
- at p_init1 = hidden global ptr @init1, section ".init_array", align 4
- at p_init2 = hidden global ptr @init2, section ".init_array", align 4
-
-define hidden void @init1() #0 { ret void }
-define hidden void @init2() #0 { ret void }
-
-
-; CHECK:        - Type:            IMPORT
-; CHECK-NEXT:     Imports:
-; CHECK-NEXT:       - Module:          env
-; CHECK-NEXT:         Field:           __linear_memory
-; CHECK-NEXT:         Kind:            MEMORY
-; CHECK-NEXT:         Memory:
-; CHECK-NEXT:           Minimum:         0x0
-; 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:         0x0
-; CHECK-NEXT:   - Type:            FUNCTION
-; CHECK-NEXT:     FunctionTypes:   [ 0, 0 ]
-; CHECK-NEXT:   - Type:            CODE
-; CHECK-NEXT:     Functions:
-; CHECK-NEXT:       - Index:           0
-; CHECK-NEXT:         Locals:          []
-; CHECK-NEXT:         Body:            0B
-; CHECK-NEXT:       - Index:           1
-; CHECK-NEXT:         Locals:          []
-; CHECK-NEXT:         Body:            0B
-; CHECK-NEXT:    - Type:            CUSTOM
-; CHECK-NEXT:      Name:            linking
-; CHECK-NEXT:      Version:         2
-; CHECK-NEXT:      SymbolTable:
-; CHECK-NEXT:        - Index:           0
-; CHECK-NEXT:          Kind:            FUNCTION
-; CHECK-NEXT:          Name:            init1
-; CHECK-NEXT:          Flags:           [ VISIBILITY_HIDDEN ]
-; CHECK-NEXT:          Function:        0
-; CHECK-NEXT:        - Index:           1
-; CHECK-NEXT:          Kind:            FUNCTION
-; CHECK-NEXT:          Name:            init2
-; CHECK-NEXT:          Flags:           [ VISIBILITY_HIDDEN ]
-; CHECK-NEXT:          Function:        1
-; CHECK-NEXT:      InitFunctions:
-; CHECK-NEXT:        - Priority:        65535
-; CHECK-NEXT:          Symbol:          0
-; CHECK-NEXT:        - Priority:        65535
-; CHECK-NEXT:          Symbol:          1
-; CHECK-NEXT: ...
diff --git a/llvm/test/MC/WebAssembly/init-array.s b/llvm/test/MC/WebAssembly/init-array.s
new file mode 100644
index 00000000000000..e79fb453ec12a3
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/init-array.s
@@ -0,0 +1,49 @@
+# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj < %s | obj2yaml | FileCheck %s
+
+init1:
+	.functype	init1 () -> ()
+	end_function
+
+init2:
+	.functype	init2 () -> ()
+	end_function
+
+	.section	.init_array,"",@
+	.p2align	2, 0
+	.int32	init1
+
+	.section	.init_array,"",@
+	.p2align	2
+	.int32	init2
+
+# CHECK:        - Type:            FUNCTION
+# CHECK-NEXT:     FunctionTypes:   [ 0, 0 ]
+# CHECK-NEXT:   - Type:            CODE
+# CHECK-NEXT:     Functions:
+# CHECK-NEXT:       - Index:           0
+# CHECK-NEXT:         Locals:          []
+# CHECK-NEXT:         Body:            0B
+# CHECK-NEXT:       - Index:           1
+# CHECK-NEXT:         Locals:          []
+# CHECK-NEXT:         Body:            0B
+# CHECK-NEXT:   - Type:            CUSTOM
+# CHECK-NEXT:     Name:            linking
+# CHECK-NEXT:     Version:         2
+# CHECK-NEXT:     SymbolTable:
+# CHECK-NEXT:       - Index:           0
+# CHECK-NEXT:         Kind:            FUNCTION
+# CHECK-NEXT:         Name:            init1
+# CHECK-NEXT:         Flags:           [ BINDING_LOCAL ]
+# CHECK-NEXT:         Function:        0
+# CHECK-NEXT:       - Index:           1
+# CHECK-NEXT:         Kind:            FUNCTION
+# CHECK-NEXT:         Name:            init2
+# CHECK-NEXT:         Flags:           [ BINDING_LOCAL ]
+# CHECK-NEXT:         Function:        1
+# CHECK-NEXT:     InitFunctions:
+# CHECK-NEXT:       - Priority:        65535
+# CHECK-NEXT:         Symbol:          0
+# CHECK-NEXT:       - Priority:        65535
+# CHECK-NEXT:         Symbol:          1
+# CHECK-NEXT: ...
+#

>From 783024ec224acf7bfb39fc373406865f29ff1cb1 Mon Sep 17 00:00:00 2001
From: George Stagg <george.stagg at posit.co>
Date: Wed, 6 Nov 2024 13:59:49 +0000
Subject: [PATCH 3/3] Skip only data symbols in .init_array

---
 llvm/lib/MC/WasmObjectWriter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index 034e058690744a..ee7ffffaf7781f 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -1770,7 +1770,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
       continue;
     }
     // Contents of .init_array sections are handled elsewhere.
-    if (WS.isDefined() &&
+    if (WS.isDefined() && WS.isData() &&
         WS.getSection().getName().starts_with(".init_array")) {
       continue;
     }



More information about the llvm-commits mailing list