enum {
Start,
Start2,
+ Start3,
IntRegs,
FloatRegs,
InputArgs,
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
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)
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;
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.
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;
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
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;
// 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:
// 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
func1:
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.
.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