llvm.org GIT mirror llvm / 39ee70c
[WinEH] Make llvm.x86.seh.restoreframe work for stack realignment prologues The incoming EBP value points to the end of a local stack allocation, so we can use that to restore ESI, the base pointer. Once we do that, we can use local stack allocations. If we know we need stack realignment, spill the original frame pointer in the prologue and reload it after restoring ESI. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241648 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 5 years ago
9 changed file(s) with 202 addition(s) and 42 deletion(s). Raw diff Collapse all Expand all
228228 /// Whether the "realign-stack" option is on.
229229 bool RealignOption;
230230
231 /// True if the function includes inline assembly that adjusts the stack
232 /// pointer.
233 bool HasInlineAsmWithSPAdjust;
231 /// True if the function dynamically adjusts the stack pointer through some
232 /// opaque mechanism like inline assembly or Win32 EH.
233 bool HasOpaqueSPAdjustment;
234234
235235 /// True if the function contains a call to the llvm.vastart intrinsic.
236236 bool HasVAStart;
268268 LocalFrameSize = 0;
269269 LocalFrameMaxAlign = 0;
270270 UseLocalStackAllocationBlock = false;
271 HasInlineAsmWithSPAdjust = false;
271 HasOpaqueSPAdjustment = false;
272272 HasVAStart = false;
273273 HasMustTailInVarArgFunc = false;
274274 Save = nullptr;
467467 bool hasCalls() const { return HasCalls; }
468468 void setHasCalls(bool V) { HasCalls = V; }
469469
470 /// Returns true if the function contains any stack-adjusting inline assembly.
471 bool hasInlineAsmWithSPAdjust() const { return HasInlineAsmWithSPAdjust; }
472 void setHasInlineAsmWithSPAdjust(bool B) { HasInlineAsmWithSPAdjust = B; }
470 /// Returns true if the function contains opaque dynamic stack adjustments.
471 bool hasOpaqueSPAdjustment() const { return HasOpaqueSPAdjustment; }
472 void setHasOpaqueSPAdjustment(bool B) { HasOpaqueSPAdjustment = B; }
473473
474474 /// Returns true if the function calls the llvm.va_start intrinsic.
475475 bool hasVAStart() const { return HasVAStart; }
147147 TLI->getRegForInlineAsmConstraint(TRI, Op.ConstraintCode,
148148 Op.ConstraintVT);
149149 if (PhysReg.first == SP)
150 MF->getFrameInfo()->setHasInlineAsmWithSPAdjust(true);
150 MF->getFrameInfo()->setHasOpaqueSPAdjustment(true);
151151 }
152152 }
153153 }
795795 if (TheReg == SP && Code == InlineAsm::Kind_Clobber) {
796796 // If we clobbered the stack pointer, MFI should know about it.
797797 assert(DAG.getMachineFunction().getFrameInfo()->
798 hasInlineAsmWithSPAdjust());
798 hasOpaqueSPAdjustment());
799799 }
800800 }
801801 }
8989 return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
9090 TRI->needsStackRealignment(MF) ||
9191 MFI->hasVarSizedObjects() ||
92 MFI->isFrameAddressTaken() || MFI->hasInlineAsmWithSPAdjust() ||
92 MFI->isFrameAddressTaken() || MFI->hasOpaqueSPAdjustment() ||
9393 MF.getInfo()->getForceFramePointer() ||
9494 MMI.callsUnwindInit() || MMI.callsEHReturn() ||
9595 MFI->hasStackMap() || MFI->hasPatchPoint());
966966 .addReg(StackPtr)
967967 .setMIFlag(MachineInstr::FrameSetup);
968968 if (X86FI->getRestoreBasePointer()) {
969 // Stash value of base pointer. Saving RSP instead of EBP shortens dependence chain.
969 // Stash value of base pointer. Saving RSP instead of EBP shortens
970 // dependence chain. Used by SjLj EH.
970971 unsigned Opm = Uses64BitFramePtr ? X86::MOV64mr : X86::MOV32mr;
971972 addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(Opm)),
972973 FramePtr, true, X86FI->getRestoreBasePointerOffset())
973974 .addReg(StackPtr)
974975 .setMIFlag(MachineInstr::FrameSetup);
976 }
977
978 if (X86FI->getHasSEHFramePtrSave()) {
979 // Stash the value of the frame pointer relative to the base pointer for
980 // Win32 EH. This supports Win32 EH, which does the inverse of the above:
981 // it recovers the frame pointer from the base pointer rather than the
982 // other way around.
983 unsigned Opm = Uses64BitFramePtr ? X86::MOV64mr : X86::MOV32mr;
984 addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(Opm)), BasePtr, true,
985 getFrameIndexOffset(MF, X86FI->getSEHFramePtrSaveIndex()))
986 .addReg(FramePtr)
987 .setMIFlag(MachineInstr::FrameSetup);
975988 }
976989 }
977990
25572557
25582558 MachineModuleInfo &MMI = MF.getMMI();
25592559 const Function *WinEHParent = nullptr;
2560 if (IsWin64 && MMI.hasWinEHFuncInfo(Fn))
2560 if (MMI.hasWinEHFuncInfo(Fn))
25612561 WinEHParent = MMI.getWinEHParent(Fn);
25622562 bool IsWinEHOutlined = WinEHParent && WinEHParent != Fn;
25632563 bool IsWinEHParent = WinEHParent && WinEHParent == Fn;
26502650
26512651 if (!MemOps.empty())
26522652 Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
2653 } else if (IsWinEHOutlined) {
2653 } else if (IsWin64 && IsWinEHOutlined) {
26542654 // Get to the caller-allocated home save location. Add 8 to account
26552655 // for the return address.
26562656 int HomeOffset = TFI.getOffsetOfLocalArea() + 8;
27382738 FuncInfo->setArgumentStackSize(StackSize);
27392739
27402740 if (IsWinEHParent) {
2741 int UnwindHelpFI = MFI->CreateStackObject(8, 8, /*isSS=*/false);
2742 SDValue StackSlot = DAG.getFrameIndex(UnwindHelpFI, MVT::i64);
2743 MMI.getWinEHFuncInfo(MF.getFunction()).UnwindHelpFrameIdx = UnwindHelpFI;
2744 SDValue Neg2 = DAG.getConstant(-2, dl, MVT::i64);
2745 Chain = DAG.getStore(Chain, dl, Neg2, StackSlot,
2746 MachinePointerInfo::getFixedStack(UnwindHelpFI),
2747 /*isVolatile=*/true,
2748 /*isNonTemporal=*/false, /*Alignment=*/0);
2741 if (Is64Bit) {
2742 int UnwindHelpFI = MFI->CreateStackObject(8, 8, /*isSS=*/false);
2743 SDValue StackSlot = DAG.getFrameIndex(UnwindHelpFI, MVT::i64);
2744 MMI.getWinEHFuncInfo(MF.getFunction()).UnwindHelpFrameIdx = UnwindHelpFI;
2745 SDValue Neg2 = DAG.getConstant(-2, dl, MVT::i64);
2746 Chain = DAG.getStore(Chain, dl, Neg2, StackSlot,
2747 MachinePointerInfo::getFixedStack(UnwindHelpFI),
2748 /*isVolatile=*/true,
2749 /*isNonTemporal=*/false, /*Alignment=*/0);
2750 } else {
2751 // Functions using Win32 EH are considered to have opaque SP adjustments
2752 // to force local variables to be addressed from the frame or base
2753 // pointers.
2754 MFI->setHasOpaqueSPAdjustment(true);
2755 }
27492756 }
27502757
27512758 return Chain;
1522915236 return DAG.getNode(X86ISD::SELECT, dl, VT, IMask, Op, PreservedSrc);
1523015237 }
1523115238
15239 static int getSEHRegistrationNodeSize(const Function *Fn) {
15240 if (!Fn->hasPersonalityFn())
15241 report_fatal_error(
15242 "querying registration node size for function without personality");
15243 // The RegNodeSize is 6 32-bit words for SEH and 4 for C++ EH. See
15244 // WinEHStatePass for the full struct definition.
15245 switch (classifyEHPersonality(Fn->getPersonalityFn())) {
15246 case EHPersonality::MSVC_X86SEH: return 24;
15247 case EHPersonality::MSVC_CXX: return 16;
15248 default: break;
15249 }
15250 report_fatal_error("can only recover FP for MSVC EH personality functions");
15251 }
15252
1523215253 /// When the 32-bit MSVC runtime transfers control to us, either to an outlined
1523315254 /// function or when returning to a parent frame after catching an exception, we
1523415255 /// recover the parent frame pointer by doing arithmetic on the incoming EBP.
1525115272 if (!Fn->hasPersonalityFn())
1525215273 return EntryEBP;
1525315274
15254 // The RegNodeSize is 6 32-bit words for SEH and 4 for C++ EH. See
15255 // WinEHStatePass for the full struct definition.
15256 int RegNodeSize;
15257 switch (classifyEHPersonality(Fn->getPersonalityFn())) {
15258 default:
15259 report_fatal_error("can only recover FP for MSVC EH personality functions");
15260 case EHPersonality::MSVC_X86SEH: RegNodeSize = 24; break;
15261 case EHPersonality::MSVC_CXX: RegNodeSize = 16; break;
15262 }
15275 int RegNodeSize = getSEHRegistrationNodeSize(Fn);
1526315276
1526415277 // Get an MCSymbol that will ultimately resolve to the frame offset of the EH
1526515278 // registration.
1596215975 static SDValue LowerSEHRESTOREFRAME(SDValue Op, const X86Subtarget *Subtarget,
1596315976 SelectionDAG &DAG) {
1596415977 MachineFunction &MF = DAG.getMachineFunction();
15978 const Function *Fn = MF.getFunction();
1596515979 SDLoc dl(Op);
1596615980 SDValue Chain = Op.getOperand(0);
1596715981
1597515989 unsigned FrameReg =
1597615990 RegInfo->getPtrSizedFrameRegister(DAG.getMachineFunction());
1597715991 unsigned SPReg = RegInfo->getStackRegister();
15992 unsigned SlotSize = RegInfo->getSlotSize();
1597815993
1597915994 // Get incoming EBP.
1598015995 SDValue IncomingEBP =
1598115996 DAG.getCopyFromReg(Chain, dl, FrameReg, VT);
1598215997
15983 // Load [EBP-24] into SP.
15984 SDValue SPAddr =
15985 DAG.getNode(ISD::ADD, dl, VT, IncomingEBP, DAG.getConstant(-24, dl, VT));
15998 // SP is saved in the first field of every registration node, so load
15999 // [EBP-RegNodeSize] into SP.
16000 int RegNodeSize = getSEHRegistrationNodeSize(Fn);
16001 SDValue SPAddr = DAG.getNode(ISD::ADD, dl, VT, IncomingEBP,
16002 DAG.getConstant(-RegNodeSize, dl, VT));
1598616003 SDValue NewSP =
1598716004 DAG.getLoad(VT, dl, Chain, SPAddr, MachinePointerInfo(), false, false,
1598816005 false, VT.getScalarSizeInBits() / 8);
1598916006 Chain = DAG.getCopyToReg(Chain, dl, SPReg, NewSP);
1599016007
15991 // FIXME: Restore the base pointer in case of stack realignment!
15992 if (RegInfo->needsStackRealignment(MF))
15993 report_fatal_error("SEH with stack realignment not yet implemented");
15994
15995 // Adjust EBP to point back to the original frame position.
15996 SDValue NewFP = recoverFramePointer(DAG, MF.getFunction(), IncomingEBP);
15997 Chain = DAG.getCopyToReg(Chain, dl, FrameReg, NewFP);
16008 if (!RegInfo->needsStackRealignment(MF)) {
16009 // Adjust EBP to point back to the original frame position.
16010 SDValue NewFP = recoverFramePointer(DAG, Fn, IncomingEBP);
16011 Chain = DAG.getCopyToReg(Chain, dl, FrameReg, NewFP);
16012 } else {
16013 assert(RegInfo->hasBasePointer(MF) &&
16014 "functions with Win32 EH must use frame or base pointer register");
16015
16016 // Reload the base pointer (ESI) with the adjusted incoming EBP.
16017 SDValue NewBP = recoverFramePointer(DAG, Fn, IncomingEBP);
16018 Chain = DAG.getCopyToReg(Chain, dl, RegInfo->getBaseRegister(), NewBP);
16019
16020 // Reload the spilled EBP value, now that the stack and base pointers are
16021 // set up.
16022 X86MachineFunctionInfo *X86FI = MF.getInfo();
16023 X86FI->setHasSEHFramePtrSave(true);
16024 int FI = MF.getFrameInfo()->CreateSpillStackObject(SlotSize, SlotSize);
16025 X86FI->setSEHFramePtrSaveIndex(FI);
16026 SDValue NewFP = DAG.getLoad(VT, dl, Chain, DAG.getFrameIndex(FI, VT),
16027 MachinePointerInfo(), false, false, false,
16028 VT.getScalarSizeInBits() / 8);
16029 Chain = DAG.getCopyToReg(NewFP, dl, FrameReg, NewFP);
16030 }
16031
1599816032 return Chain;
1599916033 }
1600016034
8383 /// of pushes to pass function parameters.
8484 bool HasPushSequences = false;
8585
86 /// True if the function uses llvm.x86.seh.restoreframe, and it needed a spill
87 /// slot for the frame pointer.
88 bool HasSEHFramePtrSave = false;
89
90 /// The frame index of a stack object containing the original frame pointer
91 /// used to address arguments in a function using a base pointer.
92 int SEHFramePtrSaveIndex = 0;
93
8694 private:
8795 /// ForwardedMustTailRegParms - A list of virtual and physical registers
8896 /// that must be forwarded to every musttail call.
142150 unsigned getNumLocalDynamicTLSAccesses() const { return NumLocalDynamics; }
143151 void incNumLocalDynamicTLSAccesses() { ++NumLocalDynamics; }
144152
153 bool getHasSEHFramePtrSave() const { return HasSEHFramePtrSave; }
154 void setHasSEHFramePtrSave(bool V) { HasSEHFramePtrSave = V; }
155
156 int getSEHFramePtrSaveIndex() const { return SEHFramePtrSaveIndex; }
157 void setSEHFramePtrSaveIndex(int Index) { SEHFramePtrSaveIndex = Index; }
158
145159 SmallVectorImpl &getForwardedMustTailRegParms() {
146160 return ForwardedMustTailRegParms;
147161 }
451451 // use both the SP and the FP, we need a separate base pointer register.
452452 bool CantUseFP = needsStackRealignment(MF);
453453 bool CantUseSP =
454 MFI->hasVarSizedObjects() || MFI->hasInlineAsmWithSPAdjust();
454 MFI->hasVarSizedObjects() || MFI->hasOpaqueSPAdjustment();
455455 return CantUseFP && CantUseSP;
456456 }
457457
3636 // dynamic stack adjustments (hopefully rare) and the base pointer would
3737 // conflict if we had to use it.
3838 MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
39 if (!MFI->hasVarSizedObjects() && !MFI->hasInlineAsmWithSPAdjust())
39 if (!MFI->hasVarSizedObjects() && !MFI->hasOpaqueSPAdjustment())
4040 return false;
4141
4242 const X86RegisterInfo *TRI = static_cast(
0 ; RUN: llc -mtriple=i686-windows-msvc < %s | FileCheck %s
1
2 ; 32-bit catch-all has to use a filter function because that's how it saves the
3 ; exception code.
4
5 @str = linkonce_odr unnamed_addr constant [27 x i8] c"GetExceptionCode(): 0x%lx\0A\00", align 1
6
7 declare i32 @_except_handler3(...)
8 declare void @crash()
9 declare i32 @printf(i8* nocapture readonly, ...) nounwind
10 declare i32 @llvm.eh.typeid.for(i8*)
11 declare i8* @llvm.frameaddress(i32)
12 declare i8* @llvm.localrecover(i8*, i8*, i32)
13 declare void @llvm.localescape(...)
14 declare i8* @llvm.x86.seh.recoverfp(i8*, i8*)
15
16 define i32 @main() personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
17 entry:
18 ; The EH code allocation is overaligned, triggering realignment.
19 %__exceptioncode = alloca i32, align 8
20 call void (...) @llvm.localescape(i32* %__exceptioncode)
21 invoke void @crash() #5
22 to label %__try.cont unwind label %lpad
23
24 lpad: ; preds = %entry
25 %0 = landingpad { i8*, i32 }
26 catch i8* bitcast (i32 ()* @"filt$main" to i8*)
27 %1 = extractvalue { i8*, i32 } %0, 1
28 %2 = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @"filt$main" to i8*)) #4
29 %matches = icmp eq i32 %1, %2
30 br i1 %matches, label %__except, label %eh.resume
31
32 __except: ; preds = %lpad
33 %3 = load i32, i32* %__exceptioncode, align 4
34 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %3) #4
35 br label %__try.cont
36
37 __try.cont: ; preds = %entry, %__except
38 ret i32 0
39
40 eh.resume: ; preds = %lpad
41 resume { i8*, i32 } %0
42 }
43
44 define internal i32 @"filt$main"() {
45 entry:
46 %ebp = tail call i8* @llvm.frameaddress(i32 1)
47 %parentfp = tail call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @main to i8*), i8* %ebp)
48 %code.i8 = tail call i8* @llvm.localrecover(i8* bitcast (i32 ()* @main to i8*), i8* %parentfp, i32 0)
49 %__exceptioncode = bitcast i8* %code.i8 to i32*
50 %info.addr = getelementptr inbounds i8, i8* %ebp, i32 -20
51 %0 = bitcast i8* %info.addr to i32***
52 %1 = load i32**, i32*** %0, align 4
53 %2 = load i32*, i32** %1, align 4
54 %3 = load i32, i32* %2, align 4
55 store i32 %3, i32* %__exceptioncode, align 4
56 ret i32 1
57 }
58
59 ; Check that we can get the exception code from eax to the printf.
60
61 ; CHECK-LABEL: _main:
62 ; CHECK: Lmain$frame_escape_0 = [[code_offs:[-0-9]+]]
63 ; CHECK: Lmain$frame_escape_1 = [[reg_offs:[-0-9]+]]
64 ; CHECK: movl %esp, [[reg_offs]](%esi)
65 ; CHECK: movl $L__ehtable$main,
66 ; EH state 0
67 ; CHECK: movl $0, 40(%esi)
68 ; CHECK: calll _crash
69 ; CHECK: retl
70 ; CHECK: # Block address taken
71 ; stackrestore
72 ; CHECK: movl -24(%ebp), %esp
73 ; CHECK: movl $Lmain$parent_frame_offset, %eax
74 ; CHECK: negl %eax
75 ; CHECK: leal -24(%ebp,%eax), %esi
76 ; CHECK: movl 12(%esi), %ebp # 4-byte Reload
77 ; EH state -1
78 ; CHECK: movl [[code_offs]](%esi), %[[code:[a-z]+]]
79 ; CHECK: movl $-1, 40(%esi)
80 ; CHECK-DAG: movl %[[code]], 4(%esp)
81 ; CHECK-DAG: movl $_str, (%esp)
82 ; CHECK: calll _printf
83
84 ; CHECK: .section .xdata,"dr"
85 ; CHECK: Lmain$parent_frame_offset = Lmain$frame_escape_1
86 ; CHECK: L__ehtable$main
87 ; CHECK-NEXT: .long -1
88 ; CHECK-NEXT: .long _filt$main
89 ; CHECK-NEXT: .long Ltmp{{[0-9]+}}
90
91 ; CHECK-LABEL: _filt$main:
92 ; CHECK: pushl %ebp
93 ; CHECK: movl %esp, %ebp
94 ; CHECK: movl (%ebp), %[[oldebp:[a-z]+]]
95 ; CHECK: movl -20(%[[oldebp]]), %[[ehinfo:[a-z]+]]
96 ; CHECK: movl (%[[ehinfo]]), %[[ehrec:[a-z]+]]
97 ; CHECK: movl (%[[ehrec]]), %[[ehcode:[a-z]+]]
98 ; CHECK: movl %[[ehcode]], {{.*}}(%{{.*}})