Skip to content

Commit 1ca763b

Browse files
authored
[llvm-readobj] [ARMWinEH] Fix printing of packed unwind with H=1, RegI=RegF=0, CR!=1 (#170294)
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).
1 parent 6822e3c commit 1ca763b

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

llvm/test/tools/llvm-readobj/COFF/arm64-packed-unwind.s

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,7 @@
105105
// CHECK-NEXT: CR: 0
106106
// CHECK-NEXT: FrameSize: 112
107107
// CHECK-NEXT: Prologue [
108-
// CHECK-NEXT: sub sp, sp, #48
109-
// CHECK-NEXT: stp x6, x7, [sp, #48]
110-
// CHECK-NEXT: stp x4, x5, [sp, #32]
111-
// CHECK-NEXT: stp x2, x3, [sp, #16]
112-
// CHECK-NEXT: stp x0, x1, [sp, #-64]!
108+
// CHECK-NEXT: sub sp, sp, #112
113109
// CHECK-NEXT: end
114110
// CHECK-NEXT: ]
115111
// CHECK-NEXT: }
@@ -276,6 +272,37 @@
276272
// CHECK-NEXT: end
277273
// CHECK-NEXT: ]
278274
// CHECK-NEXT: }
275+
// CHECK-NEXT: RuntimeFunction {
276+
// CHECK-NEXT: Function: func17
277+
// CHECK-NEXT: Fragment: No
278+
// CHECK-NEXT: FunctionLength: 44
279+
// CHECK-NEXT: RegF: 0
280+
// CHECK-NEXT: RegI: 0
281+
// CHECK-NEXT: HomedParameters: Yes
282+
// CHECK-NEXT: CR: 3
283+
// CHECK-NEXT: FrameSize: 96
284+
// CHECK-NEXT: Prologue [
285+
// CHECK-NEXT: mov x29, sp
286+
// CHECK-NEXT: stp x29, lr, [sp, #-96]!
287+
// CHECK-NEXT: end
288+
// CHECK-NEXT: ]
289+
// CHECK-NEXT: }
290+
// CHECK-NEXT: RuntimeFunction {
291+
// CHECK-NEXT: Function: func18
292+
// CHECK-NEXT: Fragment: No
293+
// CHECK-NEXT: FunctionLength: 44
294+
// CHECK-NEXT: RegF: 0
295+
// CHECK-NEXT: RegI: 0
296+
// CHECK-NEXT: HomedParameters: Yes
297+
// CHECK-NEXT: CR: 3
298+
// CHECK-NEXT: FrameSize: 528
299+
// CHECK-NEXT: Prologue [
300+
// CHECK-NEXT: mov x29, sp
301+
// CHECK-NEXT: stp x29, lr, [sp, #0]
302+
// CHECK-NEXT: sub sp, sp, #528
303+
// CHECK-NEXT: end
304+
// CHECK-NEXT: ]
305+
// CHECK-NEXT: }
279306
// CHECK-NEXT: ]
280307

281308
.text
@@ -296,6 +323,8 @@ func13:
296323
func14:
297324
func15:
298325
func16:
326+
func17:
327+
func18:
299328
ret
300329

301330
.section .pdata,"dr"
@@ -331,3 +360,7 @@ func16:
331360
.long 0x11820019 // FunctionLength=6 RegF=0 RegI=2 H=0 CR=0 FrameSize=34
332361
.long func16@IMGREL
333362
.long 0x03b00039 // FunctionLength=14 RegF=0 RegI=0 H=1 CR=1 FrameSize=7
363+
.long func17@IMGREL
364+
.long 0x0370002d // FunctionLength=11 RegF=0 RegI=0 H=1 CR=3 FrameSize=6
365+
.long func18@IMGREL
366+
.long 0x10f0002d // FunctionLength=11 RegF=0 RegI=0 H=1 CR=3 FrameSize=6

llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,12 @@ bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF,
14041404
FpSZ += 8;
14051405
int SavSZ = (IntSZ + FpSZ + 8 * 8 * RF.H() + 0xf) & ~0xf;
14061406
int LocSZ = (RF.FrameSize() << 4) - SavSZ;
1407+
bool Homing = RF.H();
1408+
1409+
if (RF.H() && RF.RegI() == 0 && RF.RegF() == 0 && RF.CR() != 1) {
1410+
LocSZ += SavSZ;
1411+
Homing = false;
1412+
}
14071413

14081414
if (RF.CR() == 2 || RF.CR() == 3) {
14091415
SW.startLine() << "mov x29, sp\n";
@@ -1419,18 +1425,11 @@ bool Decoder::dumpPackedARM64Entry(const object::COFFObjectFile &COFF,
14191425
} else if ((RF.CR() != 3 && RF.CR() != 2 && LocSZ > 0) || LocSZ > 512) {
14201426
SW.startLine() << format("sub sp, sp, #%d\n", LocSZ);
14211427
}
1422-
if (RF.H()) {
1428+
if (Homing) {
14231429
SW.startLine() << format("stp x6, x7, [sp, #%d]\n", SavSZ - 16);
14241430
SW.startLine() << format("stp x4, x5, [sp, #%d]\n", SavSZ - 32);
14251431
SW.startLine() << format("stp x2, x3, [sp, #%d]\n", SavSZ - 48);
1426-
if (RF.RegI() > 0 || RF.RegF() > 0 || RF.CR() == 1) {
1427-
SW.startLine() << format("stp x0, x1, [sp, #%d]\n", SavSZ - 64);
1428-
} else {
1429-
// This case isn't documented; if neither RegI nor RegF nor CR=1
1430-
// have decremented the stack pointer by SavSZ, we need to do it here
1431-
// (as the final stack adjustment of LocSZ excludes SavSZ).
1432-
SW.startLine() << format("stp x0, x1, [sp, #-%d]!\n", SavSZ);
1433-
}
1432+
SW.startLine() << format("stp x0, x1, [sp, #%d]\n", SavSZ - 64);
14341433
}
14351434
int FloatRegs = RF.RegF() > 0 ? RF.RegF() + 1 : 0;
14361435
for (int I = (FloatRegs + 1) / 2 - 1; I >= 0; I--) {

0 commit comments

Comments
 (0)