File: | lib/CodeGen/WinEHPrepare.cpp |
Location: | line 1743, column 7 |
Description: | Called C++ object pointer is null |
1 | //===-- WinEHPrepare - Prepare exception handling for code generation ---===// | |||||
2 | // | |||||
3 | // The LLVM Compiler Infrastructure | |||||
4 | // | |||||
5 | // This file is distributed under the University of Illinois Open Source | |||||
6 | // License. See LICENSE.TXT for details. | |||||
7 | // | |||||
8 | //===----------------------------------------------------------------------===// | |||||
9 | // | |||||
10 | // This pass lowers LLVM IR exception handling into something closer to what the | |||||
11 | // backend wants. It snifs the personality function to see which kind of | |||||
12 | // preparation is necessary. If the personality function uses the Itanium LSDA, | |||||
13 | // this pass delegates to the DWARF EH preparation pass. | |||||
14 | // | |||||
15 | //===----------------------------------------------------------------------===// | |||||
16 | ||||||
17 | #include "llvm/CodeGen/Passes.h" | |||||
18 | #include "llvm/ADT/MapVector.h" | |||||
19 | #include "llvm/ADT/STLExtras.h" | |||||
20 | #include "llvm/ADT/SmallSet.h" | |||||
21 | #include "llvm/ADT/SetVector.h" | |||||
22 | #include "llvm/ADT/TinyPtrVector.h" | |||||
23 | #include "llvm/Analysis/LibCallSemantics.h" | |||||
24 | #include "llvm/CodeGen/WinEHFuncInfo.h" | |||||
25 | #include "llvm/IR/Dominators.h" | |||||
26 | #include "llvm/IR/Function.h" | |||||
27 | #include "llvm/IR/IRBuilder.h" | |||||
28 | #include "llvm/IR/Instructions.h" | |||||
29 | #include "llvm/IR/IntrinsicInst.h" | |||||
30 | #include "llvm/IR/Module.h" | |||||
31 | #include "llvm/IR/PatternMatch.h" | |||||
32 | #include "llvm/Pass.h" | |||||
33 | #include "llvm/Support/CommandLine.h" | |||||
34 | #include "llvm/Support/Debug.h" | |||||
35 | #include "llvm/Support/raw_ostream.h" | |||||
36 | #include "llvm/Transforms/Utils/BasicBlockUtils.h" | |||||
37 | #include "llvm/Transforms/Utils/Cloning.h" | |||||
38 | #include "llvm/Transforms/Utils/Local.h" | |||||
39 | #include "llvm/Transforms/Utils/PromoteMemToReg.h" | |||||
40 | #include <memory> | |||||
41 | ||||||
42 | using namespace llvm; | |||||
43 | using namespace llvm::PatternMatch; | |||||
44 | ||||||
45 | #define DEBUG_TYPE"winehprepare" "winehprepare" | |||||
46 | ||||||
47 | namespace { | |||||
48 | ||||||
49 | // This map is used to model frame variable usage during outlining, to | |||||
50 | // construct a structure type to hold the frame variables in a frame | |||||
51 | // allocation block, and to remap the frame variable allocas (including | |||||
52 | // spill locations as needed) to GEPs that get the variable from the | |||||
53 | // frame allocation structure. | |||||
54 | typedef MapVector<Value *, TinyPtrVector<AllocaInst *>> FrameVarInfoMap; | |||||
55 | ||||||
56 | // TinyPtrVector cannot hold nullptr, so we need our own sentinel that isn't | |||||
57 | // quite null. | |||||
58 | AllocaInst *getCatchObjectSentinel() { | |||||
59 | return static_cast<AllocaInst *>(nullptr) + 1; | |||||
60 | } | |||||
61 | ||||||
62 | typedef SmallSet<BasicBlock *, 4> VisitedBlockSet; | |||||
63 | ||||||
64 | class LandingPadActions; | |||||
65 | class LandingPadMap; | |||||
66 | ||||||
67 | typedef DenseMap<const BasicBlock *, CatchHandler *> CatchHandlerMapTy; | |||||
68 | typedef DenseMap<const BasicBlock *, CleanupHandler *> CleanupHandlerMapTy; | |||||
69 | ||||||
70 | class WinEHPrepare : public FunctionPass { | |||||
71 | public: | |||||
72 | static char ID; // Pass identification, replacement for typeid. | |||||
73 | WinEHPrepare(const TargetMachine *TM = nullptr) | |||||
74 | : FunctionPass(ID), DT(nullptr), SEHExceptionCodeSlot(nullptr) {} | |||||
75 | ||||||
76 | bool runOnFunction(Function &Fn) override; | |||||
77 | ||||||
78 | bool doFinalization(Module &M) override; | |||||
79 | ||||||
80 | void getAnalysisUsage(AnalysisUsage &AU) const override; | |||||
81 | ||||||
82 | const char *getPassName() const override { | |||||
83 | return "Windows exception handling preparation"; | |||||
84 | } | |||||
85 | ||||||
86 | private: | |||||
87 | bool prepareExceptionHandlers(Function &F, | |||||
88 | SmallVectorImpl<LandingPadInst *> &LPads); | |||||
89 | void promoteLandingPadValues(LandingPadInst *LPad); | |||||
90 | void demoteValuesLiveAcrossHandlers(Function &F, | |||||
91 | SmallVectorImpl<LandingPadInst *> &LPads); | |||||
92 | void completeNestedLandingPad(Function *ParentFn, | |||||
93 | LandingPadInst *OutlinedLPad, | |||||
94 | const LandingPadInst *OriginalLPad, | |||||
95 | FrameVarInfoMap &VarInfo); | |||||
96 | bool outlineHandler(ActionHandler *Action, Function *SrcFn, | |||||
97 | LandingPadInst *LPad, BasicBlock *StartBB, | |||||
98 | FrameVarInfoMap &VarInfo); | |||||
99 | void addStubInvokeToHandlerIfNeeded(Function *Handler, Value *PersonalityFn); | |||||
100 | ||||||
101 | void mapLandingPadBlocks(LandingPadInst *LPad, LandingPadActions &Actions); | |||||
102 | CatchHandler *findCatchHandler(BasicBlock *BB, BasicBlock *&NextBB, | |||||
103 | VisitedBlockSet &VisitedBlocks); | |||||
104 | void findCleanupHandlers(LandingPadActions &Actions, BasicBlock *StartBB, | |||||
105 | BasicBlock *EndBB); | |||||
106 | ||||||
107 | void processSEHCatchHandler(CatchHandler *Handler, BasicBlock *StartBB); | |||||
108 | ||||||
109 | // All fields are reset by runOnFunction. | |||||
110 | DominatorTree *DT; | |||||
111 | EHPersonality Personality; | |||||
112 | CatchHandlerMapTy CatchHandlerMap; | |||||
113 | CleanupHandlerMapTy CleanupHandlerMap; | |||||
114 | DenseMap<const LandingPadInst *, LandingPadMap> LPadMaps; | |||||
115 | ||||||
116 | // This maps landing pad instructions found in outlined handlers to | |||||
117 | // the landing pad instruction in the parent function from which they | |||||
118 | // were cloned. The cloned/nested landing pad is used as the key | |||||
119 | // because the landing pad may be cloned into multiple handlers. | |||||
120 | // This map will be used to add the llvm.eh.actions call to the nested | |||||
121 | // landing pads after all handlers have been outlined. | |||||
122 | DenseMap<LandingPadInst *, const LandingPadInst *> NestedLPtoOriginalLP; | |||||
123 | ||||||
124 | // This maps blocks in the parent function which are destinations of | |||||
125 | // catch handlers to cloned blocks in (other) outlined handlers. This | |||||
126 | // handles the case where a nested landing pads has a catch handler that | |||||
127 | // returns to a handler function rather than the parent function. | |||||
128 | // The original block is used as the key here because there should only | |||||
129 | // ever be one handler function from which the cloned block is not pruned. | |||||
130 | // The original block will be pruned from the parent function after all | |||||
131 | // handlers have been outlined. This map will be used to adjust the | |||||
132 | // return instructions of handlers which return to the block that was | |||||
133 | // outlined into a handler. This is done after all handlers have been | |||||
134 | // outlined but before the outlined code is pruned from the parent function. | |||||
135 | DenseMap<const BasicBlock *, BasicBlock *> LPadTargetBlocks; | |||||
136 | ||||||
137 | AllocaInst *SEHExceptionCodeSlot; | |||||
138 | }; | |||||
139 | ||||||
140 | class WinEHFrameVariableMaterializer : public ValueMaterializer { | |||||
141 | public: | |||||
142 | WinEHFrameVariableMaterializer(Function *OutlinedFn, | |||||
143 | FrameVarInfoMap &FrameVarInfo); | |||||
144 | ~WinEHFrameVariableMaterializer() override {} | |||||
145 | ||||||
146 | Value *materializeValueFor(Value *V) override; | |||||
147 | ||||||
148 | void escapeCatchObject(Value *V); | |||||
149 | ||||||
150 | private: | |||||
151 | FrameVarInfoMap &FrameVarInfo; | |||||
152 | IRBuilder<> Builder; | |||||
153 | }; | |||||
154 | ||||||
155 | class LandingPadMap { | |||||
156 | public: | |||||
157 | LandingPadMap() : OriginLPad(nullptr) {} | |||||
158 | void mapLandingPad(const LandingPadInst *LPad); | |||||
159 | ||||||
160 | bool isInitialized() { return OriginLPad != nullptr; } | |||||
161 | ||||||
162 | bool isOriginLandingPadBlock(const BasicBlock *BB) const; | |||||
163 | bool isLandingPadSpecificInst(const Instruction *Inst) const; | |||||
164 | ||||||
165 | void remapEHValues(ValueToValueMapTy &VMap, Value *EHPtrValue, | |||||
166 | Value *SelectorValue) const; | |||||
167 | ||||||
168 | private: | |||||
169 | const LandingPadInst *OriginLPad; | |||||
170 | // We will normally only see one of each of these instructions, but | |||||
171 | // if more than one occurs for some reason we can handle that. | |||||
172 | TinyPtrVector<const ExtractValueInst *> ExtractedEHPtrs; | |||||
173 | TinyPtrVector<const ExtractValueInst *> ExtractedSelectors; | |||||
174 | }; | |||||
175 | ||||||
176 | class WinEHCloningDirectorBase : public CloningDirector { | |||||
177 | public: | |||||
178 | WinEHCloningDirectorBase(Function *HandlerFn, FrameVarInfoMap &VarInfo, | |||||
179 | LandingPadMap &LPadMap) | |||||
180 | : Materializer(HandlerFn, VarInfo), | |||||
181 | SelectorIDType(Type::getInt32Ty(HandlerFn->getContext())), | |||||
182 | Int8PtrType(Type::getInt8PtrTy(HandlerFn->getContext())), | |||||
183 | LPadMap(LPadMap) { | |||||
184 | auto AI = HandlerFn->getArgumentList().begin(); | |||||
185 | ++AI; | |||||
186 | EstablisherFrame = AI; | |||||
187 | } | |||||
188 | ||||||
189 | CloningAction handleInstruction(ValueToValueMapTy &VMap, | |||||
190 | const Instruction *Inst, | |||||
191 | BasicBlock *NewBB) override; | |||||
192 | ||||||
193 | virtual CloningAction handleBeginCatch(ValueToValueMapTy &VMap, | |||||
194 | const Instruction *Inst, | |||||
195 | BasicBlock *NewBB) = 0; | |||||
196 | virtual CloningAction handleEndCatch(ValueToValueMapTy &VMap, | |||||
197 | const Instruction *Inst, | |||||
198 | BasicBlock *NewBB) = 0; | |||||
199 | virtual CloningAction handleTypeIdFor(ValueToValueMapTy &VMap, | |||||
200 | const Instruction *Inst, | |||||
201 | BasicBlock *NewBB) = 0; | |||||
202 | virtual CloningAction handleInvoke(ValueToValueMapTy &VMap, | |||||
203 | const InvokeInst *Invoke, | |||||
204 | BasicBlock *NewBB) = 0; | |||||
205 | virtual CloningAction handleResume(ValueToValueMapTy &VMap, | |||||
206 | const ResumeInst *Resume, | |||||
207 | BasicBlock *NewBB) = 0; | |||||
208 | virtual CloningAction handleCompare(ValueToValueMapTy &VMap, | |||||
209 | const CmpInst *Compare, | |||||
210 | BasicBlock *NewBB) = 0; | |||||
211 | virtual CloningAction handleLandingPad(ValueToValueMapTy &VMap, | |||||
212 | const LandingPadInst *LPad, | |||||
213 | BasicBlock *NewBB) = 0; | |||||
214 | ||||||
215 | ValueMaterializer *getValueMaterializer() override { return &Materializer; } | |||||
216 | ||||||
217 | protected: | |||||
218 | WinEHFrameVariableMaterializer Materializer; | |||||
219 | Type *SelectorIDType; | |||||
220 | Type *Int8PtrType; | |||||
221 | LandingPadMap &LPadMap; | |||||
222 | ||||||
223 | /// The value representing the parent frame pointer. | |||||
224 | Value *EstablisherFrame; | |||||
225 | }; | |||||
226 | ||||||
227 | class WinEHCatchDirector : public WinEHCloningDirectorBase { | |||||
228 | public: | |||||
229 | WinEHCatchDirector( | |||||
230 | Function *CatchFn, Value *Selector, FrameVarInfoMap &VarInfo, | |||||
231 | LandingPadMap &LPadMap, | |||||
232 | DenseMap<LandingPadInst *, const LandingPadInst *> &NestedLPads) | |||||
233 | : WinEHCloningDirectorBase(CatchFn, VarInfo, LPadMap), | |||||
234 | CurrentSelector(Selector->stripPointerCasts()), | |||||
235 | ExceptionObjectVar(nullptr), NestedLPtoOriginalLP(NestedLPads) {} | |||||
236 | ||||||
237 | CloningAction handleBeginCatch(ValueToValueMapTy &VMap, | |||||
238 | const Instruction *Inst, | |||||
239 | BasicBlock *NewBB) override; | |||||
240 | CloningAction handleEndCatch(ValueToValueMapTy &VMap, const Instruction *Inst, | |||||
241 | BasicBlock *NewBB) override; | |||||
242 | CloningAction handleTypeIdFor(ValueToValueMapTy &VMap, | |||||
243 | const Instruction *Inst, | |||||
244 | BasicBlock *NewBB) override; | |||||
245 | CloningAction handleInvoke(ValueToValueMapTy &VMap, const InvokeInst *Invoke, | |||||
246 | BasicBlock *NewBB) override; | |||||
247 | CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume, | |||||
248 | BasicBlock *NewBB) override; | |||||
249 | CloningAction handleCompare(ValueToValueMapTy &VMap, | |||||
250 | const CmpInst *Compare, BasicBlock *NewBB) override; | |||||
251 | CloningAction handleLandingPad(ValueToValueMapTy &VMap, | |||||
252 | const LandingPadInst *LPad, | |||||
253 | BasicBlock *NewBB) override; | |||||
254 | ||||||
255 | Value *getExceptionVar() { return ExceptionObjectVar; } | |||||
256 | TinyPtrVector<BasicBlock *> &getReturnTargets() { return ReturnTargets; } | |||||
257 | ||||||
258 | private: | |||||
259 | Value *CurrentSelector; | |||||
260 | ||||||
261 | Value *ExceptionObjectVar; | |||||
262 | TinyPtrVector<BasicBlock *> ReturnTargets; | |||||
263 | ||||||
264 | // This will be a reference to the field of the same name in the WinEHPrepare | |||||
265 | // object which instantiates this WinEHCatchDirector object. | |||||
266 | DenseMap<LandingPadInst *, const LandingPadInst *> &NestedLPtoOriginalLP; | |||||
267 | }; | |||||
268 | ||||||
269 | class WinEHCleanupDirector : public WinEHCloningDirectorBase { | |||||
270 | public: | |||||
271 | WinEHCleanupDirector(Function *CleanupFn, FrameVarInfoMap &VarInfo, | |||||
272 | LandingPadMap &LPadMap) | |||||
273 | : WinEHCloningDirectorBase(CleanupFn, VarInfo, LPadMap) {} | |||||
274 | ||||||
275 | CloningAction handleBeginCatch(ValueToValueMapTy &VMap, | |||||
276 | const Instruction *Inst, | |||||
277 | BasicBlock *NewBB) override; | |||||
278 | CloningAction handleEndCatch(ValueToValueMapTy &VMap, const Instruction *Inst, | |||||
279 | BasicBlock *NewBB) override; | |||||
280 | CloningAction handleTypeIdFor(ValueToValueMapTy &VMap, | |||||
281 | const Instruction *Inst, | |||||
282 | BasicBlock *NewBB) override; | |||||
283 | CloningAction handleInvoke(ValueToValueMapTy &VMap, const InvokeInst *Invoke, | |||||
284 | BasicBlock *NewBB) override; | |||||
285 | CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume, | |||||
286 | BasicBlock *NewBB) override; | |||||
287 | CloningAction handleCompare(ValueToValueMapTy &VMap, | |||||
288 | const CmpInst *Compare, BasicBlock *NewBB) override; | |||||
289 | CloningAction handleLandingPad(ValueToValueMapTy &VMap, | |||||
290 | const LandingPadInst *LPad, | |||||
291 | BasicBlock *NewBB) override; | |||||
292 | }; | |||||
293 | ||||||
294 | class LandingPadActions { | |||||
295 | public: | |||||
296 | LandingPadActions() : HasCleanupHandlers(false) {} | |||||
297 | ||||||
298 | void insertCatchHandler(CatchHandler *Action) { Actions.push_back(Action); } | |||||
299 | void insertCleanupHandler(CleanupHandler *Action) { | |||||
300 | Actions.push_back(Action); | |||||
301 | HasCleanupHandlers = true; | |||||
302 | } | |||||
303 | ||||||
304 | bool includesCleanup() const { return HasCleanupHandlers; } | |||||
305 | ||||||
306 | SmallVectorImpl<ActionHandler *> &actions() { return Actions; } | |||||
307 | SmallVectorImpl<ActionHandler *>::iterator begin() { return Actions.begin(); } | |||||
308 | SmallVectorImpl<ActionHandler *>::iterator end() { return Actions.end(); } | |||||
309 | ||||||
310 | private: | |||||
311 | // Note that this class does not own the ActionHandler objects in this vector. | |||||
312 | // The ActionHandlers are owned by the CatchHandlerMap and CleanupHandlerMap | |||||
313 | // in the WinEHPrepare class. | |||||
314 | SmallVector<ActionHandler *, 4> Actions; | |||||
315 | bool HasCleanupHandlers; | |||||
316 | }; | |||||
317 | ||||||
318 | } // end anonymous namespace | |||||
319 | ||||||
320 | char WinEHPrepare::ID = 0; | |||||
321 | INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare", "Prepare Windows exceptions",static void* initializeWinEHPreparePassOnce(PassRegistry & Registry) { PassInfo *PI = new PassInfo("Prepare Windows exceptions" , "winehprepare", & WinEHPrepare ::ID, PassInfo::NormalCtor_t (callDefaultCtor< WinEHPrepare >), false, false, PassInfo ::TargetMachineCtor_t(callTargetMachineCtor< WinEHPrepare > )); Registry.registerPass(*PI, true); return PI; } void llvm:: initializeWinEHPreparePass(PassRegistry &Registry) { static volatile sys::cas_flag initialized = 0; sys::cas_flag old_val = sys::CompareAndSwap(&initialized, 1, 0); if (old_val == 0) { initializeWinEHPreparePassOnce(Registry); sys::MemoryFence (); AnnotateIgnoreWritesBegin("/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 322); AnnotateHappensBefore("/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 322, &initialized); initialized = 2; AnnotateIgnoreWritesEnd ("/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 322); } else { sys::cas_flag tmp = initialized; sys::MemoryFence (); while (tmp != 2) { tmp = initialized; sys::MemoryFence(); } } AnnotateHappensAfter("/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 322, &initialized); } | |||||
322 | false, false)static void* initializeWinEHPreparePassOnce(PassRegistry & Registry) { PassInfo *PI = new PassInfo("Prepare Windows exceptions" , "winehprepare", & WinEHPrepare ::ID, PassInfo::NormalCtor_t (callDefaultCtor< WinEHPrepare >), false, false, PassInfo ::TargetMachineCtor_t(callTargetMachineCtor< WinEHPrepare > )); Registry.registerPass(*PI, true); return PI; } void llvm:: initializeWinEHPreparePass(PassRegistry &Registry) { static volatile sys::cas_flag initialized = 0; sys::cas_flag old_val = sys::CompareAndSwap(&initialized, 1, 0); if (old_val == 0) { initializeWinEHPreparePassOnce(Registry); sys::MemoryFence (); AnnotateIgnoreWritesBegin("/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 322); AnnotateHappensBefore("/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 322, &initialized); initialized = 2; AnnotateIgnoreWritesEnd ("/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 322); } else { sys::cas_flag tmp = initialized; sys::MemoryFence (); while (tmp != 2) { tmp = initialized; sys::MemoryFence(); } } AnnotateHappensAfter("/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 322, &initialized); } | |||||
323 | ||||||
324 | FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) { | |||||
325 | return new WinEHPrepare(TM); | |||||
326 | } | |||||
327 | ||||||
328 | bool WinEHPrepare::runOnFunction(Function &Fn) { | |||||
329 | // No need to prepare outlined handlers. | |||||
330 | if (Fn.hasFnAttribute("wineh-parent")) | |||||
331 | return false; | |||||
332 | ||||||
333 | SmallVector<LandingPadInst *, 4> LPads; | |||||
334 | SmallVector<ResumeInst *, 4> Resumes; | |||||
335 | for (BasicBlock &BB : Fn) { | |||||
336 | if (auto *LP = BB.getLandingPadInst()) | |||||
337 | LPads.push_back(LP); | |||||
338 | if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator())) | |||||
339 | Resumes.push_back(Resume); | |||||
340 | } | |||||
341 | ||||||
342 | // No need to prepare functions that lack landing pads. | |||||
343 | if (LPads.empty()) | |||||
344 | return false; | |||||
345 | ||||||
346 | // Classify the personality to see what kind of preparation we need. | |||||
347 | Personality = classifyEHPersonality(LPads.back()->getPersonalityFn()); | |||||
348 | ||||||
349 | // Do nothing if this is not an MSVC personality. | |||||
350 | if (!isMSVCEHPersonality(Personality)) | |||||
351 | return false; | |||||
352 | ||||||
353 | DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); | |||||
354 | ||||||
355 | // If there were any landing pads, prepareExceptionHandlers will make changes. | |||||
356 | prepareExceptionHandlers(Fn, LPads); | |||||
357 | return true; | |||||
358 | } | |||||
359 | ||||||
360 | bool WinEHPrepare::doFinalization(Module &M) { return false; } | |||||
361 | ||||||
362 | void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const { | |||||
363 | AU.addRequired<DominatorTreeWrapperPass>(); | |||||
364 | } | |||||
365 | ||||||
366 | static bool isSelectorDispatch(BasicBlock *BB, BasicBlock *&CatchHandler, | |||||
367 | Constant *&Selector, BasicBlock *&NextBB); | |||||
368 | ||||||
369 | // Finds blocks reachable from the starting set Worklist. Does not follow unwind | |||||
370 | // edges or blocks listed in StopPoints. | |||||
371 | static void findReachableBlocks(SmallPtrSetImpl<BasicBlock *> &ReachableBBs, | |||||
372 | SetVector<BasicBlock *> &Worklist, | |||||
373 | const SetVector<BasicBlock *> *StopPoints) { | |||||
374 | while (!Worklist.empty()) { | |||||
375 | BasicBlock *BB = Worklist.pop_back_val(); | |||||
376 | ||||||
377 | // Don't cross blocks that we should stop at. | |||||
378 | if (StopPoints && StopPoints->count(BB)) | |||||
379 | continue; | |||||
380 | ||||||
381 | if (!ReachableBBs.insert(BB).second) | |||||
382 | continue; // Already visited. | |||||
383 | ||||||
384 | // Don't follow unwind edges of invokes. | |||||
385 | if (auto *II = dyn_cast<InvokeInst>(BB->getTerminator())) { | |||||
386 | Worklist.insert(II->getNormalDest()); | |||||
387 | continue; | |||||
388 | } | |||||
389 | ||||||
390 | // Otherwise, follow all successors. | |||||
391 | Worklist.insert(succ_begin(BB), succ_end(BB)); | |||||
392 | } | |||||
393 | } | |||||
394 | ||||||
395 | /// Find all points where exceptional control rejoins normal control flow via | |||||
396 | /// llvm.eh.endcatch. Add them to the normal bb reachability worklist. | |||||
397 | static void findCXXEHReturnPoints(Function &F, | |||||
398 | SetVector<BasicBlock *> &EHReturnBlocks) { | |||||
399 | for (auto BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) { | |||||
400 | BasicBlock *BB = BBI; | |||||
401 | for (Instruction &I : *BB) { | |||||
402 | if (match(&I, m_Intrinsic<Intrinsic::eh_endcatch>())) { | |||||
403 | // Split the block after the call to llvm.eh.endcatch if there is | |||||
404 | // anything other than an unconditional branch, or if the successor | |||||
405 | // starts with a phi. | |||||
406 | auto *Br = dyn_cast<BranchInst>(I.getNextNode()); | |||||
407 | if (!Br || !Br->isUnconditional() || | |||||
408 | isa<PHINode>(Br->getSuccessor(0)->begin())) { | |||||
409 | DEBUG(dbgs() << "splitting block " << BB->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << "splitting block " << BB->getName() << " with llvm.eh.endcatch\n"; } } while (0) | |||||
410 | << " with llvm.eh.endcatch\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << "splitting block " << BB->getName() << " with llvm.eh.endcatch\n"; } } while (0); | |||||
411 | BBI = BB->splitBasicBlock(I.getNextNode(), "ehreturn"); | |||||
412 | } | |||||
413 | // The next BB is normal control flow. | |||||
414 | EHReturnBlocks.insert(BB->getTerminator()->getSuccessor(0)); | |||||
415 | break; | |||||
416 | } | |||||
417 | } | |||||
418 | } | |||||
419 | } | |||||
420 | ||||||
421 | static bool isCatchAllLandingPad(const BasicBlock *BB) { | |||||
422 | const LandingPadInst *LP = BB->getLandingPadInst(); | |||||
423 | if (!LP) | |||||
424 | return false; | |||||
425 | unsigned N = LP->getNumClauses(); | |||||
426 | return (N > 0 && LP->isCatch(N - 1) && | |||||
427 | isa<ConstantPointerNull>(LP->getClause(N - 1))); | |||||
428 | } | |||||
429 | ||||||
430 | /// Find all points where exceptions control rejoins normal control flow via | |||||
431 | /// selector dispatch. | |||||
432 | static void findSEHEHReturnPoints(Function &F, | |||||
433 | SetVector<BasicBlock *> &EHReturnBlocks) { | |||||
434 | for (auto BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) { | |||||
435 | BasicBlock *BB = BBI; | |||||
436 | // If the landingpad is a catch-all, treat the whole lpad as if it is | |||||
437 | // reachable from normal control flow. | |||||
438 | // FIXME: This is imprecise. We need a better way of identifying where a | |||||
439 | // catch-all starts and cleanups stop. As far as LLVM is concerned, there | |||||
440 | // is no difference. | |||||
441 | if (isCatchAllLandingPad(BB)) { | |||||
442 | EHReturnBlocks.insert(BB); | |||||
443 | continue; | |||||
444 | } | |||||
445 | ||||||
446 | BasicBlock *CatchHandler; | |||||
447 | BasicBlock *NextBB; | |||||
448 | Constant *Selector; | |||||
449 | if (isSelectorDispatch(BB, CatchHandler, Selector, NextBB)) { | |||||
450 | // Split the edge if there is a phi node. Returning from EH to a phi node | |||||
451 | // is just as impossible as having a phi after an indirectbr. | |||||
452 | if (isa<PHINode>(CatchHandler->begin())) { | |||||
453 | DEBUG(dbgs() << "splitting EH return edge from " << BB->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << "splitting EH return edge from " << BB->getName() << " to " << CatchHandler ->getName() << '\n'; } } while (0) | |||||
454 | << " to " << CatchHandler->getName() << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << "splitting EH return edge from " << BB->getName() << " to " << CatchHandler ->getName() << '\n'; } } while (0); | |||||
455 | BBI = CatchHandler = SplitCriticalEdge( | |||||
456 | BB, std::find(succ_begin(BB), succ_end(BB), CatchHandler)); | |||||
457 | } | |||||
458 | EHReturnBlocks.insert(CatchHandler); | |||||
459 | } | |||||
460 | } | |||||
461 | } | |||||
462 | ||||||
463 | /// Ensure that all values live into and out of exception handlers are stored | |||||
464 | /// in memory. | |||||
465 | /// FIXME: This falls down when values are defined in one handler and live into | |||||
466 | /// another handler. For example, a cleanup defines a value used only by a | |||||
467 | /// catch handler. | |||||
468 | void WinEHPrepare::demoteValuesLiveAcrossHandlers( | |||||
469 | Function &F, SmallVectorImpl<LandingPadInst *> &LPads) { | |||||
470 | DEBUG(dbgs() << "Demoting values live across exception handlers in function "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << "Demoting values live across exception handlers in function " << F.getName() << '\n'; } } while (0) | |||||
471 | << F.getName() << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << "Demoting values live across exception handlers in function " << F.getName() << '\n'; } } while (0); | |||||
472 | ||||||
473 | // Build a set of all non-exceptional blocks and exceptional blocks. | |||||
474 | // - Non-exceptional blocks are blocks reachable from the entry block while | |||||
475 | // not following invoke unwind edges. | |||||
476 | // - Exceptional blocks are blocks reachable from landingpads. Analysis does | |||||
477 | // not follow llvm.eh.endcatch blocks, which mark a transition from | |||||
478 | // exceptional to normal control. | |||||
479 | SmallPtrSet<BasicBlock *, 4> NormalBlocks; | |||||
480 | SmallPtrSet<BasicBlock *, 4> EHBlocks; | |||||
481 | SetVector<BasicBlock *> EHReturnBlocks; | |||||
482 | SetVector<BasicBlock *> Worklist; | |||||
483 | ||||||
484 | if (Personality == EHPersonality::MSVC_CXX) | |||||
485 | findCXXEHReturnPoints(F, EHReturnBlocks); | |||||
486 | else | |||||
487 | findSEHEHReturnPoints(F, EHReturnBlocks); | |||||
488 | ||||||
489 | DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "identified the following blocks as EH return points:\n" ; for (BasicBlock *BB : EHReturnBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0) | |||||
490 | dbgs() << "identified the following blocks as EH return points:\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "identified the following blocks as EH return points:\n" ; for (BasicBlock *BB : EHReturnBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0) | |||||
491 | for (BasicBlock *BB : EHReturnBlocks)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "identified the following blocks as EH return points:\n" ; for (BasicBlock *BB : EHReturnBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0) | |||||
492 | dbgs() << " " << BB->getName() << '\n';do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "identified the following blocks as EH return points:\n" ; for (BasicBlock *BB : EHReturnBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0) | |||||
493 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "identified the following blocks as EH return points:\n" ; for (BasicBlock *BB : EHReturnBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0); | |||||
494 | ||||||
495 | // Join points should not have phis at this point, unless they are a | |||||
496 | // landingpad, in which case we will demote their phis later. | |||||
497 | #ifndef NDEBUG | |||||
498 | for (BasicBlock *BB : EHReturnBlocks) | |||||
499 | assert((BB->isLandingPad() || !isa<PHINode>(BB->begin())) &&(((BB->isLandingPad() || !isa<PHINode>(BB->begin( ))) && "non-lpad EH return block has phi") ? static_cast <void> (0) : __assert_fail ("(BB->isLandingPad() || !isa<PHINode>(BB->begin())) && \"non-lpad EH return block has phi\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 500, __PRETTY_FUNCTION__)) | |||||
500 | "non-lpad EH return block has phi")(((BB->isLandingPad() || !isa<PHINode>(BB->begin( ))) && "non-lpad EH return block has phi") ? static_cast <void> (0) : __assert_fail ("(BB->isLandingPad() || !isa<PHINode>(BB->begin())) && \"non-lpad EH return block has phi\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 500, __PRETTY_FUNCTION__)); | |||||
501 | #endif | |||||
502 | ||||||
503 | // Normal blocks are the blocks reachable from the entry block and all EH | |||||
504 | // return points. | |||||
505 | Worklist = EHReturnBlocks; | |||||
506 | Worklist.insert(&F.getEntryBlock()); | |||||
507 | findReachableBlocks(NormalBlocks, Worklist, nullptr); | |||||
508 | DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "marked the following blocks as normal:\n" ; for (BasicBlock *BB : NormalBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0) | |||||
509 | dbgs() << "marked the following blocks as normal:\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "marked the following blocks as normal:\n" ; for (BasicBlock *BB : NormalBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0) | |||||
510 | for (BasicBlock *BB : NormalBlocks)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "marked the following blocks as normal:\n" ; for (BasicBlock *BB : NormalBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0) | |||||
511 | dbgs() << " " << BB->getName() << '\n';do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "marked the following blocks as normal:\n" ; for (BasicBlock *BB : NormalBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0) | |||||
512 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "marked the following blocks as normal:\n" ; for (BasicBlock *BB : NormalBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0); | |||||
513 | ||||||
514 | // Exceptional blocks are the blocks reachable from landingpads that don't | |||||
515 | // cross EH return points. | |||||
516 | Worklist.clear(); | |||||
517 | for (auto *LPI : LPads) | |||||
518 | Worklist.insert(LPI->getParent()); | |||||
519 | findReachableBlocks(EHBlocks, Worklist, &EHReturnBlocks); | |||||
520 | DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "marked the following blocks as exceptional:\n" ; for (BasicBlock *BB : EHBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0) | |||||
521 | dbgs() << "marked the following blocks as exceptional:\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "marked the following blocks as exceptional:\n" ; for (BasicBlock *BB : EHBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0) | |||||
522 | for (BasicBlock *BB : EHBlocks)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "marked the following blocks as exceptional:\n" ; for (BasicBlock *BB : EHBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0) | |||||
523 | dbgs() << " " << BB->getName() << '\n';do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "marked the following blocks as exceptional:\n" ; for (BasicBlock *BB : EHBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0) | |||||
524 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "marked the following blocks as exceptional:\n" ; for (BasicBlock *BB : EHBlocks) dbgs() << " " << BB->getName() << '\n'; }; } } while (0); | |||||
525 | ||||||
526 | SetVector<Argument *> ArgsToDemote; | |||||
527 | SetVector<Instruction *> InstrsToDemote; | |||||
528 | for (BasicBlock &BB : F) { | |||||
529 | bool IsNormalBB = NormalBlocks.count(&BB); | |||||
530 | bool IsEHBB = EHBlocks.count(&BB); | |||||
531 | if (!IsNormalBB && !IsEHBB) | |||||
532 | continue; // Blocks that are neither normal nor EH are unreachable. | |||||
533 | for (Instruction &I : BB) { | |||||
534 | for (Value *Op : I.operands()) { | |||||
535 | // Don't demote static allocas, constants, and labels. | |||||
536 | if (isa<Constant>(Op) || isa<BasicBlock>(Op) || isa<InlineAsm>(Op)) | |||||
537 | continue; | |||||
538 | auto *AI = dyn_cast<AllocaInst>(Op); | |||||
539 | if (AI && AI->isStaticAlloca()) | |||||
540 | continue; | |||||
541 | ||||||
542 | if (auto *Arg = dyn_cast<Argument>(Op)) { | |||||
543 | if (IsEHBB) { | |||||
544 | DEBUG(dbgs() << "Demoting argument " << *Argdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << "Demoting argument " << *Arg << " used by EH instr: " << I << "\n" ; } } while (0) | |||||
545 | << " used by EH instr: " << I << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << "Demoting argument " << *Arg << " used by EH instr: " << I << "\n" ; } } while (0); | |||||
546 | ArgsToDemote.insert(Arg); | |||||
547 | } | |||||
548 | continue; | |||||
549 | } | |||||
550 | ||||||
551 | auto *OpI = cast<Instruction>(Op); | |||||
552 | BasicBlock *OpBB = OpI->getParent(); | |||||
553 | // If a value is produced and consumed in the same BB, we don't need to | |||||
554 | // demote it. | |||||
555 | if (OpBB == &BB) | |||||
556 | continue; | |||||
557 | bool IsOpNormalBB = NormalBlocks.count(OpBB); | |||||
558 | bool IsOpEHBB = EHBlocks.count(OpBB); | |||||
559 | if (IsNormalBB != IsOpNormalBB || IsEHBB != IsOpEHBB) { | |||||
560 | DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "Demoting instruction live in-out from EH:\n" ; dbgs() << "Instr: " << *OpI << '\n'; dbgs () << "User: " << I << '\n'; }; } } while ( 0) | |||||
561 | dbgs() << "Demoting instruction live in-out from EH:\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "Demoting instruction live in-out from EH:\n" ; dbgs() << "Instr: " << *OpI << '\n'; dbgs () << "User: " << I << '\n'; }; } } while ( 0) | |||||
562 | dbgs() << "Instr: " << *OpI << '\n';do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "Demoting instruction live in-out from EH:\n" ; dbgs() << "Instr: " << *OpI << '\n'; dbgs () << "User: " << I << '\n'; }; } } while ( 0) | |||||
563 | dbgs() << "User: " << I << '\n';do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "Demoting instruction live in-out from EH:\n" ; dbgs() << "Instr: " << *OpI << '\n'; dbgs () << "User: " << I << '\n'; }; } } while ( 0) | |||||
564 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { { dbgs() << "Demoting instruction live in-out from EH:\n" ; dbgs() << "Instr: " << *OpI << '\n'; dbgs () << "User: " << I << '\n'; }; } } while ( 0); | |||||
565 | InstrsToDemote.insert(OpI); | |||||
566 | } | |||||
567 | } | |||||
568 | } | |||||
569 | } | |||||
570 | ||||||
571 | // Demote values live into and out of handlers. | |||||
572 | // FIXME: This demotion is inefficient. We should insert spills at the point | |||||
573 | // of definition, insert one reload in each handler that uses the value, and | |||||
574 | // insert reloads in the BB used to rejoin normal control flow. | |||||
575 | Instruction *AllocaInsertPt = F.getEntryBlock().getFirstInsertionPt(); | |||||
576 | for (Instruction *I : InstrsToDemote) | |||||
577 | DemoteRegToStack(*I, false, AllocaInsertPt); | |||||
578 | ||||||
579 | // Demote arguments separately, and only for uses in EH blocks. | |||||
580 | for (Argument *Arg : ArgsToDemote) { | |||||
581 | auto *Slot = new AllocaInst(Arg->getType(), nullptr, | |||||
582 | Arg->getName() + ".reg2mem", AllocaInsertPt); | |||||
583 | SmallVector<User *, 4> Users(Arg->user_begin(), Arg->user_end()); | |||||
584 | for (User *U : Users) { | |||||
585 | auto *I = dyn_cast<Instruction>(U); | |||||
586 | if (I && EHBlocks.count(I->getParent())) { | |||||
587 | auto *Reload = new LoadInst(Slot, Arg->getName() + ".reload", false, I); | |||||
588 | U->replaceUsesOfWith(Arg, Reload); | |||||
589 | } | |||||
590 | } | |||||
591 | new StoreInst(Arg, Slot, AllocaInsertPt); | |||||
592 | } | |||||
593 | ||||||
594 | // Demote landingpad phis, as the landingpad will be removed from the machine | |||||
595 | // CFG. | |||||
596 | for (LandingPadInst *LPI : LPads) { | |||||
597 | BasicBlock *BB = LPI->getParent(); | |||||
598 | while (auto *Phi = dyn_cast<PHINode>(BB->begin())) | |||||
599 | DemotePHIToStack(Phi, AllocaInsertPt); | |||||
600 | } | |||||
601 | ||||||
602 | DEBUG(dbgs() << "Demoted " << InstrsToDemote.size() << " instructions and "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << "Demoted " << InstrsToDemote .size() << " instructions and " << ArgsToDemote.size () << " arguments for WinEHPrepare\n\n"; } } while (0) | |||||
603 | << ArgsToDemote.size() << " arguments for WinEHPrepare\n\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << "Demoted " << InstrsToDemote .size() << " instructions and " << ArgsToDemote.size () << " arguments for WinEHPrepare\n\n"; } } while (0); | |||||
604 | } | |||||
605 | ||||||
606 | bool WinEHPrepare::prepareExceptionHandlers( | |||||
607 | Function &F, SmallVectorImpl<LandingPadInst *> &LPads) { | |||||
608 | // Don't run on functions that are already prepared. | |||||
609 | for (LandingPadInst *LPad : LPads) { | |||||
610 | BasicBlock *LPadBB = LPad->getParent(); | |||||
611 | for (Instruction &Inst : *LPadBB) | |||||
612 | if (match(&Inst, m_Intrinsic<Intrinsic::eh_actions>())) | |||||
613 | return false; | |||||
614 | } | |||||
615 | ||||||
616 | demoteValuesLiveAcrossHandlers(F, LPads); | |||||
617 | ||||||
618 | // These containers are used to re-map frame variables that are used in | |||||
619 | // outlined catch and cleanup handlers. They will be populated as the | |||||
620 | // handlers are outlined. | |||||
621 | FrameVarInfoMap FrameVarInfo; | |||||
622 | ||||||
623 | bool HandlersOutlined = false; | |||||
624 | ||||||
625 | Module *M = F.getParent(); | |||||
626 | LLVMContext &Context = M->getContext(); | |||||
627 | ||||||
628 | // Create a new function to receive the handler contents. | |||||
629 | PointerType *Int8PtrType = Type::getInt8PtrTy(Context); | |||||
630 | Type *Int32Type = Type::getInt32Ty(Context); | |||||
631 | Function *ActionIntrin = Intrinsic::getDeclaration(M, Intrinsic::eh_actions); | |||||
632 | ||||||
633 | if (isAsynchronousEHPersonality(Personality)) { | |||||
634 | // FIXME: Switch the ehptr type to i32 and then switch this. | |||||
635 | SEHExceptionCodeSlot = | |||||
636 | new AllocaInst(Int8PtrType, nullptr, "seh_exception_code", | |||||
637 | F.getEntryBlock().getFirstInsertionPt()); | |||||
638 | } | |||||
639 | ||||||
640 | for (LandingPadInst *LPad : LPads) { | |||||
641 | // Look for evidence that this landingpad has already been processed. | |||||
642 | bool LPadHasActionList = false; | |||||
643 | BasicBlock *LPadBB = LPad->getParent(); | |||||
644 | for (Instruction &Inst : *LPadBB) { | |||||
645 | if (match(&Inst, m_Intrinsic<Intrinsic::eh_actions>())) { | |||||
646 | LPadHasActionList = true; | |||||
647 | break; | |||||
648 | } | |||||
649 | } | |||||
650 | ||||||
651 | // If we've already outlined the handlers for this landingpad, | |||||
652 | // there's nothing more to do here. | |||||
653 | if (LPadHasActionList) | |||||
654 | continue; | |||||
655 | ||||||
656 | // If either of the values in the aggregate returned by the landing pad is | |||||
657 | // extracted and stored to memory, promote the stored value to a register. | |||||
658 | promoteLandingPadValues(LPad); | |||||
659 | ||||||
660 | LandingPadActions Actions; | |||||
661 | mapLandingPadBlocks(LPad, Actions); | |||||
662 | ||||||
663 | HandlersOutlined |= !Actions.actions().empty(); | |||||
664 | for (ActionHandler *Action : Actions) { | |||||
665 | if (Action->hasBeenProcessed()) | |||||
666 | continue; | |||||
667 | BasicBlock *StartBB = Action->getStartBlock(); | |||||
668 | ||||||
669 | // SEH doesn't do any outlining for catches. Instead, pass the handler | |||||
670 | // basic block addr to llvm.eh.actions and list the block as a return | |||||
671 | // target. | |||||
672 | if (isAsynchronousEHPersonality(Personality)) { | |||||
673 | if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) { | |||||
674 | processSEHCatchHandler(CatchAction, StartBB); | |||||
675 | continue; | |||||
676 | } | |||||
677 | } | |||||
678 | ||||||
679 | outlineHandler(Action, &F, LPad, StartBB, FrameVarInfo); | |||||
680 | } | |||||
681 | ||||||
682 | // Split the block after the landingpad instruction so that it is just a | |||||
683 | // call to llvm.eh.actions followed by indirectbr. | |||||
684 | assert(!isa<PHINode>(LPadBB->begin()) && "lpad phi not removed")((!isa<PHINode>(LPadBB->begin()) && "lpad phi not removed" ) ? static_cast<void> (0) : __assert_fail ("!isa<PHINode>(LPadBB->begin()) && \"lpad phi not removed\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 684, __PRETTY_FUNCTION__)); | |||||
685 | LPadBB->splitBasicBlock(LPad->getNextNode(), | |||||
686 | LPadBB->getName() + ".prepsplit"); | |||||
687 | // Erase the branch inserted by the split so we can insert indirectbr. | |||||
688 | LPadBB->getTerminator()->eraseFromParent(); | |||||
689 | ||||||
690 | // Replace all extracted values with undef and ultimately replace the | |||||
691 | // landingpad with undef. | |||||
692 | SmallVector<Instruction *, 4> SEHCodeUses; | |||||
693 | SmallVector<Instruction *, 4> EHUndefs; | |||||
694 | for (User *U : LPad->users()) { | |||||
695 | auto *E = dyn_cast<ExtractValueInst>(U); | |||||
696 | if (!E) | |||||
697 | continue; | |||||
698 | assert(E->getNumIndices() == 1 &&((E->getNumIndices() == 1 && "Unexpected operation: extracting both landing pad values" ) ? static_cast<void> (0) : __assert_fail ("E->getNumIndices() == 1 && \"Unexpected operation: extracting both landing pad values\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 699, __PRETTY_FUNCTION__)) | |||||
699 | "Unexpected operation: extracting both landing pad values")((E->getNumIndices() == 1 && "Unexpected operation: extracting both landing pad values" ) ? static_cast<void> (0) : __assert_fail ("E->getNumIndices() == 1 && \"Unexpected operation: extracting both landing pad values\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 699, __PRETTY_FUNCTION__)); | |||||
700 | unsigned Idx = *E->idx_begin(); | |||||
701 | assert((Idx == 0 || Idx == 1) && "unexpected index")(((Idx == 0 || Idx == 1) && "unexpected index") ? static_cast <void> (0) : __assert_fail ("(Idx == 0 || Idx == 1) && \"unexpected index\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 701, __PRETTY_FUNCTION__)); | |||||
702 | if (Idx == 0 && isAsynchronousEHPersonality(Personality)) | |||||
703 | SEHCodeUses.push_back(E); | |||||
704 | else | |||||
705 | EHUndefs.push_back(E); | |||||
706 | } | |||||
707 | for (Instruction *E : EHUndefs) { | |||||
708 | E->replaceAllUsesWith(UndefValue::get(E->getType())); | |||||
709 | E->eraseFromParent(); | |||||
710 | } | |||||
711 | LPad->replaceAllUsesWith(UndefValue::get(LPad->getType())); | |||||
712 | ||||||
713 | // Rewrite uses of the exception pointer to loads of an alloca. | |||||
714 | for (Instruction *E : SEHCodeUses) { | |||||
715 | SmallVector<Use *, 4> Uses; | |||||
716 | for (Use &U : E->uses()) | |||||
717 | Uses.push_back(&U); | |||||
718 | for (Use *U : Uses) { | |||||
719 | auto *I = cast<Instruction>(U->getUser()); | |||||
720 | if (isa<ResumeInst>(I)) | |||||
721 | continue; | |||||
722 | LoadInst *LI; | |||||
723 | if (auto *Phi = dyn_cast<PHINode>(I)) | |||||
724 | LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false, | |||||
725 | Phi->getIncomingBlock(*U)); | |||||
726 | else | |||||
727 | LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false, I); | |||||
728 | U->set(LI); | |||||
729 | } | |||||
730 | E->replaceAllUsesWith(UndefValue::get(E->getType())); | |||||
731 | E->eraseFromParent(); | |||||
732 | } | |||||
733 | ||||||
734 | // Add a call to describe the actions for this landing pad. | |||||
735 | std::vector<Value *> ActionArgs; | |||||
736 | for (ActionHandler *Action : Actions) { | |||||
737 | // Action codes from docs are: 0 cleanup, 1 catch. | |||||
738 | if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) { | |||||
739 | ActionArgs.push_back(ConstantInt::get(Int32Type, 1)); | |||||
740 | ActionArgs.push_back(CatchAction->getSelector()); | |||||
741 | // Find the frame escape index of the exception object alloca in the | |||||
742 | // parent. | |||||
743 | int FrameEscapeIdx = -1; | |||||
744 | Value *EHObj = const_cast<Value *>(CatchAction->getExceptionVar()); | |||||
745 | if (EHObj && !isa<ConstantPointerNull>(EHObj)) { | |||||
746 | auto I = FrameVarInfo.find(EHObj); | |||||
747 | assert(I != FrameVarInfo.end() &&((I != FrameVarInfo.end() && "failed to map llvm.eh.begincatch var" ) ? static_cast<void> (0) : __assert_fail ("I != FrameVarInfo.end() && \"failed to map llvm.eh.begincatch var\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 748, __PRETTY_FUNCTION__)) | |||||
748 | "failed to map llvm.eh.begincatch var")((I != FrameVarInfo.end() && "failed to map llvm.eh.begincatch var" ) ? static_cast<void> (0) : __assert_fail ("I != FrameVarInfo.end() && \"failed to map llvm.eh.begincatch var\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 748, __PRETTY_FUNCTION__)); | |||||
749 | FrameEscapeIdx = std::distance(FrameVarInfo.begin(), I); | |||||
750 | } | |||||
751 | ActionArgs.push_back(ConstantInt::get(Int32Type, FrameEscapeIdx)); | |||||
752 | } else { | |||||
753 | ActionArgs.push_back(ConstantInt::get(Int32Type, 0)); | |||||
754 | } | |||||
755 | ActionArgs.push_back(Action->getHandlerBlockOrFunc()); | |||||
756 | } | |||||
757 | CallInst *Recover = | |||||
758 | CallInst::Create(ActionIntrin, ActionArgs, "recover", LPadBB); | |||||
759 | ||||||
760 | // Add an indirect branch listing possible successors of the catch handlers. | |||||
761 | SetVector<BasicBlock *> ReturnTargets; | |||||
762 | for (ActionHandler *Action : Actions) { | |||||
763 | if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) { | |||||
764 | const auto &CatchTargets = CatchAction->getReturnTargets(); | |||||
765 | ReturnTargets.insert(CatchTargets.begin(), CatchTargets.end()); | |||||
766 | } | |||||
767 | } | |||||
768 | IndirectBrInst *Branch = | |||||
769 | IndirectBrInst::Create(Recover, ReturnTargets.size(), LPadBB); | |||||
770 | for (BasicBlock *Target : ReturnTargets) | |||||
771 | Branch->addDestination(Target); | |||||
772 | } // End for each landingpad | |||||
773 | ||||||
774 | // If nothing got outlined, there is no more processing to be done. | |||||
775 | if (!HandlersOutlined) | |||||
776 | return false; | |||||
777 | ||||||
778 | // Replace any nested landing pad stubs with the correct action handler. | |||||
779 | // This must be done before we remove unreachable blocks because it | |||||
780 | // cleans up references to outlined blocks that will be deleted. | |||||
781 | for (auto &LPadPair : NestedLPtoOriginalLP) | |||||
782 | completeNestedLandingPad(&F, LPadPair.first, LPadPair.second, FrameVarInfo); | |||||
783 | NestedLPtoOriginalLP.clear(); | |||||
784 | ||||||
785 | F.addFnAttr("wineh-parent", F.getName()); | |||||
786 | ||||||
787 | // Delete any blocks that were only used by handlers that were outlined above. | |||||
788 | removeUnreachableBlocks(F); | |||||
789 | ||||||
790 | BasicBlock *Entry = &F.getEntryBlock(); | |||||
791 | IRBuilder<> Builder(F.getParent()->getContext()); | |||||
792 | Builder.SetInsertPoint(Entry->getFirstInsertionPt()); | |||||
793 | ||||||
794 | Function *FrameEscapeFn = | |||||
795 | Intrinsic::getDeclaration(M, Intrinsic::frameescape); | |||||
796 | Function *RecoverFrameFn = | |||||
797 | Intrinsic::getDeclaration(M, Intrinsic::framerecover); | |||||
798 | SmallVector<Value *, 8> AllocasToEscape; | |||||
799 | ||||||
800 | // Scan the entry block for an existing call to llvm.frameescape. We need to | |||||
801 | // keep escaping those objects. | |||||
802 | for (Instruction &I : F.front()) { | |||||
803 | auto *II = dyn_cast<IntrinsicInst>(&I); | |||||
804 | if (II && II->getIntrinsicID() == Intrinsic::frameescape) { | |||||
805 | auto Args = II->arg_operands(); | |||||
806 | AllocasToEscape.append(Args.begin(), Args.end()); | |||||
807 | II->eraseFromParent(); | |||||
808 | break; | |||||
809 | } | |||||
810 | } | |||||
811 | ||||||
812 | // Finally, replace all of the temporary allocas for frame variables used in | |||||
813 | // the outlined handlers with calls to llvm.framerecover. | |||||
814 | for (auto &VarInfoEntry : FrameVarInfo) { | |||||
815 | Value *ParentVal = VarInfoEntry.first; | |||||
816 | TinyPtrVector<AllocaInst *> &Allocas = VarInfoEntry.second; | |||||
817 | AllocaInst *ParentAlloca = cast<AllocaInst>(ParentVal); | |||||
818 | ||||||
819 | // FIXME: We should try to sink unescaped allocas from the parent frame into | |||||
820 | // the child frame. If the alloca is escaped, we have to use the lifetime | |||||
821 | // markers to ensure that the alloca is only live within the child frame. | |||||
822 | ||||||
823 | // Add this alloca to the list of things to escape. | |||||
824 | AllocasToEscape.push_back(ParentAlloca); | |||||
825 | ||||||
826 | // Next replace all outlined allocas that are mapped to it. | |||||
827 | for (AllocaInst *TempAlloca : Allocas) { | |||||
828 | if (TempAlloca == getCatchObjectSentinel()) | |||||
829 | continue; // Skip catch parameter sentinels. | |||||
830 | Function *HandlerFn = TempAlloca->getParent()->getParent(); | |||||
831 | // FIXME: Sink this GEP into the blocks where it is used. | |||||
832 | Builder.SetInsertPoint(TempAlloca); | |||||
833 | Builder.SetCurrentDebugLocation(TempAlloca->getDebugLoc()); | |||||
834 | Value *RecoverArgs[] = { | |||||
835 | Builder.CreateBitCast(&F, Int8PtrType, ""), | |||||
836 | &(HandlerFn->getArgumentList().back()), | |||||
837 | llvm::ConstantInt::get(Int32Type, AllocasToEscape.size() - 1)}; | |||||
838 | Value *RecoveredAlloca = Builder.CreateCall(RecoverFrameFn, RecoverArgs); | |||||
839 | // Add a pointer bitcast if the alloca wasn't an i8. | |||||
840 | if (RecoveredAlloca->getType() != TempAlloca->getType()) { | |||||
841 | RecoveredAlloca->setName(Twine(TempAlloca->getName()) + ".i8"); | |||||
842 | RecoveredAlloca = | |||||
843 | Builder.CreateBitCast(RecoveredAlloca, TempAlloca->getType()); | |||||
844 | } | |||||
845 | TempAlloca->replaceAllUsesWith(RecoveredAlloca); | |||||
846 | TempAlloca->removeFromParent(); | |||||
847 | RecoveredAlloca->takeName(TempAlloca); | |||||
848 | delete TempAlloca; | |||||
849 | } | |||||
850 | } // End for each FrameVarInfo entry. | |||||
851 | ||||||
852 | // Insert 'call void (...)* @llvm.frameescape(...)' at the end of the entry | |||||
853 | // block. | |||||
854 | Builder.SetInsertPoint(&F.getEntryBlock().back()); | |||||
855 | Builder.CreateCall(FrameEscapeFn, AllocasToEscape); | |||||
856 | ||||||
857 | if (SEHExceptionCodeSlot) { | |||||
858 | if (SEHExceptionCodeSlot->hasNUses(0)) | |||||
859 | SEHExceptionCodeSlot->eraseFromParent(); | |||||
860 | else | |||||
861 | PromoteMemToReg(SEHExceptionCodeSlot, *DT); | |||||
862 | } | |||||
863 | ||||||
864 | // Clean up the handler action maps we created for this function | |||||
865 | DeleteContainerSeconds(CatchHandlerMap); | |||||
866 | CatchHandlerMap.clear(); | |||||
867 | DeleteContainerSeconds(CleanupHandlerMap); | |||||
868 | CleanupHandlerMap.clear(); | |||||
869 | ||||||
870 | return HandlersOutlined; | |||||
871 | } | |||||
872 | ||||||
873 | void WinEHPrepare::promoteLandingPadValues(LandingPadInst *LPad) { | |||||
874 | // If the return values of the landing pad instruction are extracted and | |||||
875 | // stored to memory, we want to promote the store locations to reg values. | |||||
876 | SmallVector<AllocaInst *, 2> EHAllocas; | |||||
877 | ||||||
878 | // The landingpad instruction returns an aggregate value. Typically, its | |||||
879 | // value will be passed to a pair of extract value instructions and the | |||||
880 | // results of those extracts are often passed to store instructions. | |||||
881 | // In unoptimized code the stored value will often be loaded and then stored | |||||
882 | // again. | |||||
883 | for (auto *U : LPad->users()) { | |||||
884 | ExtractValueInst *Extract = dyn_cast<ExtractValueInst>(U); | |||||
885 | if (!Extract) | |||||
886 | continue; | |||||
887 | ||||||
888 | for (auto *EU : Extract->users()) { | |||||
889 | if (auto *Store = dyn_cast<StoreInst>(EU)) { | |||||
890 | auto *AV = cast<AllocaInst>(Store->getPointerOperand()); | |||||
891 | EHAllocas.push_back(AV); | |||||
892 | } | |||||
893 | } | |||||
894 | } | |||||
895 | ||||||
896 | // We can't do this without a dominator tree. | |||||
897 | assert(DT)((DT) ? static_cast<void> (0) : __assert_fail ("DT", "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 897, __PRETTY_FUNCTION__)); | |||||
898 | ||||||
899 | if (!EHAllocas.empty()) { | |||||
900 | PromoteMemToReg(EHAllocas, *DT); | |||||
901 | EHAllocas.clear(); | |||||
902 | } | |||||
903 | ||||||
904 | // After promotion, some extracts may be trivially dead. Remove them. | |||||
905 | SmallVector<Value *, 4> Users(LPad->user_begin(), LPad->user_end()); | |||||
906 | for (auto *U : Users) | |||||
907 | RecursivelyDeleteTriviallyDeadInstructions(U); | |||||
908 | } | |||||
909 | ||||||
910 | void WinEHPrepare::completeNestedLandingPad(Function *ParentFn, | |||||
911 | LandingPadInst *OutlinedLPad, | |||||
912 | const LandingPadInst *OriginalLPad, | |||||
913 | FrameVarInfoMap &FrameVarInfo) { | |||||
914 | // Get the nested block and erase the unreachable instruction that was | |||||
915 | // temporarily inserted as its terminator. | |||||
916 | LLVMContext &Context = ParentFn->getContext(); | |||||
917 | BasicBlock *OutlinedBB = OutlinedLPad->getParent(); | |||||
918 | assert(isa<UnreachableInst>(OutlinedBB->getTerminator()))((isa<UnreachableInst>(OutlinedBB->getTerminator())) ? static_cast<void> (0) : __assert_fail ("isa<UnreachableInst>(OutlinedBB->getTerminator())" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 918, __PRETTY_FUNCTION__)); | |||||
919 | OutlinedBB->getTerminator()->eraseFromParent(); | |||||
920 | // That should leave OutlinedLPad as the last instruction in its block. | |||||
921 | assert(&OutlinedBB->back() == OutlinedLPad)((&OutlinedBB->back() == OutlinedLPad) ? static_cast< void> (0) : __assert_fail ("&OutlinedBB->back() == OutlinedLPad" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 921, __PRETTY_FUNCTION__)); | |||||
922 | ||||||
923 | // The original landing pad will have already had its action intrinsic | |||||
924 | // built by the outlining loop. We need to clone that into the outlined | |||||
925 | // location. It may also be necessary to add references to the exception | |||||
926 | // variables to the outlined handler in which this landing pad is nested | |||||
927 | // and remap return instructions in the nested handlers that should return | |||||
928 | // to an address in the outlined handler. | |||||
929 | Function *OutlinedHandlerFn = OutlinedBB->getParent(); | |||||
930 | BasicBlock::const_iterator II = OriginalLPad; | |||||
931 | ++II; | |||||
932 | // The instruction after the landing pad should now be a call to eh.actions. | |||||
933 | const Instruction *Recover = II; | |||||
934 | assert(match(Recover, m_Intrinsic<Intrinsic::eh_actions>()))((match(Recover, m_Intrinsic<Intrinsic::eh_actions>())) ? static_cast<void> (0) : __assert_fail ("match(Recover, m_Intrinsic<Intrinsic::eh_actions>())" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 934, __PRETTY_FUNCTION__)); | |||||
935 | IntrinsicInst *EHActions = cast<IntrinsicInst>(Recover->clone()); | |||||
936 | ||||||
937 | // Remap the exception variables into the outlined function. | |||||
938 | WinEHFrameVariableMaterializer Materializer(OutlinedHandlerFn, FrameVarInfo); | |||||
939 | SmallVector<BlockAddress *, 4> ActionTargets; | |||||
940 | SmallVector<ActionHandler *, 4> ActionList; | |||||
941 | parseEHActions(EHActions, ActionList); | |||||
942 | for (auto *Action : ActionList) { | |||||
943 | auto *Catch = dyn_cast<CatchHandler>(Action); | |||||
944 | if (!Catch) | |||||
945 | continue; | |||||
946 | // The dyn_cast to function here selects C++ catch handlers and skips | |||||
947 | // SEH catch handlers. | |||||
948 | auto *Handler = dyn_cast<Function>(Catch->getHandlerBlockOrFunc()); | |||||
949 | if (!Handler) | |||||
950 | continue; | |||||
951 | // Visit all the return instructions, looking for places that return | |||||
952 | // to a location within OutlinedHandlerFn. | |||||
953 | for (BasicBlock &NestedHandlerBB : *Handler) { | |||||
954 | auto *Ret = dyn_cast<ReturnInst>(NestedHandlerBB.getTerminator()); | |||||
955 | if (!Ret) | |||||
956 | continue; | |||||
957 | ||||||
958 | // Handler functions must always return a block address. | |||||
959 | BlockAddress *BA = cast<BlockAddress>(Ret->getReturnValue()); | |||||
960 | // The original target will have been in the main parent function, | |||||
961 | // but if it is the address of a block that has been outlined, it | |||||
962 | // should be a block that was outlined into OutlinedHandlerFn. | |||||
963 | assert(BA->getFunction() == ParentFn)((BA->getFunction() == ParentFn) ? static_cast<void> (0) : __assert_fail ("BA->getFunction() == ParentFn", "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 963, __PRETTY_FUNCTION__)); | |||||
964 | ||||||
965 | // Ignore targets that aren't part of OutlinedHandlerFn. | |||||
966 | if (!LPadTargetBlocks.count(BA->getBasicBlock())) | |||||
967 | continue; | |||||
968 | ||||||
969 | // If the return value is the address ofF a block that we | |||||
970 | // previously outlined into the parent handler function, replace | |||||
971 | // the return instruction and add the mapped target to the list | |||||
972 | // of possible return addresses. | |||||
973 | BasicBlock *MappedBB = LPadTargetBlocks[BA->getBasicBlock()]; | |||||
974 | assert(MappedBB->getParent() == OutlinedHandlerFn)((MappedBB->getParent() == OutlinedHandlerFn) ? static_cast <void> (0) : __assert_fail ("MappedBB->getParent() == OutlinedHandlerFn" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 974, __PRETTY_FUNCTION__)); | |||||
975 | BlockAddress *NewBA = BlockAddress::get(OutlinedHandlerFn, MappedBB); | |||||
976 | Ret->eraseFromParent(); | |||||
977 | ReturnInst::Create(Context, NewBA, &NestedHandlerBB); | |||||
978 | ActionTargets.push_back(NewBA); | |||||
979 | } | |||||
980 | } | |||||
981 | DeleteContainerPointers(ActionList); | |||||
982 | ActionList.clear(); | |||||
983 | OutlinedBB->getInstList().push_back(EHActions); | |||||
984 | ||||||
985 | // Insert an indirect branch into the outlined landing pad BB. | |||||
986 | IndirectBrInst *IBr = IndirectBrInst::Create(EHActions, 0, OutlinedBB); | |||||
987 | // Add the previously collected action targets. | |||||
988 | for (auto *Target : ActionTargets) | |||||
989 | IBr->addDestination(Target->getBasicBlock()); | |||||
990 | } | |||||
991 | ||||||
992 | // This function examines a block to determine whether the block ends with a | |||||
993 | // conditional branch to a catch handler based on a selector comparison. | |||||
994 | // This function is used both by the WinEHPrepare::findSelectorComparison() and | |||||
995 | // WinEHCleanupDirector::handleTypeIdFor(). | |||||
996 | static bool isSelectorDispatch(BasicBlock *BB, BasicBlock *&CatchHandler, | |||||
997 | Constant *&Selector, BasicBlock *&NextBB) { | |||||
998 | ICmpInst::Predicate Pred; | |||||
999 | BasicBlock *TBB, *FBB; | |||||
1000 | Value *LHS, *RHS; | |||||
1001 | ||||||
1002 | if (!match(BB->getTerminator(), | |||||
1003 | m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)), TBB, FBB))) | |||||
1004 | return false; | |||||
1005 | ||||||
1006 | if (!match(LHS, | |||||
1007 | m_Intrinsic<Intrinsic::eh_typeid_for>(m_Constant(Selector))) && | |||||
1008 | !match(RHS, m_Intrinsic<Intrinsic::eh_typeid_for>(m_Constant(Selector)))) | |||||
1009 | return false; | |||||
1010 | ||||||
1011 | if (Pred == CmpInst::ICMP_EQ) { | |||||
1012 | CatchHandler = TBB; | |||||
1013 | NextBB = FBB; | |||||
1014 | return true; | |||||
1015 | } | |||||
1016 | ||||||
1017 | if (Pred == CmpInst::ICMP_NE) { | |||||
1018 | CatchHandler = FBB; | |||||
1019 | NextBB = TBB; | |||||
1020 | return true; | |||||
1021 | } | |||||
1022 | ||||||
1023 | return false; | |||||
1024 | } | |||||
1025 | ||||||
1026 | static bool isCatchBlock(BasicBlock *BB) { | |||||
1027 | for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg(), IE = BB->end(); | |||||
1028 | II != IE; ++II) { | |||||
1029 | if (match(cast<Value>(II), m_Intrinsic<Intrinsic::eh_begincatch>())) | |||||
1030 | return true; | |||||
1031 | } | |||||
1032 | return false; | |||||
1033 | } | |||||
1034 | ||||||
1035 | static BasicBlock *createStubLandingPad(Function *Handler, | |||||
1036 | Value *PersonalityFn) { | |||||
1037 | // FIXME: Finish this! | |||||
1038 | LLVMContext &Context = Handler->getContext(); | |||||
1039 | BasicBlock *StubBB = BasicBlock::Create(Context, "stub"); | |||||
1040 | Handler->getBasicBlockList().push_back(StubBB); | |||||
1041 | IRBuilder<> Builder(StubBB); | |||||
1042 | LandingPadInst *LPad = Builder.CreateLandingPad( | |||||
1043 | llvm::StructType::get(Type::getInt8PtrTy(Context), | |||||
1044 | Type::getInt32Ty(Context), nullptr), | |||||
1045 | PersonalityFn, 0); | |||||
1046 | // Insert a call to llvm.eh.actions so that we don't try to outline this lpad. | |||||
1047 | Function *ActionIntrin = Intrinsic::getDeclaration(Handler->getParent(), | |||||
1048 | Intrinsic::eh_actions); | |||||
1049 | Builder.CreateCall(ActionIntrin, "recover"); | |||||
1050 | LPad->setCleanup(true); | |||||
1051 | Builder.CreateUnreachable(); | |||||
1052 | return StubBB; | |||||
1053 | } | |||||
1054 | ||||||
1055 | // Cycles through the blocks in an outlined handler function looking for an | |||||
1056 | // invoke instruction and inserts an invoke of llvm.donothing with an empty | |||||
1057 | // landing pad if none is found. The code that generates the .xdata tables for | |||||
1058 | // the handler needs at least one landing pad to identify the parent function's | |||||
1059 | // personality. | |||||
1060 | void WinEHPrepare::addStubInvokeToHandlerIfNeeded(Function *Handler, | |||||
1061 | Value *PersonalityFn) { | |||||
1062 | ReturnInst *Ret = nullptr; | |||||
1063 | UnreachableInst *Unreached = nullptr; | |||||
1064 | for (BasicBlock &BB : *Handler) { | |||||
1065 | TerminatorInst *Terminator = BB.getTerminator(); | |||||
1066 | // If we find an invoke, there is nothing to be done. | |||||
1067 | auto *II = dyn_cast<InvokeInst>(Terminator); | |||||
1068 | if (II) | |||||
1069 | return; | |||||
1070 | // If we've already recorded a return instruction, keep looking for invokes. | |||||
1071 | if (!Ret) | |||||
1072 | Ret = dyn_cast<ReturnInst>(Terminator); | |||||
1073 | // If we haven't recorded an unreachable instruction, try this terminator. | |||||
1074 | if (!Unreached) | |||||
1075 | Unreached = dyn_cast<UnreachableInst>(Terminator); | |||||
1076 | } | |||||
1077 | ||||||
1078 | // If we got this far, the handler contains no invokes. We should have seen | |||||
1079 | // at least one return or unreachable instruction. We'll insert an invoke of | |||||
1080 | // llvm.donothing ahead of that instruction. | |||||
1081 | assert(Ret || Unreached)((Ret || Unreached) ? static_cast<void> (0) : __assert_fail ("Ret || Unreached", "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1081, __PRETTY_FUNCTION__)); | |||||
1082 | TerminatorInst *Term; | |||||
1083 | if (Ret) | |||||
1084 | Term = Ret; | |||||
1085 | else | |||||
1086 | Term = Unreached; | |||||
1087 | BasicBlock *OldRetBB = Term->getParent(); | |||||
1088 | BasicBlock *NewRetBB = SplitBlock(OldRetBB, Term); | |||||
1089 | // SplitBlock adds an unconditional branch instruction at the end of the | |||||
1090 | // parent block. We want to replace that with an invoke call, so we can | |||||
1091 | // erase it now. | |||||
1092 | OldRetBB->getTerminator()->eraseFromParent(); | |||||
1093 | BasicBlock *StubLandingPad = createStubLandingPad(Handler, PersonalityFn); | |||||
1094 | Function *F = | |||||
1095 | Intrinsic::getDeclaration(Handler->getParent(), Intrinsic::donothing); | |||||
1096 | InvokeInst::Create(F, NewRetBB, StubLandingPad, None, "", OldRetBB); | |||||
1097 | } | |||||
1098 | ||||||
1099 | bool WinEHPrepare::outlineHandler(ActionHandler *Action, Function *SrcFn, | |||||
1100 | LandingPadInst *LPad, BasicBlock *StartBB, | |||||
1101 | FrameVarInfoMap &VarInfo) { | |||||
1102 | Module *M = SrcFn->getParent(); | |||||
1103 | LLVMContext &Context = M->getContext(); | |||||
1104 | ||||||
1105 | // Create a new function to receive the handler contents. | |||||
1106 | Type *Int8PtrType = Type::getInt8PtrTy(Context); | |||||
1107 | std::vector<Type *> ArgTys; | |||||
1108 | ArgTys.push_back(Int8PtrType); | |||||
1109 | ArgTys.push_back(Int8PtrType); | |||||
1110 | Function *Handler; | |||||
1111 | if (Action->getType() == Catch) { | |||||
1112 | FunctionType *FnType = FunctionType::get(Int8PtrType, ArgTys, false); | |||||
1113 | Handler = Function::Create(FnType, GlobalVariable::InternalLinkage, | |||||
1114 | SrcFn->getName() + ".catch", M); | |||||
1115 | } else { | |||||
1116 | FunctionType *FnType = | |||||
1117 | FunctionType::get(Type::getVoidTy(Context), ArgTys, false); | |||||
1118 | Handler = Function::Create(FnType, GlobalVariable::InternalLinkage, | |||||
1119 | SrcFn->getName() + ".cleanup", M); | |||||
1120 | } | |||||
1121 | ||||||
1122 | Handler->addFnAttr("wineh-parent", SrcFn->getName()); | |||||
1123 | ||||||
1124 | // Generate a standard prolog to setup the frame recovery structure. | |||||
1125 | IRBuilder<> Builder(Context); | |||||
1126 | BasicBlock *Entry = BasicBlock::Create(Context, "entry"); | |||||
1127 | Handler->getBasicBlockList().push_front(Entry); | |||||
1128 | Builder.SetInsertPoint(Entry); | |||||
1129 | Builder.SetCurrentDebugLocation(LPad->getDebugLoc()); | |||||
1130 | ||||||
1131 | std::unique_ptr<WinEHCloningDirectorBase> Director; | |||||
1132 | ||||||
1133 | ValueToValueMapTy VMap; | |||||
1134 | ||||||
1135 | LandingPadMap &LPadMap = LPadMaps[LPad]; | |||||
1136 | if (!LPadMap.isInitialized()) | |||||
1137 | LPadMap.mapLandingPad(LPad); | |||||
1138 | if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) { | |||||
1139 | Constant *Sel = CatchAction->getSelector(); | |||||
1140 | Director.reset(new WinEHCatchDirector(Handler, Sel, VarInfo, LPadMap, | |||||
1141 | NestedLPtoOriginalLP)); | |||||
1142 | LPadMap.remapEHValues(VMap, UndefValue::get(Int8PtrType), | |||||
1143 | ConstantInt::get(Type::getInt32Ty(Context), 1)); | |||||
1144 | } else { | |||||
1145 | Director.reset(new WinEHCleanupDirector(Handler, VarInfo, LPadMap)); | |||||
1146 | LPadMap.remapEHValues(VMap, UndefValue::get(Int8PtrType), | |||||
1147 | UndefValue::get(Type::getInt32Ty(Context))); | |||||
1148 | } | |||||
1149 | ||||||
1150 | SmallVector<ReturnInst *, 8> Returns; | |||||
1151 | ClonedCodeInfo OutlinedFunctionInfo; | |||||
1152 | ||||||
1153 | // If the start block contains PHI nodes, we need to map them. | |||||
1154 | BasicBlock::iterator II = StartBB->begin(); | |||||
1155 | while (auto *PN = dyn_cast<PHINode>(II)) { | |||||
1156 | bool Mapped = false; | |||||
1157 | // Look for PHI values that we have already mapped (such as the selector). | |||||
1158 | for (Value *Val : PN->incoming_values()) { | |||||
1159 | if (VMap.count(Val)) { | |||||
1160 | VMap[PN] = VMap[Val]; | |||||
1161 | Mapped = true; | |||||
1162 | } | |||||
1163 | } | |||||
1164 | // If we didn't find a match for this value, map it as an undef. | |||||
1165 | if (!Mapped) { | |||||
1166 | VMap[PN] = UndefValue::get(PN->getType()); | |||||
1167 | } | |||||
1168 | ++II; | |||||
1169 | } | |||||
1170 | ||||||
1171 | // The landing pad value may be used by PHI nodes. It will ultimately be | |||||
1172 | // eliminated, but we need it in the map for intermediate handling. | |||||
1173 | VMap[LPad] = UndefValue::get(LPad->getType()); | |||||
1174 | ||||||
1175 | // Skip over PHIs and, if applicable, landingpad instructions. | |||||
1176 | II = StartBB->getFirstInsertionPt(); | |||||
1177 | ||||||
1178 | CloneAndPruneIntoFromInst(Handler, SrcFn, II, VMap, | |||||
1179 | /*ModuleLevelChanges=*/false, Returns, "", | |||||
1180 | &OutlinedFunctionInfo, Director.get()); | |||||
1181 | ||||||
1182 | // Move all the instructions in the cloned "entry" block into our entry block. | |||||
1183 | // Depending on how the parent function was laid out, the block that will | |||||
1184 | // correspond to the outlined entry block may not be the first block in the | |||||
1185 | // list. We can recognize it, however, as the cloned block which has no | |||||
1186 | // predecessors. Any other block wouldn't have been cloned if it didn't | |||||
1187 | // have a predecessor which was also cloned. | |||||
1188 | Function::iterator ClonedIt = std::next(Function::iterator(Entry)); | |||||
1189 | while (!pred_empty(ClonedIt)) | |||||
1190 | ++ClonedIt; | |||||
1191 | BasicBlock *ClonedEntryBB = ClonedIt; | |||||
1192 | assert(ClonedEntryBB)((ClonedEntryBB) ? static_cast<void> (0) : __assert_fail ("ClonedEntryBB", "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1192, __PRETTY_FUNCTION__)); | |||||
1193 | Entry->getInstList().splice(Entry->end(), ClonedEntryBB->getInstList()); | |||||
1194 | ClonedEntryBB->eraseFromParent(); | |||||
1195 | ||||||
1196 | // Make sure we can identify the handler's personality later. | |||||
1197 | addStubInvokeToHandlerIfNeeded(Handler, LPad->getPersonalityFn()); | |||||
1198 | ||||||
1199 | if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) { | |||||
1200 | WinEHCatchDirector *CatchDirector = | |||||
1201 | reinterpret_cast<WinEHCatchDirector *>(Director.get()); | |||||
1202 | CatchAction->setExceptionVar(CatchDirector->getExceptionVar()); | |||||
1203 | CatchAction->setReturnTargets(CatchDirector->getReturnTargets()); | |||||
1204 | ||||||
1205 | // Look for blocks that are not part of the landing pad that we just | |||||
1206 | // outlined but terminate with a call to llvm.eh.endcatch and a | |||||
1207 | // branch to a block that is in the handler we just outlined. | |||||
1208 | // These blocks will be part of a nested landing pad that intends to | |||||
1209 | // return to an address in this handler. This case is best handled | |||||
1210 | // after both landing pads have been outlined, so for now we'll just | |||||
1211 | // save the association of the blocks in LPadTargetBlocks. The | |||||
1212 | // return instructions which are created from these branches will be | |||||
1213 | // replaced after all landing pads have been outlined. | |||||
1214 | for (const auto MapEntry : VMap) { | |||||
1215 | // VMap maps all values and blocks that were just cloned, but dead | |||||
1216 | // blocks which were pruned will map to nullptr. | |||||
1217 | if (!isa<BasicBlock>(MapEntry.first) || MapEntry.second == nullptr) | |||||
1218 | continue; | |||||
1219 | const BasicBlock *MappedBB = cast<BasicBlock>(MapEntry.first); | |||||
1220 | for (auto *Pred : predecessors(const_cast<BasicBlock *>(MappedBB))) { | |||||
1221 | auto *Branch = dyn_cast<BranchInst>(Pred->getTerminator()); | |||||
1222 | if (!Branch || !Branch->isUnconditional() || Pred->size() <= 1) | |||||
1223 | continue; | |||||
1224 | BasicBlock::iterator II = const_cast<BranchInst *>(Branch); | |||||
1225 | --II; | |||||
1226 | if (match(cast<Value>(II), m_Intrinsic<Intrinsic::eh_endcatch>())) { | |||||
1227 | // This would indicate that a nested landing pad wants to return | |||||
1228 | // to a block that is outlined into two different handlers. | |||||
1229 | assert(!LPadTargetBlocks.count(MappedBB))((!LPadTargetBlocks.count(MappedBB)) ? static_cast<void> (0) : __assert_fail ("!LPadTargetBlocks.count(MappedBB)", "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1229, __PRETTY_FUNCTION__)); | |||||
1230 | LPadTargetBlocks[MappedBB] = cast<BasicBlock>(MapEntry.second); | |||||
1231 | } | |||||
1232 | } | |||||
1233 | } | |||||
1234 | } // End if (CatchAction) | |||||
1235 | ||||||
1236 | Action->setHandlerBlockOrFunc(Handler); | |||||
1237 | ||||||
1238 | return true; | |||||
1239 | } | |||||
1240 | ||||||
1241 | /// This BB must end in a selector dispatch. All we need to do is pass the | |||||
1242 | /// handler block to llvm.eh.actions and list it as a possible indirectbr | |||||
1243 | /// target. | |||||
1244 | void WinEHPrepare::processSEHCatchHandler(CatchHandler *CatchAction, | |||||
1245 | BasicBlock *StartBB) { | |||||
1246 | BasicBlock *HandlerBB; | |||||
1247 | BasicBlock *NextBB; | |||||
1248 | Constant *Selector; | |||||
1249 | bool Res = isSelectorDispatch(StartBB, HandlerBB, Selector, NextBB); | |||||
1250 | if (Res) { | |||||
1251 | // If this was EH dispatch, this must be a conditional branch to the handler | |||||
1252 | // block. | |||||
1253 | // FIXME: Handle instructions in the dispatch block. Currently we drop them, | |||||
1254 | // leading to crashes if some optimization hoists stuff here. | |||||
1255 | assert(CatchAction->getSelector() && HandlerBB &&((CatchAction->getSelector() && HandlerBB && "expected catch EH dispatch") ? static_cast<void> (0) : __assert_fail ("CatchAction->getSelector() && HandlerBB && \"expected catch EH dispatch\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1256, __PRETTY_FUNCTION__)) | |||||
1256 | "expected catch EH dispatch")((CatchAction->getSelector() && HandlerBB && "expected catch EH dispatch") ? static_cast<void> (0) : __assert_fail ("CatchAction->getSelector() && HandlerBB && \"expected catch EH dispatch\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1256, __PRETTY_FUNCTION__)); | |||||
1257 | } else { | |||||
1258 | // This must be a catch-all. Split the block after the landingpad. | |||||
1259 | assert(CatchAction->getSelector()->isNullValue() && "expected catch-all")((CatchAction->getSelector()->isNullValue() && "expected catch-all" ) ? static_cast<void> (0) : __assert_fail ("CatchAction->getSelector()->isNullValue() && \"expected catch-all\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1259, __PRETTY_FUNCTION__)); | |||||
1260 | HandlerBB = | |||||
1261 | StartBB->splitBasicBlock(StartBB->getFirstInsertionPt(), "catch.all"); | |||||
1262 | } | |||||
1263 | IRBuilder<> Builder(HandlerBB->getFirstInsertionPt()); | |||||
1264 | Function *EHCodeFn = Intrinsic::getDeclaration( | |||||
1265 | StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode); | |||||
1266 | Value *Code = Builder.CreateCall(EHCodeFn, "sehcode"); | |||||
1267 | Code = Builder.CreateIntToPtr(Code, SEHExceptionCodeSlot->getAllocatedType()); | |||||
1268 | Builder.CreateStore(Code, SEHExceptionCodeSlot); | |||||
1269 | CatchAction->setHandlerBlockOrFunc(BlockAddress::get(HandlerBB)); | |||||
1270 | TinyPtrVector<BasicBlock *> Targets(HandlerBB); | |||||
1271 | CatchAction->setReturnTargets(Targets); | |||||
1272 | } | |||||
1273 | ||||||
1274 | void LandingPadMap::mapLandingPad(const LandingPadInst *LPad) { | |||||
1275 | // Each instance of this class should only ever be used to map a single | |||||
1276 | // landing pad. | |||||
1277 | assert(OriginLPad == nullptr || OriginLPad == LPad)((OriginLPad == nullptr || OriginLPad == LPad) ? static_cast< void> (0) : __assert_fail ("OriginLPad == nullptr || OriginLPad == LPad" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1277, __PRETTY_FUNCTION__)); | |||||
1278 | ||||||
1279 | // If the landing pad has already been mapped, there's nothing more to do. | |||||
1280 | if (OriginLPad == LPad) | |||||
1281 | return; | |||||
1282 | ||||||
1283 | OriginLPad = LPad; | |||||
1284 | ||||||
1285 | // The landingpad instruction returns an aggregate value. Typically, its | |||||
1286 | // value will be passed to a pair of extract value instructions and the | |||||
1287 | // results of those extracts will have been promoted to reg values before | |||||
1288 | // this routine is called. | |||||
1289 | for (auto *U : LPad->users()) { | |||||
1290 | const ExtractValueInst *Extract = dyn_cast<ExtractValueInst>(U); | |||||
1291 | if (!Extract) | |||||
1292 | continue; | |||||
1293 | assert(Extract->getNumIndices() == 1 &&((Extract->getNumIndices() == 1 && "Unexpected operation: extracting both landing pad values" ) ? static_cast<void> (0) : __assert_fail ("Extract->getNumIndices() == 1 && \"Unexpected operation: extracting both landing pad values\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1294, __PRETTY_FUNCTION__)) | |||||
1294 | "Unexpected operation: extracting both landing pad values")((Extract->getNumIndices() == 1 && "Unexpected operation: extracting both landing pad values" ) ? static_cast<void> (0) : __assert_fail ("Extract->getNumIndices() == 1 && \"Unexpected operation: extracting both landing pad values\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1294, __PRETTY_FUNCTION__)); | |||||
1295 | unsigned int Idx = *(Extract->idx_begin()); | |||||
1296 | assert((Idx == 0 || Idx == 1) &&(((Idx == 0 || Idx == 1) && "Unexpected operation: extracting an unknown landing pad element" ) ? static_cast<void> (0) : __assert_fail ("(Idx == 0 || Idx == 1) && \"Unexpected operation: extracting an unknown landing pad element\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1297, __PRETTY_FUNCTION__)) | |||||
1297 | "Unexpected operation: extracting an unknown landing pad element")(((Idx == 0 || Idx == 1) && "Unexpected operation: extracting an unknown landing pad element" ) ? static_cast<void> (0) : __assert_fail ("(Idx == 0 || Idx == 1) && \"Unexpected operation: extracting an unknown landing pad element\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1297, __PRETTY_FUNCTION__)); | |||||
1298 | if (Idx == 0) { | |||||
1299 | ExtractedEHPtrs.push_back(Extract); | |||||
1300 | } else if (Idx == 1) { | |||||
1301 | ExtractedSelectors.push_back(Extract); | |||||
1302 | } | |||||
1303 | } | |||||
1304 | } | |||||
1305 | ||||||
1306 | bool LandingPadMap::isOriginLandingPadBlock(const BasicBlock *BB) const { | |||||
1307 | return BB->getLandingPadInst() == OriginLPad; | |||||
1308 | } | |||||
1309 | ||||||
1310 | bool LandingPadMap::isLandingPadSpecificInst(const Instruction *Inst) const { | |||||
1311 | if (Inst == OriginLPad) | |||||
1312 | return true; | |||||
1313 | for (auto *Extract : ExtractedEHPtrs) { | |||||
1314 | if (Inst == Extract) | |||||
1315 | return true; | |||||
1316 | } | |||||
1317 | for (auto *Extract : ExtractedSelectors) { | |||||
1318 | if (Inst == Extract) | |||||
1319 | return true; | |||||
1320 | } | |||||
1321 | return false; | |||||
1322 | } | |||||
1323 | ||||||
1324 | void LandingPadMap::remapEHValues(ValueToValueMapTy &VMap, Value *EHPtrValue, | |||||
1325 | Value *SelectorValue) const { | |||||
1326 | // Remap all landing pad extract instructions to the specified values. | |||||
1327 | for (auto *Extract : ExtractedEHPtrs) | |||||
1328 | VMap[Extract] = EHPtrValue; | |||||
1329 | for (auto *Extract : ExtractedSelectors) | |||||
1330 | VMap[Extract] = SelectorValue; | |||||
1331 | } | |||||
1332 | ||||||
1333 | static bool isFrameAddressCall(const Value *V) { | |||||
1334 | return match(const_cast<Value *>(V), | |||||
1335 | m_Intrinsic<Intrinsic::frameaddress>(m_SpecificInt(0))); | |||||
1336 | } | |||||
1337 | ||||||
1338 | CloningDirector::CloningAction WinEHCloningDirectorBase::handleInstruction( | |||||
1339 | ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { | |||||
1340 | // If this is one of the boilerplate landing pad instructions, skip it. | |||||
1341 | // The instruction will have already been remapped in VMap. | |||||
1342 | if (LPadMap.isLandingPadSpecificInst(Inst)) | |||||
1343 | return CloningDirector::SkipInstruction; | |||||
1344 | ||||||
1345 | // Nested landing pads will be cloned as stubs, with just the | |||||
1346 | // landingpad instruction and an unreachable instruction. When | |||||
1347 | // all landingpads have been outlined, we'll replace this with the | |||||
1348 | // llvm.eh.actions call and indirect branch created when the | |||||
1349 | // landing pad was outlined. | |||||
1350 | if (auto *LPad = dyn_cast<LandingPadInst>(Inst)) { | |||||
1351 | return handleLandingPad(VMap, LPad, NewBB); | |||||
1352 | } | |||||
1353 | ||||||
1354 | if (auto *Invoke = dyn_cast<InvokeInst>(Inst)) | |||||
1355 | return handleInvoke(VMap, Invoke, NewBB); | |||||
1356 | ||||||
1357 | if (auto *Resume = dyn_cast<ResumeInst>(Inst)) | |||||
1358 | return handleResume(VMap, Resume, NewBB); | |||||
1359 | ||||||
1360 | if (auto *Cmp = dyn_cast<CmpInst>(Inst)) | |||||
1361 | return handleCompare(VMap, Cmp, NewBB); | |||||
1362 | ||||||
1363 | if (match(Inst, m_Intrinsic<Intrinsic::eh_begincatch>())) | |||||
1364 | return handleBeginCatch(VMap, Inst, NewBB); | |||||
1365 | if (match(Inst, m_Intrinsic<Intrinsic::eh_endcatch>())) | |||||
1366 | return handleEndCatch(VMap, Inst, NewBB); | |||||
1367 | if (match(Inst, m_Intrinsic<Intrinsic::eh_typeid_for>())) | |||||
1368 | return handleTypeIdFor(VMap, Inst, NewBB); | |||||
1369 | ||||||
1370 | // When outlining llvm.frameaddress(i32 0), remap that to the second argument, | |||||
1371 | // which is the FP of the parent. | |||||
1372 | if (isFrameAddressCall(Inst)) { | |||||
1373 | VMap[Inst] = EstablisherFrame; | |||||
1374 | return CloningDirector::SkipInstruction; | |||||
1375 | } | |||||
1376 | ||||||
1377 | // Continue with the default cloning behavior. | |||||
1378 | return CloningDirector::CloneInstruction; | |||||
1379 | } | |||||
1380 | ||||||
1381 | CloningDirector::CloningAction WinEHCatchDirector::handleLandingPad( | |||||
1382 | ValueToValueMapTy &VMap, const LandingPadInst *LPad, BasicBlock *NewBB) { | |||||
1383 | Instruction *NewInst = LPad->clone(); | |||||
1384 | if (LPad->hasName()) | |||||
1385 | NewInst->setName(LPad->getName()); | |||||
1386 | // Save this correlation for later processing. | |||||
1387 | NestedLPtoOriginalLP[cast<LandingPadInst>(NewInst)] = LPad; | |||||
1388 | VMap[LPad] = NewInst; | |||||
1389 | BasicBlock::InstListType &InstList = NewBB->getInstList(); | |||||
1390 | InstList.push_back(NewInst); | |||||
1391 | InstList.push_back(new UnreachableInst(NewBB->getContext())); | |||||
1392 | return CloningDirector::StopCloningBB; | |||||
1393 | } | |||||
1394 | ||||||
1395 | CloningDirector::CloningAction WinEHCatchDirector::handleBeginCatch( | |||||
1396 | ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { | |||||
1397 | // The argument to the call is some form of the first element of the | |||||
1398 | // landingpad aggregate value, but that doesn't matter. It isn't used | |||||
1399 | // here. | |||||
1400 | // The second argument is an outparameter where the exception object will be | |||||
1401 | // stored. Typically the exception object is a scalar, but it can be an | |||||
1402 | // aggregate when catching by value. | |||||
1403 | // FIXME: Leave something behind to indicate where the exception object lives | |||||
1404 | // for this handler. Should it be part of llvm.eh.actions? | |||||
1405 | assert(ExceptionObjectVar == nullptr && "Multiple calls to "((ExceptionObjectVar == nullptr && "Multiple calls to " "llvm.eh.begincatch found while " "outlining catch handler." ) ? static_cast<void> (0) : __assert_fail ("ExceptionObjectVar == nullptr && \"Multiple calls to \" \"llvm.eh.begincatch found while \" \"outlining catch handler.\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1407, __PRETTY_FUNCTION__)) | |||||
1406 | "llvm.eh.begincatch found while "((ExceptionObjectVar == nullptr && "Multiple calls to " "llvm.eh.begincatch found while " "outlining catch handler." ) ? static_cast<void> (0) : __assert_fail ("ExceptionObjectVar == nullptr && \"Multiple calls to \" \"llvm.eh.begincatch found while \" \"outlining catch handler.\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1407, __PRETTY_FUNCTION__)) | |||||
1407 | "outlining catch handler.")((ExceptionObjectVar == nullptr && "Multiple calls to " "llvm.eh.begincatch found while " "outlining catch handler." ) ? static_cast<void> (0) : __assert_fail ("ExceptionObjectVar == nullptr && \"Multiple calls to \" \"llvm.eh.begincatch found while \" \"outlining catch handler.\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1407, __PRETTY_FUNCTION__)); | |||||
1408 | ExceptionObjectVar = Inst->getOperand(1)->stripPointerCasts(); | |||||
1409 | if (isa<ConstantPointerNull>(ExceptionObjectVar)) | |||||
1410 | return CloningDirector::SkipInstruction; | |||||
1411 | assert(cast<AllocaInst>(ExceptionObjectVar)->isStaticAlloca() &&((cast<AllocaInst>(ExceptionObjectVar)->isStaticAlloca () && "catch parameter is not static alloca") ? static_cast <void> (0) : __assert_fail ("cast<AllocaInst>(ExceptionObjectVar)->isStaticAlloca() && \"catch parameter is not static alloca\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1412, __PRETTY_FUNCTION__)) | |||||
1412 | "catch parameter is not static alloca")((cast<AllocaInst>(ExceptionObjectVar)->isStaticAlloca () && "catch parameter is not static alloca") ? static_cast <void> (0) : __assert_fail ("cast<AllocaInst>(ExceptionObjectVar)->isStaticAlloca() && \"catch parameter is not static alloca\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1412, __PRETTY_FUNCTION__)); | |||||
1413 | Materializer.escapeCatchObject(ExceptionObjectVar); | |||||
1414 | return CloningDirector::SkipInstruction; | |||||
1415 | } | |||||
1416 | ||||||
1417 | CloningDirector::CloningAction | |||||
1418 | WinEHCatchDirector::handleEndCatch(ValueToValueMapTy &VMap, | |||||
1419 | const Instruction *Inst, BasicBlock *NewBB) { | |||||
1420 | auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst); | |||||
1421 | // It might be interesting to track whether or not we are inside a catch | |||||
1422 | // function, but that might make the algorithm more brittle than it needs | |||||
1423 | // to be. | |||||
1424 | ||||||
1425 | // The end catch call can occur in one of two places: either in a | |||||
1426 | // landingpad block that is part of the catch handlers exception mechanism, | |||||
1427 | // or at the end of the catch block. However, a catch-all handler may call | |||||
1428 | // end catch from the original landing pad. If the call occurs in a nested | |||||
1429 | // landing pad block, we must skip it and continue so that the landing pad | |||||
1430 | // gets cloned. | |||||
1431 | auto *ParentBB = IntrinCall->getParent(); | |||||
1432 | if (ParentBB->isLandingPad() && !LPadMap.isOriginLandingPadBlock(ParentBB)) | |||||
1433 | return CloningDirector::SkipInstruction; | |||||
1434 | ||||||
1435 | // If an end catch occurs anywhere else we want to terminate the handler | |||||
1436 | // with a return to the code that follows the endcatch call. If the | |||||
1437 | // next instruction is not an unconditional branch, we need to split the | |||||
1438 | // block to provide a clear target for the return instruction. | |||||
1439 | BasicBlock *ContinueBB; | |||||
1440 | auto Next = std::next(BasicBlock::const_iterator(IntrinCall)); | |||||
1441 | const BranchInst *Branch = dyn_cast<BranchInst>(Next); | |||||
1442 | if (!Branch || !Branch->isUnconditional()) { | |||||
1443 | // We're interrupting the cloning process at this location, so the | |||||
1444 | // const_cast we're doing here will not cause a problem. | |||||
1445 | ContinueBB = SplitBlock(const_cast<BasicBlock *>(ParentBB), | |||||
1446 | const_cast<Instruction *>(cast<Instruction>(Next))); | |||||
1447 | } else { | |||||
1448 | ContinueBB = Branch->getSuccessor(0); | |||||
1449 | } | |||||
1450 | ||||||
1451 | ReturnInst::Create(NewBB->getContext(), BlockAddress::get(ContinueBB), NewBB); | |||||
1452 | ReturnTargets.push_back(ContinueBB); | |||||
1453 | ||||||
1454 | // We just added a terminator to the cloned block. | |||||
1455 | // Tell the caller to stop processing the current basic block so that | |||||
1456 | // the branch instruction will be skipped. | |||||
1457 | return CloningDirector::StopCloningBB; | |||||
1458 | } | |||||
1459 | ||||||
1460 | CloningDirector::CloningAction WinEHCatchDirector::handleTypeIdFor( | |||||
1461 | ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { | |||||
1462 | auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst); | |||||
1463 | Value *Selector = IntrinCall->getArgOperand(0)->stripPointerCasts(); | |||||
1464 | // This causes a replacement that will collapse the landing pad CFG based | |||||
1465 | // on the filter function we intend to match. | |||||
1466 | if (Selector == CurrentSelector) | |||||
1467 | VMap[Inst] = ConstantInt::get(SelectorIDType, 1); | |||||
1468 | else | |||||
1469 | VMap[Inst] = ConstantInt::get(SelectorIDType, 0); | |||||
1470 | // Tell the caller not to clone this instruction. | |||||
1471 | return CloningDirector::SkipInstruction; | |||||
1472 | } | |||||
1473 | ||||||
1474 | CloningDirector::CloningAction | |||||
1475 | WinEHCatchDirector::handleInvoke(ValueToValueMapTy &VMap, | |||||
1476 | const InvokeInst *Invoke, BasicBlock *NewBB) { | |||||
1477 | return CloningDirector::CloneInstruction; | |||||
1478 | } | |||||
1479 | ||||||
1480 | CloningDirector::CloningAction | |||||
1481 | WinEHCatchDirector::handleResume(ValueToValueMapTy &VMap, | |||||
1482 | const ResumeInst *Resume, BasicBlock *NewBB) { | |||||
1483 | // Resume instructions shouldn't be reachable from catch handlers. | |||||
1484 | // We still need to handle it, but it will be pruned. | |||||
1485 | BasicBlock::InstListType &InstList = NewBB->getInstList(); | |||||
1486 | InstList.push_back(new UnreachableInst(NewBB->getContext())); | |||||
1487 | return CloningDirector::StopCloningBB; | |||||
1488 | } | |||||
1489 | ||||||
1490 | CloningDirector::CloningAction | |||||
1491 | WinEHCatchDirector::handleCompare(ValueToValueMapTy &VMap, | |||||
1492 | const CmpInst *Compare, BasicBlock *NewBB) { | |||||
1493 | const IntrinsicInst *IntrinCall = nullptr; | |||||
1494 | if (match(Compare->getOperand(0), m_Intrinsic<Intrinsic::eh_typeid_for>())) { | |||||
1495 | IntrinCall = dyn_cast<IntrinsicInst>(Compare->getOperand(0)); | |||||
1496 | } else if (match(Compare->getOperand(1), m_Intrinsic<Intrinsic::eh_typeid_for>())) { | |||||
1497 | IntrinCall = dyn_cast<IntrinsicInst>(Compare->getOperand(1)); | |||||
1498 | } | |||||
1499 | if (IntrinCall) { | |||||
1500 | Value *Selector = IntrinCall->getArgOperand(0)->stripPointerCasts(); | |||||
1501 | // This causes a replacement that will collapse the landing pad CFG based | |||||
1502 | // on the filter function we intend to match. | |||||
1503 | if (Selector == CurrentSelector->stripPointerCasts()) { | |||||
1504 | VMap[Compare] = ConstantInt::get(SelectorIDType, 1); | |||||
1505 | } | |||||
1506 | else { | |||||
1507 | VMap[Compare] = ConstantInt::get(SelectorIDType, 0); | |||||
1508 | } | |||||
1509 | return CloningDirector::SkipInstruction; | |||||
1510 | } | |||||
1511 | return CloningDirector::CloneInstruction; | |||||
1512 | } | |||||
1513 | ||||||
1514 | CloningDirector::CloningAction WinEHCleanupDirector::handleLandingPad( | |||||
1515 | ValueToValueMapTy &VMap, const LandingPadInst *LPad, BasicBlock *NewBB) { | |||||
1516 | // The MS runtime will terminate the process if an exception occurs in a | |||||
1517 | // cleanup handler, so we shouldn't encounter landing pads in the actual | |||||
1518 | // cleanup code, but they may appear in catch blocks. Depending on where | |||||
1519 | // we started cloning we may see one, but it will get dropped during dead | |||||
1520 | // block pruning. | |||||
1521 | Instruction *NewInst = new UnreachableInst(NewBB->getContext()); | |||||
1522 | VMap[LPad] = NewInst; | |||||
1523 | BasicBlock::InstListType &InstList = NewBB->getInstList(); | |||||
1524 | InstList.push_back(NewInst); | |||||
1525 | return CloningDirector::StopCloningBB; | |||||
1526 | } | |||||
1527 | ||||||
1528 | CloningDirector::CloningAction WinEHCleanupDirector::handleBeginCatch( | |||||
1529 | ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { | |||||
1530 | // Cleanup code may flow into catch blocks or the catch block may be part | |||||
1531 | // of a branch that will be optimized away. We'll insert a return | |||||
1532 | // instruction now, but it may be pruned before the cloning process is | |||||
1533 | // complete. | |||||
1534 | ReturnInst::Create(NewBB->getContext(), nullptr, NewBB); | |||||
1535 | return CloningDirector::StopCloningBB; | |||||
1536 | } | |||||
1537 | ||||||
1538 | CloningDirector::CloningAction WinEHCleanupDirector::handleEndCatch( | |||||
1539 | ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { | |||||
1540 | // Cleanup handlers nested within catch handlers may begin with a call to | |||||
1541 | // eh.endcatch. We can just ignore that instruction. | |||||
1542 | return CloningDirector::SkipInstruction; | |||||
1543 | } | |||||
1544 | ||||||
1545 | CloningDirector::CloningAction WinEHCleanupDirector::handleTypeIdFor( | |||||
1546 | ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { | |||||
1547 | // If we encounter a selector comparison while cloning a cleanup handler, | |||||
1548 | // we want to stop cloning immediately. Anything after the dispatch | |||||
1549 | // will be outlined into a different handler. | |||||
1550 | BasicBlock *CatchHandler; | |||||
1551 | Constant *Selector; | |||||
1552 | BasicBlock *NextBB; | |||||
1553 | if (isSelectorDispatch(const_cast<BasicBlock *>(Inst->getParent()), | |||||
1554 | CatchHandler, Selector, NextBB)) { | |||||
1555 | ReturnInst::Create(NewBB->getContext(), nullptr, NewBB); | |||||
1556 | return CloningDirector::StopCloningBB; | |||||
1557 | } | |||||
1558 | // If eg.typeid.for is called for any other reason, it can be ignored. | |||||
1559 | VMap[Inst] = ConstantInt::get(SelectorIDType, 0); | |||||
1560 | return CloningDirector::SkipInstruction; | |||||
1561 | } | |||||
1562 | ||||||
1563 | CloningDirector::CloningAction WinEHCleanupDirector::handleInvoke( | |||||
1564 | ValueToValueMapTy &VMap, const InvokeInst *Invoke, BasicBlock *NewBB) { | |||||
1565 | // All invokes in cleanup handlers can be replaced with calls. | |||||
1566 | SmallVector<Value *, 16> CallArgs(Invoke->op_begin(), Invoke->op_end() - 3); | |||||
1567 | // Insert a normal call instruction... | |||||
1568 | CallInst *NewCall = | |||||
1569 | CallInst::Create(const_cast<Value *>(Invoke->getCalledValue()), CallArgs, | |||||
1570 | Invoke->getName(), NewBB); | |||||
1571 | NewCall->setCallingConv(Invoke->getCallingConv()); | |||||
1572 | NewCall->setAttributes(Invoke->getAttributes()); | |||||
1573 | NewCall->setDebugLoc(Invoke->getDebugLoc()); | |||||
1574 | VMap[Invoke] = NewCall; | |||||
1575 | ||||||
1576 | // Remap the operands. | |||||
1577 | llvm::RemapInstruction(NewCall, VMap, RF_None, nullptr, &Materializer); | |||||
1578 | ||||||
1579 | // Insert an unconditional branch to the normal destination. | |||||
1580 | BranchInst::Create(Invoke->getNormalDest(), NewBB); | |||||
1581 | ||||||
1582 | // The unwind destination won't be cloned into the new function, so | |||||
1583 | // we don't need to clean up its phi nodes. | |||||
1584 | ||||||
1585 | // We just added a terminator to the cloned block. | |||||
1586 | // Tell the caller to stop processing the current basic block. | |||||
1587 | return CloningDirector::CloneSuccessors; | |||||
1588 | } | |||||
1589 | ||||||
1590 | CloningDirector::CloningAction WinEHCleanupDirector::handleResume( | |||||
1591 | ValueToValueMapTy &VMap, const ResumeInst *Resume, BasicBlock *NewBB) { | |||||
1592 | ReturnInst::Create(NewBB->getContext(), nullptr, NewBB); | |||||
1593 | ||||||
1594 | // We just added a terminator to the cloned block. | |||||
1595 | // Tell the caller to stop processing the current basic block so that | |||||
1596 | // the branch instruction will be skipped. | |||||
1597 | return CloningDirector::StopCloningBB; | |||||
1598 | } | |||||
1599 | ||||||
1600 | CloningDirector::CloningAction | |||||
1601 | WinEHCleanupDirector::handleCompare(ValueToValueMapTy &VMap, | |||||
1602 | const CmpInst *Compare, BasicBlock *NewBB) { | |||||
1603 | if (match(Compare->getOperand(0), m_Intrinsic<Intrinsic::eh_typeid_for>()) || | |||||
1604 | match(Compare->getOperand(1), m_Intrinsic<Intrinsic::eh_typeid_for>())) { | |||||
1605 | VMap[Compare] = ConstantInt::get(SelectorIDType, 1); | |||||
1606 | return CloningDirector::SkipInstruction; | |||||
1607 | } | |||||
1608 | return CloningDirector::CloneInstruction; | |||||
1609 | ||||||
1610 | } | |||||
1611 | ||||||
1612 | WinEHFrameVariableMaterializer::WinEHFrameVariableMaterializer( | |||||
1613 | Function *OutlinedFn, FrameVarInfoMap &FrameVarInfo) | |||||
1614 | : FrameVarInfo(FrameVarInfo), Builder(OutlinedFn->getContext()) { | |||||
1615 | BasicBlock *EntryBB = &OutlinedFn->getEntryBlock(); | |||||
1616 | Builder.SetInsertPoint(EntryBB, EntryBB->getFirstInsertionPt()); | |||||
1617 | } | |||||
1618 | ||||||
1619 | Value *WinEHFrameVariableMaterializer::materializeValueFor(Value *V) { | |||||
1620 | // If we're asked to materialize a static alloca, we temporarily create an | |||||
1621 | // alloca in the outlined function and add this to the FrameVarInfo map. When | |||||
1622 | // all the outlining is complete, we'll replace these temporary allocas with | |||||
1623 | // calls to llvm.framerecover. | |||||
1624 | if (auto *AV = dyn_cast<AllocaInst>(V)) { | |||||
1625 | assert(AV->isStaticAlloca() &&((AV->isStaticAlloca() && "cannot materialize un-demoted dynamic alloca" ) ? static_cast<void> (0) : __assert_fail ("AV->isStaticAlloca() && \"cannot materialize un-demoted dynamic alloca\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1626, __PRETTY_FUNCTION__)) | |||||
1626 | "cannot materialize un-demoted dynamic alloca")((AV->isStaticAlloca() && "cannot materialize un-demoted dynamic alloca" ) ? static_cast<void> (0) : __assert_fail ("AV->isStaticAlloca() && \"cannot materialize un-demoted dynamic alloca\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1626, __PRETTY_FUNCTION__)); | |||||
1627 | AllocaInst *NewAlloca = dyn_cast<AllocaInst>(AV->clone()); | |||||
1628 | Builder.Insert(NewAlloca, AV->getName()); | |||||
1629 | FrameVarInfo[AV].push_back(NewAlloca); | |||||
1630 | return NewAlloca; | |||||
1631 | } | |||||
1632 | ||||||
1633 | if (isa<Instruction>(V) || isa<Argument>(V)) { | |||||
1634 | errs() << "Failed to demote instruction used in exception handler:\n"; | |||||
1635 | errs() << " " << *V << '\n'; | |||||
1636 | report_fatal_error("WinEHPrepare failed to demote instruction"); | |||||
1637 | } | |||||
1638 | ||||||
1639 | // Don't materialize other values. | |||||
1640 | return nullptr; | |||||
1641 | } | |||||
1642 | ||||||
1643 | void WinEHFrameVariableMaterializer::escapeCatchObject(Value *V) { | |||||
1644 | // Catch parameter objects have to live in the parent frame. When we see a use | |||||
1645 | // of a catch parameter, add a sentinel to the multimap to indicate that it's | |||||
1646 | // used from another handler. This will prevent us from trying to sink the | |||||
1647 | // alloca into the handler and ensure that the catch parameter is present in | |||||
1648 | // the call to llvm.frameescape. | |||||
1649 | FrameVarInfo[V].push_back(getCatchObjectSentinel()); | |||||
1650 | } | |||||
1651 | ||||||
1652 | // This function maps the catch and cleanup handlers that are reachable from the | |||||
1653 | // specified landing pad. The landing pad sequence will have this basic shape: | |||||
1654 | // | |||||
1655 | // <cleanup handler> | |||||
1656 | // <selector comparison> | |||||
1657 | // <catch handler> | |||||
1658 | // <cleanup handler> | |||||
1659 | // <selector comparison> | |||||
1660 | // <catch handler> | |||||
1661 | // <cleanup handler> | |||||
1662 | // ... | |||||
1663 | // | |||||
1664 | // Any of the cleanup slots may be absent. The cleanup slots may be occupied by | |||||
1665 | // any arbitrary control flow, but all paths through the cleanup code must | |||||
1666 | // eventually reach the next selector comparison and no path can skip to a | |||||
1667 | // different selector comparisons, though some paths may terminate abnormally. | |||||
1668 | // Therefore, we will use a depth first search from the start of any given | |||||
1669 | // cleanup block and stop searching when we find the next selector comparison. | |||||
1670 | // | |||||
1671 | // If the landingpad instruction does not have a catch clause, we will assume | |||||
1672 | // that any instructions other than selector comparisons and catch handlers can | |||||
1673 | // be ignored. In practice, these will only be the boilerplate instructions. | |||||
1674 | // | |||||
1675 | // The catch handlers may also have any control structure, but we are only | |||||
1676 | // interested in the start of the catch handlers, so we don't need to actually | |||||
1677 | // follow the flow of the catch handlers. The start of the catch handlers can | |||||
1678 | // be located from the compare instructions, but they can be skipped in the | |||||
1679 | // flow by following the contrary branch. | |||||
1680 | void WinEHPrepare::mapLandingPadBlocks(LandingPadInst *LPad, | |||||
1681 | LandingPadActions &Actions) { | |||||
1682 | unsigned int NumClauses = LPad->getNumClauses(); | |||||
1683 | unsigned int HandlersFound = 0; | |||||
1684 | BasicBlock *BB = LPad->getParent(); | |||||
1685 | ||||||
1686 | DEBUG(dbgs() << "Mapping landing pad: " << BB->getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << "Mapping landing pad: " << BB->getName() << "\n"; } } while (0); | |||||
1687 | ||||||
1688 | if (NumClauses == 0) { | |||||
| ||||||
1689 | findCleanupHandlers(Actions, BB, nullptr); | |||||
1690 | return; | |||||
1691 | } | |||||
1692 | ||||||
1693 | VisitedBlockSet VisitedBlocks; | |||||
1694 | ||||||
1695 | while (HandlersFound != NumClauses) { | |||||
1696 | BasicBlock *NextBB = nullptr; | |||||
1697 | ||||||
1698 | // Skip over filter clauses. | |||||
1699 | if (LPad->isFilter(HandlersFound)) { | |||||
1700 | ++HandlersFound; | |||||
1701 | continue; | |||||
1702 | } | |||||
1703 | ||||||
1704 | // See if the clause we're looking for is a catch-all. | |||||
1705 | // If so, the catch begins immediately. | |||||
1706 | Constant *ExpectedSelector = LPad->getClause(HandlersFound)->stripPointerCasts(); | |||||
1707 | if (isa<ConstantPointerNull>(ExpectedSelector)) { | |||||
1708 | // The catch all must occur last. | |||||
1709 | assert(HandlersFound == NumClauses - 1)((HandlersFound == NumClauses - 1) ? static_cast<void> ( 0) : __assert_fail ("HandlersFound == NumClauses - 1", "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1709, __PRETTY_FUNCTION__)); | |||||
1710 | ||||||
1711 | // There can be additional selector dispatches in the call chain that we | |||||
1712 | // need to ignore. | |||||
1713 | BasicBlock *CatchBlock = nullptr; | |||||
1714 | Constant *Selector; | |||||
1715 | while (BB && isSelectorDispatch(BB, CatchBlock, Selector, NextBB)) { | |||||
1716 | DEBUG(dbgs() << " Found extra catch dispatch in block "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found extra catch dispatch in block " << CatchBlock->getName() << "\n"; } } while ( 0) | |||||
1717 | << CatchBlock->getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found extra catch dispatch in block " << CatchBlock->getName() << "\n"; } } while ( 0); | |||||
1718 | BB = NextBB; | |||||
1719 | } | |||||
1720 | ||||||
1721 | // For C++ EH, check if there is any interesting cleanup code before we | |||||
1722 | // begin the catch. This is important because cleanups cannot rethrow | |||||
1723 | // exceptions but code called from catches can. For SEH, it isn't | |||||
1724 | // important if some finally code before a catch-all is executed out of | |||||
1725 | // line or after recovering from the exception. | |||||
1726 | if (Personality == EHPersonality::MSVC_CXX) | |||||
1727 | findCleanupHandlers(Actions, BB, BB); | |||||
1728 | ||||||
1729 | // Add the catch handler to the action list. | |||||
1730 | CatchHandler *Action = nullptr; | |||||
1731 | if (CatchHandlerMap.count(BB) && CatchHandlerMap[BB] != nullptr) { | |||||
1732 | // If the CatchHandlerMap already has an entry for this BB, re-use it. | |||||
1733 | Action = CatchHandlerMap[BB]; | |||||
1734 | assert(Action->getSelector() == ExpectedSelector)((Action->getSelector() == ExpectedSelector) ? static_cast <void> (0) : __assert_fail ("Action->getSelector() == ExpectedSelector" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1734, __PRETTY_FUNCTION__)); | |||||
1735 | } else { | |||||
1736 | // Since this is a catch-all handler, the selector won't actually appear | |||||
1737 | // in the code anywhere. ExpectedSelector here is the constant null ptr | |||||
1738 | // that we got from the landing pad instruction. | |||||
1739 | Action = new CatchHandler(BB, ExpectedSelector, nullptr); | |||||
1740 | CatchHandlerMap[BB] = Action; | |||||
1741 | } | |||||
1742 | Actions.insertCatchHandler(Action); | |||||
1743 | DEBUG(dbgs() << " Catch all handler at block " << BB->getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Catch all handler at block " << BB->getName() << "\n"; } } while (0); | |||||
| ||||||
1744 | ++HandlersFound; | |||||
1745 | ||||||
1746 | // Once we reach a catch-all, don't expect to hit a resume instruction. | |||||
1747 | BB = nullptr; | |||||
1748 | break; | |||||
1749 | } | |||||
1750 | ||||||
1751 | CatchHandler *CatchAction = findCatchHandler(BB, NextBB, VisitedBlocks); | |||||
1752 | assert(CatchAction)((CatchAction) ? static_cast<void> (0) : __assert_fail ( "CatchAction", "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 1752, __PRETTY_FUNCTION__)); | |||||
1753 | ||||||
1754 | // See if there is any interesting code executed before the dispatch. | |||||
1755 | findCleanupHandlers(Actions, BB, CatchAction->getStartBlock()); | |||||
1756 | ||||||
1757 | // When the source program contains multiple nested try blocks the catch | |||||
1758 | // handlers can get strung together in such a way that we can encounter | |||||
1759 | // a dispatch for a selector that we've already had a handler for. | |||||
1760 | if (CatchAction->getSelector()->stripPointerCasts() == ExpectedSelector) { | |||||
1761 | ++HandlersFound; | |||||
1762 | ||||||
1763 | // Add the catch handler to the action list. | |||||
1764 | DEBUG(dbgs() << " Found catch dispatch in block "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found catch dispatch in block " << CatchAction->getStartBlock()->getName() << "\n"; } } while (0) | |||||
1765 | << CatchAction->getStartBlock()->getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found catch dispatch in block " << CatchAction->getStartBlock()->getName() << "\n"; } } while (0); | |||||
1766 | Actions.insertCatchHandler(CatchAction); | |||||
1767 | } else { | |||||
1768 | // Under some circumstances optimized IR will flow unconditionally into a | |||||
1769 | // handler block without checking the selector. This can only happen if | |||||
1770 | // the landing pad has a catch-all handler and the handler for the | |||||
1771 | // preceeding catch clause is identical to the catch-call handler | |||||
1772 | // (typically an empty catch). In this case, the handler must be shared | |||||
1773 | // by all remaining clauses. | |||||
1774 | if (isa<ConstantPointerNull>( | |||||
1775 | CatchAction->getSelector()->stripPointerCasts())) { | |||||
1776 | DEBUG(dbgs() << " Applying early catch-all handler in block "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Applying early catch-all handler in block " << CatchAction->getStartBlock()->getName() << " to all remaining clauses.\n"; } } while (0) | |||||
1777 | << CatchAction->getStartBlock()->getName()do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Applying early catch-all handler in block " << CatchAction->getStartBlock()->getName() << " to all remaining clauses.\n"; } } while (0) | |||||
1778 | << " to all remaining clauses.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Applying early catch-all handler in block " << CatchAction->getStartBlock()->getName() << " to all remaining clauses.\n"; } } while (0); | |||||
1779 | Actions.insertCatchHandler(CatchAction); | |||||
1780 | return; | |||||
1781 | } | |||||
1782 | ||||||
1783 | DEBUG(dbgs() << " Found extra catch dispatch in block "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found extra catch dispatch in block " << CatchAction->getStartBlock()->getName() << "\n"; } } while (0) | |||||
1784 | << CatchAction->getStartBlock()->getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found extra catch dispatch in block " << CatchAction->getStartBlock()->getName() << "\n"; } } while (0); | |||||
1785 | } | |||||
1786 | ||||||
1787 | // Move on to the block after the catch handler. | |||||
1788 | BB = NextBB; | |||||
1789 | } | |||||
1790 | ||||||
1791 | // If we didn't wind up in a catch-all, see if there is any interesting code | |||||
1792 | // executed before the resume. | |||||
1793 | findCleanupHandlers(Actions, BB, BB); | |||||
1794 | ||||||
1795 | // It's possible that some optimization moved code into a landingpad that | |||||
1796 | // wasn't | |||||
1797 | // previously being used for cleanup. If that happens, we need to execute | |||||
1798 | // that | |||||
1799 | // extra code from a cleanup handler. | |||||
1800 | if (Actions.includesCleanup() && !LPad->isCleanup()) | |||||
1801 | LPad->setCleanup(true); | |||||
1802 | } | |||||
1803 | ||||||
1804 | // This function searches starting with the input block for the next | |||||
1805 | // block that terminates with a branch whose condition is based on a selector | |||||
1806 | // comparison. This may be the input block. See the mapLandingPadBlocks | |||||
1807 | // comments for a discussion of control flow assumptions. | |||||
1808 | // | |||||
1809 | CatchHandler *WinEHPrepare::findCatchHandler(BasicBlock *BB, | |||||
1810 | BasicBlock *&NextBB, | |||||
1811 | VisitedBlockSet &VisitedBlocks) { | |||||
1812 | // See if we've already found a catch handler use it. | |||||
1813 | // Call count() first to avoid creating a null entry for blocks | |||||
1814 | // we haven't seen before. | |||||
1815 | if (CatchHandlerMap.count(BB) && CatchHandlerMap[BB] != nullptr) { | |||||
1816 | CatchHandler *Action = cast<CatchHandler>(CatchHandlerMap[BB]); | |||||
1817 | NextBB = Action->getNextBB(); | |||||
1818 | return Action; | |||||
1819 | } | |||||
1820 | ||||||
1821 | // VisitedBlocks applies only to the current search. We still | |||||
1822 | // need to consider blocks that we've visited while mapping other | |||||
1823 | // landing pads. | |||||
1824 | VisitedBlocks.insert(BB); | |||||
1825 | ||||||
1826 | BasicBlock *CatchBlock = nullptr; | |||||
1827 | Constant *Selector = nullptr; | |||||
1828 | ||||||
1829 | // If this is the first time we've visited this block from any landing pad | |||||
1830 | // look to see if it is a selector dispatch block. | |||||
1831 | if (!CatchHandlerMap.count(BB)) { | |||||
1832 | if (isSelectorDispatch(BB, CatchBlock, Selector, NextBB)) { | |||||
1833 | CatchHandler *Action = new CatchHandler(BB, Selector, NextBB); | |||||
1834 | CatchHandlerMap[BB] = Action; | |||||
1835 | return Action; | |||||
1836 | } | |||||
1837 | // If we encounter a block containing an llvm.eh.begincatch before we | |||||
1838 | // find a selector dispatch block, the handler is assumed to be | |||||
1839 | // reached unconditionally. This happens for catch-all blocks, but | |||||
1840 | // it can also happen for other catch handlers that have been combined | |||||
1841 | // with the catch-all handler during optimization. | |||||
1842 | if (isCatchBlock(BB)) { | |||||
1843 | PointerType *Int8PtrTy = Type::getInt8PtrTy(BB->getContext()); | |||||
1844 | Constant *NullSelector = ConstantPointerNull::get(Int8PtrTy); | |||||
1845 | CatchHandler *Action = new CatchHandler(BB, NullSelector, nullptr); | |||||
1846 | CatchHandlerMap[BB] = Action; | |||||
1847 | return Action; | |||||
1848 | } | |||||
1849 | } | |||||
1850 | ||||||
1851 | // Visit each successor, looking for the dispatch. | |||||
1852 | // FIXME: We expect to find the dispatch quickly, so this will probably | |||||
1853 | // work better as a breadth first search. | |||||
1854 | for (BasicBlock *Succ : successors(BB)) { | |||||
1855 | if (VisitedBlocks.count(Succ)) | |||||
1856 | continue; | |||||
1857 | ||||||
1858 | CatchHandler *Action = findCatchHandler(Succ, NextBB, VisitedBlocks); | |||||
1859 | if (Action) | |||||
1860 | return Action; | |||||
1861 | } | |||||
1862 | return nullptr; | |||||
1863 | } | |||||
1864 | ||||||
1865 | // These are helper functions to combine repeated code from findCleanupHandlers. | |||||
1866 | static void createCleanupHandler(LandingPadActions &Actions, | |||||
1867 | CleanupHandlerMapTy &CleanupHandlerMap, | |||||
1868 | BasicBlock *BB) { | |||||
1869 | CleanupHandler *Action = new CleanupHandler(BB); | |||||
1870 | CleanupHandlerMap[BB] = Action; | |||||
1871 | Actions.insertCleanupHandler(Action); | |||||
1872 | DEBUG(dbgs() << " Found cleanup code in block "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found cleanup code in block " << Action->getStartBlock()->getName() << "\n" ; } } while (0) | |||||
1873 | << Action->getStartBlock()->getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found cleanup code in block " << Action->getStartBlock()->getName() << "\n" ; } } while (0); | |||||
1874 | } | |||||
1875 | ||||||
1876 | static CallSite matchOutlinedFinallyCall(BasicBlock *BB, | |||||
1877 | Instruction *MaybeCall) { | |||||
1878 | // Look for finally blocks that Clang has already outlined for us. | |||||
1879 | // %fp = call i8* @llvm.frameaddress(i32 0) | |||||
1880 | // call void @"fin$parent"(iN 1, i8* %fp) | |||||
1881 | if (isFrameAddressCall(MaybeCall) && MaybeCall != BB->getTerminator()) | |||||
1882 | MaybeCall = MaybeCall->getNextNode(); | |||||
1883 | CallSite FinallyCall(MaybeCall); | |||||
1884 | if (!FinallyCall || FinallyCall.arg_size() != 2) | |||||
1885 | return CallSite(); | |||||
1886 | if (!match(FinallyCall.getArgument(0), m_SpecificInt(1))) | |||||
1887 | return CallSite(); | |||||
1888 | if (!isFrameAddressCall(FinallyCall.getArgument(1))) | |||||
1889 | return CallSite(); | |||||
1890 | return FinallyCall; | |||||
1891 | } | |||||
1892 | ||||||
1893 | static BasicBlock *followSingleUnconditionalBranches(BasicBlock *BB) { | |||||
1894 | // Skip single ubr blocks. | |||||
1895 | while (BB->getFirstNonPHIOrDbg() == BB->getTerminator()) { | |||||
1896 | auto *Br = dyn_cast<BranchInst>(BB->getTerminator()); | |||||
1897 | if (Br && Br->isUnconditional()) | |||||
1898 | BB = Br->getSuccessor(0); | |||||
1899 | else | |||||
1900 | return BB; | |||||
1901 | } | |||||
1902 | return BB; | |||||
1903 | } | |||||
1904 | ||||||
1905 | // This function searches starting with the input block for the next block that | |||||
1906 | // contains code that is not part of a catch handler and would not be eliminated | |||||
1907 | // during handler outlining. | |||||
1908 | // | |||||
1909 | void WinEHPrepare::findCleanupHandlers(LandingPadActions &Actions, | |||||
1910 | BasicBlock *StartBB, BasicBlock *EndBB) { | |||||
1911 | // Here we will skip over the following: | |||||
1912 | // | |||||
1913 | // landing pad prolog: | |||||
1914 | // | |||||
1915 | // Unconditional branches | |||||
1916 | // | |||||
1917 | // Selector dispatch | |||||
1918 | // | |||||
1919 | // Resume pattern | |||||
1920 | // | |||||
1921 | // Anything else marks the start of an interesting block | |||||
1922 | ||||||
1923 | BasicBlock *BB = StartBB; | |||||
1924 | // Anything other than an unconditional branch will kick us out of this loop | |||||
1925 | // one way or another. | |||||
1926 | while (BB) { | |||||
1927 | BB = followSingleUnconditionalBranches(BB); | |||||
1928 | // If we've already scanned this block, don't scan it again. If it is | |||||
1929 | // a cleanup block, there will be an action in the CleanupHandlerMap. | |||||
1930 | // If we've scanned it and it is not a cleanup block, there will be a | |||||
1931 | // nullptr in the CleanupHandlerMap. If we have not scanned it, there will | |||||
1932 | // be no entry in the CleanupHandlerMap. We must call count() first to | |||||
1933 | // avoid creating a null entry for blocks we haven't scanned. | |||||
1934 | if (CleanupHandlerMap.count(BB)) { | |||||
1935 | if (auto *Action = CleanupHandlerMap[BB]) { | |||||
1936 | Actions.insertCleanupHandler(Action); | |||||
1937 | DEBUG(dbgs() << " Found cleanup code in block "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found cleanup code in block " << Action->getStartBlock()->getName() << "\n" ; } } while (0) | |||||
1938 | << Action->getStartBlock()->getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found cleanup code in block " << Action->getStartBlock()->getName() << "\n" ; } } while (0); | |||||
1939 | // FIXME: This cleanup might chain into another, and we need to discover | |||||
1940 | // that. | |||||
1941 | return; | |||||
1942 | } else { | |||||
1943 | // Here we handle the case where the cleanup handler map contains a | |||||
1944 | // value for this block but the value is a nullptr. This means that | |||||
1945 | // we have previously analyzed the block and determined that it did | |||||
1946 | // not contain any cleanup code. Based on the earlier analysis, we | |||||
1947 | // know the the block must end in either an unconditional branch, a | |||||
1948 | // resume or a conditional branch that is predicated on a comparison | |||||
1949 | // with a selector. Either the resume or the selector dispatch | |||||
1950 | // would terminate the search for cleanup code, so the unconditional | |||||
1951 | // branch is the only case for which we might need to continue | |||||
1952 | // searching. | |||||
1953 | BasicBlock *SuccBB = followSingleUnconditionalBranches(BB); | |||||
1954 | if (SuccBB == BB || SuccBB == EndBB) | |||||
1955 | return; | |||||
1956 | BB = SuccBB; | |||||
1957 | continue; | |||||
1958 | } | |||||
1959 | } | |||||
1960 | ||||||
1961 | // Create an entry in the cleanup handler map for this block. Initially | |||||
1962 | // we create an entry that says this isn't a cleanup block. If we find | |||||
1963 | // cleanup code, the caller will replace this entry. | |||||
1964 | CleanupHandlerMap[BB] = nullptr; | |||||
1965 | ||||||
1966 | TerminatorInst *Terminator = BB->getTerminator(); | |||||
1967 | ||||||
1968 | // Landing pad blocks have extra instructions we need to accept. | |||||
1969 | LandingPadMap *LPadMap = nullptr; | |||||
1970 | if (BB->isLandingPad()) { | |||||
1971 | LandingPadInst *LPad = BB->getLandingPadInst(); | |||||
1972 | LPadMap = &LPadMaps[LPad]; | |||||
1973 | if (!LPadMap->isInitialized()) | |||||
1974 | LPadMap->mapLandingPad(LPad); | |||||
1975 | } | |||||
1976 | ||||||
1977 | // Look for the bare resume pattern: | |||||
1978 | // %lpad.val1 = insertvalue { i8*, i32 } undef, i8* %exn, 0 | |||||
1979 | // %lpad.val2 = insertvalue { i8*, i32 } %lpad.val1, i32 %sel, 1 | |||||
1980 | // resume { i8*, i32 } %lpad.val2 | |||||
1981 | if (auto *Resume = dyn_cast<ResumeInst>(Terminator)) { | |||||
1982 | InsertValueInst *Insert1 = nullptr; | |||||
1983 | InsertValueInst *Insert2 = nullptr; | |||||
1984 | Value *ResumeVal = Resume->getOperand(0); | |||||
1985 | // If the resume value isn't a phi or landingpad value, it should be a | |||||
1986 | // series of insertions. Identify them so we can avoid them when scanning | |||||
1987 | // for cleanups. | |||||
1988 | if (!isa<PHINode>(ResumeVal) && !isa<LandingPadInst>(ResumeVal)) { | |||||
1989 | Insert2 = dyn_cast<InsertValueInst>(ResumeVal); | |||||
1990 | if (!Insert2) | |||||
1991 | return createCleanupHandler(Actions, CleanupHandlerMap, BB); | |||||
1992 | Insert1 = dyn_cast<InsertValueInst>(Insert2->getAggregateOperand()); | |||||
1993 | if (!Insert1) | |||||
1994 | return createCleanupHandler(Actions, CleanupHandlerMap, BB); | |||||
1995 | } | |||||
1996 | for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg(), IE = BB->end(); | |||||
1997 | II != IE; ++II) { | |||||
1998 | Instruction *Inst = II; | |||||
1999 | if (LPadMap && LPadMap->isLandingPadSpecificInst(Inst)) | |||||
2000 | continue; | |||||
2001 | if (Inst == Insert1 || Inst == Insert2 || Inst == Resume) | |||||
2002 | continue; | |||||
2003 | if (!Inst->hasOneUse() || | |||||
2004 | (Inst->user_back() != Insert1 && Inst->user_back() != Insert2)) { | |||||
2005 | return createCleanupHandler(Actions, CleanupHandlerMap, BB); | |||||
2006 | } | |||||
2007 | } | |||||
2008 | return; | |||||
2009 | } | |||||
2010 | ||||||
2011 | BranchInst *Branch = dyn_cast<BranchInst>(Terminator); | |||||
2012 | if (Branch && Branch->isConditional()) { | |||||
2013 | // Look for the selector dispatch. | |||||
2014 | // %2 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIf to i8*)) | |||||
2015 | // %matches = icmp eq i32 %sel, %2 | |||||
2016 | // br i1 %matches, label %catch14, label %eh.resume | |||||
2017 | CmpInst *Compare = dyn_cast<CmpInst>(Branch->getCondition()); | |||||
2018 | if (!Compare || !Compare->isEquality()) | |||||
2019 | return createCleanupHandler(Actions, CleanupHandlerMap, BB); | |||||
2020 | for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg(), IE = BB->end(); | |||||
2021 | II != IE; ++II) { | |||||
2022 | Instruction *Inst = II; | |||||
2023 | if (LPadMap && LPadMap->isLandingPadSpecificInst(Inst)) | |||||
2024 | continue; | |||||
2025 | if (Inst == Compare || Inst == Branch) | |||||
2026 | continue; | |||||
2027 | if (match(Inst, m_Intrinsic<Intrinsic::eh_typeid_for>())) | |||||
2028 | continue; | |||||
2029 | return createCleanupHandler(Actions, CleanupHandlerMap, BB); | |||||
2030 | } | |||||
2031 | // The selector dispatch block should always terminate our search. | |||||
2032 | assert(BB == EndBB)((BB == EndBB) ? static_cast<void> (0) : __assert_fail ( "BB == EndBB", "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 2032, __PRETTY_FUNCTION__)); | |||||
2033 | return; | |||||
2034 | } | |||||
2035 | ||||||
2036 | if (isAsynchronousEHPersonality(Personality)) { | |||||
2037 | // If this is a landingpad block, split the block at the first non-landing | |||||
2038 | // pad instruction. | |||||
2039 | Instruction *MaybeCall = BB->getFirstNonPHIOrDbg(); | |||||
2040 | if (LPadMap) { | |||||
2041 | while (MaybeCall != BB->getTerminator() && | |||||
2042 | LPadMap->isLandingPadSpecificInst(MaybeCall)) | |||||
2043 | MaybeCall = MaybeCall->getNextNode(); | |||||
2044 | } | |||||
2045 | ||||||
2046 | // Look for outlined finally calls. | |||||
2047 | if (CallSite FinallyCall = matchOutlinedFinallyCall(BB, MaybeCall)) { | |||||
2048 | Function *Fin = FinallyCall.getCalledFunction(); | |||||
2049 | assert(Fin && "outlined finally call should be direct")((Fin && "outlined finally call should be direct") ? static_cast <void> (0) : __assert_fail ("Fin && \"outlined finally call should be direct\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 2049, __PRETTY_FUNCTION__)); | |||||
2050 | auto *Action = new CleanupHandler(BB); | |||||
2051 | Action->setHandlerBlockOrFunc(Fin); | |||||
2052 | Actions.insertCleanupHandler(Action); | |||||
2053 | CleanupHandlerMap[BB] = Action; | |||||
2054 | DEBUG(dbgs() << " Found frontend-outlined finally call to "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found frontend-outlined finally call to " << Fin->getName() << " in block " << Action ->getStartBlock()->getName() << "\n"; } } while ( 0) | |||||
2055 | << Fin->getName() << " in block "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found frontend-outlined finally call to " << Fin->getName() << " in block " << Action ->getStartBlock()->getName() << "\n"; } } while ( 0) | |||||
2056 | << Action->getStartBlock()->getName() << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("winehprepare")) { dbgs() << " Found frontend-outlined finally call to " << Fin->getName() << " in block " << Action ->getStartBlock()->getName() << "\n"; } } while ( 0); | |||||
2057 | ||||||
2058 | // Split the block if there were more interesting instructions and look | |||||
2059 | // for finally calls in the normal successor block. | |||||
2060 | BasicBlock *SuccBB = BB; | |||||
2061 | if (FinallyCall.getInstruction() != BB->getTerminator() && | |||||
2062 | FinallyCall.getInstruction()->getNextNode() != BB->getTerminator()) { | |||||
2063 | SuccBB = BB->splitBasicBlock(FinallyCall.getInstruction()->getNextNode()); | |||||
2064 | } else { | |||||
2065 | if (FinallyCall.isInvoke()) { | |||||
2066 | SuccBB = cast<InvokeInst>(FinallyCall.getInstruction())->getNormalDest(); | |||||
2067 | } else { | |||||
2068 | SuccBB = BB->getUniqueSuccessor(); | |||||
2069 | assert(SuccBB && "splitOutlinedFinallyCalls didn't insert a branch")((SuccBB && "splitOutlinedFinallyCalls didn't insert a branch" ) ? static_cast<void> (0) : __assert_fail ("SuccBB && \"splitOutlinedFinallyCalls didn't insert a branch\"" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 2069, __PRETTY_FUNCTION__)); | |||||
2070 | } | |||||
2071 | } | |||||
2072 | BB = SuccBB; | |||||
2073 | if (BB == EndBB) | |||||
2074 | return; | |||||
2075 | continue; | |||||
2076 | } | |||||
2077 | } | |||||
2078 | ||||||
2079 | // Anything else is either a catch block or interesting cleanup code. | |||||
2080 | for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg(), IE = BB->end(); | |||||
2081 | II != IE; ++II) { | |||||
2082 | Instruction *Inst = II; | |||||
2083 | if (LPadMap && LPadMap->isLandingPadSpecificInst(Inst)) | |||||
2084 | continue; | |||||
2085 | // Unconditional branches fall through to this loop. | |||||
2086 | if (Inst == Branch) | |||||
2087 | continue; | |||||
2088 | // If this is a catch block, there is no cleanup code to be found. | |||||
2089 | if (match(Inst, m_Intrinsic<Intrinsic::eh_begincatch>())) | |||||
2090 | return; | |||||
2091 | // If this a nested landing pad, it may contain an endcatch call. | |||||
2092 | if (match(Inst, m_Intrinsic<Intrinsic::eh_endcatch>())) | |||||
2093 | return; | |||||
2094 | // Anything else makes this interesting cleanup code. | |||||
2095 | return createCleanupHandler(Actions, CleanupHandlerMap, BB); | |||||
2096 | } | |||||
2097 | ||||||
2098 | // Only unconditional branches in empty blocks should get this far. | |||||
2099 | assert(Branch && Branch->isUnconditional())((Branch && Branch->isUnconditional()) ? static_cast <void> (0) : __assert_fail ("Branch && Branch->isUnconditional()" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 2099, __PRETTY_FUNCTION__)); | |||||
2100 | if (BB == EndBB) | |||||
2101 | return; | |||||
2102 | BB = Branch->getSuccessor(0); | |||||
2103 | } | |||||
2104 | } | |||||
2105 | ||||||
2106 | // This is a public function, declared in WinEHFuncInfo.h and is also | |||||
2107 | // referenced by WinEHNumbering in FunctionLoweringInfo.cpp. | |||||
2108 | void llvm::parseEHActions(const IntrinsicInst *II, | |||||
2109 | SmallVectorImpl<ActionHandler *> &Actions) { | |||||
2110 | for (unsigned I = 0, E = II->getNumArgOperands(); I != E;) { | |||||
2111 | uint64_t ActionKind = | |||||
2112 | cast<ConstantInt>(II->getArgOperand(I))->getZExtValue(); | |||||
2113 | if (ActionKind == /*catch=*/1) { | |||||
2114 | auto *Selector = cast<Constant>(II->getArgOperand(I + 1)); | |||||
2115 | ConstantInt *EHObjIndex = cast<ConstantInt>(II->getArgOperand(I + 2)); | |||||
2116 | int64_t EHObjIndexVal = EHObjIndex->getSExtValue(); | |||||
2117 | Constant *Handler = cast<Constant>(II->getArgOperand(I + 3)); | |||||
2118 | I += 4; | |||||
2119 | auto *CH = new CatchHandler(/*BB=*/nullptr, Selector, /*NextBB=*/nullptr); | |||||
2120 | CH->setHandlerBlockOrFunc(Handler); | |||||
2121 | CH->setExceptionVarIndex(EHObjIndexVal); | |||||
2122 | Actions.push_back(CH); | |||||
2123 | } else if (ActionKind == 0) { | |||||
2124 | Constant *Handler = cast<Constant>(II->getArgOperand(I + 1)); | |||||
2125 | I += 2; | |||||
2126 | auto *CH = new CleanupHandler(/*BB=*/nullptr); | |||||
2127 | CH->setHandlerBlockOrFunc(Handler); | |||||
2128 | Actions.push_back(CH); | |||||
2129 | } else { | |||||
2130 | llvm_unreachable("Expected either a catch or cleanup handler!")::llvm::llvm_unreachable_internal("Expected either a catch or cleanup handler!" , "/tmp/buildd/llvm-toolchain-snapshot-3.7~svn235822/lib/CodeGen/WinEHPrepare.cpp" , 2130); | |||||
2131 | } | |||||
2132 | } | |||||
2133 | std::reverse(Actions.begin(), Actions.end()); | |||||
2134 | } |