[llvm] [llvm-readobj] [ARMWinEH] Fix printing of packed unwind with H=1, RegI=RegF=0, CR!=1 (PR #170294)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 2 11:51:45 PST 2025
Martin =?utf-8?q?Storsjö?= <martin at martin.st>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/170294 at github.com>
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-binary-utilities
Author: Martin Storsjö (mstorsjo)
<details>
<summary>Changes</summary>
In these cases, there are no other GPRs or float registers that would have been backed up before the register homing area, that would have allocated space on the stack for the saved registers.
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, there's no space to store them in. The previous printout, printing "stp x0, x1, [sp, #-N]!" wouldn't work when interpreted as 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).
---
Full diff: https://github.com/llvm/llvm-project/pull/170294.diff
2 Files Affected:
- (modified) llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s (+38-5)
- (modified) llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp (+8-9)
``````````diff
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..489d385468b70 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,37 @@
// 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: 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
@@ -296,6 +323,8 @@ func13:
func14:
func15:
func16:
+func17:
+func18:
ret
.section .pdata,"dr"
@@ -331,3 +360,7 @@ 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
+ .long func18 at IMGREL
+ .long 0x10f0002d // 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--) {
``````````
</details>
https://github.com/llvm/llvm-project/pull/170294
More information about the llvm-commits
mailing list