[llvm] afa6bb6 - [MC] [Win64EH] Generate ARM64 packed unwind info with signed return addresses
Martin Storsjö via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 12 01:07:52 PDT 2022
Author: Martin Storsjö
Date: 2022-10-12T11:07:12+03:00
New Revision: afa6bb643fd4a691262f407c3ed477c5cb293529
URL: https://github.com/llvm/llvm-project/commit/afa6bb643fd4a691262f407c3ed477c5cb293529
DIFF: https://github.com/llvm/llvm-project/commit/afa6bb643fd4a691262f407c3ed477c5cb293529.diff
LOG: [MC] [Win64EH] Generate ARM64 packed unwind info with signed return addresses
Differential Revision: https://reviews.llvm.org/D135660
Added:
Modified:
llvm/lib/MC/MCWin64EH.cpp
llvm/test/MC/AArch64/seh-packed-unwind.s
Removed:
################################################################################
diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp
index f39383ed3eb7..d2afb9cf0329 100644
--- a/llvm/lib/MC/MCWin64EH.cpp
+++ b/llvm/lib/MC/MCWin64EH.cpp
@@ -734,6 +734,7 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
enum {
Start,
Start2,
+ Start3,
IntRegs,
FloatRegs,
InputArgs,
@@ -742,6 +743,7 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
End
} Location = Start;
bool StandaloneLR = false, FPLRPair = false;
+ bool PAC = false;
int StackOffset = 0;
int Nops = 0;
// Iterate over the prolog and check that all opcodes exactly match
@@ -757,15 +759,21 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
return false;
Location = Start2;
break;
- case Win64EH::UOP_SaveR19R20X:
+ case Win64EH::UOP_PACSignReturnAddress:
if (Location != Start2)
return false;
+ PAC = true;
+ Location = Start3;
+ break;
+ case Win64EH::UOP_SaveR19R20X:
+ if (Location != Start2 && Location != Start3)
+ return false;
Predecrement = Inst.Offset;
RegI = 2;
Location = IntRegs;
break;
case Win64EH::UOP_SaveRegX:
- if (Location != Start2)
+ if (Location != Start2 && Location != Start3)
return false;
Predecrement = Inst.Offset;
if (Inst.Register == 19)
@@ -828,7 +836,7 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
Location = InputArgs;
break;
case Win64EH::UOP_SaveFRegPX:
- if (Location != Start2 || Inst.Register != 8)
+ if ((Location != Start2 && Location != Start3) || Inst.Register != 8)
return false;
Predecrement = Inst.Offset;
RegF = 2;
@@ -858,8 +866,9 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
break;
case Win64EH::UOP_AllocSmall:
case Win64EH::UOP_AllocMedium:
- if (Location != Start2 && Location != IntRegs && Location != FloatRegs &&
- Location != InputArgs && Location != StackAdjust)
+ if (Location != Start2 && Location != Start3 && Location != IntRegs &&
+ Location != FloatRegs && Location != InputArgs &&
+ Location != StackAdjust)
return false;
// Can have either a single decrement, or a pair of decrements with
// 4080 and another decrement.
@@ -874,8 +883,8 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
case Win64EH::UOP_SaveFPLRX:
// Not allowing FPLRX after StackAdjust; if a StackAdjust is used, it
// should be followed by a FPLR instead.
- if (Location != Start2 && Location != IntRegs && Location != FloatRegs &&
- Location != InputArgs)
+ if (Location != Start2 && Location != Start3 && Location != IntRegs &&
+ Location != FloatRegs && Location != InputArgs)
return false;
StackOffset = Inst.Offset;
Location = FrameRecord;
@@ -903,6 +912,8 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
return false;
if (Nops != 0 && Nops != 4)
return false;
+ if (PAC && !FPLRPair)
+ return false;
int H = Nops == 4;
// There's an inconsistency regarding packed unwind info with homed
// parameters; according to the documentation, the epilog shouldn't have
@@ -933,7 +944,7 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
RegF--; // Convert from actual number of registers, to value stored
assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
int Flag = 0x01; // Function segments not supported yet
- int CR = FPLRPair ? 3 : StandaloneLR ? 1 : 0;
+ int CR = PAC ? 2 : FPLRPair ? 3 : StandaloneLR ? 1 : 0;
info->PackedInfo |= Flag << 0;
info->PackedInfo |= (FuncLength & 0x7FF) << 2;
info->PackedInfo |= (RegF & 0x7) << 13;
diff --git a/llvm/test/MC/AArch64/seh-packed-unwind.s b/llvm/test/MC/AArch64/seh-packed-unwind.s
index a27792c17577..4276c7fb4ff4 100644
--- a/llvm/test/MC/AArch64/seh-packed-unwind.s
+++ b/llvm/test/MC/AArch64/seh-packed-unwind.s
@@ -243,6 +243,58 @@
// CHECK-NEXT: end
// CHECK-NEXT: ]
// CHECK-NEXT: }
+// CHECK-NEXT: RuntimeFunction {
+// CHECK-NEXT: Function: func16
+// CHECK-NEXT: Fragment: No
+// CHECK-NEXT: FunctionLength: 28
+// CHECK-NEXT: RegF: 0
+// CHECK-NEXT: RegI: 0
+// CHECK-NEXT: HomedParameters: No
+// CHECK-NEXT: CR: 2
+// CHECK-NEXT: FrameSize: 32
+// CHECK-NEXT: Prologue [
+// CHECK-NEXT: mov x29, sp
+// CHECK-NEXT: stp x29, lr, [sp, #-32]!
+// CHECK-NEXT: pacibsp
+// CHECK-NEXT: end
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
+// CHECK-NEXT: RuntimeFunction {
+// CHECK-NEXT: Function: func17
+// CHECK-NEXT: Fragment: No
+// CHECK-NEXT: FunctionLength: 40
+// CHECK-NEXT: RegF: 0
+// CHECK-NEXT: RegI: 2
+// CHECK-NEXT: HomedParameters: No
+// CHECK-NEXT: CR: 2
+// CHECK-NEXT: FrameSize: 48
+// CHECK-NEXT: Prologue [
+// CHECK-NEXT: mov x29, sp
+// CHECK-NEXT: stp x29, lr, [sp, #-32]!
+// CHECK-NEXT: stp x19, x20, [sp, #-16]!
+// CHECK-NEXT: pacibsp
+// CHECK-NEXT: end
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
+// CHECK-NEXT: RuntimeFunction {
+// CHECK-NEXT: Function: func18
+// CHECK-NEXT: Fragment: No
+// CHECK-NEXT: FunctionLength: 56
+// CHECK-NEXT: RegF: 0
+// CHECK-NEXT: RegI: 2
+// CHECK-NEXT: HomedParameters: No
+// CHECK-NEXT: CR: 2
+// CHECK-NEXT: FrameSize: 4112
+// CHECK-NEXT: Prologue [
+// CHECK-NEXT: mov x29, sp
+// CHECK-NEXT: stp x29, lr, [sp, #0]
+// CHECK-NEXT: sub sp, sp, #16
+// CHECK-NEXT: sub sp, sp, #4080
+// CHECK-NEXT: stp x19, x20, [sp, #-16]!
+// CHECK-NEXT: pacibsp
+// CHECK-NEXT: end
+// CHECK-NEXT: ]
+// CHECK-NEXT: }
// CHECK: RuntimeFunction {
// CHECK-NEXT: Function: nonpacked1
// CHECK-NEXT: ExceptionRecord:
@@ -307,6 +359,16 @@
// CHECK-NEXT: Function: nonpacked13
// CHECK-NEXT: ExceptionRecord:
// CHECK-NEXT: ExceptionData {
+// CHECK: EpiloguePacked: Yes
+// CHECK: RuntimeFunction {
+// CHECK-NEXT: Function: nonpacked14
+// CHECK-NEXT: ExceptionRecord:
+// CHECK-NEXT: ExceptionData {
+// CHECK: EpiloguePacked: Yes
+// CHECK: RuntimeFunction {
+// CHECK-NEXT: Function: nonpacked15
+// CHECK-NEXT: ExceptionRecord:
+// CHECK-NEXT: ExceptionData {
// CHECK: EpiloguePacked: Yes
.text
@@ -664,6 +726,83 @@ func15:
ret
.seh_endproc
+func16:
+ .seh_proc func16
+ pacibsp
+ .seh_pac_sign_return_address
+ stp x29, lr, [sp, #-32]!
+ .seh_save_fplr_x 32
+ mov x29, sp
+ .seh_set_fp
+ .seh_endprologue
+ nop
+ .seh_startepilogue
+ ldp x29, lr, [sp], #32
+ .seh_save_fplr_x 32
+ autibsp
+ .seh_pac_sign_return_address
+ .seh_endepilogue
+ ret
+ .seh_endproc
+
+func17:
+ .seh_proc func17
+ pacibsp
+ .seh_pac_sign_return_address
+ stp x19, x20, [sp, #-16]!
+ .seh_save_r19r20_x 16
+ stp x29, lr, [sp, #-32]!
+ .seh_save_fplr_x 32
+ mov x29, sp
+ .seh_set_fp
+ .seh_endprologue
+ nop
+ .seh_startepilogue
+ mov sp, x29
+ .seh_set_fp
+ ldp x29, lr, [sp], #32
+ .seh_save_fplr_x 32
+ ldp x19, x20, [sp], #16
+ .seh_save_r19r20_x 16
+ autibsp
+ .seh_pac_sign_return_address
+ .seh_endepilogue
+ ret
+ .seh_endproc
+
+func18:
+ .seh_proc func18
+ pacibsp
+ .seh_pac_sign_return_address
+ stp x19, x20, [sp, #-16]!
+ .seh_save_r19r20_x 16
+ sub sp, sp, #4080
+ .seh_stackalloc 4080
+ sub sp, sp, #16
+ .seh_stackalloc 16
+ stp x29, lr, [sp, #0]
+ .seh_save_fplr 0
+ mov x29, sp
+ .seh_set_fp
+ .seh_endprologue
+ nop
+ .seh_startepilogue
+ mov sp, x29
+ .seh_set_fp
+ ldp x29, lr, [sp, #0]
+ .seh_save_fplr 0
+ add sp, sp, #16
+ .seh_stackalloc 16
+ add sp, sp, #4080
+ .seh_stackalloc 4080
+ ldp x19, x20, [sp], #16
+ .seh_save_r19r20_x 16
+ autibsp
+ .seh_pac_sign_return_address
+ .seh_endepilogue
+ ret
+ .seh_endproc
+
nonpacked1:
.seh_proc nonpacked1
// Can't be packed; can't save integer registers after float registers.
@@ -930,3 +1069,49 @@ nonpacked13:
.long 0
.text
.seh_endproc
+
+nonpacked14:
+ .seh_proc nonpacked14
+ // Can't be packed; a signed return address can only be expressed if
+ // we save both x29 and lr on the stack.
+ pacibsp
+ .seh_pac_sign_return_address
+ str lr, [sp, #-32]!
+ .seh_save_reg_x lr, 32
+ .seh_endprologue
+ nop
+ .seh_startepilogue
+ ldr lr, [sp], #32
+ .seh_save_reg_x lr, 32
+ autibsp
+ .seh_pac_sign_return_address
+ .seh_endepilogue
+ ret
+ .seh_endproc
+
+nonpacked15:
+ .seh_proc nonpacked15
+ // Can't be packed; a signed return address can only be expressed if
+ // we save both x29 and lr on the stack.
+ pacibsp
+ .seh_pac_sign_return_address
+ stp x19, x20, [sp, #-32]!
+ .seh_save_r19r20_x 32
+ stp x21, lr, [sp, #16]
+ .seh_save_lrpair x21, 16
+ sub sp, sp, #16
+ .seh_stackalloc 16
+ .seh_endprologue
+ nop
+ .seh_startepilogue
+ add sp, sp, #16
+ .seh_stackalloc 16
+ ldp x21, lr, [sp, #16]
+ .seh_save_lrpair x21, 16
+ ldp x19, x20, [sp], #32
+ .seh_save_r19r20_x 32
+ autibsp
+ .seh_pac_sign_return_address
+ .seh_endepilogue
+ ret
+ .seh_endproc
More information about the llvm-commits
mailing list