llvm.org GIT mirror llvm / 42be08a
[WinEH] Calculate state numbers for the new EH representation State numbers are calculated by performing a walk from the innermost funclet to the outermost funclet. Rudimentary support for the new EH constructs has been added to the assembly printer, just enough to test the new machinery. Differential Revision: http://reviews.llvm.org/D12098 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@245331 91177308-0d34-0410-b5e6-96231b3b80d8 David Majnemer 4 years ago
8 changed file(s) with 298 addition(s) and 34 deletion(s). Raw diff Collapse all Expand all
114114
115115 struct WinEHUnwindMapEntry {
116116 int ToState;
117 Function *Cleanup;
117 const Value *Cleanup;
118118 };
119119
120120 struct WinEHHandlerType {
121121 int Adjectives;
122122 GlobalVariable *TypeDescriptor;
123123 int CatchObjRecoverIdx;
124 Function *Handler;
124 const Value *Handler;
125125 };
126126
127127 struct WinEHTryBlockMapEntry {
128128 int TryLow;
129129 int TryHigh;
130 int CatchHigh = -1;
130131 SmallVector HandlerArray;
131132 };
132133
135136 DenseMap LastInvoke;
136137 DenseMap HandlerEnclosedState;
137138 DenseMap LastInvokeVisited;
138 DenseMapLandingPadInst *, int> LandingPadStateMap;
139 DenseMapInstruction *, int> EHPadStateMap;
139140 DenseMap CatchHandlerParentFrameObjIdx;
140141 DenseMap CatchHandlerParentFrameObjOffset;
141142 DenseMap CatchHandlerMaxState;
146147 int UnwindHelpFrameIdx = INT_MAX;
147148 int UnwindHelpFrameOffset = -1;
148149 unsigned NumIPToStateFuncsVisited = 0;
150
151 int getLastStateNumber() const { return UnwindMap.size() - 1; }
149152
150153 /// localescape index of the 32-bit EH registration node. Set by
151154 /// WinEHStatePass and used indirectly by SEH filter functions of the parent.
181181 Asm->OutContext);
182182 }
183183
184 const MCExpr *WinException::create32bitRef(const GlobalValue *GV) {
185 if (!GV)
184 const MCExpr *WinException::create32bitRef(const Value *V) {
185 if (!V)
186186 return MCConstantExpr::create(0, Asm->OutContext);
187 return create32bitRef(Asm->getSymbol(GV));
187 return create32bitRef(Asm->getSymbol(cast(V)));
188188 }
189189
190190 /// Emit the language-specific data that __C_specific_handler expects. This
412412 int CatchHigh = -1;
413413 for (WinEHHandlerType &HT : TBME.HandlerArray)
414414 CatchHigh =
415 std::max(CatchHigh, FuncInfo.CatchHandlerMaxState[HT.Handler]);
415 std::max(CatchHigh,
416 FuncInfo.CatchHandlerMaxState[cast(HT.Handler)]);
416417
417418 assert(TBME.TryLow <= TBME.TryHigh);
418419 OS.EmitIntValue(TBME.TryLow, 4); // TryLow
1717
1818 namespace llvm {
1919 class Function;
20 class GlobalValue;
2120 class MachineFunction;
2221 class MCExpr;
22 class Value;
2323 struct WinEHFuncInfo;
2424
2525 class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer {
5555 StringRef FLinkageName);
5656
5757 const MCExpr *create32bitRef(const MCSymbol *Value);
58 const MCExpr *create32bitRef(const GlobalValue *GV);
58 const MCExpr *create32bitRef(const Value *V);
5959
6060 public:
6161 //===--------------------------------------------------------------------===//
282282 Personality == EHPersonality::MSVC_X86SEH) {
283283 for (const LandingPadInst *LP : LPads) {
284284 MachineBasicBlock *LPadMBB = MBBMap[LP->getParent()];
285 MMI.addWinEHState(LPadMBB, EHInfo.LandingPadStateMap[LP]);
285 MMI.addWinEHState(LPadMBB, EHInfo.EHPadStateMap[LP]);
286286 }
287287 }
288288 }
25742574 };
25752575 }
25762576
2577 void WinEHNumbering::createUnwindMapEntry(int ToState, ActionHandler *AH) {
2577 static int addUnwindMapEntry(WinEHFuncInfo &FuncInfo, int ToState,
2578 const Value *V) {
25782579 WinEHUnwindMapEntry UME;
25792580 UME.ToState = ToState;
2581 UME.Cleanup = V;
2582 FuncInfo.UnwindMap.push_back(UME);
2583 return FuncInfo.getLastStateNumber();
2584 }
2585
2586 static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow,
2587 int TryHigh, int CatchHigh,
2588 ArrayRef Handlers) {
2589 WinEHTryBlockMapEntry TBME;
2590 TBME.TryLow = TryLow;
2591 TBME.TryHigh = TryHigh;
2592 TBME.CatchHigh = CatchHigh;
2593 assert(TBME.TryLow <= TBME.TryHigh);
2594 for (const CatchPadInst *CPI : Handlers) {
2595 WinEHHandlerType HT;
2596 Constant *TypeInfo = cast(CPI->getArgOperand(0));
2597 if (TypeInfo->isNullValue()) {
2598 HT.Adjectives = 0x40;
2599 HT.TypeDescriptor = nullptr;
2600 } else {
2601 auto *GV = cast(TypeInfo->stripPointerCasts());
2602 // Selectors are always pointers to GlobalVariables with 'struct' type.
2603 // The struct has two fields, adjectives and a type descriptor.
2604 auto *CS = cast(GV->getInitializer());
2605 HT.Adjectives =
2606 cast(CS->getAggregateElement(0U))->getZExtValue();
2607 HT.TypeDescriptor =
2608 cast(CS->getAggregateElement(1)->stripPointerCasts());
2609 }
2610 HT.Handler = CPI->getParent();
2611 // FIXME: Pass CPI->getArgOperand(1).
2612 HT.CatchObjRecoverIdx = -1;
2613 TBME.HandlerArray.push_back(HT);
2614 }
2615 FuncInfo.TryBlockMap.push_back(TBME);
2616 }
2617
2618 void WinEHNumbering::createUnwindMapEntry(int ToState, ActionHandler *AH) {
2619 Value *V = nullptr;
25802620 if (auto *CH = dyn_cast_or_null(AH))
2581 UME.Cleanup = cast(CH->getHandlerBlockOrFunc());
2582 else
2583 UME.Cleanup = nullptr;
2584 FuncInfo.UnwindMap.push_back(UME);
2621 V = cast(CH->getHandlerBlockOrFunc());
2622 addUnwindMapEntry(FuncInfo, ToState, V);
25852623 }
25862624
25872625 void WinEHNumbering::createTryBlockMapEntry(int TryLow, int TryHigh,
28372875 continue;
28382876 processCallSite(ActionList, II);
28392877 ActionList.clear();
2840 FuncInfo.LandingPadStateMap[LPI] = currentEHNumber();
2878 FuncInfo.EHPadStateMap[LPI] = currentEHNumber();
28412879 DEBUG(dbgs() << "Assigning state " << currentEHNumber()
28422880 << " to landing pad at " << LPI->getParent()->getName()
28432881 << '\n');
29012939 }
29022940 }
29032941
2942 static const BasicBlock *getSingleCatchPadPredecessor(const BasicBlock &BB) {
2943 for (const BasicBlock *PredBlock : predecessors(&BB))
2944 if (isa(PredBlock->getFirstNonPHI()))
2945 return PredBlock;
2946 return nullptr;
2947 }
2948
2949 // Given BB which ends in an unwind edge, return the EHPad that this BB belongs
2950 // to. If the unwind edge came from an invoke, return null.
2951 static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB) {
2952 const TerminatorInst *TI = BB->getTerminator();
2953 if (isa(TI))
2954 return nullptr;
2955 if (isa(TI) || isa(TI) ||
2956 isa(TI))
2957 return BB;
2958 return cast(cast(TI)->getReturnValue())
2959 ->getParent();
2960 }
2961
2962 static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo,
2963 const BasicBlock &BB,
2964 int ParentState) {
2965 assert(BB.isEHPad());
2966 const Instruction *FirstNonPHI = BB.getFirstNonPHI();
2967 // All catchpad instructions will be handled when we process their
2968 // respective catchendpad instruction.
2969 if (isa(FirstNonPHI))
2970 return;
2971
2972 if (isa(FirstNonPHI)) {
2973 const BasicBlock *TryPad = &BB;
2974 const BasicBlock *LastTryPad = nullptr;
2975 SmallVector Handlers;
2976 do {
2977 LastTryPad = TryPad;
2978 TryPad = getSingleCatchPadPredecessor(*TryPad);
2979 if (TryPad)
2980 Handlers.push_back(cast(TryPad->getFirstNonPHI()));
2981 } while (TryPad);
2982 // We've pushed these back into reverse source order. Reverse them to get
2983 // the list back into source order.
2984 std::reverse(Handlers.begin(), Handlers.end());
2985 int TryLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
2986 FuncInfo.EHPadStateMap[Handlers.front()] = TryLow;
2987 for (const BasicBlock *PredBlock : predecessors(LastTryPad))
2988 if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
2989 calculateExplicitStateNumbers(FuncInfo, *PredBlock, TryLow);
2990 int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
2991 FuncInfo.EHPadStateMap[FirstNonPHI] = CatchLow;
2992 int TryHigh = CatchLow - 1;
2993 for (const BasicBlock *PredBlock : predecessors(&BB))
2994 if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
2995 calculateExplicitStateNumbers(FuncInfo, *PredBlock, CatchLow);
2996 int CatchHigh = FuncInfo.getLastStateNumber();
2997 addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers);
2998 DEBUG(dbgs() << "TryLow[" << LastTryPad->getName() << "]: " << TryLow
2999 << '\n');
3000 DEBUG(dbgs() << "TryHigh[" << LastTryPad->getName() << "]: " << TryHigh
3001 << '\n');
3002 DEBUG(dbgs() << "CatchHigh[" << LastTryPad->getName() << "]: " << CatchHigh
3003 << '\n');
3004 } else if (isa(FirstNonPHI)) {
3005 int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, &BB);
3006 FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
3007 DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
3008 << BB.getName() << '\n');
3009 for (const BasicBlock *PredBlock : predecessors(&BB))
3010 if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
3011 calculateExplicitStateNumbers(FuncInfo, *PredBlock, CleanupState);
3012 } else if (isa(FirstNonPHI)) {
3013 report_fatal_error("Not yet implemented!");
3014 } else {
3015 llvm_unreachable("unexpected EH Pad!");
3016 }
3017 }
3018
29043019 void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn,
29053020 WinEHFuncInfo &FuncInfo) {
29063021 // Return if it's already been done.
2907 if (!FuncInfo.LandingPadStateMap.empty())
3022 if (!FuncInfo.EHPadStateMap.empty())
3023 return;
3024
3025 bool IsExplicit = false;
3026 for (const BasicBlock &BB : *ParentFn) {
3027 if (!BB.isEHPad())
3028 continue;
3029 // Check if the EH Pad has no exceptional successors (i.e. it unwinds to
3030 // caller). Cleanups are a little bit of a special case because their
3031 // control flow cannot be determined by looking at the pad but instead by
3032 // the pad's users.
3033 bool HasNoSuccessors = false;
3034 const Instruction *FirstNonPHI = BB.getFirstNonPHI();
3035 if (FirstNonPHI->mayThrow()) {
3036 HasNoSuccessors = true;
3037 } else if (auto *CPI = dyn_cast(FirstNonPHI)) {
3038 HasNoSuccessors =
3039 CPI->use_empty() ||
3040 cast(CPI->user_back())->unwindsToCaller();
3041 }
3042
3043 if (!HasNoSuccessors)
3044 continue;
3045 calculateExplicitStateNumbers(FuncInfo, BB, -1);
3046 IsExplicit = true;
3047 }
3048
3049 if (IsExplicit)
29083050 return;
29093051
29103052 WinEHNumbering Num(FuncInfo);
31403282
31413283 BlockColors.clear();
31423284 FuncletBlocks.clear();
3285
31433286 return true;
31443287 }
31453288
2727 cl::desc("Enable the machine combiner pass"),
2828 cl::init(true), cl::Hidden);
2929
30 namespace llvm {
31 void initializeWinEHStatePassPass(PassRegistry &);
32 }
33
3034 extern "C" void LLVMInitializeX86Target() {
3135 // Register the target.
3236 RegisterTargetMachine X(TheX86_32Target);
3337 RegisterTargetMachine Y(TheX86_64Target);
38
39 PassRegistry &PR = *PassRegistry::getPassRegistry();
40 initializeWinEHStatePassPass(PR);
3441 }
3542
3643 static std::unique_ptr createTLOF(const Triple &TT) {
3737
3838 #define DEBUG_TYPE "winehstate"
3939
40 namespace llvm { void initializeWinEHStatePassPass(PassRegistry &); }
41
4042 namespace {
4143 class WinEHStatePass : public FunctionPass {
4244 public:
4345 static char ID; // Pass identification, replacement for typeid.
4446
45 WinEHStatePass() : FunctionPass(ID) {}
47 WinEHStatePass() : FunctionPass(ID) {
48 initializeWinEHStatePassPass(*PassRegistry::getPassRegistry());
49 }
4650
4751 bool runOnFunction(Function &Fn) override;
4852
6165
6266 void linkExceptionRegistration(IRBuilder<> &Builder, Function *Handler);
6367 void unlinkExceptionRegistration(IRBuilder<> &Builder);
64 void addCXXStateStores(Function &F, MachineModuleInfo &MMI);
65 void addSEHStateStores(Function &F, MachineModuleInfo &MMI);
68 void addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo);
69 void addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo);
6670 void addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo,
6771 Function &F, int BaseState);
6872 void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State);
109113 FunctionPass *llvm::createX86WinEHStatePass() { return new WinEHStatePass(); }
110114
111115 char WinEHStatePass::ID = 0;
116
117 INITIALIZE_PASS(WinEHStatePass, "x86-winehstate",
118 "Insert stores for EH state numbers", false, false)
112119
113120 bool WinEHStatePass::doInitialization(Module &M) {
114121 TheModule = &M;
162169
163170 emitExceptionRegistrationRecord(&F);
164171
165 auto *MMIPtr = getAnalysisIfAvailable();
166 assert(MMIPtr && "MachineModuleInfo should always be available");
167 MachineModuleInfo &MMI = *MMIPtr;
172 auto *MMI = getAnalysisIfAvailable();
173 // If MMI is null, create our own WinEHFuncInfo. This only happens in opt
174 // tests.
175 std::unique_ptr FuncInfoPtr;
176 if (!MMI)
177 FuncInfoPtr.reset(new WinEHFuncInfo());
178 WinEHFuncInfo &FuncInfo =
179 *(MMI ? &MMI->getWinEHFuncInfo(&F) : FuncInfoPtr.get());
180
168181 switch (Personality) {
169182 default: llvm_unreachable("unexpected personality function");
170 case EHPersonality::MSVC_CXX: addCXXStateStores(F, MMI); break;
171 case EHPersonality::MSVC_X86SEH: addSEHStateStores(F, MMI); break;
183 case EHPersonality::MSVC_CXX:
184 addCXXStateStores(F, FuncInfo);
185 break;
186 case EHPersonality::MSVC_X86SEH:
187 addSEHStateStores(F, FuncInfo);
188 break;
172189 }
173190
174191 // Reset per-function state.
390407 Builder.CreateStore(Next, FSZero);
391408 }
392409
393 void WinEHStatePass::addCXXStateStores(Function &F, MachineModuleInfo &MMI) {
394 WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(&F);
410 void WinEHStatePass::addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
395411 calculateWinCXXEHStateNumbers(&F, FuncInfo);
396412
397413 // The base state for the parent is -1.
465481 insertStateNumberStore(ParentRegNode, CI, BaseState);
466482 } else if (auto *II = dyn_cast(&I)) {
467483 // Look up the state number of the landingpad this unwinds to.
468 LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst();
484 Instruction *PadInst = II->getUnwindDest()->getFirstNonPHI();
469485 // FIXME: Why does this assertion fail?
470 //assert(FuncInfo.LandingPadStateMap.count(LPI) && "LP has no state!");
471 int State = FuncInfo.LandingPadStateMap[LPI];
486 //assert(FuncInfo.EHPadStateMap.count(PadInst) && "EH Pad has no state!");
487 int State = FuncInfo.EHPadStateMap[PadInst];
472488 insertStateNumberStore(ParentRegNode, II, State);
473489 }
474490 }
480496 /// handlers aren't outlined and the runtime doesn't have to figure out which
481497 /// catch handler frame to unwind to.
482498 /// FIXME: __finally blocks are outlined, so this approach may break down there.
483 void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) {
484 WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(&F);
485
499 void WinEHStatePass::addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo) {
486500 // Remember and return the index that we used. We save it in WinEHFuncInfo so
487501 // that we can lower llvm.x86.seh.recoverfp later in filter functions without
488502 // too much trouble.
506520 // Look up the state number of the landingpad this unwinds to.
507521 LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst();
508522 auto InsertionPair =
509 FuncInfo.LandingPadStateMap.insert(std::make_pair(LPI, CurState));
523 FuncInfo.EHPadStateMap.insert(std::make_pair(LPI, CurState));
510524 auto Iter = InsertionPair.first;
511525 int &State = Iter->second;
512526 bool Inserted = InsertionPair.second;
0 ; RUN: opt -mtriple=i686-pc-windows-msvc -S -x86-winehstate < %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 %rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
6 %eh.CatchableType = type { i32, i8*, i32, i32, i32, i32, i8* }
7 %eh.CatchableTypeArray.1 = type { i32, [1 x %eh.CatchableType*] }
8 %eh.ThrowInfo = type { i32, i8*, i8*, i8* }
9
10 $"\01??_R0H@8" = comdat any
11
12 $"_CT??_R0H@84" = comdat any
13
14 $_CTA1H = comdat any
15
16 $_TI1H = comdat any
17
18 @"\01??_7type_info@@6B@" = external constant i8*
19 @"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
20 @"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i32 -1, i32 0, i32 4, i8* null }, section ".xdata", comdat
21 @_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0H@84"] }, section ".xdata", comdat
22 @_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* null, i8* null, i8* bitcast (%eh.CatchableTypeArray.1* @_CTA1H to i8*) }, section ".xdata", comdat
23
24 define i32 @main() #0 personality i32 (...)* @__CxxFrameHandler3 {
25 entry:
26 %tmp = alloca i32, align 4
27 ; CHECK: entry:
28 ; CHECK: store i32 -1
29 ; CHECK: call void @g(i32 3)
30 call void @g(i32 3)
31 store i32 0, i32* %tmp, align 4
32 %0 = bitcast i32* %tmp to i8*
33 ; CHECK: store i32 0
34 ; CHECK: invoke void @_CxxThrowException(
35 invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* nonnull @_TI1H) #1
36 to label %unreachable.for.entry unwind label %catch.dispatch
37
38 catch.dispatch: ; preds = %entry
39 %1 = catchpad token [i8* null, i8* null] to label %catch unwind label %catchendblock
40
41 catch: ; preds = %catch.dispatch
42 ; CHECK: catch:
43 ; CHECK: store i32 2
44 ; CHECK: invoke void @_CxxThrowException(
45 invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1
46 to label %unreachable unwind label %catch.dispatch.1
47
48 catch.dispatch.1: ; preds = %catch
49 %2 = catchpad token [i8* null, i8* null] to label %catch.3 unwind label %catchendblock.2
50
51 catch.3: ; preds = %catch.dispatch.1
52 ; CHECK: catch.3:
53 ; CHECK: store i32 3
54 ; CHECK: invoke void @g(i32 1)
55 invoke void @g(i32 1)
56 to label %invoke.cont unwind label %catchendblock.2
57
58 invoke.cont: ; preds = %catch.3
59 catchret token %2 to label %try.cont
60
61 try.cont: ; preds = %invoke.cont
62 ; CHECK: try.cont:
63 ; CHECK: store i32 1
64 ; CHECK: invoke void @g(i32 2)
65 invoke void @g(i32 2)
66 to label %invoke.cont.4 unwind label %catchendblock
67
68 invoke.cont.4: ; preds = %try.cont
69 unreachable
70
71 catchendblock.2: ; preds = %catch.3, %catch.dispatch.1
72 catchendpad unwind label %catchendblock
73
74 catchendblock: ; preds = %catchendblock.2, %try.cont, %catch.dispatch
75 catchendpad unwind to caller
76
77 unreachable: ; preds = %catch
78 unreachable
79
80 unreachable.for.entry: ; preds = %entry
81 unreachable
82 }
83
84 declare void @g(i32) #0
85
86 declare x86_stdcallcc void @_CxxThrowException(i8*, %eh.ThrowInfo*)
87
88 declare i32 @__CxxFrameHandler3(...)
89
90 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" }
91 attributes #1 = { noreturn }
92
93 !llvm.ident = !{!0}
94
95 !0 = !{!"clang version 3.8.0 (trunk 245153) (llvm/trunk 245238)"}