[WinEH] Make UnwindHelp a fixed stack object allocated after XMM CSRs
authorReid Kleckner <rnk@google.com>
Fri, 13 Nov 2015 19:06:01 +0000 (19:06 +0000)
committerReid Kleckner <rnk@google.com>
Fri, 13 Nov 2015 19:06:01 +0000 (19:06 +0000)
Now the offset of UnwindHelp in our EH tables and the offset that we
store to in the prologue agree.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@253059 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86FrameLowering.cpp
lib/Target/X86/X86FrameLowering.h
lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/catchpad-realign-savexmm.ll [new file with mode: 0644]
test/CodeGen/X86/cleanuppad-realign.ll
test/CodeGen/X86/win-catchpad-csrs.ll
test/CodeGen/X86/win-catchpad-varargs.ll
test/CodeGen/X86/win-catchpad.ll
test/CodeGen/X86/win-cleanuppad.ll

index da48a871930235239aefdbc01695e1a605fb0532..302fc93674452406750d6ff52189d3cdb4b772a3 100644 (file)
@@ -1696,10 +1696,11 @@ int X86FrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF,
     //   RETADDR
     //   PUSH RBP   <-- RBP points here
     //   PUSH CSRs
-    //   ~~~~~~~    <-- optional stack realignment dynamic adjustment
+    //   ~~~~~~~    <-- possible stack realignment (non-win64)
     //   ...
     //   STACK OBJECTS
     //   ...        <-- RSP after prologue points here
+    //   ~~~~~~~    <-- possible stack realignment (win64)
     //
     // if (hasVarSizedObjects()):
     //   ...        <-- "base pointer" (ESI/RBX) points here
@@ -1721,7 +1722,8 @@ int X86FrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF,
     // answer we give is relative to the SP after the prologue, and not the
     // SP in the middle of the function.
 
-    assert((!TRI->needsStackRealignment(MF) || !MFI->isFixedObjectIndex(FI)) &&
+    assert((!MFI->isFixedObjectIndex(FI) || !TRI->needsStackRealignment(MF) ||
+            STI.isTargetWin64()) &&
            "offset from fixed object to SP is not static");
 
     // We don't handle tail calls, and shouldn't be seeing them either.
@@ -2642,3 +2644,40 @@ unsigned X86FrameLowering::getWinEHParentFrameOffset(const MachineFunction &MF)
   Offset += getWinEHFuncletFrameSize(MF);
   return Offset;
 }
+
+void X86FrameLowering::processFunctionBeforeFrameFinalized(
+    MachineFunction &MF, RegScavenger *RS) const {
+  // If this function isn't doing Win64-style C++ EH, we don't need to do
+  // anything.
+  const Function *Fn = MF.getFunction();
+  if (!STI.is64Bit() || !Fn->hasPersonalityFn() ||
+      classifyEHPersonality(MF.getFunction()->getPersonalityFn()) !=
+          EHPersonality::MSVC_CXX)
+    return;
+
+  // Win64 C++ EH needs to allocate the UnwindHelp object at some fixed offset
+  // relative to RSP after the prologue.  Find the offset of the last fixed
+  // object, so that we can allocate a slot immediately following it. Fixed
+  // objects have negative frame indices.
+  MachineFrameInfo *MFI = MF.getFrameInfo();
+  int64_t MinFixedObjOffset = 0;
+  for (int I = MFI->getObjectIndexBegin(); I < 0; ++I)
+    MinFixedObjOffset = std::min(MinFixedObjOffset, MFI->getObjectOffset(I));
+
+  int64_t UnwindHelpOffset = MinFixedObjOffset - SlotSize;
+  int UnwindHelpFI =
+      MFI->CreateFixedObject(SlotSize, UnwindHelpOffset, /*Immutable=*/false);
+  MF.getMMI().getWinEHFuncInfo(Fn).UnwindHelpFrameIdx = UnwindHelpFI;
+
+  // Store -2 into UnwindHelp on function entry. We have to scan forwards past
+  // other frame setup instructions.
+  MachineBasicBlock &MBB = MF.front();
+  auto MBBI = MBB.begin();
+  while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup))
+    ++MBBI;
+
+  DebugLoc DL = MBB.findDebugLoc(MBBI);
+  addFrameReference(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64mi32)),
+                    UnwindHelpFI)
+      .addImm(-2);
+}
index 753d155657d967b32386d8d118698a33cf28a351..68dc8edfd4309b660156097dec3674a55cc1a242 100644 (file)
@@ -109,6 +109,9 @@ public:
 
   unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override;
 
+  void processFunctionBeforeFrameFinalized(MachineFunction &MF,
+                                           RegScavenger *RS) const override;
+
   /// Check the instruction before/after the passed instruction. If
   /// it is an ADD/SUB/LEA instruction it is deleted argument and the
   /// stack adjustment is returned as a positive value for ADD/LEA and
index fdb716ebca4c6e59491ce0e98dc0c5044cf6a19e..93a4dc291f5399ea42216308c161eec63f734bc3 100644 (file)
@@ -2880,20 +2880,7 @@ SDValue X86TargetLowering::LowerFormalArguments(
 
   if (MMI.hasWinEHFuncInfo(Fn)) {
     EHPersonality Personality = classifyEHPersonality(Fn->getPersonalityFn());
-    if (Personality == EHPersonality::MSVC_CXX) {
-      if (Is64Bit) {
-        int UnwindHelpFI = MFI->CreateStackObject(8, 8, /*isSS=*/false);
-        SDValue StackSlot = DAG.getFrameIndex(UnwindHelpFI, MVT::i64);
-        MMI.getWinEHFuncInfo(MF.getFunction()).UnwindHelpFrameIdx =
-            UnwindHelpFI;
-        SDValue Neg2 = DAG.getConstant(-2, dl, MVT::i64);
-        Chain = DAG.getStore(Chain, dl, Neg2, StackSlot,
-                             MachinePointerInfo::getFixedStack(
-                                 DAG.getMachineFunction(), UnwindHelpFI),
-                             /*isVolatile=*/true,
-                             /*isNonTemporal=*/false, /*Alignment=*/0);
-      }
-    } else if (Personality == EHPersonality::CoreCLR) {
+    if (Personality == EHPersonality::CoreCLR) {
       assert(Is64Bit);
       // TODO: Add a mechanism to frame lowering that will allow us to indicate
       // that we'd prefer this slot be allocated towards the bottom of the frame
diff --git a/test/CodeGen/X86/catchpad-realign-savexmm.ll b/test/CodeGen/X86/catchpad-realign-savexmm.ll
new file mode 100644 (file)
index 0000000..a1578d4
--- /dev/null
@@ -0,0 +1,55 @@
+; RUN: llc -verify-machineinstrs < %s | FileCheck %s
+
+; We should store -2 into UnwindHelp in a slot immediately after the last XMM
+; CSR save.
+
+declare void @g()
+declare i32 @__CxxFrameHandler3(...)
+
+@fp_global = global double 0.0
+
+define void @f() personality i32 (...)* @__CxxFrameHandler3 {
+  %v = load double, double* @fp_global
+  call void @g()
+  %v1 = fadd double %v, 1.0
+  store double %v1, double* @fp_global
+  invoke void @g()
+      to label %return unwind label %catch
+
+return:
+  ret void
+
+catch:
+  %p = catchpad [i8* null, i32 64, i8* null]
+      to label %catchit unwind label %endpad
+
+catchit:
+  catchret %p to label %return
+endpad:
+  catchendpad unwind to caller
+}
+
+; CHECK: f: # @f
+; CHECK: pushq   %rbp
+; CHECK: .seh_pushreg 5
+; CHECK: subq    $64, %rsp
+; CHECK: .seh_stackalloc 64
+; CHECK: leaq    64(%rsp), %rbp
+; CHECK: .seh_setframe 5, 64
+; CHECK: movaps  %xmm6, -16(%rbp)        # 16-byte Spill
+; CHECK: .seh_savexmm 6, 48
+; CHECK: .seh_endprologue
+; CHECK: movq    $-2, -24(%rbp)
+; CHECK: movsd   fp_global(%rip), %xmm6  # xmm6 = mem[0],zero
+; CHECK: callq   g
+; CHECK: addsd   __real@3ff0000000000000(%rip), %xmm6
+; CHECK: movsd   %xmm6, fp_global(%rip)
+; CHECK: .Ltmp{{.*}}
+; CHECK: callq   g
+; CHECK: .Ltmp{{.*}}
+; CHECK: .LBB{{.*}} # Block address taken
+; CHECK: movaps  -16(%rbp), %xmm6
+; CHECK: addq    $64, %rsp
+; CHECK: popq    %rbp
+; CHECK: retq
+; CHECK: .seh_handlerdata
index c80077e80c659cedf5d9afdc8dcf928427b28bf0..a19cf2613073ddafdad27bec3141c23d3b1c1ff3 100644 (file)
@@ -50,15 +50,16 @@ ehcleanup:                                        ; preds = %entry
 ; X64:         .seh_pushreg 5
 ; X64:         pushq   %rbx
 ; X64:         .seh_pushreg 3
-; X64:         subq    $72, %rsp
-; X64:         .seh_stackalloc 72
-; X64:         leaq    64(%rsp), %rbp
-; X64:         .seh_setframe 5, 64
+; X64:         subq    $104, %rsp
+; X64:         .seh_stackalloc 104
+; X64:         leaq    96(%rsp), %rbp
+; X64:         .seh_setframe 5, 96
 ; X64:         .seh_endprologue
 ; X64:         andq    $-32, %rsp
 ; X64:         movq    %rsp, %rbx
 ;      RBP will reload from this offset.
-; X64:         movq    %rbp, 48(%rbx)
+; X64:         movq    %rbp, 56(%rbx)
+; X64:                movq    $-2, (%rbp)
 
 ; X64-LABEL: "?dtor$2@?0?realigned_cleanup@4HA":
 ; X64:         movq    %rdx, 16(%rsp)
@@ -68,7 +69,7 @@ ehcleanup:                                        ; preds = %entry
 ; X64:         .seh_pushreg 3
 ; X64:         subq    $40, %rsp
 ; X64:         .seh_stackalloc 40
-; X64:         leaq    64(%rdx), %rbp
+; X64:         leaq    96(%rdx), %rbp
 ; X64:         .seh_endprologue
 ; X64:                andq    $-32, %rdx
 ; X64:                movq    %rdx, %rbx
index 114cc8be62209da8de49b8460e22f14039fcee24..f759a4ef0d96754a681f7e768a0c9000626ef42f 100644 (file)
@@ -106,6 +106,7 @@ catchendblock:                                    ; preds = %catch,
 ; X64: leaq 32(%rsp), %rbp
 ; X64: .seh_setframe 5, 32
 ; X64: .seh_endprologue
+; X64: movq $-2, (%rbp)
 ; X64: callq getint
 ; X64: callq getint
 ; X64: callq getint
index f25bacfd63062b2ed81b8bd97976fa30c4473c8d..03c6c70dc69a999fda6041168c607195552ed1f2 100644 (file)
@@ -38,13 +38,14 @@ return:                                           ; preds = %entry, %catch
 ; X64: pushq %rsi
 ; X64: subq $56, %rsp
 ; X64: leaq 48(%rsp), %rbp
+; X64: movq $-2, (%rbp)
 ; X64: callq g
 ; X64: movl %esi, %eax
 ; X64: addq $56, %rsp
 ; X64: popq %rsi
 ; X64: popq %rbp
 
-; X64: movl 4(%rbp), %esi
+; X64: movl -4(%rbp), %esi
 ; X64: jmp
 
 ; X64-LABEL: "?catch$1@?0?f@4HA":
@@ -64,7 +65,7 @@ return:                                           ; preds = %entry, %catch
 ; - 48 for setframe
 ; = 40
 ; X64:         movl    40(%rbp), %eax
-; X64:         movl    %eax, 4(%rbp)
+; X64:         movl    %eax, -4(%rbp)
 ; X64:         leaq    .LBB0_2(%rip), %rax
 ; X64:         addq    $40, %rsp
 ; X64:                popq    %rsi
index a9fd47a5dcf9e250073c840237b8a37e9ff3143f..826fae522a30d9921063b321776ac2129af561cd 100644 (file)
@@ -138,6 +138,7 @@ catchendblock:                                    ; preds = %catch, %catch.2, %c
 ; X64: leaq 48(%rsp), %rbp
 ; X64: .seh_setframe 5, 48
 ; X64: .seh_endprologue
+; X64: movq $-2, -8(%rbp)
 ; X64: .Ltmp0
 ; X64-DAG: leaq -[[local_offs:[0-9]+]](%rbp), %rdx
 ; X64-DAG: movl $1, %ecx
@@ -159,7 +160,7 @@ catchendblock:                                    ; preds = %catch, %catch.2, %c
 ; X64: .seh_endprologue
 ; X64-DAG: .Ltmp4
 ; X64-DAG: leaq -[[local_offs]](%rbp), %rdx
-; X64-DAG: movl -4(%rbp), %ecx
+; X64-DAG: movl -12(%rbp), %ecx
 ; X64: callq f
 ; X64: leaq [[contbb]](%rip), %rax
 ; X64-NEXT: addq $32, %rsp
@@ -192,7 +193,7 @@ catchendblock:                                    ; preds = %catch, %catch.2, %c
 ; X64-NEXT: .long   ($tryMap$try_catch_catch)@IMGREL
 ; X64-NEXT: .long   4
 ; X64-NEXT: .long   ($ip2state$try_catch_catch)@IMGREL
-; X64-NEXT: .long   32
+; X64-NEXT: .long   40
 ; X64-NEXT: .long   0
 ; X64-NEXT: .long   1
 
@@ -206,8 +207,7 @@ catchendblock:                                    ; preds = %catch, %catch.2, %c
 ; X64: $handlerMap$0$try_catch_catch:
 ; X64-NEXT:   .long   0
 ; X64-NEXT:   .long   "??_R0H@8"@IMGREL
-; FIXME: This should probably be offset from rsp, not rbp.
-; X64-NEXT:   .long   44
+; X64-NEXT:   .long   36
 ; X64-NEXT:   .long   "?catch$[[catch1bb]]@?0?try_catch_catch@4HA"@IMGREL
 ; X64-NEXT:   .long   56
 ; X64-NEXT:   .long   64
index 927a6e604c16929ad2fe9546c040389d721cf10a..aed410f79b154baf6363e7d0f25c890a6c2d4407 100644 (file)
@@ -142,7 +142,7 @@ cleanup.outer:                                      ; preds = %invoke.cont.1, %c
 ; X64-NEXT: .long   0
 ; X64-NEXT: .long   5
 ; X64-NEXT: .long   ($ip2state$nested_cleanup)@IMGREL
-; X64-NEXT: .long   40
+; X64-NEXT: .long   56
 ; X64-NEXT: .long   0
 ; X64-NEXT: .long   1