[llvm] 494abe1 - [AArch64] Change AArch64 Windows EH UnwindHelp object to be a fixed object

Eli Friedman via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 31 14:21:58 PDT 2020


Author: Daniel Frampton
Date: 2020-03-31T14:21:21-07:00
New Revision: 494abe139a9aab991582f1b3f3370b99b252944c

URL: https://github.com/llvm/llvm-project/commit/494abe139a9aab991582f1b3f3370b99b252944c
DIFF: https://github.com/llvm/llvm-project/commit/494abe139a9aab991582f1b3f3370b99b252944c.diff

LOG: [AArch64] Change AArch64 Windows EH UnwindHelp object to be a fixed object

The UnwindHelp object is used during exception handling by runtime
code. It must be findable from a fixed offset from FP.

This change allocates the UnwindHelp object as a fixed object (as is
done for x86_64) to ensure that both the generated code and runtime
agree on the location of the object.

Fixes https://bugs.llvm.org/show_bug.cgi?id=45346

Differential Revision: https://reviews.llvm.org/D77016

Added: 
    llvm/test/CodeGen/AArch64/wineh-unwindhelp-via-fp.ll

Modified: 
    llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
    llvm/test/CodeGen/AArch64/seh-finally.ll
    llvm/test/CodeGen/AArch64/wineh-try-catch-cbz.ll
    llvm/test/CodeGen/AArch64/wineh-try-catch-realign.ll
    llvm/test/CodeGen/AArch64/wineh-try-catch.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
index a8fdf23a9a5d..f16c96ed70ec 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -216,6 +216,24 @@ AArch64FrameLowering::getStackIDForScalableVectors() const {
   return TargetStackID::SVEVector;
 }
 
+/// Returns the size of the fixed object area (allocated next to sp on entry)
+/// On Win64 this may include a var args area and an UnwindHelp object for EH.
+static unsigned getFixedObjectSize(const MachineFunction &MF,
+                                   const AArch64FunctionInfo *AFI, bool IsWin64,
+                                   bool IsFunclet) {
+  if (!IsWin64 || IsFunclet) {
+    // Only Win64 uses fixed objects, and then only for the function (not
+    // funclets)
+    return 0;
+  } else {
+    // Var args are stored here in the primary function.
+    const unsigned VarArgsArea = AFI->getVarArgsGPRSize();
+    // To support EH funclets we allocate an UnwindHelp object
+    const unsigned UnwindHelpObject = (MF.hasEHFunclets() ? 8 : 0);
+    return alignTo(VarArgsArea + UnwindHelpObject, 16);
+  }
+}
+
 /// Returns the size of the entire SVE stackframe (calleesaves + spills).
 static StackOffset getSVEStackSize(const MachineFunction &MF) {
   const AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
@@ -995,10 +1013,7 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
 
   bool IsWin64 =
       Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv());
-  // Var args are accounted for in the containing function, so don't
-  // include them for funclets.
-  unsigned FixedObject = (IsWin64 && !IsFunclet) ?
-                         alignTo(AFI->getVarArgsGPRSize(), 16) : 0;
+  unsigned FixedObject = getFixedObjectSize(MF, AFI, IsWin64, IsFunclet);
 
   auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
   // All of the remaining stack allocations are for locals.
@@ -1477,10 +1492,7 @@ void AArch64FrameLowering::emitEpilogue(MachineFunction &MF,
 
   bool IsWin64 =
       Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv());
-  // Var args are accounted for in the containing function, so don't
-  // include them for funclets.
-  unsigned FixedObject =
-      (IsWin64 && !IsFunclet) ? alignTo(AFI->getVarArgsGPRSize(), 16) : 0;
+  unsigned FixedObject = getFixedObjectSize(MF, AFI, IsWin64, IsFunclet);
 
   uint64_t AfterCSRPopSize = ArgumentPopSize;
   auto PrologueSaveSize = AFI->getCalleeSavedStackSize() + FixedObject;
@@ -1706,7 +1718,9 @@ static StackOffset getFPOffset(const MachineFunction &MF, int64_t ObjectOffset)
   const auto &Subtarget = MF.getSubtarget<AArch64Subtarget>();
   bool IsWin64 =
       Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv());
-  unsigned FixedObject = IsWin64 ? alignTo(AFI->getVarArgsGPRSize(), 16) : 0;
+
+  unsigned FixedObject =
+      getFixedObjectSize(MF, AFI, IsWin64, /*IsFunclet=*/false);
   unsigned FPAdjust = isTargetDarwin(MF)
                         ? 16 : AFI->getCalleeSavedStackSize(MF.getFrameInfo());
   return {ObjectOffset + FixedObject + FPAdjust, MVT::i8};
@@ -2659,9 +2673,14 @@ void AArch64FrameLowering::processFunctionBeforeFrameFinalized(
     ++MBBI;
 
   // Create an UnwindHelp object.
-  int UnwindHelpFI =
-      MFI.CreateStackObject(/*size*/8, /*alignment*/16, false);
+  // The UnwindHelp object is allocated at the start of the fixed object area
+  int64_t FixedObject =
+      getFixedObjectSize(MF, AFI, /*IsWin64*/ true, /*IsFunclet*/ false);
+  int UnwindHelpFI = MFI.CreateFixedObject(/*Size*/ 8,
+                                           /*SPOffset*/ -FixedObject,
+                                           /*IsImmutable=*/false);
   EHInfo.UnwindHelpFrameIdx = UnwindHelpFI;
+
   // We need to store -2 into the UnwindHelp object at the start of the
   // function.
   DebugLoc DL;
@@ -3073,10 +3092,14 @@ int AArch64FrameLowering::getFrameIndexReferencePreferSP(
     const MachineFunction &MF, int FI, unsigned &FrameReg,
     bool IgnoreSPUpdates) const {
   const MachineFrameInfo &MFI = MF.getFrameInfo();
-  LLVM_DEBUG(dbgs() << "Offset from the SP for " << FI << " is "
-                    << MFI.getObjectOffset(FI) << "\n");
-  FrameReg = AArch64::SP;
-  return MFI.getObjectOffset(FI);
+  if (IgnoreSPUpdates) {
+    LLVM_DEBUG(dbgs() << "Offset from the SP for " << FI << " is "
+                      << MFI.getObjectOffset(FI) << "\n");
+    FrameReg = AArch64::SP;
+    return MFI.getObjectOffset(FI);
+  }
+
+  return getFrameIndexReference(MF, FI, FrameReg);
 }
 
 /// The parent frame offset (aka dispFrame) is only used on X86_64 to retrieve

diff  --git a/llvm/test/CodeGen/AArch64/seh-finally.ll b/llvm/test/CodeGen/AArch64/seh-finally.ll
index 66558c90a79c..dbc6c4b0804b 100644
--- a/llvm/test/CodeGen/AArch64/seh-finally.ll
+++ b/llvm/test/CodeGen/AArch64/seh-finally.ll
@@ -37,7 +37,7 @@ entry:
 ; CHECK-LABEL: simple_seh
 ; CHECK: add     x29, sp, #16
 ; CHECK: mov     x0, #-2
-; CHECK: stur    x0, [x29, #-16]
+; CHECK: stur    x0, [x29, #16]
 ; CHECK: .set .Lsimple_seh$frame_escape_0, -8
 ; CHECK: ldur    w0, [x29, #-8]
 ; CHECK: bl      foo
@@ -87,13 +87,13 @@ define void @stack_realign() #0 personality i8* bitcast (i32 (...)* @__C_specifi
 entry:
 ; CHECK-LABEL: stack_realign
 ; CHECK: mov     x29, sp
-; CHECK: sub     x9, sp, #64
+; CHECK: sub     x9, sp, #16
 ; CHECK: and     sp, x9, #0xffffffffffffffe0
 ; CHECK: mov     x19, sp
 ; CHECK: mov     x0, #-2
-; CHECK: stur    x0, [x19, #16]
-; CHECK: .set .Lstack_realign$frame_escape_0, 32
-; CHECK: ldr     w0, [x19, #32]
+; CHECK: stur    x0, [x29, #32]
+; CHECK: .set .Lstack_realign$frame_escape_0, 0
+; CHECK: ldr     w0, [x19]
 ; CHECK: bl      foo
 
   %o = alloca %struct.S, align 32
@@ -142,7 +142,7 @@ entry:
 ; CHECK-LABEL: vla_present
 ; CHECK: add     x29, sp, #32
 ; CHECK: mov     x1, #-2
-; CHECK: stur    x1, [x29, #-32]
+; CHECK: stur    x1, [x29, #16]
 ; CHECK: .set .Lvla_present$frame_escape_0, -4
 ; CHECK: stur    w0, [x29, #-4]
 ; CHECK: ldur    w8, [x29, #-4]
@@ -206,17 +206,17 @@ define void @vla_and_realign(i32 %n) #0 personality i8* bitcast (i32 (...)* @__C
 entry:
 ; CHECK-LABEL: vla_and_realign
 ; CHECK: mov     x29, sp
-; CHECK: sub     x9, sp, #64
+; CHECK: sub     x9, sp, #48
 ; CHECK: and     sp, x9, #0xffffffffffffffe0
 ; CHECK: mov     x19, sp
 ; CHECK: mov     x1, #-2
-; CHECK: stur    x1, [x19]
+; CHECK: stur    x1, [x29, #32]
 ; CHECK: .set .Lvla_and_realign$frame_escape_0, 32
-; CHECK: str     w0, [x29, #28]
-; CHECK: ldr     w8, [x29, #28]
+; CHECK: str     w0, [x29, #44]
+; CHECK: ldr     w8, [x29, #44]
 ; CHECK: mov     x9, sp
-; CHECK: str     x9, [x19, #24]
-; CHECK: str     x8, [x19, #16]
+; CHECK: str     x9, [x29, #24]
+; CHECK: str     x8, [x19, #24]
 ; CHECK: ldr     w0, [x19, #32]
 ; CHECK: bl      foo
 

diff  --git a/llvm/test/CodeGen/AArch64/wineh-try-catch-cbz.ll b/llvm/test/CodeGen/AArch64/wineh-try-catch-cbz.ll
index d84c07f8bc1a..cbed64ab99e3 100644
--- a/llvm/test/CodeGen/AArch64/wineh-try-catch-cbz.ll
+++ b/llvm/test/CodeGen/AArch64/wineh-try-catch-cbz.ll
@@ -4,11 +4,10 @@
 ; but the original issue only reproduced if the cbz was immediately
 ; after the frame setup.)
 
-; CHECK:      sub     sp, sp, #32
-; CHECK-NEXT: stp     x29, x30, [sp, #16]
-; CHECK-NEXT: add     x29, sp, #16
+; CHECK: stp     x29, x30, [sp, #-32]!
+; CHECK-NEXT: mov     x29, sp
 ; CHECK-NEXT: mov     x1, #-2
-; CHECK-NEXT: stur    x1, [x29, #-16]
+; CHECK-NEXT: stur    x1, [x29, #16]
 ; CHECK-NEXT: cbz     w0, .LBB0_2
 
 target datalayout = "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"

diff  --git a/llvm/test/CodeGen/AArch64/wineh-try-catch-realign.ll b/llvm/test/CodeGen/AArch64/wineh-try-catch-realign.ll
index b10a0f3033a0..a66ec10748e7 100644
--- a/llvm/test/CodeGen/AArch64/wineh-try-catch-realign.ll
+++ b/llvm/test/CodeGen/AArch64/wineh-try-catch-realign.ll
@@ -12,7 +12,7 @@
 ; CHECK:      stp     x29, x30, [sp, #-32]!
 ; CHECK-NEXT: str     x28, [sp, #16]
 ; CHECK-NEXT: str     x19, [sp, #24]
-; CHECK-NEXT: add     x0, x19, #64
+; CHECK-NEXT: add     x0, x19, #0
 ; CHECK-NEXT: mov     w1, wzr
 ; CHECK-NEXT: bl      "?bb@@YAXPEAHH at Z"
 ; CHECK-NEXT: adrp    x0, .LBB0_1

diff  --git a/llvm/test/CodeGen/AArch64/wineh-try-catch.ll b/llvm/test/CodeGen/AArch64/wineh-try-catch.ll
index 3ae2df37efe4..73909825d377 100644
--- a/llvm/test/CodeGen/AArch64/wineh-try-catch.ll
+++ b/llvm/test/CodeGen/AArch64/wineh-try-catch.ll
@@ -11,11 +11,11 @@
 ;    and the parent function.
 
 ; The following checks that the unwind help object has -2 stored into it at
-; fp - 400 - 256 = fp - 656, which is on-entry sp - 48 + 32 - 656 =
-; on-entry sp - 672.  We check this offset in the table later on.
+; fp + 16, which is on-entry sp - 16.
+; We check this offset in the table later on.
 
 ; CHECK-LABEL: "?func@@YAHXZ":
-; CHECK:       stp     x29, x30, [sp, #-48]!
+; CHECK:       stp     x29, x30, [sp, #-64]!
 ; CHECK:       str     x28, [sp, #16]
 ; CHECK:       str     x21, [sp, #24]
 ; CHECK:       stp     x19, x20, [sp, #32]
@@ -23,7 +23,7 @@
 ; CHECK:       sub     sp, sp, #624
 ; CHECK:       mov     x19, sp
 ; CHECK:       mov     x0, #-2
-; CHECK:       stur    x0, [x19]
+; CHECK:       stur    x0, [x29, #48]
 
 ; Now check that x is stored at fp - 20.  We check that this is the same
 ; location accessed from the funclet to retrieve x.
@@ -72,7 +72,7 @@
 
 ; Now check that the offset of the unwind help object from the stack pointer on
 ; entry to func is encoded in cppxdata that is passed to __CxxFrameHandler3.  As
-; computed above, this comes to -672.
+; computed above, this comes to -16.
 ; CHECK-LABEL:        "$cppxdata$?func@@YAHXZ":
 ; CHECK-NEXT:         .word   429065506               ; MagicNumber
 ; CHECK-NEXT:         .word   2                       ; MaxState
@@ -81,7 +81,7 @@
 ; CHECK-NEXT:         .word   ("$tryMap$?func@@YAHXZ")@IMGREL ; TryBlockMap
 ; CHECK-NEXT:         .word   4                       ; IPMapEntries
 ; CHECK-NEXT:         .word   ("$ip2state$?func@@YAHXZ")@IMGREL ; IPToStateXData
-; CHECK-NEXT:         .word   -672                    ; UnwindHelp
+; CHECK-NEXT:         .word   -16                     ; UnwindHelp
 
 ; UNWIND: Function: ?func@@YAHXZ (0x0)
 ; UNWIND: Prologue [
@@ -91,7 +91,7 @@
 ; UNWIND-NEXT: ; stp x19, x20, [sp, #32]
 ; UNWIND-NEXT: ; str x21, [sp, #24]
 ; UNWIND-NEXT: ; str x28, [sp, #16]
-; UNWIND-NEXT: ; stp x29, x30, [sp, #-48]!
+; UNWIND-NEXT: ; stp x29, x30, [sp, #-64]!
 ; UNWIND-NEXT: ; end
 ; UNWIND: Function: ?catch$2@?0??func@@YAHXZ at 4HA
 ; UNWIND: Prologue [

diff  --git a/llvm/test/CodeGen/AArch64/wineh-unwindhelp-via-fp.ll b/llvm/test/CodeGen/AArch64/wineh-unwindhelp-via-fp.ll
new file mode 100644
index 000000000000..6ec78087020c
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/wineh-unwindhelp-via-fp.ll
@@ -0,0 +1,69 @@
+; RUN: llc -o - %s -mtriple=aarch64-windows | FileCheck %s
+; Check that we allocate the unwind help stack object in a fixed location from fp
+; so that the runtime can find it when handling an exception
+target datalayout = "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128"
+target triple = "aarch64-pc-windows-msvc19.25.28611"
+
+; Check that the store to the unwind help object for func2 is via FP
+; CHECK-LABEL: ?func2@@YAXXZ
+; CHECK: mov x[[#SCRATCH_REG:]], #-2
+; CHECK: stur x[[#SCRATCH_REG:]], [x29, #[[#]]]
+;
+; // struct that requires greater than stack alignment
+; struct alignas(32) A
+; {
+;     // data that would be invalid for unwind help (> 0)
+;     int _x[4]{42, 42, 42, 42};
+;     ~A() {}
+; };
+; 
+; // cause us to run the funclet in func2
+; void func3()
+; {
+;     throw 1;
+; }
+; 
+; // the funclet that ensures we have the unwind help correct
+; void func2()
+; {
+;     A a;
+;     func3();
+; }
+; 
+; // function to ensure we are misaligned in func2
+; void func1()
+; {
+;     func2();
+; }
+; 
+; // set things up and ensure alignment for func1
+; void test()
+; {
+;     try {
+;         A a;
+;         func1();
+;     } catch(...) {}
+; }
+
+%struct.A = type { [4 x i32], [16 x i8] }
+declare dso_local %struct.A* @"??0A@@QEAA at XZ"(%struct.A* returned %0)
+declare dso_local void @"??1A@@QEAA at XZ"(%struct.A* %0)
+declare dso_local i32 @__CxxFrameHandler3(...)
+declare dso_local void @"?func3@@YAXXZ"()
+
+; Function Attrs: noinline optnone uwtable
+define dso_local void @"?func2@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) {
+  %1 = alloca %struct.A, align 32
+  %2 = call %struct.A* @"??0A@@QEAA at XZ"(%struct.A* %1) #3
+  invoke void @"?func3@@YAXXZ"()
+          to label %3 unwind label %4
+
+3:                                                ; preds = %0
+  call void @"??1A@@QEAA at XZ"(%struct.A* %1) #3
+  ret void
+
+4:                                                ; preds = %0
+  %5 = cleanuppad within none []
+  call void @"??1A@@QEAA at XZ"(%struct.A* %1) #3 [ "funclet"(token %5) ]
+  cleanupret from %5 unwind to caller
+}


        


More information about the llvm-commits mailing list