llvm.org GIT mirror llvm / 69d051c
[SEH] Emit 32-bit SEH tables for the new EH IR The 32-bit tables don't actually contain PC range data, so emitting them is incredibly simple. The 64-bit tables, on the other hand, use the same table for state numbering as well as label ranges. This makes things more difficult, so it will be implemented later. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@247192 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 4 years ago
9 changed file(s) with 523 addition(s) and 104 deletion(s). Raw diff Collapse all Expand all
1313 #ifndef LLVM_CODEGEN_WINEHFUNCINFO_H
1414 #define LLVM_CODEGEN_WINEHFUNCINFO_H
1515
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/PointerUnion.h"
1618 #include "llvm/ADT/SmallVector.h"
1719 #include "llvm/ADT/TinyPtrVector.h"
18 #include "llvm/ADT/DenseMap.h"
1920
2021 namespace llvm {
2122 class AllocaInst;
119120 const Value *Cleanup;
120121 };
121122
123 typedef PointerUnion MBBOrBasicBlock;
124 typedef PointerUnion ValueOrMBB;
125
126 /// Similar to WinEHUnwindMapEntry, but supports SEH filters.
127 struct SEHUnwindMapEntry {
128 /// If unwinding continues through this handler, transition to the handler at
129 /// this state. This indexes into SEHUnwindMap.
130 int ToState = -1;
131
132 /// Holds the filter expression function.
133 const Function *Filter = nullptr;
134
135 /// Holds the __except or __finally basic block.
136 MBBOrBasicBlock Handler;
137 };
138
122139 struct WinEHHandlerType {
123140 int Adjectives;
124141 GlobalVariable *TypeDescriptor;
125142 int CatchObjRecoverIdx;
126 const Value *Handler;
127 MachineBasicBlock *HandlerMBB;
143 ValueOrMBB Handler;
128144 };
129145
130146 struct WinEHTryBlockMapEntry {
131 int TryLow;
132 int TryHigh;
147 int TryLow = -1;
148 int TryHigh = -1;
133149 int CatchHigh = -1;
134150 SmallVector HandlerArray;
135151 };
146162 DenseMap HandlerBaseState;
147163 SmallVector UnwindMap;
148164 SmallVector TryBlockMap;
165 SmallVector SEHUnwindMap;
149166 SmallVector, 4> IPToStateList;
150167 int UnwindHelpFrameIdx = INT_MAX;
151168 int UnwindHelpFrameOffset = -1;
168185 void calculateWinCXXEHStateNumbers(const Function *ParentFn,
169186 WinEHFuncInfo &FuncInfo);
170187
188 void calculateSEHStateNumbers(const Function *ParentFn,
189 WinEHFuncInfo &FuncInfo);
171190 }
172191 #endif // LLVM_CODEGEN_WINEHFUNCINFO_H
160160 // Emit the tables appropriate to the personality function in use. If we
161161 // don't recognize the personality, assume it uses an Itanium-style LSDA.
162162 if (Per == EHPersonality::MSVC_Win64SEH)
163 emitCSpecificHandlerTable();
163 emitCSpecificHandlerTable(MF);
164164 else if (Per == EHPersonality::MSVC_X86SEH)
165165 emitExceptHandlerTable(MF);
166166 else if (Per == EHPersonality::MSVC_CXX)
221221 /// imagerel32 LabelLPad; // Zero means __finally.
222222 /// } Entries[NumEntries];
223223 /// };
224 void WinException::emitCSpecificHandlerTable() {
224 void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) {
225225 const std::vector &PadInfos = MMI->getLandingPads();
226
227 WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(MF->getFunction());
228 if (!FuncInfo.SEHUnwindMap.empty())
229 report_fatal_error("x64 SEH tables not yet implemented");
226230
227231 // Simplifying assumptions for first implementation:
228232 // - Cleanups are not implemented.
306310 Asm->OutStreamer->EmitIntValue(0, 4);
307311 }
308312 }
313 }
314
315 /// Retreive the MCSymbol for a GlobalValue or MachineBasicBlock. GlobalValues
316 /// are used in the old WinEH scheme, and they will be removed eventually.
317 static MCSymbol *getMCSymbolForMBBOrGV(AsmPrinter *Asm, ValueOrMBB Handler) {
318 if (Handler.is())
319 return Handler.get()->getSymbol();
320 else
321 return Asm->getSymbol(cast(Handler.get()));
309322 }
310323
311324 void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
421434 int CatchHigh = TBME.CatchHigh;
422435 if (CatchHigh == -1) {
423436 for (WinEHHandlerType &HT : TBME.HandlerArray)
424 CatchHigh = std::max(
425 CatchHigh,
426 FuncInfo.CatchHandlerMaxState[cast(HT.Handler)]);
437 CatchHigh =
438 std::max(CatchHigh, FuncInfo.CatchHandlerMaxState[cast(
439 HT.Handler.get())]);
427440 }
428441
429442 assert(TBME.TryLow <= TBME.TryHigh);
463476 FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext);
464477 }
465478
466 OS.EmitIntValue(HT.Adjectives, 4); // Adjectives
467 OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); // Type
468 OS.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset
469 if (HT.HandlerMBB) // Handler
470 OS.EmitValue(create32bitRef(HT.HandlerMBB->getSymbol()), 4);
471 else
472 OS.EmitValue(create32bitRef(HT.Handler), 4);
479 MCSymbol *HandlerSym = getMCSymbolForMBBOrGV(Asm, HT.Handler);
480
481 OS.EmitIntValue(HT.Adjectives, 4); // Adjectives
482 OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); // Type
483 OS.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset
484 OS.EmitValue(create32bitRef(HandlerSym), 4); // Handler
473485
474486 if (shouldEmitPersonality) {
475487 if (FuncInfo.CatchHandlerParentFrameObjOffset.empty()) {
481493 } else {
482494 MCSymbol *ParentFrameOffset =
483495 Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
484 GlobalValue::getRealLinkageName(HT.Handler->getName()));
496 GlobalValue::getRealLinkageName(
497 HT.Handler.get()->getName()));
485498 const MCSymbolRefExpr *ParentFrameOffsetRef =
486499 MCSymbolRefExpr::create(ParentFrameOffset, Asm->OutContext);
487500 OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
640653 OS.EmitIntValue(0, 4);
641654 BaseState = -2;
642655 }
656
657 if (!FuncInfo.SEHUnwindMap.empty()) {
658 for (SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) {
659 MCSymbol *ExceptOrFinally =
660 UME.Handler.get()->getSymbol();
661 OS.EmitIntValue(UME.ToState, 4); // ToState
662 OS.EmitValue(create32bitRef(UME.Filter), 4); // Filter
663 OS.EmitValue(create32bitRef(ExceptOrFinally), 4); // Except/Finally
664 }
665 return;
666 }
667 // FIXME: The following code is for the old landingpad-based SEH
668 // implementation. Remove it when possible.
643669
644670 // Build a list of pointers to LandingPadInfos and then sort by WinEHState.
645671 const std::vector &PadInfos = MMI->getLandingPads();
3535 /// True if this is a 64-bit target and we should use image relative offsets.
3636 bool useImageRel32 = false;
3737
38 void emitCSpecificHandlerTable();
38 void emitCSpecificHandlerTable(const MachineFunction *MF);
3939
4040 /// Emit the EH table data for 32-bit and 64-bit functions using
4141 /// the __CxxFrameHandler3 personality.
286286 addSEHHandlersForLPads(LPads);
287287 }
288288
289 // Calculate state numbers if we haven't already.
289290 WinEHFuncInfo &EHInfo = MMI.getWinEHFuncInfo(&fn);
290291 if (Personality == EHPersonality::MSVC_CXX) {
291 // Calculate state numbers and then map from funclet BBs to MBBs.
292292 const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
293293 calculateWinCXXEHStateNumbers(WinEHParentFn, EHInfo);
294 } else {
295 const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
296 calculateSEHStateNumbers(WinEHParentFn, EHInfo);
297 }
298
299 // Map all BB references in the EH data to MBBs.
294300 for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap)
295301 for (WinEHHandlerType &H : TBME.HandlerArray)
296 if (const auto *BB = dyn_cast(H.Handler))
297 H.HandlerMBB = MBBMap[BB];
298 // If there's an explicit EH registration node on the stack, record its
299 // frame index.
300 if (EHInfo.EHRegNode && EHInfo.EHRegNode->getParent()->getParent() == Fn) {
301 assert(StaticAllocaMap.count(EHInfo.EHRegNode));
302 EHInfo.EHRegNodeFrameIndex = StaticAllocaMap[EHInfo.EHRegNode];
303 }
302 if (const auto *BB =
303 dyn_cast(H.Handler.get()))
304 H.Handler = MBBMap[BB];
305 for (SEHUnwindMapEntry &UME : EHInfo.SEHUnwindMap) {
306 const BasicBlock *BB = UME.Handler.get();
307 UME.Handler = MBBMap[BB];
308 }
309 // If there's an explicit EH registration node on the stack, record its
310 // frame index.
311 if (EHInfo.EHRegNode && EHInfo.EHRegNode->getParent()->getParent() == Fn) {
312 assert(StaticAllocaMap.count(EHInfo.EHRegNode));
313 EHInfo.EHRegNodeFrameIndex = StaticAllocaMap[EHInfo.EHRegNode];
304314 }
305315
306316 // Copy the state numbers to LandingPadInfo for the current function, which
19881988 // and catchendpads for successors.
19891989 MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)];
19901990 const BasicBlock *EHPadBB = I.getSuccessor(1);
1991 bool IsLandingPad = EHPadBB->isLandingPad();
19921991
19931992 const Value *Callee(I.getCalledValue());
19941993 const Function *Fn = dyn_cast(Callee);
20242023 // Catchpads are conditional branches that add real MBB destinations and
20252024 // continue the loop. EH "end" pads are not real BBs and simply continue.
20262025 SmallVector UnwindDests;
2026 bool IsMSVCCXX = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn()) ==
2027 EHPersonality::MSVC_CXX;
20272028 while (EHPadBB) {
20282029 const Instruction *Pad = EHPadBB->getFirstNonPHI();
2029 if (isa(Pad) || isa(Pad)) {
2030 assert(FuncInfo.MBBMap[EHPadBB]);
2031 // Stop on cleanup pads and landingpads.
2030 if (isa(Pad)) {
2031 // Stop on landingpads. They are not funclets.
20322032 UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
2033 break;
2034 } else if (isa(Pad) || isa(Pad)) {
2035 // Stop on cleanup pads. Cleanups are always funclet entries for all known
2036 // personalities.
2037 UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
2038 UnwindDests.back()->setIsEHFuncletEntry();
20332039 break;
20342040 } else if (const auto *CPI = dyn_cast(Pad)) {
20352041 // Add the catchpad handler to the possible destinations.
20362042 UnwindDests.push_back(FuncInfo.MBBMap[CPI->getNormalDest()]);
2043 // In MSVC C++, catchblocks are funclets and need prologues.
2044 if (IsMSVCCXX)
2045 UnwindDests.back()->setIsEHFuncletEntry();
20372046 EHPadBB = CPI->getUnwindDest();
20382047 } else if (const auto *CEPI = dyn_cast(Pad)) {
20392048 EHPadBB = CEPI->getUnwindDest();
20422051 }
20432052 }
20442053
2045 // Update successor info
2054 // Update successor info.
20462055 // FIXME: The weights for catchpads will be wrong.
20472056 addSuccessorWithWeight(InvokeMBB, Return);
2048 for (auto *UnwindDest : UnwindDests) {
2057 for (MachineBasicBlock *UnwindDest : UnwindDests) {
20492058 UnwindDest->setIsEHPad();
2050 if (!IsLandingPad)
2051 UnwindDest->setIsEHFuncletEntry();
20522059 addSuccessorWithWeight(InvokeMBB, UnwindDest);
20532060 }
20542061
26152615 cast(CS->getAggregateElement(1)->stripPointerCasts());
26162616 }
26172617 HT.Handler = CPI->getNormalDest();
2618 HT.HandlerMBB = nullptr;
26192618 // FIXME: Pass CPI->getArgOperand(1).
26202619 HT.CatchObjRecoverIdx = -1;
26212620 TBME.HandlerArray.push_back(HT);
26442643 continue;
26452644 int N;
26462645 for (N = 0; N < NumHandlers; ++N) {
2647 if (Entry.HandlerArray[N].Handler != Handlers[N]->getHandlerBlockOrFunc())
2646 if (Entry.HandlerArray[N].Handler.get() !=
2647 Handlers[N]->getHandlerBlockOrFunc())
26482648 break; // breaks out of inner loop
26492649 }
26502650 // If all the handlers match, this is what we were looking for.
26912691 cast(CS->getAggregateElement(1)->stripPointerCasts());
26922692 }
26932693 HT.Handler = cast(CH->getHandlerBlockOrFunc());
2694 HT.HandlerMBB = nullptr;
26952694 HT.CatchObjRecoverIdx = CH->getExceptionVarIndex();
26962695 TBME.HandlerArray.push_back(HT);
26972696 }
29482947 }
29492948 }
29502949
2951 static const BasicBlock *getSingleCatchPadPredecessor(const BasicBlock &BB) {
2952 for (const BasicBlock *PredBlock : predecessors(&BB))
2953 if (isa(PredBlock->getFirstNonPHI()))
2954 return PredBlock;
2950 static const CatchPadInst *getSingleCatchPadPredecessor(const BasicBlock *BB) {
2951 for (const BasicBlock *PredBlock : predecessors(BB))
2952 if (auto *CPI = dyn_cast(PredBlock->getFirstNonPHI()))
2953 return CPI;
29552954 return nullptr;
2955 }
2956
2957 /// Find all the catchpads that feed directly into the catchendpad. Frontends
2958 /// using this personality should ensure that each catchendpad and catchpad has
2959 /// one or zero catchpad predecessors.
2960 ///
2961 /// The following C++ generates the IR after it:
2962 /// try {
2963 /// } catch (A) {
2964 /// } catch (B) {
2965 /// }
2966 ///
2967 /// IR:
2968 /// %catchpad.A
2969 /// catchpad [i8* A typeinfo]
2970 /// to label %catch.A unwind label %catchpad.B
2971 /// %catchpad.B
2972 /// catchpad [i8* B typeinfo]
2973 /// to label %catch.B unwind label %endcatches
2974 /// %endcatches
2975 /// catchendblock unwind to caller
2976 void findCatchPadsForCatchEndPad(
2977 const BasicBlock *CatchEndBB,
2978 SmallVectorImpl &Handlers) {
2979 const CatchPadInst *CPI = getSingleCatchPadPredecessor(CatchEndBB);
2980 while (CPI) {
2981 Handlers.push_back(CPI);
2982 CPI = getSingleCatchPadPredecessor(CPI->getParent());
2983 }
2984 // We've pushed these back into reverse source order. Reverse them to get
2985 // the list back into source order.
2986 std::reverse(Handlers.begin(), Handlers.end());
29562987 }
29572988
29582989 // Given BB which ends in an unwind edge, return the EHPad that this BB belongs
29693000 return cast(TI)->getCleanupPad()->getParent();
29703001 }
29713002
2972 static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo,
2973 const BasicBlock &BB,
2974 int ParentState) {
3003 static void calculateExplicitCXXStateNumbers(WinEHFuncInfo &FuncInfo,
3004 const BasicBlock &BB,
3005 int ParentState) {
29753006 assert(BB.isEHPad());
29763007 const Instruction *FirstNonPHI = BB.getFirstNonPHI();
29773008 // All catchpad instructions will be handled when we process their
29803011 return;
29813012
29823013 if (isa(FirstNonPHI)) {
2983 const BasicBlock *TryPad = &BB;
2984 const BasicBlock *LastTryPad = nullptr;
29853014 SmallVector Handlers;
2986 do {
2987 LastTryPad = TryPad;
2988 TryPad = getSingleCatchPadPredecessor(*TryPad);
2989 if (TryPad)
2990 Handlers.push_back(cast(TryPad->getFirstNonPHI()));
2991 } while (TryPad);
2992 // We've pushed these back into reverse source order. Reverse them to get
2993 // the list back into source order.
2994 std::reverse(Handlers.begin(), Handlers.end());
3015 findCatchPadsForCatchEndPad(&BB, Handlers);
3016 const BasicBlock *FirstTryPad = Handlers.front()->getParent();
29953017 int TryLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
29963018 FuncInfo.EHPadStateMap[Handlers.front()] = TryLow;
2997 for (const BasicBlock *PredBlock : predecessors(LastTryPad))
3019 for (const BasicBlock *PredBlock : predecessors(FirstTryPad))
29983020 if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
2999 calculateExplicitStateNumbers(FuncInfo, *PredBlock, TryLow);
3021 calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, TryLow);
30003022 int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
3023
3024 // catchpads are separate funclets in C++ EH due to the way rethrow works.
3025 // In SEH, they aren't, so no invokes will unwind to the catchendpad.
30013026 FuncInfo.EHPadStateMap[FirstNonPHI] = CatchLow;
30023027 int TryHigh = CatchLow - 1;
30033028 for (const BasicBlock *PredBlock : predecessors(&BB))
30043029 if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
3005 calculateExplicitStateNumbers(FuncInfo, *PredBlock, CatchLow);
3030 calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CatchLow);
30063031 int CatchHigh = FuncInfo.getLastStateNumber();
30073032 addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers);
3008 DEBUG(dbgs() << "TryLow[" << LastTryPad->getName() << "]: " << TryLow
3033 DEBUG(dbgs() << "TryLow[" << FirstTryPad->getName() << "]: " << TryLow
30093034 << '\n');
3010 DEBUG(dbgs() << "TryHigh[" << LastTryPad->getName() << "]: " << TryHigh
3035 DEBUG(dbgs() << "TryHigh[" << FirstTryPad->getName() << "]: " << TryHigh
30113036 << '\n');
3012 DEBUG(dbgs() << "CatchHigh[" << LastTryPad->getName() << "]: " << CatchHigh
3037 DEBUG(dbgs() << "CatchHigh[" << FirstTryPad->getName() << "]: " << CatchHigh
30133038 << '\n');
30143039 } else if (isa(FirstNonPHI)) {
30153040 int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, &BB);
30183043 << BB.getName() << '\n');
30193044 for (const BasicBlock *PredBlock : predecessors(&BB))
30203045 if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
3021 calculateExplicitStateNumbers(FuncInfo, *PredBlock, CleanupState);
3046 calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CleanupState);
30223047 } else if (isa(FirstNonPHI)) {
30233048 report_fatal_error("Not yet implemented!");
30243049 } else {
30253050 llvm_unreachable("unexpected EH Pad!");
3051 }
3052 }
3053
3054 static int addSEHHandler(WinEHFuncInfo &FuncInfo, int ParentState,
3055 const Function *Filter, const BasicBlock *Handler) {
3056 SEHUnwindMapEntry Entry;
3057 Entry.ToState = ParentState;
3058 Entry.Filter = Filter;
3059 Entry.Handler = Handler;
3060 FuncInfo.SEHUnwindMap.push_back(Entry);
3061 return FuncInfo.SEHUnwindMap.size() - 1;
3062 }
3063
3064 static void calculateExplicitSEHStateNumbers(WinEHFuncInfo &FuncInfo,
3065 const BasicBlock &BB,
3066 int ParentState) {
3067 assert(BB.isEHPad());
3068 const Instruction *FirstNonPHI = BB.getFirstNonPHI();
3069 // All catchpad instructions will be handled when we process their
3070 // respective catchendpad instruction.
3071 if (isa(FirstNonPHI))
3072 return;
3073
3074 if (isa(FirstNonPHI)) {
3075 // Extract the filter function and the __except basic block and create a
3076 // state for them.
3077 SmallVector Handlers;
3078 findCatchPadsForCatchEndPad(&BB, Handlers);
3079 assert(Handlers.size() == 1 &&
3080 "SEH doesn't have multiple handlers per __try");
3081 const CatchPadInst *CPI = Handlers.front();
3082 const BasicBlock *CatchPadBB = CPI->getParent();
3083 const Function *Filter =
3084 cast(CPI->getArgOperand(0)->stripPointerCasts());
3085 int TryState =
3086 addSEHHandler(FuncInfo, ParentState, Filter, CPI->getNormalDest());
3087
3088 // Everything in the __try block uses TryState as its parent state.
3089 FuncInfo.EHPadStateMap[CPI] = TryState;
3090 DEBUG(dbgs() << "Assigning state #" << TryState << " to BB "
3091 << CatchPadBB->getName() << '\n');
3092 for (const BasicBlock *PredBlock : predecessors(CatchPadBB))
3093 if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
3094 calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, TryState);
3095
3096 // Everything in the __except block unwinds to ParentState, just like code
3097 // outside the __try.
3098 FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState;
3099 DEBUG(dbgs() << "Assigning state #" << ParentState << " to BB "
3100 << BB.getName() << '\n');
3101 for (const BasicBlock *PredBlock : predecessors(&BB))
3102 if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
3103 calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, ParentState);
3104 } else if (isa(FirstNonPHI)) {
3105 int CleanupState =
3106 addSEHHandler(FuncInfo, ParentState, /*Filter=*/nullptr, &BB);
3107 FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
3108 DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
3109 << BB.getName() << '\n');
3110 for (const BasicBlock *PredBlock : predecessors(&BB))
3111 if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
3112 calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, CleanupState);
3113 } else if (isa(FirstNonPHI)) {
3114 report_fatal_error("Not yet implemented!");
3115 } else {
3116 llvm_unreachable("unexpected EH Pad!");
3117 }
3118 }
3119
3120 /// Check if the EH Pad unwinds to caller. Cleanups are a little bit of a
3121 /// special case because we have to look at the cleanupret instruction that uses
3122 /// the cleanuppad.
3123 static bool doesEHPadUnwindToCaller(const Instruction *EHPad) {
3124 auto *CPI = dyn_cast(EHPad);
3125 if (!CPI)
3126 return EHPad->mayThrow();
3127
3128 // This cleanup does not return or unwind, so we say it unwinds to caller.
3129 if (CPI->use_empty())
3130 return true;
3131
3132 const Instruction *User = CPI->user_back();
3133 if (auto *CRI = dyn_cast(User))
3134 return CRI->unwindsToCaller();
3135 return cast(User)->unwindsToCaller();
3136 }
3137
3138 void llvm::calculateSEHStateNumbers(const Function *ParentFn,
3139 WinEHFuncInfo &FuncInfo) {
3140 // Don't compute state numbers twice.
3141 if (!FuncInfo.SEHUnwindMap.empty())
3142 return;
3143
3144 for (const BasicBlock &BB : *ParentFn) {
3145 if (!BB.isEHPad() || !doesEHPadUnwindToCaller(BB.getFirstNonPHI()))
3146 continue;
3147 calculateExplicitSEHStateNumbers(FuncInfo, BB, -1);
30263148 }
30273149 }
30283150
30403162 // Skip cleanupendpads; they are exits, not entries.
30413163 if (isa(FirstNonPHI))
30423164 continue;
3043 // Check if the EH Pad has no exceptional successors (i.e. it unwinds to
3044 // caller). Cleanups are a little bit of a special case because their
3045 // control flow cannot be determined by looking at the pad but instead by
3046 // the pad's users.
3047 bool HasNoSuccessors = false;
3048 if (FirstNonPHI->mayThrow()) {
3049 HasNoSuccessors = true;
3050 } else if (auto *CPI = dyn_cast(FirstNonPHI)) {
3051 if (CPI->use_empty()) {
3052 HasNoSuccessors = true;
3053 } else {
3054 const Instruction *User = CPI->user_back();
3055 if (auto *CRI = dyn_cast(User))
3056 HasNoSuccessors = CRI->unwindsToCaller();
3057 else
3058 HasNoSuccessors = cast(User)->unwindsToCaller();
3059 }
3060 }
3061
3062 if (!HasNoSuccessors)
3165 if (!doesEHPadUnwindToCaller(FirstNonPHI))
30633166 continue;
3064 calculateExplicitStateNumbers(FuncInfo, BB, -1);
3167 calculateExplicitCXXStateNumbers(FuncInfo, BB, -1);
30653168 IsExplicit = true;
30663169 }
30673170
1687916879 SDLoc DL(Op);
1688016880
1688116881 MVT PtrVT = getPointerTy(DAG.getDataLayout());
16882
16883 MachineFunction &MF = DAG.getMachineFunction();
16884 if (isAsynchronousEHPersonality(
16885 classifyEHPersonality(MF.getFunction()->getPersonalityFn()))) {
16886 // For SEH, codegen catchret as a branch for now.
16887 // FIXME: Insert something to restore the frame.
16888 return DAG.getNode(ISD::BR, DL, MVT::Other, Chain, Dest);
16889 }
16890
16891
1688216892 unsigned ReturnReg = (PtrVT == MVT::i64 ? X86::RAX : X86::EAX);
1688316893
1688416894 // Load the address of the destination block.
6767 void unlinkExceptionRegistration(IRBuilder<> &Builder);
6868 void addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo);
6969 void addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo);
70 void addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo,
71 Function &F, int BaseState);
70 void addStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo,
71 Function &F, int BaseState);
7272 void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State);
73 void insertRestoreFrame(BasicBlock *BB);
7374
7475 Value *emitEHLSDA(IRBuilder<> &Builder, Function *F);
7576
9091 Function *FrameRecover = nullptr;
9192 Function *FrameAddress = nullptr;
9293 Function *FrameEscape = nullptr;
94 Function *RestoreFrame = nullptr;
9395
9496 // Per-function state
9597 EHPersonality Personality = EHPersonality::Unknown;
122124 FrameEscape = Intrinsic::getDeclaration(TheModule, Intrinsic::localescape);
123125 FrameRecover = Intrinsic::getDeclaration(TheModule, Intrinsic::localrecover);
124126 FrameAddress = Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress);
127 RestoreFrame =
128 Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe);
125129 return false;
126130 }
127131
413417 calculateWinCXXEHStateNumbers(&F, FuncInfo);
414418
415419 // The base state for the parent is -1.
416 addCXXStateStoresToFunclet(RegNode, FuncInfo, F, -1);
420 addStateStoresToFunclet(RegNode, FuncInfo, F, -1);
417421
418422 // Set up RegNodeEscapeIndex
419423 int RegNodeEscapeIndex = escapeRegNode(F);
433437 FrameRecover, {FI8, ParentFP, Builder.getInt32(RegNodeEscapeIndex)});
434438 RecoveredRegNode =
435439 Builder.CreateBitCast(RecoveredRegNode, RegNodeTy->getPointerTo(0));
436 addCXXStateStoresToFunclet(RecoveredRegNode, FuncInfo, *Handler, BaseState);
440 addStateStoresToFunclet(RecoveredRegNode, FuncInfo, *Handler, BaseState);
437441 }
438442 }
439443
469473 return Args.size() - 1;
470474 }
471475
472 void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode,
473 WinEHFuncInfo &FuncInfo,
474 Function &F, int BaseState) {
475 Function *RestoreFrame =
476 Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe);
476 void WinEHStatePass::insertRestoreFrame(BasicBlock *BB) {
477 Instruction *Start = BB->getFirstInsertionPt();
478 if (match(Start, m_Intrinsic()))
479 return;
480 IRBuilder<> Builder(Start);
481 Builder.CreateCall(RestoreFrame, {});
482 }
483
484 void WinEHStatePass::addStateStoresToFunclet(Value *ParentRegNode,
485 WinEHFuncInfo &FuncInfo,
486 Function &F, int BaseState) {
477487 // Iterate all the instructions and emit state number stores.
478488 for (BasicBlock &BB : F) {
479489 for (Instruction &I : BB) {
493503 }
494504 }
495505
496 // Insert calls to llvm.x86.seh.restoreframe at catchret destinations.
497 if (auto *CR = dyn_cast(BB.getTerminator())) {
498 Instruction *Start = CR->getSuccessor()->begin();
499 assert(!isa(Start) &&
500 "winehprepare failed to demote phi after catchret");
501 if (match(Start, m_Intrinsic()))
502 continue;
503 IRBuilder<> Builder(Start);
504 Builder.CreateCall(RestoreFrame, {});
505 }
506 // Insert calls to llvm.x86.seh.restoreframe at catchret destinations. In
507 // SEH, insert them before the catchret.
508 // FIXME: We should probably do this as part of catchret lowering in the
509 // DAG.
510 if (auto *CR = dyn_cast(BB.getTerminator()))
511 insertRestoreFrame(Personality == EHPersonality::MSVC_X86SEH
512 ? CR->getParent()
513 : CR->getSuccessor());
506514 }
507515 }
508516
517525 // too much trouble.
518526 int RegNodeEscapeIndex = escapeRegNode(F);
519527 FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex;
528
529 // If this funciton uses the new EH IR, use the explicit state numbering
530 // algorithm and return early.
531 bool UsesLPads = false;
532 for (BasicBlock &BB : F) {
533 if (BB.isLandingPad()) {
534 UsesLPads = true;
535 break;
536 }
537 }
538 if (!UsesLPads) {
539 calculateSEHStateNumbers(&F, FuncInfo);
540 addStateStoresToFunclet(RegNode, FuncInfo, F, -1);
541 return;
542 }
543 // FIXME: Delete the rest of this code and clean things up when new EH is
544 // done.
520545
521546 // Iterate all the instructions and emit state number stores.
522547 int CurState = 0;
0 ; RUN: llc < %s | FileCheck %s
1
2 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
3 target triple = "i686-pc-windows-msvc"
4
5 define void @try_except() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
6 entry:
7 %__exception_code = alloca i32, align 4
8 call void (...) @llvm.localescape(i32* %__exception_code)
9 invoke void @f(i32 1) #3
10 to label %invoke.cont unwind label %catch.dispatch
11
12 catch.dispatch: ; preds = %entry
13 %0 = catchpad [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
14
15 __except.ret: ; preds = %catch.dispatch
16 catchret %0 to label %__except
17
18 __except: ; preds = %__except.ret
19 call void @f(i32 2)
20 br label %__try.cont
21
22 __try.cont: ; preds = %__except, %invoke.cont
23 call void @f(i32 3)
24 ret void
25
26 catchendblock: ; preds = %catch.dispatch
27 catchendpad unwind to caller
28
29 invoke.cont: ; preds = %entry
30 br label %__try.cont
31 }
32
33 ; CHECK-LABEL: _try_except:
34 ; Store state #0
35 ; CHECK: movl $0, -[[state:[0-9]+]](%ebp)
36 ; CHECK: movl $1, (%esp)
37 ; CHECK: calll _f
38 ; CHECK: movl $-1, -[[state]](%ebp)
39 ; CHECK: movl $3, (%esp)
40 ; CHECK: calll _f
41 ; CHECK: retl
42
43 ; __except
44 ; CHECK: movl $-1, -[[state]](%ebp)
45 ; CHECK: movl $2, (%esp)
46 ; CHECK: calll _f
47
48 ; CHECK: .section .xdata,"dr"
49 ; CHECK: L__ehtable$try_except:
50 ; CHECK: .long -1
51 ; CHECK: .long _try_except_filter_catchall
52 ; CHECK: .long LBB0_1
53
54 define internal i32 @try_except_filter_catchall() #0 {
55 entry:
56 %0 = call i8* @llvm.frameaddress(i32 1)
57 %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @try_except to i8*), i8* %0)
58 %2 = call i8* @llvm.localrecover(i8* bitcast (void ()* @try_except to i8*), i8* %1, i32 0)
59 %__exception_code = bitcast i8* %2 to i32*
60 %3 = getelementptr inbounds i8, i8* %0, i32 -20
61 %4 = bitcast i8* %3 to i8**
62 %5 = load i8*, i8** %4, align 4
63 %6 = bitcast i8* %5 to { i32*, i8* }*
64 %7 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %6, i32 0, i32 0
65 %8 = load i32*, i32** %7, align 4
66 %9 = load i32, i32* %8, align 4
67 store i32 %9, i32* %__exception_code, align 4
68 ret i32 1
69 }
70
71 define void @nested_exceptions() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
72 entry:
73 %__exception_code = alloca i32, align 4
74 call void (...) @llvm.localescape(i32* %__exception_code)
75 invoke void @crash() #3
76 to label %__try.cont unwind label %catch.dispatch
77
78 catch.dispatch: ; preds = %entry
79 %0 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
80
81 __except.ret: ; preds = %catch.dispatch
82 catchret %0 to label %__try.cont
83
84 __try.cont: ; preds = %entry, %__except.ret
85 invoke void @crash() #3
86 to label %__try.cont.9 unwind label %catch.dispatch.5
87
88 catch.dispatch.5: ; preds = %__try.cont
89 %1 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.7 unwind label %catchendblock.6
90
91 __except.ret.7: ; preds = %catch.dispatch.5
92 catchret %1 to label %__try.cont.9
93
94 __try.cont.9: ; preds = %__try.cont, %__except.ret.7
95 invoke void @crash() #3
96 to label %__try.cont.15 unwind label %catch.dispatch.11
97
98 catch.dispatch.11: ; preds = %catchendblock, %catchendblock.6, %__try.cont.9
99 %2 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.13 unwind label %catchendblock.12
100
101 __except.ret.13: ; preds = %catch.dispatch.11
102 catchret %2 to label %__try.cont.15
103
104 __try.cont.15: ; preds = %__try.cont.9, %__except.ret.13
105 invoke void @crash() #3
106 to label %__try.cont.35 unwind label %catch.dispatch.17
107
108 catch.dispatch.17: ; preds = %catchendblock.12, %__try.cont.15
109 %3 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.19 unwind label %catchendblock.18
110
111 __except.ret.19: ; preds = %catch.dispatch.17
112 catchret %3 to label %__except.20
113
114 __except.20: ; preds = %__except.ret.19
115 invoke void @crash() #3
116 to label %__try.cont.27 unwind label %catch.dispatch.23
117
118 catch.dispatch.23: ; preds = %__except.20
119 %4 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.25 unwind label %catchendblock.24
120
121 __except.ret.25: ; preds = %catch.dispatch.23
122 catchret %4 to label %__try.cont.27
123
124 __try.cont.27: ; preds = %__except.20, %__except.ret.25
125 invoke void @crash() #3
126 to label %__try.cont.35 unwind label %catch.dispatch.30
127
128 catch.dispatch.30: ; preds = %__try.cont.27
129 %5 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.32 unwind label %catchendblock.31
130
131 __except.ret.32: ; preds = %catch.dispatch.30
132 catchret %5 to label %__try.cont.35
133
134 __try.cont.35: ; preds = %__try.cont.15, %__try.cont.27, %__except.ret.32
135 ret void
136
137 catchendblock.31: ; preds = %catch.dispatch.30
138 catchendpad unwind to caller
139
140 catchendblock.24: ; preds = %catch.dispatch.23
141 catchendpad unwind to caller
142
143 catchendblock.18: ; preds = %catch.dispatch.17
144 catchendpad unwind to caller
145
146 catchendblock.12: ; preds = %catch.dispatch.11
147 catchendpad unwind label %catch.dispatch.17
148
149 catchendblock.6: ; preds = %catch.dispatch.5
150 catchendpad unwind label %catch.dispatch.11
151
152 catchendblock: ; preds = %catch.dispatch
153 catchendpad unwind label %catch.dispatch.11
154 }
155
156 ; This table is equivalent to the one produced by MSVC, even if it isn't in
157 ; quite the same order.
158
159 ; CHECK-LABEL: _nested_exceptions:
160 ; CHECK: L__ehtable$nested_exceptions:
161 ; CHECK: .long -1
162 ; CHECK: .long _nested_exceptions_filter_catchall
163 ; CHECK: .long LBB
164 ; CHECK: .long -1
165 ; CHECK: .long _nested_exceptions_filter_catchall
166 ; CHECK: .long LBB
167 ; CHECK: .long -1
168 ; CHECK: .long _nested_exceptions_filter_catchall
169 ; CHECK: .long LBB
170 ; CHECK: .long 2
171 ; CHECK: .long _nested_exceptions_filter_catchall
172 ; CHECK: .long LBB
173 ; CHECK: .long 3
174 ; CHECK: .long _nested_exceptions_filter_catchall
175 ; CHECK: .long LBB
176 ; CHECK: .long 3
177 ; CHECK: .long _nested_exceptions_filter_catchall
178 ; CHECK: .long LBB
179
180 declare void @crash() #0
181
182 define internal i32 @nested_exceptions_filter_catchall() #0 {
183 entry:
184 %0 = call i8* @llvm.frameaddress(i32 1)
185 %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @nested_exceptions to i8*), i8* %0)
186 %2 = call i8* @llvm.localrecover(i8* bitcast (void ()* @nested_exceptions to i8*), i8* %1, i32 0)
187 %__exception_code3 = bitcast i8* %2 to i32*
188 %3 = getelementptr inbounds i8, i8* %0, i32 -20
189 %4 = bitcast i8* %3 to i8**
190 %5 = load i8*, i8** %4, align 4
191 %6 = bitcast i8* %5 to { i32*, i8* }*
192 %7 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %6, i32 0, i32 0
193 %8 = load i32*, i32** %7, align 4
194 %9 = load i32, i32* %8, align 4
195 store i32 %9, i32* %__exception_code3, align 4
196 ret i32 1
197 }
198
199 ; Function Attrs: nounwind readnone
200 declare i8* @llvm.frameaddress(i32) #1
201
202 ; Function Attrs: nounwind readnone
203 declare i8* @llvm.x86.seh.recoverfp(i8*, i8*) #1
204
205 ; Function Attrs: nounwind readnone
206 declare i8* @llvm.localrecover(i8*, i8*, i32) #1
207
208 declare void @f(i32) #0
209
210 declare i32 @_except_handler3(...)
211
212 ; Function Attrs: nounwind
213 declare void @llvm.localescape(...) #2
214
215 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" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
216 attributes #1 = { nounwind readnone }
217 attributes #2 = { nounwind }
218 attributes #3 = { noinline }