Remove unused member variables (-Wunused-private-field)
[oota-llvm.git] / lib / CodeGen / WinEHPrepare.cpp
1 //===-- WinEHPrepare - Prepare exception handling for code generation ---===//\r
2 //\r
3 //                     The LLVM Compiler Infrastructure\r
4 //\r
5 // This file is distributed under the University of Illinois Open Source\r
6 // License. See LICENSE.TXT for details.\r
7 //\r
8 //===----------------------------------------------------------------------===//\r
9 //\r
10 // This pass lowers LLVM IR exception handling into something closer to what the\r
11 // backend wants. It snifs the personality function to see which kind of\r
12 // preparation is necessary. If the personality function uses the Itanium LSDA,\r
13 // this pass delegates to the DWARF EH preparation pass.\r
14 //\r
15 //===----------------------------------------------------------------------===//\r
16 \r
17 #include "llvm/CodeGen/Passes.h"\r
18 #include "llvm/Analysis/LibCallSemantics.h"\r
19 #include "llvm/IR/Function.h"\r
20 #include "llvm/IR/IRBuilder.h"\r
21 #include "llvm/IR/Instructions.h"\r
22 #include "llvm/IR/IntrinsicInst.h"\r
23 #include "llvm/IR/Module.h"\r
24 #include "llvm/IR/PatternMatch.h"\r
25 #include "llvm/Pass.h"\r
26 #include "llvm/Transforms/Utils/Cloning.h"\r
27 #include "llvm/Transforms/Utils/Local.h"\r
28 #include <memory>\r
29 \r
30 using namespace llvm;\r
31 using namespace llvm::PatternMatch;\r
32 \r
33 #define DEBUG_TYPE "winehprepare"\r
34 \r
35 namespace {\r
36 class WinEHPrepare : public FunctionPass {\r
37   std::unique_ptr<FunctionPass> DwarfPrepare;\r
38 \r
39 public:\r
40   static char ID; // Pass identification, replacement for typeid.\r
41   WinEHPrepare(const TargetMachine *TM = nullptr)\r
42       : FunctionPass(ID), DwarfPrepare(createDwarfEHPass(TM)) {}\r
43 \r
44   bool runOnFunction(Function &Fn) override;\r
45 \r
46   bool doFinalization(Module &M) override;\r
47 \r
48   void getAnalysisUsage(AnalysisUsage &AU) const override;\r
49 \r
50   const char *getPassName() const override {\r
51     return "Windows exception handling preparation";\r
52   }\r
53 \r
54 private:\r
55   bool prepareCPPEHHandlers(Function &F,\r
56                             SmallVectorImpl<LandingPadInst *> &LPads);\r
57   bool outlineCatchHandler(Function *SrcFn, Constant *SelectorType,\r
58                            LandingPadInst *LPad, StructType *EHDataStructTy);\r
59 };\r
60 \r
61 class WinEHCatchDirector : public CloningDirector {\r
62 public:\r
63   WinEHCatchDirector(LandingPadInst *LPI, Value *Selector, Value *EHObj)\r
64       : LPI(LPI), CurrentSelector(Selector->stripPointerCasts()), EHObj(EHObj),\r
65         SelectorIDType(Type::getInt32Ty(LPI->getContext())),\r
66         Int8PtrType(Type::getInt8PtrTy(LPI->getContext())) {}\r
67   virtual ~WinEHCatchDirector() {}\r
68 \r
69   CloningAction handleInstruction(ValueToValueMapTy &VMap,\r
70                                   const Instruction *Inst,\r
71                                   BasicBlock *NewBB) override;\r
72 \r
73 private:\r
74   LandingPadInst *LPI;\r
75   Value *CurrentSelector;\r
76   Value *EHObj;\r
77   Type *SelectorIDType;\r
78   Type *Int8PtrType;\r
79 \r
80   const Value *ExtractedEHPtr;\r
81   const Value *ExtractedSelector;\r
82   const Value *EHPtrStoreAddr;\r
83   const Value *SelectorStoreAddr;\r
84 };\r
85 } // end anonymous namespace\r
86 \r
87 char WinEHPrepare::ID = 0;\r
88 INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare", "Prepare Windows exceptions",\r
89                    false, false)\r
90 \r
91 FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {\r
92   return new WinEHPrepare(TM);\r
93 }\r
94 \r
95 static bool isMSVCPersonality(EHPersonality Pers) {\r
96   return Pers == EHPersonality::MSVC_Win64SEH ||\r
97          Pers == EHPersonality::MSVC_CXX;\r
98 }\r
99 \r
100 bool WinEHPrepare::runOnFunction(Function &Fn) {\r
101   SmallVector<LandingPadInst *, 4> LPads;\r
102   SmallVector<ResumeInst *, 4> Resumes;\r
103   for (BasicBlock &BB : Fn) {\r
104     if (auto *LP = BB.getLandingPadInst())\r
105       LPads.push_back(LP);\r
106     if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator()))\r
107       Resumes.push_back(Resume);\r
108   }\r
109 \r
110   // No need to prepare functions that lack landing pads.\r
111   if (LPads.empty())\r
112     return false;\r
113 \r
114   // Classify the personality to see what kind of preparation we need.\r
115   EHPersonality Pers = classifyEHPersonality(LPads.back()->getPersonalityFn());\r
116 \r
117   // Delegate through to the DWARF pass if this is unrecognized.\r
118   if (!isMSVCPersonality(Pers))\r
119     return DwarfPrepare->runOnFunction(Fn);\r
120 \r
121   // FIXME: This only returns true if the C++ EH handlers were outlined.\r
122   //        When that code is complete, it should always return whatever\r
123   //        prepareCPPEHHandlers returns.\r
124   if (Pers == EHPersonality::MSVC_CXX && prepareCPPEHHandlers(Fn, LPads))\r
125     return true;\r
126 \r
127   // FIXME: SEH Cleanups are unimplemented. Replace them with unreachable.\r
128   if (Resumes.empty())\r
129     return false;\r
130 \r
131   for (ResumeInst *Resume : Resumes) {\r
132     IRBuilder<>(Resume).CreateUnreachable();\r
133     Resume->eraseFromParent();\r
134   }\r
135 \r
136   return true;\r
137 }\r
138 \r
139 bool WinEHPrepare::doFinalization(Module &M) {\r
140   return DwarfPrepare->doFinalization(M);\r
141 }\r
142 \r
143 void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {\r
144   DwarfPrepare->getAnalysisUsage(AU);\r
145 }\r
146 \r
147 bool WinEHPrepare::prepareCPPEHHandlers(\r
148     Function &F, SmallVectorImpl<LandingPadInst *> &LPads) {\r
149   // FIXME: Find all frame variable references in the handlers\r
150   //        to populate the structure elements.\r
151   SmallVector<Type *, 2> AllocStructTys;\r
152   AllocStructTys.push_back(Type::getInt32Ty(F.getContext()));   // EH state\r
153   AllocStructTys.push_back(Type::getInt8PtrTy(F.getContext())); // EH object\r
154   StructType *EHDataStructTy =\r
155       StructType::create(F.getContext(), AllocStructTys, \r
156                          "struct." + F.getName().str() + ".ehdata");\r
157   bool HandlersOutlined = false;\r
158 \r
159   for (LandingPadInst *LPad : LPads) {\r
160     // Look for evidence that this landingpad has already been processed.\r
161     bool LPadHasActionList = false;\r
162     BasicBlock *LPadBB = LPad->getParent();\r
163     for (Instruction &Inst : LPadBB->getInstList()) {\r
164       // FIXME: Make this an intrinsic.\r
165       if (auto *Call = dyn_cast<CallInst>(&Inst))\r
166         if (Call->getCalledFunction()->getName() == "llvm.eh.actions") {\r
167           LPadHasActionList = true;\r
168           break;\r
169         }\r
170     }\r
171 \r
172     // If we've already outlined the handlers for this landingpad,\r
173     // there's nothing more to do here.\r
174     if (LPadHasActionList)\r
175       continue;\r
176 \r
177     for (unsigned Idx = 0, NumClauses = LPad->getNumClauses(); Idx < NumClauses;\r
178          ++Idx) {\r
179       if (LPad->isCatch(Idx))\r
180         HandlersOutlined =\r
181             outlineCatchHandler(&F, LPad->getClause(Idx), LPad, EHDataStructTy);\r
182     } // End for each clause\r
183   }   // End for each landingpad\r
184 \r
185   return HandlersOutlined;\r
186 }\r
187 \r
188 bool WinEHPrepare::outlineCatchHandler(Function *SrcFn, Constant *SelectorType,\r
189                                        LandingPadInst *LPad,\r
190                                        StructType *EHDataStructTy) {\r
191   Module *M = SrcFn->getParent();\r
192   LLVMContext &Context = M->getContext();\r
193 \r
194   // Create a new function to receive the handler contents.\r
195   Type *Int8PtrType = Type::getInt8PtrTy(Context);\r
196   std::vector<Type *> ArgTys;\r
197   ArgTys.push_back(Int8PtrType);\r
198   ArgTys.push_back(Int8PtrType);\r
199   FunctionType *FnType = FunctionType::get(Int8PtrType, ArgTys, false);\r
200   Function *CatchHandler = Function::Create(\r
201       FnType, GlobalVariable::ExternalLinkage, SrcFn->getName() + ".catch", M);\r
202 \r
203   // Generate a standard prolog to setup the frame recovery structure.\r
204   IRBuilder<> Builder(Context);\r
205   BasicBlock *Entry = BasicBlock::Create(Context, "catch.entry");\r
206   CatchHandler->getBasicBlockList().push_front(Entry);\r
207   Builder.SetInsertPoint(Entry);\r
208   Builder.SetCurrentDebugLocation(LPad->getDebugLoc());\r
209 \r
210   // The outlined handler will be called with the parent's frame pointer as\r
211   // its second argument. To enable the handler to access variables from\r
212   // the parent frame, we use that pointer to get locate a special block\r
213   // of memory that was allocated using llvm.eh.allocateframe for this\r
214   // purpose.  During the outlining process we will determine which frame\r
215   // variables are used in handlers and create a structure that maps these\r
216   // variables into the frame allocation block.\r
217   //\r
218   // The frame allocation block also contains an exception state variable\r
219   // used by the runtime and a pointer to the exception object pointer\r
220   // which will be filled in by the runtime for use in the handler.\r
221   Function *RecoverFrameFn =\r
222       Intrinsic::getDeclaration(M, Intrinsic::framerecover);\r
223   Value *RecoverArgs[] = {Builder.CreateBitCast(SrcFn, Int8PtrType, ""),\r
224                           &(CatchHandler->getArgumentList().back())};\r
225   CallInst *EHAlloc =\r
226       Builder.CreateCall(RecoverFrameFn, RecoverArgs, "eh.alloc");\r
227   Value *EHData =\r
228       Builder.CreateBitCast(EHAlloc, EHDataStructTy->getPointerTo(), "ehdata");\r
229   Value *EHObjPtr =\r
230       Builder.CreateConstInBoundsGEP2_32(EHData, 0, 1, "eh.obj.ptr");\r
231 \r
232   // This will give us a raw pointer to the exception object, which\r
233   // corresponds to the formal parameter of the catch statement.  If the\r
234   // handler uses this object, we will generate code during the outlining\r
235   // process to cast the pointer to the appropriate type and deference it\r
236   // as necessary.  The un-outlined landing pad code represents the\r
237   // exception object as the result of the llvm.eh.begincatch call.\r
238   Value *EHObj = Builder.CreateLoad(EHObjPtr, false, "eh.obj");\r
239 \r
240   ValueToValueMapTy VMap;\r
241 \r
242   // FIXME: Map other values referenced in the filter handler.\r
243 \r
244   WinEHCatchDirector Director(LPad, SelectorType, EHObj);\r
245 \r
246   SmallVector<ReturnInst *, 8> Returns;\r
247   ClonedCodeInfo InlinedFunctionInfo;\r
248 \r
249   BasicBlock::iterator II = LPad;\r
250 \r
251   CloneAndPruneIntoFromInst(CatchHandler, SrcFn, ++II, VMap,\r
252                             /*ModuleLevelChanges=*/false, Returns, "",\r
253                             &InlinedFunctionInfo,\r
254                             SrcFn->getParent()->getDataLayout(), &Director);\r
255 \r
256   // Move all the instructions in the first cloned block into our entry block.\r
257   BasicBlock *FirstClonedBB = std::next(Function::iterator(Entry));\r
258   Entry->getInstList().splice(Entry->end(), FirstClonedBB->getInstList());\r
259   FirstClonedBB->eraseFromParent();\r
260 \r
261   return true;\r
262 }\r
263 \r
264 CloningDirector::CloningAction WinEHCatchDirector::handleInstruction(\r
265     ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {\r
266   // Intercept instructions which extract values from the landing pad aggregate.\r
267   if (auto *Extract = dyn_cast<ExtractValueInst>(Inst)) {\r
268     if (Extract->getAggregateOperand() == LPI) {\r
269       assert(Extract->getNumIndices() == 1 &&\r
270              "Unexpected operation: extracting both landing pad values");\r
271       assert((*(Extract->idx_begin()) == 0 || *(Extract->idx_begin()) == 1) &&\r
272              "Unexpected operation: extracting an unknown landing pad element");\r
273 \r
274       if (*(Extract->idx_begin()) == 0) {\r
275         // Element 0 doesn't directly corresponds to anything in the WinEH scheme.\r
276         // It will be stored to a memory location, then later loaded and finally\r
277         // the loaded value will be used as the argument to an llvm.eh.begincatch\r
278         // call.  We're tracking it here so that we can skip the store and load.\r
279         ExtractedEHPtr = Inst;\r
280       } else {\r
281         // Element 1 corresponds to the filter selector.  We'll map it to 1 for\r
282         // matching purposes, but it will also probably be stored to memory and\r
283         // reloaded, so we need to track the instuction so that we can map the\r
284         // loaded value too.\r
285         VMap[Inst] = ConstantInt::get(SelectorIDType, 1);\r
286         ExtractedSelector = Inst;\r
287       }\r
288 \r
289       // Tell the caller not to clone this instruction.\r
290       return CloningDirector::SkipInstruction;\r
291     }\r
292     // Other extract value instructions just get cloned.\r
293     return CloningDirector::CloneInstruction;\r
294   }\r
295 \r
296   if (auto *Store = dyn_cast<StoreInst>(Inst)) {\r
297     // Look for and suppress stores of the extracted landingpad values.\r
298     const Value *StoredValue = Store->getValueOperand();\r
299     if (StoredValue == ExtractedEHPtr) {\r
300       EHPtrStoreAddr = Store->getPointerOperand();\r
301       return CloningDirector::SkipInstruction;\r
302     }\r
303     if (StoredValue == ExtractedSelector) {\r
304       SelectorStoreAddr = Store->getPointerOperand();\r
305       return CloningDirector::SkipInstruction;\r
306     }\r
307 \r
308     // Any other store just gets cloned.\r
309     return CloningDirector::CloneInstruction;\r
310   }\r
311 \r
312   if (auto *Load = dyn_cast<LoadInst>(Inst)) {\r
313     // Look for loads of (previously suppressed) landingpad values.\r
314     // The EHPtr load can be ignored (it should only be used as\r
315     // an argument to llvm.eh.begincatch), but the selector value\r
316     // needs to be mapped to a constant value of 1 to be used to\r
317     // simplify the branching to always flow to the current handler.\r
318     const Value *LoadAddr = Load->getPointerOperand();\r
319     if (LoadAddr == EHPtrStoreAddr) {\r
320       VMap[Inst] = UndefValue::get(Int8PtrType);\r
321       return CloningDirector::SkipInstruction;\r
322     }\r
323     if (LoadAddr == SelectorStoreAddr) {\r
324       VMap[Inst] = ConstantInt::get(SelectorIDType, 1);\r
325       return CloningDirector::SkipInstruction;\r
326     }\r
327 \r
328     // Any other loads just get cloned.\r
329     return CloningDirector::CloneInstruction;\r
330   }\r
331 \r
332   if (match(Inst, m_Intrinsic<Intrinsic::eh_begincatch>())) {\r
333     // The argument to the call is some form of the first element of the\r
334     // landingpad aggregate value, but that doesn't matter.  It isn't used\r
335     // here.\r
336     // The return value of this instruction, however, is used to access the\r
337     // EH object pointer.  We have generated an instruction to get that value\r
338     // from the EH alloc block, so we can just map to that here.\r
339     VMap[Inst] = EHObj;\r
340     return CloningDirector::SkipInstruction;\r
341   }\r
342   if (match(Inst, m_Intrinsic<Intrinsic::eh_endcatch>())) {\r
343     auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst);\r
344     // It might be interesting to track whether or not we are inside a catch\r
345     // function, but that might make the algorithm more brittle than it needs\r
346     // to be.\r
347 \r
348     // The end catch call can occur in one of two places: either in a\r
349     // landingpad\r
350     // block that is part of the catch handlers exception mechanism, or at the\r
351     // end of the catch block.  If it occurs in a landing pad, we must skip it\r
352     // and continue so that the landing pad gets cloned.\r
353     // FIXME: This case isn't fully supported yet and shouldn't turn up in any\r
354     //        of the test cases until it is.\r
355     if (IntrinCall->getParent()->isLandingPad())\r
356       return CloningDirector::SkipInstruction;\r
357 \r
358     // If an end catch occurs anywhere else the next instruction should be an\r
359     // unconditional branch instruction that we want to replace with a return\r
360     // to the the address of the branch target.\r
361     const BasicBlock *EndCatchBB = IntrinCall->getParent();\r
362     const TerminatorInst *Terminator = EndCatchBB->getTerminator();\r
363     const BranchInst *Branch = dyn_cast<BranchInst>(Terminator);\r
364     assert(Branch && Branch->isUnconditional());\r
365     assert(std::next(BasicBlock::const_iterator(IntrinCall)) ==\r
366             BasicBlock::const_iterator(Branch));\r
367 \r
368     ReturnInst::Create(NewBB->getContext(),\r
369                         BlockAddress::get(Branch->getSuccessor(0)), NewBB);\r
370 \r
371     // We just added a terminator to the cloned block.\r
372     // Tell the caller to stop processing the current basic block so that\r
373     // the branch instruction will be skipped.\r
374     return CloningDirector::StopCloningBB;\r
375   }\r
376   if (match(Inst, m_Intrinsic<Intrinsic::eh_typeid_for>())) {\r
377     auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst);\r
378     Value *Selector = IntrinCall->getArgOperand(0)->stripPointerCasts();\r
379     // This causes a replacement that will collapse the landing pad CFG based\r
380     // on the filter function we intend to match.\r
381     if (Selector == CurrentSelector)\r
382       VMap[Inst] = ConstantInt::get(SelectorIDType, 1);\r
383     else\r
384       VMap[Inst] = ConstantInt::get(SelectorIDType, 0);\r
385     // Tell the caller not to clone this instruction.\r
386     return CloningDirector::SkipInstruction;\r
387   }\r
388 \r
389   // Continue with the default cloning behavior.\r
390   return CloningDirector::CloneInstruction;\r
391 }\r