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

release/19.x: [WebAssembly] Handle symbols in .init_array sections (#119127) #119533

Merged
merged 2 commits into from
Dec 17, 2024

Conversation

llvmbot
Copy link
Member

@llvmbot llvmbot commented Dec 11, 2024

Backport ac5dd45 ed91843

Requested by: @nikic

@llvmbot llvmbot added this to the LLVM 19.X Release milestone Dec 11, 2024
@llvmbot
Copy link
Member Author

llvmbot commented Dec 11, 2024

@sbc100 @sbc100 What do you think about merging this PR to the release branch?

@llvmbot
Copy link
Member Author

llvmbot commented Dec 11, 2024

@llvm/pr-subscribers-mc

Author: None (llvmbot)

Changes

Backport ac5dd45 ed91843

Requested by: @nikic


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

3 Files Affected:

  • (modified) llvm/lib/MC/WasmObjectWriter.cpp (+67-44)
  • (added) llvm/test/MC/WebAssembly/init-array-label.s (+91)
  • (added) llvm/test/MC/WebAssembly/init-array.s (+49)
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index f25dc92fa235a2..85264692456767 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -1326,6 +1326,22 @@ static bool isInSymtab(const MCSymbolWasm &Sym) {
   return true;
 }
 
+static bool isSectionReferenced(MCAssembler &Asm, MCSectionWasm &Section) {
+  StringRef SectionName = Section.getName();
+
+  for (const MCSymbol &S : Asm.symbols()) {
+    const auto &WS = static_cast<const MCSymbolWasm &>(S);
+    if (WS.isData() && WS.isInSection()) {
+      auto &RefSection = static_cast<MCSectionWasm &>(WS.getSection());
+      if (RefSection.getName() == SectionName) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
 void WasmObjectWriter::prepareImports(
     SmallVectorImpl<wasm::WasmImport> &Imports, MCAssembler &Asm) {
   // For now, always emit the memory import, since loads and stores are not
@@ -1482,8 +1498,10 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
     LLVM_DEBUG(dbgs() << "Processing Section " << SectionName << "  group "
                       << Section.getGroup() << "\n";);
 
-    // .init_array sections are handled specially elsewhere.
-    if (SectionName.starts_with(".init_array"))
+    // .init_array sections are handled specially elsewhere, include them in
+    // data segments if and only if referenced by a symbol.
+    if (SectionName.starts_with(".init_array") &&
+        !isSectionReferenced(Asm, Section))
       continue;
 
     // Code is handled separately
@@ -1853,49 +1871,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-label.s b/llvm/test/MC/WebAssembly/init-array-label.s
new file mode 100644
index 00000000000000..0b4a5ea2da0b59
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/init-array-label.s
@@ -0,0 +1,91 @@
+# 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.42,"",@
+	.p2align	2, 0x0
+	.int32	init1
+
+	.section	.init_array,"",@
+	.globl	p_init1
+	.p2align	2, 0x0
+p_init1:
+	.int32	init1
+	.size	p_init1, 4
+
+	.section	.init_array,"",@
+	.globl	p_init2
+	.p2align	2, 0x0
+p_init2:
+	.int32	init1
+	.int32	init2
+	.size	p_init2, 8
+
+# CHECK:        - Type:            FUNCTION
+# CHECK-NEXT:     FunctionTypes:   [ 0, 0 ]
+# CHECK-NEXT:   - Type:            DATACOUNT
+# CHECK-NEXT:     Count:           1
+# 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:            DATA
+# CHECK-NEXT:     Segments:
+# CHECK-NEXT:       - SectionOffset:   6
+# CHECK-NEXT:         InitFlags:       0
+# CHECK-NEXT:         Offset:
+# CHECK-NEXT:           Opcode:          I32_CONST
+# CHECK-NEXT:           Value:           0
+# CHECK-NEXT:         Content:         '000000000000000000000000'
+# 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:       - Index:           2
+# CHECK-NEXT:         Kind:            DATA
+# CHECK-NEXT:         Name:            p_init1
+# CHECK-NEXT:         Flags:           [  ]
+# CHECK-NEXT:         Segment:         0
+# CHECK-NEXT:         Size:            4
+# CHECK-NEXT:       - Index:           3
+# CHECK-NEXT:         Kind:            DATA
+# CHECK-NEXT:         Name:            p_init2
+# CHECK-NEXT:         Flags:           [  ]
+# CHECK-NEXT:         Segment:         0
+# CHECK-NEXT:         Offset:          4
+# CHECK-NEXT:         Size:            8
+# CHECK-NEXT:     SegmentInfo:
+# CHECK-NEXT:       - Index:           0
+# CHECK-NEXT:         Name:            .init_array
+# CHECK-NEXT:         Alignment:       2
+# CHECK-NEXT:         Flags:           [  ]
+# CHECK-NEXT:     InitFunctions:
+# CHECK-NEXT:       - Priority:        42
+# CHECK-NEXT:         Symbol:          0
+# CHECK-NEXT:       - Priority:        65535
+# CHECK-NEXT:         Symbol:          0
+# 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: ...
+#

@llvmbot
Copy link
Member Author

llvmbot commented Dec 11, 2024

@llvm/pr-subscribers-backend-webassembly

Author: None (llvmbot)

Changes

Backport ac5dd45 ed91843

Requested by: @nikic


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

3 Files Affected:

  • (modified) llvm/lib/MC/WasmObjectWriter.cpp (+67-44)
  • (added) llvm/test/MC/WebAssembly/init-array-label.s (+91)
  • (added) llvm/test/MC/WebAssembly/init-array.s (+49)
diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index f25dc92fa235a2..85264692456767 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -1326,6 +1326,22 @@ static bool isInSymtab(const MCSymbolWasm &Sym) {
   return true;
 }
 
+static bool isSectionReferenced(MCAssembler &Asm, MCSectionWasm &Section) {
+  StringRef SectionName = Section.getName();
+
+  for (const MCSymbol &S : Asm.symbols()) {
+    const auto &WS = static_cast<const MCSymbolWasm &>(S);
+    if (WS.isData() && WS.isInSection()) {
+      auto &RefSection = static_cast<MCSectionWasm &>(WS.getSection());
+      if (RefSection.getName() == SectionName) {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
 void WasmObjectWriter::prepareImports(
     SmallVectorImpl<wasm::WasmImport> &Imports, MCAssembler &Asm) {
   // For now, always emit the memory import, since loads and stores are not
@@ -1482,8 +1498,10 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
     LLVM_DEBUG(dbgs() << "Processing Section " << SectionName << "  group "
                       << Section.getGroup() << "\n";);
 
-    // .init_array sections are handled specially elsewhere.
-    if (SectionName.starts_with(".init_array"))
+    // .init_array sections are handled specially elsewhere, include them in
+    // data segments if and only if referenced by a symbol.
+    if (SectionName.starts_with(".init_array") &&
+        !isSectionReferenced(Asm, Section))
       continue;
 
     // Code is handled separately
@@ -1853,49 +1871,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-label.s b/llvm/test/MC/WebAssembly/init-array-label.s
new file mode 100644
index 00000000000000..0b4a5ea2da0b59
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/init-array-label.s
@@ -0,0 +1,91 @@
+# 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.42,"",@
+	.p2align	2, 0x0
+	.int32	init1
+
+	.section	.init_array,"",@
+	.globl	p_init1
+	.p2align	2, 0x0
+p_init1:
+	.int32	init1
+	.size	p_init1, 4
+
+	.section	.init_array,"",@
+	.globl	p_init2
+	.p2align	2, 0x0
+p_init2:
+	.int32	init1
+	.int32	init2
+	.size	p_init2, 8
+
+# CHECK:        - Type:            FUNCTION
+# CHECK-NEXT:     FunctionTypes:   [ 0, 0 ]
+# CHECK-NEXT:   - Type:            DATACOUNT
+# CHECK-NEXT:     Count:           1
+# 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:            DATA
+# CHECK-NEXT:     Segments:
+# CHECK-NEXT:       - SectionOffset:   6
+# CHECK-NEXT:         InitFlags:       0
+# CHECK-NEXT:         Offset:
+# CHECK-NEXT:           Opcode:          I32_CONST
+# CHECK-NEXT:           Value:           0
+# CHECK-NEXT:         Content:         '000000000000000000000000'
+# 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:       - Index:           2
+# CHECK-NEXT:         Kind:            DATA
+# CHECK-NEXT:         Name:            p_init1
+# CHECK-NEXT:         Flags:           [  ]
+# CHECK-NEXT:         Segment:         0
+# CHECK-NEXT:         Size:            4
+# CHECK-NEXT:       - Index:           3
+# CHECK-NEXT:         Kind:            DATA
+# CHECK-NEXT:         Name:            p_init2
+# CHECK-NEXT:         Flags:           [  ]
+# CHECK-NEXT:         Segment:         0
+# CHECK-NEXT:         Offset:          4
+# CHECK-NEXT:         Size:            8
+# CHECK-NEXT:     SegmentInfo:
+# CHECK-NEXT:       - Index:           0
+# CHECK-NEXT:         Name:            .init_array
+# CHECK-NEXT:         Alignment:       2
+# CHECK-NEXT:         Flags:           [  ]
+# CHECK-NEXT:     InitFunctions:
+# CHECK-NEXT:       - Priority:        42
+# CHECK-NEXT:         Symbol:          0
+# CHECK-NEXT:       - Priority:        65535
+# CHECK-NEXT:         Symbol:          0
+# 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: ...
+#

Copy link
Collaborator

@sbc100 sbc100 left a comment

Choose a reason for hiding this comment

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

LGTM if tests pass

@tru tru merged commit 8e9465b into llvm:release/19.x Dec 17, 2024
9 of 11 checks passed
Copy link

@nikic (or anyone else). If you would like to add a note about this fix in the release notes (completely optional). Please reply to this comment with a one or two sentence description of the fix. When you are done, please add the release:note label to this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:WebAssembly mc Machine (object) code
Projects
Development

Successfully merging this pull request may close these issues.

4 participants