diff options
author | Reid Kleckner <rnk@google.com> | 2015-10-07 23:55:01 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2015-10-07 23:55:01 +0000 |
commit | 97797419e6539ef3a222e12bb7ad04ef8aafed0f (patch) | |
tree | fea9f68158058890f101211f09e3c647d52fe6aa /llvm | |
parent | 9ea49c794883ab641468e6238cfa98bc27b8a978 (diff) | |
download | bcm5719-llvm-97797419e6539ef3a222e12bb7ad04ef8aafed0f.tar.gz bcm5719-llvm-97797419e6539ef3a222e12bb7ad04ef8aafed0f.zip |
[WinEH] Fix 32-bit funclet epilogues in the presence of dynamic allocas
In particular, passing non-trivially copyable objects by value on win32
uses a dynamic alloca (inalloca). We would clobber ESP in the epilogue
and end up returning to outer space.
llvm-svn: 249637
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Target/X86/X86FrameLowering.cpp | 7 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/cleanuppad-inalloca.ll | 68 |
2 files changed, 73 insertions, 2 deletions
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index fc314d76c64..7f05e5b3b13 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -1057,6 +1057,7 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); bool NeedsWinCFI = IsWin64Prologue && MF.getFunction()->needsUnwindTableEntry(); + bool IsFunclet = isFuncletReturnInstr(MBBI); // Get the number of bytes to allocate from the FrameInfo. uint64_t StackSize = MFI->getStackSize(); @@ -1170,8 +1171,10 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, // If dynamic alloca is used, then reset esp to point to the last callee-saved // slot before popping them off! Same applies for the case, when stack was - // realigned. - if (TRI->needsStackRealignment(MF) || MFI->hasVarSizedObjects()) { + // realigned. Don't do this if this was a funclet epilogue, since the funclets + // will not do realignment or dynamic stack allocation. + if ((TRI->needsStackRealignment(MF) || MFI->hasVarSizedObjects()) && + !IsFunclet) { if (TRI->needsStackRealignment(MF)) MBBI = FirstCSPop; unsigned SEHFrameOffset = calculateSetFPREG(SEHStackAllocAmt); diff --git a/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll b/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll new file mode 100644 index 00000000000..8858f3704a1 --- /dev/null +++ b/llvm/test/CodeGen/X86/cleanuppad-inalloca.ll @@ -0,0 +1,68 @@ +; RUN: llc < %s | FileCheck %s + +; Based on this C++: +; struct A { +; int x; +; A(); +; A(const A &a); +; ~A(); +; }; +; extern "C" void takes_two(A a1, A a2); +; extern "C" void passes_two() { takes_two(A(), A()); } + +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i686--windows-msvc" + +%struct.A = type { i32 } + +define void @passes_two() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { +entry: + %argmem = alloca inalloca <{ %struct.A, %struct.A }>, align 4 + %0 = getelementptr inbounds <{ %struct.A, %struct.A }>, <{ %struct.A, %struct.A }>* %argmem, i32 0, i32 1 + %call = call x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %0) + %1 = getelementptr inbounds <{ %struct.A, %struct.A }>, <{ %struct.A, %struct.A }>* %argmem, i32 0, i32 0 + %call1 = invoke x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* %1) + to label %invoke.cont unwind label %ehcleanup + +invoke.cont: ; preds = %entry + call void @takes_two(<{ %struct.A, %struct.A }>* inalloca nonnull %argmem) + ret void + +ehcleanup: ; preds = %entry + %2 = cleanuppad [] + call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %0) + cleanupret %2 unwind to caller +} + +; CHECK: _passes_two: +; CHECK: pushl %ebp +; CHECK: movl %esp, %ebp +; CHECK: subl ${{[0-9]+}}, %esp +; CHECK: movl $8, %eax +; CHECK: calll __chkstk +; CHECK: calll "??0A@@QAE@XZ" +; CHECK: calll "??0A@@QAE@XZ" +; CHECK: calll _takes_two +; ESP must be restored via EBP due to "dynamic" alloca. +; CHECK: leal -{{[0-9]+}}(%ebp), %esp +; CHECK: popl %ebp +; CHECK: retl + +; CHECK: "?dtor$2@?0?passes_two@4HA": +; CHECK: pushl %ebp +; CHECK: subl $8, %esp +; CHECK: addl $12, %ebp +; CHECK: {{movl|leal}} -{{[0-9]+}}(%ebp), %ecx +; CHECK: calll "??1A@@QAE@XZ" +; CHECK: addl $8, %esp +; CHECK: retl + +declare void @takes_two(<{ %struct.A, %struct.A }>* inalloca) #0 + +declare x86_thiscallcc %struct.A* @"\01??0A@@QAE@XZ"(%struct.A* returned) #0 + +declare i32 @__CxxFrameHandler3(...) + +declare x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A*) #0 + +attributes #0 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } |