llvm.org GIT mirror llvm / 7d21fd6
[WinEH] Implement state numbering for CoreCLR Summary: Assign one state number per handler/funclet, tracking parent state, handler type, and catch type token. State numbers are arranged such that ancestors have lower state numbers than their descendants. Reviewers: majnemer, andrew.w.kaylor, rnk Subscribers: pgavlin, AndyAyers, llvm-commits Differential Revision: http://reviews.llvm.org/D13450 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249457 91177308-0d34-0410-b5e6-96231b3b80d8 Joseph Tremoulet 4 years ago
3 changed file(s) with 103 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
160160 SmallVector HandlerArray;
161161 };
162162
163 enum class ClrHandlerType { Catch, Finally, Fault, Filter };
164
165 struct ClrEHUnwindMapEntry {
166 MBBOrBasicBlock Handler;
167 uint32_t TypeToken;
168 int Parent;
169 ClrHandlerType HandlerType;
170 };
171
163172 struct WinEHFuncInfo {
164173 DenseMap EHPadStateMap;
165174 DenseMap
168177 SmallVector UnwindMap;
169178 SmallVector TryBlockMap;
170179 SmallVector SEHUnwindMap;
180 SmallVector ClrEHUnwindMap;
171181 int UnwindHelpFrameIdx = INT_MAX;
172182 int UnwindHelpFrameOffset = -1;
173183
195205 void calculateSEHStateNumbers(const Function *ParentFn,
196206 WinEHFuncInfo &FuncInfo);
197207
208 void calculateClrEHStateNumbers(const Function *Fn, WinEHFuncInfo &FuncInfo);
209
198210 void calculateCatchReturnSuccessorColors(const Function *Fn,
199211 WinEHFuncInfo &FuncInfo);
200212 }
291291 calculateWinCXXEHStateNumbers(WinEHParentFn, EHInfo);
292292 else if (isAsynchronousEHPersonality(Personality))
293293 calculateSEHStateNumbers(WinEHParentFn, EHInfo);
294 else if (Personality == EHPersonality::CoreCLR)
295 calculateClrEHStateNumbers(WinEHParentFn, EHInfo);
294296
295297 calculateCatchReturnSuccessorColors(WinEHParentFn, EHInfo);
296298
314316 for (SEHUnwindMapEntry &UME : EHInfo.SEHUnwindMap) {
315317 const BasicBlock *BB = UME.Handler.get();
316318 UME.Handler = MBBMap[BB];
319 }
320 for (ClrEHUnwindMapEntry &CME : EHInfo.ClrEHUnwindMap) {
321 const BasicBlock *BB = CME.Handler.get();
322 CME.Handler = MBBMap[BB];
317323 }
318324
319325 // If there's an explicit EH registration node on the stack, record its
28602860 if (!doesEHPadUnwindToCaller(FirstNonPHI))
28612861 continue;
28622862 calculateExplicitCXXStateNumbers(FuncInfo, BB, -1);
2863 }
2864 }
2865
2866 static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int ParentState,
2867 ClrHandlerType HandlerType, uint32_t TypeToken,
2868 const BasicBlock *Handler) {
2869 ClrEHUnwindMapEntry Entry;
2870 Entry.Parent = ParentState;
2871 Entry.Handler = Handler;
2872 Entry.HandlerType = HandlerType;
2873 Entry.TypeToken = TypeToken;
2874 FuncInfo.ClrEHUnwindMap.push_back(Entry);
2875 return FuncInfo.ClrEHUnwindMap.size() - 1;
2876 }
2877
2878 void llvm::calculateClrEHStateNumbers(const Function *Fn,
2879 WinEHFuncInfo &FuncInfo) {
2880 // Return if it's already been done.
2881 if (!FuncInfo.EHPadStateMap.empty())
2882 return;
2883
2884 SmallVector, 8> Worklist;
2885
2886 // Each pad needs to be able to refer to its parent, so scan the function
2887 // looking for top-level handlers and seed the worklist with them.
2888 for (const BasicBlock &BB : *Fn) {
2889 if (!BB.isEHPad())
2890 continue;
2891 if (BB.isLandingPad())
2892 report_fatal_error("CoreCLR EH cannot use landingpads");
2893 const Instruction *FirstNonPHI = BB.getFirstNonPHI();
2894 if (!doesEHPadUnwindToCaller(FirstNonPHI))
2895 continue;
2896 // queue this with sentinel parent state -1 to mean unwind to caller.
2897 Worklist.emplace_back(FirstNonPHI, -1);
2898 }
2899
2900 while (!Worklist.empty()) {
2901 const Instruction *Pad;
2902 int ParentState;
2903 std::tie(Pad, ParentState) = Worklist.pop_back_val();
2904
2905 int PredState;
2906 if (const CleanupEndPadInst *EndPad = dyn_cast(Pad)) {
2907 FuncInfo.EHPadStateMap[EndPad] = ParentState;
2908 // Queue the cleanuppad, in case it doesn't have a cleanupret.
2909 Worklist.emplace_back(EndPad->getCleanupPad(), ParentState);
2910 // Preds of the endpad should get the parent state.
2911 PredState = ParentState;
2912 } else if (const CleanupPadInst *Cleanup = dyn_cast(Pad)) {
2913 // A cleanup can have multiple exits; don't re-process after the first.
2914 if (FuncInfo.EHPadStateMap.count(Pad))
2915 continue;
2916 // CoreCLR personality uses arity to distinguish faults from finallies.
2917 const BasicBlock *PadBlock = Cleanup->getParent();
2918 ClrHandlerType HandlerType =
2919 (Cleanup->getNumOperands() ? ClrHandlerType::Fault
2920 : ClrHandlerType::Finally);
2921 int NewState =
2922 addClrEHHandler(FuncInfo, ParentState, HandlerType, 0, PadBlock);
2923 FuncInfo.EHPadStateMap[Cleanup] = NewState;
2924 // Propagate the new state to all preds of the cleanup
2925 PredState = NewState;
2926 } else if (const CatchEndPadInst *EndPad = dyn_cast(Pad)) {
2927 FuncInfo.EHPadStateMap[EndPad] = ParentState;
2928 // Preds of the endpad should get the parent state.
2929 PredState = ParentState;
2930 } else if (const CatchPadInst *Catch = dyn_cast(Pad)) {
2931 const BasicBlock *Handler = Catch->getNormalDest();
2932 uint32_t TypeToken = static_cast(
2933 cast(Catch->getArgOperand(0))->getZExtValue());
2934 int NewState = addClrEHHandler(FuncInfo, ParentState,
2935 ClrHandlerType::Catch, TypeToken, Handler);
2936 FuncInfo.EHPadStateMap[Catch] = NewState;
2937 // Preds of the catch get its state
2938 PredState = NewState;
2939 } else {
2940 llvm_unreachable("Unexpected EH pad");
2941 }
2942
2943 // Queue all predecessors with the given state
2944 for (const BasicBlock *Pred : predecessors(Pad->getParent())) {
2945 if ((Pred = getEHPadFromPredecessor(Pred)))
2946 Worklist.emplace_back(Pred->getFirstNonPHI(), PredState);
2947 }
28632948 }
28642949 }
28652950