[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