llvm.org GIT mirror llvm / d0b2625
[WinEH] Make llvm.x86.seh.recoverfp work on x64 It adjusts from RSP-after-prologue to RBP, which is what SEH filters need to do before they can use llvm.localrecover. Fixes SEH filter captures, which were broken in r250088. Issue reported by Alex Crichton. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255707 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 4 years ago
10 changed file(s) with 41 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
107107
108108 int EHRegNodeFrameIndex = INT_MAX;
109109 int EHRegNodeEndOffset = INT_MAX;
110 int SEHSetFrameOffset = INT_MAX;
110111
111112 WinEHFuncInfo() {}
112113 };
505505 void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) {
506506 auto &OS = *Asm->OutStreamer;
507507 MCContext &Ctx = Asm->OutContext;
508
509508 const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
509
510 // Emit a label assignment with the SEH frame offset so we can use it for
511 // llvm.x86.seh.recoverfp.
512 StringRef FLinkageName =
513 GlobalValue::getRealLinkageName(MF->getFunction()->getName());
514 MCSymbol *ParentFrameOffset =
515 Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
516 const MCExpr *MCOffset =
517 MCConstantExpr::create(FuncInfo.SEHSetFrameOffset, Ctx);
518 Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset);
519
510520 // Use the assembler to compute the number of table entries through label
511521 // difference and division.
512522 MCSymbol *TableBegin =
911911 uint64_t MaxAlign = calculateMaxStackAlign(MF); // Desired stack alignment.
912912 uint64_t StackSize = MFI->getStackSize(); // Number of bytes to allocate.
913913 bool IsFunclet = MBB.isEHFuncletEntry();
914 EHPersonality Personality = EHPersonality::Unknown;
915 if (Fn->hasPersonalityFn())
916 Personality = classifyEHPersonality(Fn->getPersonalityFn());
914917 bool FnHasClrFunclet =
915 MMI.hasEHFunclets() &&
916 classifyEHPersonality(Fn->getPersonalityFn()) == EHPersonality::CoreCLR;
918 MMI.hasEHFunclets() && Personality == EHPersonality::CoreCLR;
917919 bool IsClrFunclet = IsFunclet && FnHasClrFunclet;
918920 bool HasFP = hasFP(MF);
919921 bool IsWin64CC = STI.isCallingConvWin64(Fn->getCallingConv());
12491251 .addReg(SPOrEstablisher);
12501252
12511253 // If this is not a funclet, emit the CFI describing our frame pointer.
1252 if (NeedsWinCFI && !IsFunclet)
1254 if (NeedsWinCFI && !IsFunclet) {
12531255 BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SetFrame))
12541256 .addImm(FramePtr)
12551257 .addImm(SEHFrameOffset)
12561258 .setMIFlag(MachineInstr::FrameSetup);
1259 if (isAsynchronousEHPersonality(Personality))
1260 MF.getWinEHFuncInfo()->SEHSetFrameOffset = SEHFrameOffset;
1261 }
12571262 } else if (IsFunclet && STI.is32Bit()) {
12581263 // Reset EBP / ESI to something good for funclets.
12591264 MBBI = restoreWin32EHStackPointers(MBB, MBBI, DL);
12601265 // If we're a catch funclet, we can be returned to via catchret. Save ESP
12611266 // into the registration node so that the runtime will restore it for us.
12621267 if (!MBB.isCleanupFuncletEntry()) {
1263 assert(classifyEHPersonality(Fn->getPersonalityFn()) ==
1264 EHPersonality::MSVC_CXX);
1268 assert(Personality == EHPersonality::MSVC_CXX);
12651269 unsigned FrameReg;
12661270 int FI = MF.getWinEHFuncInfo()->EHRegNodeFrameIndex;
12671271 int64_t EHRegOffset = getFrameIndexReference(MF, FI, FrameReg);
1617216172 "can only recover FP for 32-bit MSVC EH personality functions");
1617316173 }
1617416174
16175 /// When the 32-bit MSVC runtime transfers control to us, either to an outlined
16175 /// When the MSVC runtime transfers control to us, either to an outlined
1617616176 /// function or when returning to a parent frame after catching an exception, we
1617716177 /// recover the parent frame pointer by doing arithmetic on the incoming EBP.
1617816178 /// Here's the math:
1617916179 /// RegNodeBase = EntryEBP - RegNodeSize
16180 /// ParentFP = RegNodeBase - RegNodeFrameOffset
16180 /// ParentFP = RegNodeBase - ParentFrameOffset
1618116181 /// Subtracting RegNodeSize takes us to the offset of the registration node, and
1618216182 /// subtracting the offset (negative on x86) takes us back to the parent FP.
1618316183 static SDValue recoverFramePointer(SelectionDAG &DAG, const Function *Fn,
1619416194 if (!Fn->hasPersonalityFn())
1619516195 return EntryEBP;
1619616196
16197 int RegNodeSize = getSEHRegistrationNodeSize(Fn);
16198
1619916197 // Get an MCSymbol that will ultimately resolve to the frame offset of the EH
16200 // registration.
16198 // registration, or the .set_setframe offset.
1620116199 MCSymbol *OffsetSym =
1620216200 MF.getMMI().getContext().getOrCreateParentFrameOffsetSymbol(
1620316201 GlobalValue::getRealLinkageName(Fn->getName()));
1620416202 SDValue OffsetSymVal = DAG.getMCSymbol(OffsetSym, PtrVT);
16205 SDValue RegNodeFrameOffset =
16203 SDValue ParentFrameOffset =
1620616204 DAG.getNode(ISD::LOCAL_RECOVER, dl, PtrVT, OffsetSymVal);
1620716205
16206 // Return EntryEBP + ParentFrameOffset for x64. This adjusts from RSP after
16207 // prologue to RBP in the parent function.
16208 const X86Subtarget &Subtarget =
16209 static_cast(DAG.getSubtarget());
16210 if (Subtarget.is64Bit())
16211 return DAG.getNode(ISD::ADD, dl, PtrVT, EntryEBP, ParentFrameOffset);
16212
16213 int RegNodeSize = getSEHRegistrationNodeSize(Fn);
1620816214 // RegNodeBase = EntryEBP - RegNodeSize
16209 // ParentFP = RegNodeBase - RegNodeFrameOffset
16215 // ParentFP = RegNodeBase - ParentFrameOffset
1621016216 SDValue RegNodeBase = DAG.getNode(ISD::SUB, dl, PtrVT, EntryEBP,
1621116217 DAG.getConstant(RegNodeSize, dl, PtrVT));
16212 return DAG.getNode(ISD::SUB, dl, PtrVT, RegNodeBase, RegNodeFrameOffset);
16218 return DAG.getNode(ISD::SUB, dl, PtrVT, RegNodeBase, ParentFrameOffset);
1621316219 }
1621416220
1621516221 static SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, const X86Subtarget *Subtarget,
4141 ; CHECK: .LBB0_[[return]]:
4242
4343 ; CHECK: .seh_handlerdata
44 ; CHECK-NEXT: .Lfoo$parent_frame_offset = 32
4445 ; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
4546 ; CHECK-NEXT: .Llsda_begin0:
4647 ; CHECK-NEXT: .long .Ltmp0@IMGREL+1
3535 ; CHECK: callq printf
3636
3737 ; CHECK: .seh_handlerdata
38 ; CHECK-NEXT: .Lmain$parent_frame_offset
3839 ; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
3940 ; CHECK-NEXT: .Llsda_begin0:
4041 ; CHECK-NEXT: .long .Ltmp{{[0-9]+}}@IMGREL
116116 ; CHECK: jmp .LBB1_[[epilogue]]
117117
118118 ; CHECK: .seh_handlerdata
119 ; CHECK-NEXT: .Lmain$parent_frame_offset = 32
119120 ; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
120121 ; CHECK-NEXT: .Llsda_begin0:
121122 ; CHECK-NEXT: .long .Ltmp0@IMGREL+1
7878 ; CHECK: retq
7979 ;
8080 ; CHECK: .seh_handlerdata
81 ; CHECK-NEXT: .Luse_both$parent_frame_offset
8182 ; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
8283 ; CHECK-NEXT: .Llsda_begin0:
8384 ; CHECK-NEXT: .long .Ltmp0@IMGREL+1
2525 ; X64: retq
2626
2727 ; X64: .seh_handlerdata
28 ; X64-NEXT: .Lmain$parent_frame_offset = 32
2829 ; X64-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
2930 ; X64-NEXT: .Llsda_begin0:
3031 ; X64-NEXT: .long .Ltmp0@IMGREL+1
7777 ; CHECK: jmp [[cont_bb]]
7878
7979 ; CHECK: .seh_handlerdata
80 ; CHECK-NEXT: .Lsafe_div$parent_frame_offset
8081 ; CHECK-NEXT: .long (.Llsda_end0-.Llsda_begin0)/16
8182 ; CHECK-NEXT: .Llsda_begin0:
8283 ; CHECK-NEXT: .long .Ltmp0@IMGREL+1