[WinEH] Don't let UnwindHelp alias the return address
authorReid Kleckner <rnk@google.com>
Mon, 16 Nov 2015 18:47:25 +0000 (18:47 +0000)
committerReid Kleckner <rnk@google.com>
Mon, 16 Nov 2015 18:47:25 +0000 (18:47 +0000)
On top of that, don't bother allocating and initializing UnwindHelp if
we don't have any funclets. Currently we always use RBP as our frame
pointer when funclets are present, so this change makes it impossible to
come here without any fixed stack objects.

Fixes PR25533.

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

lib/Target/X86/X86FrameLowering.cpp
test/CodeGen/X86/win-cleanuppad.ll
test/CodeGen/X86/wineh-no-ehpads.ll [new file with mode: 0644]

index 3c557fe8a1161b669482bc88c5af974a69e7f990..72baa078661ad2051d6cc0eda53b4f256b89810e 100644 (file)
@@ -2662,17 +2662,17 @@ void X86FrameLowering::processFunctionBeforeFrameFinalized(
   // 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)
+  if (!STI.is64Bit() || !MF.getMMI().hasEHFunclets() ||
+      classifyEHPersonality(Fn->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.
+  // object, so that we can allocate a slot immediately following it. If there
+  // were no fixed objects, use offset -SlotSize, which is immediately after the
+  // return address. Fixed objects have negative frame indices.
   MachineFrameInfo *MFI = MF.getFrameInfo();
-  int64_t MinFixedObjOffset = 0;
+  int64_t MinFixedObjOffset = -SlotSize;
   for (int I = MFI->getObjectIndexBegin(); I < 0; ++I)
     MinFixedObjOffset = std::min(MinFixedObjOffset, MFI->getObjectOffset(I));
 
index aed410f79b154baf6363e7d0f25c890a6c2d4407..27bb6e2abed66e28a9a9b6de66af6b23b9e639e1 100644 (file)
@@ -19,6 +19,36 @@ ehcleanup:                                        ; preds = %entry
   cleanupret %0 unwind to caller
 }
 
+; CHECK: simple_cleanup:                         # @simple_cleanup
+; CHECK:         pushq   %rbp
+; CHECK:         subq    $48, %rsp
+; CHECK:         leaq    48(%rsp), %rbp
+; CHECK:         movq    $-2, -8(%rbp)
+; CHECK:         movl    $1, %ecx
+; CHECK:         callq   f
+; CHECK:         callq   "??1Dtor@@QAE@XZ"
+; CHECK:         nop
+; CHECK:         addq    $48, %rsp
+; CHECK:         popq    %rbp
+; CHECK:         retq
+
+; CHECK: "?dtor$2@?0?simple_cleanup@4HA":
+; CHECK:         callq   "??1Dtor@@QAE@XZ"
+; CHECK:         retq
+
+; CHECK: $cppxdata$simple_cleanup:
+; CHECK-NEXT:         .long   429065506
+; CHECK-NEXT:         .long   1
+; CHECK-NEXT:         .long   ($stateUnwindMap$simple_cleanup)@IMGREL
+; CHECK-NEXT:         .long   0
+; CHECK-NEXT:         .long   0
+; CHECK-NEXT:         .long   3
+; CHECK-NEXT:         .long   ($ip2state$simple_cleanup)@IMGREL
+; UnwindHelp offset should match the -2 store above
+; CHECK-NEXT:         .long   40
+; CHECK-NEXT:         .long   0
+; CHECK-NEXT:         .long   1
+
 declare void @f(i32) #0
 
 declare i32 @__CxxFrameHandler3(...)
diff --git a/test/CodeGen/X86/wineh-no-ehpads.ll b/test/CodeGen/X86/wineh-no-ehpads.ll
new file mode 100644 (file)
index 0000000..fd6798f
--- /dev/null
@@ -0,0 +1,20 @@
+; RUN: llc < %s | FileCheck %s
+
+target triple = "x86_64-pc-windows-msvc"
+
+declare void @g()
+declare i32 @__CxxFrameHandler3(...)
+
+define void @personality_no_ehpad() personality i32 (...)* @__CxxFrameHandler3 {
+  call void @g()
+  ret void
+}
+
+; CHECK-LABEL: personality_no_ehpad: # @personality_no_ehpad
+; CHECK-NOT: movq $-2,
+; CHECK: callq g
+; CHECK: nop
+; CHECK: retq
+
+; Shouldn't have any LSDA either.
+; CHECK-NOT: cppxdata