[llvm] [llvm-readobj] [ARMWinEH] Fix printing of packed unwind with H=1, RegI=RegF=0, CR!=1 (PR #170294)
Martin Storsjö via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 2 11:51:11 PST 2025
https://github.com/mstorsjo updated https://github.com/llvm/llvm-project/pull/170294
>From 362c71f4b5be15d63ee44cc0bfdd4d576fb4b5e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Tue, 2 Dec 2025 15:47:17 +0200
Subject: [PATCH 1/2] [llvm-readobj] [ARMWinEH] Fix printing of packed unwind
with H=1, RegI=RegF=0
In these cases, there are no other GPRs or float registers that
would have been backed up before the register homing area.
Normally, the register homing part of the prologue consists of
4 nop unwind codes. However, if we haven't allocated stack space
for those arguments yet, we can't store them. The previous
printout, printing "stp x0, x1, [sp, #-N]!" wouldn't work, as
that wouldn't work when mapped to a nop unwind code.
Based on "dumpbin -unwindinfo", and from empirical inspection
with RtlVirtualUnwind, it turns out that the homing of argument
registers is done outside of the prologue. In these cases,
"dumpbin -unwindinfo" prints an annotation "(argument registers
homed post-prolog)".
Adjust the printout accordingly. In these cases, the later
stack allocation (either "stp x29, x30, [sp, #-LocSZ]! or
"sub sp, sp, #LocSZ") is adjusted to include the space the
homed registers (i.e. be the full size from FrameSize).
---
.../llvm-readobj/COFF/arm64-packed-unwind.s | 24 +++++++++++++++----
llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp | 17 +++++++------
2 files changed, 27 insertions(+), 14 deletions(-)
diff --git a/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s b/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s
index 72e79b77a01ad..ae967f22d0c73 100644
--- a/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s
+++ b/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s
@@ -105,11 +105,7 @@
// CHECK-NEXT: CR: 0
// CHECK-NEXT: FrameSize: 112
// CHECK-NEXT: Prologue [
-// CHECK-NEXT: sub sp, sp, #48
-// CHECK-NEXT: stp x6, x7, [sp, #48]
-// CHECK-NEXT: stp x4, x5, [sp, #32]
-// CHECK-NEXT: stp x2, x3, [sp, #16]
-// CHECK-NEXT: stp x0, x1, [sp, #-64]!
+// CHECK-NEXT: sub sp, sp, #112
// CHECK-NEXT: end
// CHECK-NEXT: ]
// CHECK-NEXT: }
@@ -276,6 +272,21 @@
// CHECK-NEXT: end
// CHECK-NEXT: ]
// CHECK-NEXT: }
+// CHECK-NEXT: RuntimeFunction {
+// CHECK-NEXT: Function: func17
+// CHECK-NEXT: Fragment: No
+// CHECK-NEXT: FunctionLength: 44
+// CHECK-NEXT: RegF: 0
+// CHECK-NEXT: RegI: 0
+// CHECK-NEXT: HomedParameters: Yes
+// CHECK-NEXT: CR: 3
+// CHECK-NEXT: FrameSize: 96
+// CHECK-NEXT: Prologue [
+// CHECK-NEXT: mov x29, sp
+// CHECK-NEXT: stp x29, lr, [sp, #-96]!
+// CHECK-NEXT: end
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
// CHECK-NEXT: ]
.text
@@ -296,6 +307,7 @@ func13:
func14:
func15:
func16:
+func17:
ret
.section .pdata,"dr"
@@ -331,3 +343,5 @@ func16:
.long 0x11820019 // FunctionLength=6 RegF=0 RegI=2 H=0 CR=0 FrameSize=34
.long func16 at IMGREL
.long 0x03b00039 // FunctionLength=14 RegF=0 RegI=0 H=1 CR=1 FrameSize=7
+ .long func17 at IMGREL
+ .long 0x0370002d // FunctionLength=11 RegF=0 RegI=0 H=1 CR=3 FrameSize=6
diff --git a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
index 3b2ea5b551117..32e3d059f44d3 100644
--- a/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -1404,6 +1404,12 @@ bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF,
FpSZ += 8;
int SavSZ = (IntSZ + FpSZ + 8 * 8 * RF.H() + 0xf) & ~0xf;
int LocSZ = (RF.FrameSize() << 4) - SavSZ;
+ bool Homing = RF.H();
+
+ if (RF.H() && RF.RegI() == 0 && RF.RegF() == 0 && RF.CR() != 1) {
+ LocSZ += SavSZ;
+ Homing = false;
+ }
if (RF.CR() == 2 || RF.CR() == 3) {
SW.startLine() << "mov x29, sp\n";
@@ -1419,18 +1425,11 @@ bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF,
} else if ((RF.CR() != 3 && RF.CR() != 2 && LocSZ > 0) || LocSZ > 512) {
SW.startLine() << format("sub sp, sp, #%d\n", LocSZ);
}
- if (RF.H()) {
+ if (Homing) {
SW.startLine() << format("stp x6, x7, [sp, #%d]\n", SavSZ - 16);
SW.startLine() << format("stp x4, x5, [sp, #%d]\n", SavSZ - 32);
SW.startLine() << format("stp x2, x3, [sp, #%d]\n", SavSZ - 48);
- if (RF.RegI() > 0 || RF.RegF() > 0 || RF.CR() == 1) {
- SW.startLine() << format("stp x0, x1, [sp, #%d]\n", SavSZ - 64);
- } else {
- // This case isn't documented; if neither RegI nor RegF nor CR=1
- // have decremented the stack pointer by SavSZ, we need to do it here
- // (as the final stack adjustment of LocSZ excludes SavSZ).
- SW.startLine() << format("stp x0, x1, [sp, #-%d]!\n", SavSZ);
- }
+ SW.startLine() << format("stp x0, x1, [sp, #%d]\n", SavSZ - 64);
}
int FloatRegs = RF.RegF() > 0 ? RF.RegF() + 1 : 0;
for (int I = (FloatRegs + 1) / 2 - 1; I >= 0; I--) {
>From ceb78b9182136ec5b5657ec17f97174ff1bb8bdf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Storsj=C3=B6?= <martin at martin.st>
Date: Tue, 2 Dec 2025 21:50:48 +0200
Subject: [PATCH 2/2] Add a testcase for FrameSize=528
---
.../llvm-readobj/COFF/arm64-packed-unwind.s | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s b/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s
index ae967f22d0c73..489d385468b70 100644
--- a/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s
+++ b/llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s
@@ -287,6 +287,22 @@
// CHECK-NEXT: end
// CHECK-NEXT: ]
// CHECK-NEXT: }
+// CHECK-NEXT: RuntimeFunction {
+// CHECK-NEXT: Function: func18
+// CHECK-NEXT: Fragment: No
+// CHECK-NEXT: FunctionLength: 44
+// CHECK-NEXT: RegF: 0
+// CHECK-NEXT: RegI: 0
+// CHECK-NEXT: HomedParameters: Yes
+// CHECK-NEXT: CR: 3
+// CHECK-NEXT: FrameSize: 528
+// CHECK-NEXT: Prologue [
+// CHECK-NEXT: mov x29, sp
+// CHECK-NEXT: stp x29, lr, [sp, #0]
+// CHECK-NEXT: sub sp, sp, #528
+// CHECK-NEXT: end
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
// CHECK-NEXT: ]
.text
@@ -308,6 +324,7 @@ func14:
func15:
func16:
func17:
+func18:
ret
.section .pdata,"dr"
@@ -345,3 +362,5 @@ func17:
.long 0x03b00039 // FunctionLength=14 RegF=0 RegI=0 H=1 CR=1 FrameSize=7
.long func17 at IMGREL
.long 0x0370002d // FunctionLength=11 RegF=0 RegI=0 H=1 CR=3 FrameSize=6
+ .long func18 at IMGREL
+ .long 0x10f0002d // FunctionLength=11 RegF=0 RegI=0 H=1 CR=3 FrameSize=6
More information about the llvm-commits
mailing list