blob: 148c0a4217588c013234787cf558587f7225c296 [file] [log] [blame]
Andrew Kaylor1476e6d2015-02-24 20:49:35 +00001//===-- 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/TinyPtrVector.h"
20#include "llvm/Analysis/LibCallSemantics.h"
21#include "llvm/IR/Function.h"
22#include "llvm/IR/IRBuilder.h"
23#include "llvm/IR/Instructions.h"
24#include "llvm/IR/IntrinsicInst.h"
25#include "llvm/IR/Module.h"
26#include "llvm/IR/PatternMatch.h"
27#include "llvm/Pass.h"
28#include "llvm/Transforms/Utils/Cloning.h"
29#include "llvm/Transforms/Utils/Local.h"
30#include <memory>
31
32using namespace llvm;
33using namespace llvm::PatternMatch;
34
35#define DEBUG_TYPE "winehprepare"
36
37namespace {
38
39struct HandlerAllocas {
40 TinyPtrVector<AllocaInst *> Allocas;
41 int ParentFrameAllocationIndex;
42};
43
44// This map is used to model frame variable usage during outlining, to
45// construct a structure type to hold the frame variables in a frame
46// allocation block, and to remap the frame variable allocas (including
47// spill locations as needed) to GEPs that get the variable from the
48// frame allocation structure.
Andrew Kaylor72029c62015-03-03 00:41:03 +000049typedef MapVector<Value *, HandlerAllocas> FrameVarInfoMap;
Andrew Kaylor1476e6d2015-02-24 20:49:35 +000050
51class WinEHPrepare : public FunctionPass {
52 std::unique_ptr<FunctionPass> DwarfPrepare;
53
Andrew Kaylorf0f5e462015-03-03 20:00:16 +000054 enum HandlerType { Catch, Cleanup };
55
Andrew Kaylor1476e6d2015-02-24 20:49:35 +000056public:
57 static char ID; // Pass identification, replacement for typeid.
58 WinEHPrepare(const TargetMachine *TM = nullptr)
59 : FunctionPass(ID), DwarfPrepare(createDwarfEHPass(TM)) {}
60
61 bool runOnFunction(Function &Fn) override;
62
63 bool doFinalization(Module &M) override;
64
65 void getAnalysisUsage(AnalysisUsage &AU) const override;
66
67 const char *getPassName() const override {
68 return "Windows exception handling preparation";
69 }
70
71private:
72 bool prepareCPPEHHandlers(Function &F,
73 SmallVectorImpl<LandingPadInst *> &LPads);
Andrew Kaylorf0f5e462015-03-03 20:00:16 +000074 bool outlineHandler(HandlerType CatchOrCleanup, Function *SrcFn,
75 Constant *SelectorType, LandingPadInst *LPad,
Reid Kleckner42366532015-03-03 23:20:30 +000076 CallInst *&EHAlloc, FrameVarInfoMap &VarInfo);
Andrew Kaylor1476e6d2015-02-24 20:49:35 +000077};
78
79class WinEHFrameVariableMaterializer : public ValueMaterializer {
80public:
81 WinEHFrameVariableMaterializer(Function *OutlinedFn,
82 FrameVarInfoMap &FrameVarInfo);
83 ~WinEHFrameVariableMaterializer() {}
84
85 virtual Value *materializeValueFor(Value *V) override;
86
87private:
88 FrameVarInfoMap &FrameVarInfo;
89 IRBuilder<> Builder;
90};
91
Andrew Kaylorf0f5e462015-03-03 20:00:16 +000092class WinEHCloningDirectorBase : public CloningDirector {
Andrew Kaylor1476e6d2015-02-24 20:49:35 +000093public:
Andrew Kaylorf0f5e462015-03-03 20:00:16 +000094 WinEHCloningDirectorBase(LandingPadInst *LPI, Function *HandlerFn,
95 FrameVarInfoMap &VarInfo)
96 : LPI(LPI), Materializer(HandlerFn, VarInfo),
Andrew Kaylor1476e6d2015-02-24 20:49:35 +000097 SelectorIDType(Type::getInt32Ty(LPI->getContext())),
98 Int8PtrType(Type::getInt8PtrTy(LPI->getContext())) {}
99
100 CloningAction handleInstruction(ValueToValueMapTy &VMap,
101 const Instruction *Inst,
102 BasicBlock *NewBB) override;
103
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000104 virtual CloningAction handleBeginCatch(ValueToValueMapTy &VMap,
105 const Instruction *Inst,
106 BasicBlock *NewBB) = 0;
107 virtual CloningAction handleEndCatch(ValueToValueMapTy &VMap,
108 const Instruction *Inst,
109 BasicBlock *NewBB) = 0;
110 virtual CloningAction handleTypeIdFor(ValueToValueMapTy &VMap,
111 const Instruction *Inst,
112 BasicBlock *NewBB) = 0;
113 virtual CloningAction handleResume(ValueToValueMapTy &VMap,
114 const ResumeInst *Resume,
115 BasicBlock *NewBB) = 0;
116
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000117 ValueMaterializer *getValueMaterializer() override { return &Materializer; }
118
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000119protected:
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000120 LandingPadInst *LPI;
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000121 WinEHFrameVariableMaterializer Materializer;
122 Type *SelectorIDType;
123 Type *Int8PtrType;
124
125 const Value *ExtractedEHPtr;
126 const Value *ExtractedSelector;
127 const Value *EHPtrStoreAddr;
128 const Value *SelectorStoreAddr;
129};
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000130
131class WinEHCatchDirector : public WinEHCloningDirectorBase {
132public:
133 WinEHCatchDirector(LandingPadInst *LPI, Function *CatchFn, Value *Selector,
Reid Kleckner42366532015-03-03 23:20:30 +0000134 FrameVarInfoMap &VarInfo)
Andrew Kaylore07b2a02015-03-03 20:22:09 +0000135 : WinEHCloningDirectorBase(LPI, CatchFn, VarInfo),
Reid Kleckner42366532015-03-03 23:20:30 +0000136 CurrentSelector(Selector->stripPointerCasts()) {}
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000137
138 CloningAction handleBeginCatch(ValueToValueMapTy &VMap,
139 const Instruction *Inst,
140 BasicBlock *NewBB) override;
141 CloningAction handleEndCatch(ValueToValueMapTy &VMap, const Instruction *Inst,
142 BasicBlock *NewBB) override;
143 CloningAction handleTypeIdFor(ValueToValueMapTy &VMap,
144 const Instruction *Inst,
145 BasicBlock *NewBB) override;
146 CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume,
147 BasicBlock *NewBB) override;
148
149private:
150 Value *CurrentSelector;
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000151};
152
153class WinEHCleanupDirector : public WinEHCloningDirectorBase {
154public:
155 WinEHCleanupDirector(LandingPadInst *LPI, Function *CleanupFn,
156 FrameVarInfoMap &VarInfo)
157 : WinEHCloningDirectorBase(LPI, CleanupFn, VarInfo) {}
158
159 CloningAction handleBeginCatch(ValueToValueMapTy &VMap,
160 const Instruction *Inst,
161 BasicBlock *NewBB) override;
162 CloningAction handleEndCatch(ValueToValueMapTy &VMap, const Instruction *Inst,
163 BasicBlock *NewBB) override;
164 CloningAction handleTypeIdFor(ValueToValueMapTy &VMap,
165 const Instruction *Inst,
166 BasicBlock *NewBB) override;
167 CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume,
168 BasicBlock *NewBB) override;
169};
170
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000171} // end anonymous namespace
172
173char WinEHPrepare::ID = 0;
174INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare", "Prepare Windows exceptions",
175 false, false)
176
177FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
178 return new WinEHPrepare(TM);
179}
180
181static bool isMSVCPersonality(EHPersonality Pers) {
182 return Pers == EHPersonality::MSVC_Win64SEH ||
183 Pers == EHPersonality::MSVC_CXX;
184}
185
186bool WinEHPrepare::runOnFunction(Function &Fn) {
187 SmallVector<LandingPadInst *, 4> LPads;
188 SmallVector<ResumeInst *, 4> Resumes;
189 for (BasicBlock &BB : Fn) {
190 if (auto *LP = BB.getLandingPadInst())
191 LPads.push_back(LP);
192 if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator()))
193 Resumes.push_back(Resume);
194 }
195
196 // No need to prepare functions that lack landing pads.
197 if (LPads.empty())
198 return false;
199
200 // Classify the personality to see what kind of preparation we need.
201 EHPersonality Pers = classifyEHPersonality(LPads.back()->getPersonalityFn());
202
203 // Delegate through to the DWARF pass if this is unrecognized.
204 if (!isMSVCPersonality(Pers))
205 return DwarfPrepare->runOnFunction(Fn);
206
207 // FIXME: This only returns true if the C++ EH handlers were outlined.
208 // When that code is complete, it should always return whatever
209 // prepareCPPEHHandlers returns.
210 if (Pers == EHPersonality::MSVC_CXX && prepareCPPEHHandlers(Fn, LPads))
211 return true;
212
213 // FIXME: SEH Cleanups are unimplemented. Replace them with unreachable.
214 if (Resumes.empty())
215 return false;
216
217 for (ResumeInst *Resume : Resumes) {
218 IRBuilder<>(Resume).CreateUnreachable();
219 Resume->eraseFromParent();
220 }
221
222 return true;
223}
224
225bool WinEHPrepare::doFinalization(Module &M) {
226 return DwarfPrepare->doFinalization(M);
227}
228
229void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
230 DwarfPrepare->getAnalysisUsage(AU);
231}
232
233bool WinEHPrepare::prepareCPPEHHandlers(
234 Function &F, SmallVectorImpl<LandingPadInst *> &LPads) {
235 // These containers are used to re-map frame variables that are used in
236 // outlined catch and cleanup handlers. They will be populated as the
237 // handlers are outlined.
238 FrameVarInfoMap FrameVarInfo;
239 SmallVector<CallInst *, 4> HandlerAllocs;
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000240
241 bool HandlersOutlined = false;
242
243 for (LandingPadInst *LPad : LPads) {
244 // Look for evidence that this landingpad has already been processed.
245 bool LPadHasActionList = false;
246 BasicBlock *LPadBB = LPad->getParent();
247 for (Instruction &Inst : LPadBB->getInstList()) {
248 // FIXME: Make this an intrinsic.
249 if (auto *Call = dyn_cast<CallInst>(&Inst))
250 if (Call->getCalledFunction()->getName() == "llvm.eh.actions") {
251 LPadHasActionList = true;
252 break;
253 }
254 }
255
256 // If we've already outlined the handlers for this landingpad,
257 // there's nothing more to do here.
258 if (LPadHasActionList)
259 continue;
260
261 for (unsigned Idx = 0, NumClauses = LPad->getNumClauses(); Idx < NumClauses;
262 ++Idx) {
263 if (LPad->isCatch(Idx)) {
264 // Create a new instance of the handler data structure in the
265 // HandlerData vector.
266 CallInst *EHAlloc = nullptr;
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000267 bool Outlined = outlineHandler(Catch, &F, LPad->getClause(Idx), LPad,
Reid Kleckner42366532015-03-03 23:20:30 +0000268 EHAlloc, FrameVarInfo);
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000269 if (Outlined) {
270 HandlersOutlined = true;
271 // These values must be resolved after all handlers have been
272 // outlined.
273 if (EHAlloc)
274 HandlerAllocs.push_back(EHAlloc);
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000275 }
276 } // End if (isCatch)
277 } // End for each clause
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000278
279 // FIXME: This only handles the simple case where there is a 1:1
280 // correspondence between landing pad and cleanup blocks.
281 // It does not handle cases where there are catch blocks between
282 // cleanup blocks or the case where a cleanup block is shared by
283 // multiple landing pads. Those cases will be supported later
284 // when landing pad block analysis is added.
285 if (LPad->isCleanup()) {
286 CallInst *EHAlloc = nullptr;
Reid Kleckner42366532015-03-03 23:20:30 +0000287 bool Outlined =
288 outlineHandler(Cleanup, &F, nullptr, LPad, EHAlloc, FrameVarInfo);
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000289 if (Outlined) {
290 HandlersOutlined = true;
291 // This value must be resolved after all handlers have been outlined.
292 if (EHAlloc)
293 HandlerAllocs.push_back(EHAlloc);
294 }
295 }
296 } // End for each landingpad
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000297
298 // If nothing got outlined, there is no more processing to be done.
299 if (!HandlersOutlined)
300 return false;
301
302 // FIXME: We will replace the landingpad bodies with llvm.eh.actions
303 // calls and indirect branches here and then delete blocks
304 // which are no longer reachable. That will get rid of the
305 // handlers that we have outlined. There is code below
306 // that looks for allocas with no uses in the parent function.
307 // That will only happen after the pruning is implemented.
308
309 // Remap the frame variables.
310 SmallVector<Type *, 2> StructTys;
311 StructTys.push_back(Type::getInt32Ty(F.getContext())); // EH state
312 StructTys.push_back(Type::getInt8PtrTy(F.getContext())); // EH object
313
314 // Start the index at two since we always have the above fields at 0 and 1.
315 int Idx = 2;
316
317 // FIXME: Sort the FrameVarInfo vector by the ParentAlloca size and alignment
318 // and add padding as necessary to provide the proper alignment.
319
320 // Map the alloca instructions to the corresponding index in the
321 // frame allocation structure. If any alloca is used only in a single
322 // handler and is not used in the parent frame after outlining, it will
323 // be assigned an index of -1, meaning the handler can keep its
324 // "temporary" alloca and the original alloca can be erased from the
325 // parent function. If we later encounter this alloca in a second
326 // handler, we will assign it a place in the frame allocation structure
327 // at that time. Since the instruction replacement doesn't happen until
328 // all the entries in the HandlerData have been processed this isn't a
329 // problem.
330 for (auto &VarInfoEntry : FrameVarInfo) {
Andrew Kaylor72029c62015-03-03 00:41:03 +0000331 Value *ParentVal = VarInfoEntry.first;
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000332 HandlerAllocas &AllocaInfo = VarInfoEntry.second;
333
Andrew Kaylor72029c62015-03-03 00:41:03 +0000334 if (auto *ParentAlloca = dyn_cast<AllocaInst>(ParentVal)) {
335 // If the instruction still has uses in the parent function or if it is
336 // referenced by more than one handler, add it to the frame allocation
337 // structure.
338 if (ParentAlloca->getNumUses() != 0 || AllocaInfo.Allocas.size() > 1) {
339 Type *VarTy = ParentAlloca->getAllocatedType();
340 StructTys.push_back(VarTy);
341 AllocaInfo.ParentFrameAllocationIndex = Idx++;
342 } else {
343 // If the variable is not used in the parent frame and it is only used
344 // in one handler, the alloca can be removed from the parent frame
345 // and the handler will keep its "temporary" alloca to define the value.
346 // An element index of -1 is used to indicate this condition.
347 AllocaInfo.ParentFrameAllocationIndex = -1;
348 }
349 } else {
350 // FIXME: Sink non-alloca values into the handler if they have no other
351 // uses in the parent function after outlining and are only used in
352 // one handler.
353 Type *VarTy = ParentVal->getType();
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000354 StructTys.push_back(VarTy);
355 AllocaInfo.ParentFrameAllocationIndex = Idx++;
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000356 }
357 }
358
359 // Having filled the StructTys vector and assigned an index to each element,
360 // we can now create the structure.
361 StructType *EHDataStructTy = StructType::create(
362 F.getContext(), StructTys, "struct." + F.getName().str() + ".ehdata");
363 IRBuilder<> Builder(F.getParent()->getContext());
364
365 // Create a frame allocation.
366 Module *M = F.getParent();
367 LLVMContext &Context = M->getContext();
368 BasicBlock *Entry = &F.getEntryBlock();
369 Builder.SetInsertPoint(Entry->getFirstInsertionPt());
370 Function *FrameAllocFn =
371 Intrinsic::getDeclaration(M, Intrinsic::frameallocate);
372 uint64_t EHAllocSize = M->getDataLayout()->getTypeAllocSize(EHDataStructTy);
373 Value *FrameAllocArgs[] = {
374 ConstantInt::get(Type::getInt32Ty(Context), EHAllocSize)};
375 CallInst *FrameAlloc =
376 Builder.CreateCall(FrameAllocFn, FrameAllocArgs, "frame.alloc");
377
378 Value *FrameEHData = Builder.CreateBitCast(
379 FrameAlloc, EHDataStructTy->getPointerTo(), "eh.data");
380
381 // Now visit each handler that is using the structure and bitcast its EHAlloc
382 // value to be a pointer to the frame alloc structure.
383 DenseMap<Function *, Value *> EHDataMap;
384 for (CallInst *EHAlloc : HandlerAllocs) {
385 // The EHAlloc has no uses at this time, so we need to just insert the
386 // cast before the next instruction. There is always a next instruction.
387 BasicBlock::iterator II = EHAlloc;
388 ++II;
389 Builder.SetInsertPoint(cast<Instruction>(II));
390 Value *EHData = Builder.CreateBitCast(
391 EHAlloc, EHDataStructTy->getPointerTo(), "eh.data");
392 EHDataMap[EHAlloc->getParent()->getParent()] = EHData;
393 }
394
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000395 // Finally, replace all of the temporary allocas for frame variables used in
396 // the outlined handlers and the original frame allocas with GEP instructions
397 // that get the equivalent pointer from the frame allocation struct.
Andrew Kaylor72029c62015-03-03 00:41:03 +0000398 Instruction *FrameEHDataInst = cast<Instruction>(FrameEHData);
399 BasicBlock::iterator II = FrameEHDataInst;
400 ++II;
401 Instruction *AllocaInsertPt = II;
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000402 for (auto &VarInfoEntry : FrameVarInfo) {
Andrew Kaylor72029c62015-03-03 00:41:03 +0000403 Value *ParentVal = VarInfoEntry.first;
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000404 HandlerAllocas &AllocaInfo = VarInfoEntry.second;
405 int Idx = AllocaInfo.ParentFrameAllocationIndex;
406
Andrew Kaylor72029c62015-03-03 00:41:03 +0000407 // If the mapped value isn't already an alloca, we need to spill it if it
408 // is a computed value or copy it if it is an argument.
409 AllocaInst *ParentAlloca = dyn_cast<AllocaInst>(ParentVal);
410 if (!ParentAlloca) {
411 if (auto *Arg = dyn_cast<Argument>(ParentVal)) {
412 // Lower this argument to a copy and then demote that to the stack.
413 // We can't just use the argument location because the handler needs
414 // it to be in the frame allocation block.
415 // Use 'select i8 true, %arg, undef' to simulate a 'no-op' instruction.
416 Value *TrueValue = ConstantInt::getTrue(Context);
417 Value *UndefValue = UndefValue::get(Arg->getType());
418 Instruction *SI =
419 SelectInst::Create(TrueValue, Arg, UndefValue,
420 Arg->getName() + ".tmp", AllocaInsertPt);
421 Arg->replaceAllUsesWith(SI);
422 // Reset the select operand, because it was clobbered by the RAUW above.
423 SI->setOperand(1, Arg);
424 ParentAlloca = DemoteRegToStack(*SI, true, SI);
425 } else if (auto *PN = dyn_cast<PHINode>(ParentVal)) {
426 ParentAlloca = DemotePHIToStack(PN, AllocaInsertPt);
427 } else {
428 Instruction *ParentInst = cast<Instruction>(ParentVal);
429 ParentAlloca = DemoteRegToStack(*ParentInst, true, ParentInst);
430 }
431 }
432
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000433 // If we have an index of -1 for this instruction, it means it isn't used
434 // outside of this handler. In that case, we just keep the "temporary"
435 // alloca in the handler and erase the original alloca from the parent.
436 if (Idx == -1) {
437 ParentAlloca->eraseFromParent();
438 } else {
439 // Otherwise, we replace the parent alloca and all outlined allocas
440 // which map to it with GEP instructions.
441
442 // First replace the original alloca.
443 Builder.SetInsertPoint(ParentAlloca);
444 Builder.SetCurrentDebugLocation(ParentAlloca->getDebugLoc());
445 Value *ElementPtr =
446 Builder.CreateConstInBoundsGEP2_32(FrameEHData, 0, Idx);
447 ParentAlloca->replaceAllUsesWith(ElementPtr);
448 ParentAlloca->removeFromParent();
449 ElementPtr->takeName(ParentAlloca);
Andrew Kaylor72029c62015-03-03 00:41:03 +0000450 if (ParentAlloca == AllocaInsertPt)
451 AllocaInsertPt = dyn_cast<Instruction>(ElementPtr);
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000452 delete ParentAlloca;
453
454 // Next replace all outlined allocas that are mapped to it.
455 for (AllocaInst *TempAlloca : AllocaInfo.Allocas) {
456 Value *EHData = EHDataMap[TempAlloca->getParent()->getParent()];
457 // FIXME: Sink this GEP into the blocks where it is used.
458 Builder.SetInsertPoint(TempAlloca);
459 Builder.SetCurrentDebugLocation(TempAlloca->getDebugLoc());
460 ElementPtr = Builder.CreateConstInBoundsGEP2_32(EHData, 0, Idx);
461 TempAlloca->replaceAllUsesWith(ElementPtr);
462 TempAlloca->removeFromParent();
463 ElementPtr->takeName(TempAlloca);
464 delete TempAlloca;
465 }
466 } // end else of if (Idx == -1)
467 } // End for each FrameVarInfo entry.
468
469 return HandlersOutlined;
470}
471
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000472bool WinEHPrepare::outlineHandler(HandlerType CatchOrCleanup, Function *SrcFn,
473 Constant *SelectorType, LandingPadInst *LPad,
Reid Kleckner42366532015-03-03 23:20:30 +0000474 CallInst *&EHAlloc,
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000475 FrameVarInfoMap &VarInfo) {
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000476 Module *M = SrcFn->getParent();
477 LLVMContext &Context = M->getContext();
478
479 // Create a new function to receive the handler contents.
480 Type *Int8PtrType = Type::getInt8PtrTy(Context);
481 std::vector<Type *> ArgTys;
482 ArgTys.push_back(Int8PtrType);
483 ArgTys.push_back(Int8PtrType);
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000484 Function *Handler;
485 if (CatchOrCleanup == Catch) {
486 FunctionType *FnType = FunctionType::get(Int8PtrType, ArgTys, false);
487 Handler = Function::Create(FnType, GlobalVariable::InternalLinkage,
488 SrcFn->getName() + ".catch", M);
489 } else {
490 FunctionType *FnType =
491 FunctionType::get(Type::getVoidTy(Context), ArgTys, false);
492 Handler = Function::Create(FnType, GlobalVariable::InternalLinkage,
493 SrcFn->getName() + ".cleanup", M);
494 }
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000495
496 // Generate a standard prolog to setup the frame recovery structure.
497 IRBuilder<> Builder(Context);
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000498 BasicBlock *Entry = BasicBlock::Create(Context, "entry");
499 Handler->getBasicBlockList().push_front(Entry);
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000500 Builder.SetInsertPoint(Entry);
501 Builder.SetCurrentDebugLocation(LPad->getDebugLoc());
502
503 // The outlined handler will be called with the parent's frame pointer as
504 // its second argument. To enable the handler to access variables from
505 // the parent frame, we use that pointer to get locate a special block
506 // of memory that was allocated using llvm.eh.allocateframe for this
507 // purpose. During the outlining process we will determine which frame
508 // variables are used in handlers and create a structure that maps these
509 // variables into the frame allocation block.
510 //
511 // The frame allocation block also contains an exception state variable
512 // used by the runtime and a pointer to the exception object pointer
513 // which will be filled in by the runtime for use in the handler.
514 Function *RecoverFrameFn =
515 Intrinsic::getDeclaration(M, Intrinsic::framerecover);
516 Value *RecoverArgs[] = {Builder.CreateBitCast(SrcFn, Int8PtrType, ""),
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000517 &(Handler->getArgumentList().back())};
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000518 EHAlloc = Builder.CreateCall(RecoverFrameFn, RecoverArgs, "eh.alloc");
519
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000520 std::unique_ptr<WinEHCloningDirectorBase> Director;
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000521
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000522 if (CatchOrCleanup == Catch) {
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000523 Director.reset(
Reid Kleckner42366532015-03-03 23:20:30 +0000524 new WinEHCatchDirector(LPad, Handler, SelectorType, VarInfo));
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000525 } else {
526 Director.reset(new WinEHCleanupDirector(LPad, Handler, VarInfo));
527 }
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000528
529 ValueToValueMapTy VMap;
530
531 // FIXME: Map other values referenced in the filter handler.
532
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000533 SmallVector<ReturnInst *, 8> Returns;
534 ClonedCodeInfo InlinedFunctionInfo;
535
536 BasicBlock::iterator II = LPad;
537
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000538 CloneAndPruneIntoFromInst(
539 Handler, SrcFn, ++II, VMap,
540 /*ModuleLevelChanges=*/false, Returns, "", &InlinedFunctionInfo,
541 SrcFn->getParent()->getDataLayout(), Director.get());
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000542
543 // Move all the instructions in the first cloned block into our entry block.
544 BasicBlock *FirstClonedBB = std::next(Function::iterator(Entry));
545 Entry->getInstList().splice(Entry->end(), FirstClonedBB->getInstList());
546 FirstClonedBB->eraseFromParent();
547
548 return true;
549}
550
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000551CloningDirector::CloningAction WinEHCloningDirectorBase::handleInstruction(
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000552 ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {
553 // Intercept instructions which extract values from the landing pad aggregate.
554 if (auto *Extract = dyn_cast<ExtractValueInst>(Inst)) {
555 if (Extract->getAggregateOperand() == LPI) {
556 assert(Extract->getNumIndices() == 1 &&
557 "Unexpected operation: extracting both landing pad values");
558 assert((*(Extract->idx_begin()) == 0 || *(Extract->idx_begin()) == 1) &&
559 "Unexpected operation: extracting an unknown landing pad element");
560
561 if (*(Extract->idx_begin()) == 0) {
562 // Element 0 doesn't directly corresponds to anything in the WinEH
563 // scheme.
564 // It will be stored to a memory location, then later loaded and finally
565 // the loaded value will be used as the argument to an
566 // llvm.eh.begincatch
567 // call. We're tracking it here so that we can skip the store and load.
568 ExtractedEHPtr = Inst;
569 } else {
570 // Element 1 corresponds to the filter selector. We'll map it to 1 for
571 // matching purposes, but it will also probably be stored to memory and
572 // reloaded, so we need to track the instuction so that we can map the
573 // loaded value too.
574 VMap[Inst] = ConstantInt::get(SelectorIDType, 1);
575 ExtractedSelector = Inst;
576 }
577
578 // Tell the caller not to clone this instruction.
579 return CloningDirector::SkipInstruction;
580 }
581 // Other extract value instructions just get cloned.
582 return CloningDirector::CloneInstruction;
583 }
584
585 if (auto *Store = dyn_cast<StoreInst>(Inst)) {
586 // Look for and suppress stores of the extracted landingpad values.
587 const Value *StoredValue = Store->getValueOperand();
588 if (StoredValue == ExtractedEHPtr) {
589 EHPtrStoreAddr = Store->getPointerOperand();
590 return CloningDirector::SkipInstruction;
591 }
592 if (StoredValue == ExtractedSelector) {
593 SelectorStoreAddr = Store->getPointerOperand();
594 return CloningDirector::SkipInstruction;
595 }
596
597 // Any other store just gets cloned.
598 return CloningDirector::CloneInstruction;
599 }
600
601 if (auto *Load = dyn_cast<LoadInst>(Inst)) {
602 // Look for loads of (previously suppressed) landingpad values.
603 // The EHPtr load can be ignored (it should only be used as
604 // an argument to llvm.eh.begincatch), but the selector value
605 // needs to be mapped to a constant value of 1 to be used to
606 // simplify the branching to always flow to the current handler.
607 const Value *LoadAddr = Load->getPointerOperand();
608 if (LoadAddr == EHPtrStoreAddr) {
609 VMap[Inst] = UndefValue::get(Int8PtrType);
610 return CloningDirector::SkipInstruction;
611 }
612 if (LoadAddr == SelectorStoreAddr) {
613 VMap[Inst] = ConstantInt::get(SelectorIDType, 1);
614 return CloningDirector::SkipInstruction;
615 }
616
617 // Any other loads just get cloned.
618 return CloningDirector::CloneInstruction;
619 }
620
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000621 if (auto *Resume = dyn_cast<ResumeInst>(Inst))
622 return handleResume(VMap, Resume, NewBB);
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000623
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000624 if (match(Inst, m_Intrinsic<Intrinsic::eh_begincatch>()))
625 return handleBeginCatch(VMap, Inst, NewBB);
626 if (match(Inst, m_Intrinsic<Intrinsic::eh_endcatch>()))
627 return handleEndCatch(VMap, Inst, NewBB);
628 if (match(Inst, m_Intrinsic<Intrinsic::eh_typeid_for>()))
629 return handleTypeIdFor(VMap, Inst, NewBB);
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000630
631 // Continue with the default cloning behavior.
632 return CloningDirector::CloneInstruction;
633}
634
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000635CloningDirector::CloningAction WinEHCatchDirector::handleBeginCatch(
636 ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {
637 // The argument to the call is some form of the first element of the
638 // landingpad aggregate value, but that doesn't matter. It isn't used
639 // here.
Reid Kleckner42366532015-03-03 23:20:30 +0000640 // The second argument is an outparameter where the exception object will be
641 // stored. Typically the exception object is a scalar, but it can be an
642 // aggregate when catching by value.
643 // FIXME: Leave something behind to indicate where the exception object lives
644 // for this handler. Should it be part of llvm.eh.actions?
Andrew Kaylorf0f5e462015-03-03 20:00:16 +0000645 return CloningDirector::SkipInstruction;
646}
647
648CloningDirector::CloningAction
649WinEHCatchDirector::handleEndCatch(ValueToValueMapTy &VMap,
650 const Instruction *Inst, BasicBlock *NewBB) {
651 auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst);
652 // It might be interesting to track whether or not we are inside a catch
653 // function, but that might make the algorithm more brittle than it needs
654 // to be.
655
656 // The end catch call can occur in one of two places: either in a
657 // landingpad
658 // block that is part of the catch handlers exception mechanism, or at the
659 // end of the catch block. If it occurs in a landing pad, we must skip it
660 // and continue so that the landing pad gets cloned.
661 // FIXME: This case isn't fully supported yet and shouldn't turn up in any
662 // of the test cases until it is.
663 if (IntrinCall->getParent()->isLandingPad())
664 return CloningDirector::SkipInstruction;
665
666 // If an end catch occurs anywhere else the next instruction should be an
667 // unconditional branch instruction that we want to replace with a return
668 // to the the address of the branch target.
669 const BasicBlock *EndCatchBB = IntrinCall->getParent();
670 const TerminatorInst *Terminator = EndCatchBB->getTerminator();
671 const BranchInst *Branch = dyn_cast<BranchInst>(Terminator);
672 assert(Branch && Branch->isUnconditional());
673 assert(std::next(BasicBlock::const_iterator(IntrinCall)) ==
674 BasicBlock::const_iterator(Branch));
675
676 ReturnInst::Create(NewBB->getContext(),
677 BlockAddress::get(Branch->getSuccessor(0)), NewBB);
678
679 // We just added a terminator to the cloned block.
680 // Tell the caller to stop processing the current basic block so that
681 // the branch instruction will be skipped.
682 return CloningDirector::StopCloningBB;
683}
684
685CloningDirector::CloningAction WinEHCatchDirector::handleTypeIdFor(
686 ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {
687 auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst);
688 Value *Selector = IntrinCall->getArgOperand(0)->stripPointerCasts();
689 // This causes a replacement that will collapse the landing pad CFG based
690 // on the filter function we intend to match.
691 if (Selector == CurrentSelector)
692 VMap[Inst] = ConstantInt::get(SelectorIDType, 1);
693 else
694 VMap[Inst] = ConstantInt::get(SelectorIDType, 0);
695 // Tell the caller not to clone this instruction.
696 return CloningDirector::SkipInstruction;
697}
698
699CloningDirector::CloningAction
700WinEHCatchDirector::handleResume(ValueToValueMapTy &VMap,
701 const ResumeInst *Resume, BasicBlock *NewBB) {
702 // Resume instructions shouldn't be reachable from catch handlers.
703 // We still need to handle it, but it will be pruned.
704 BasicBlock::InstListType &InstList = NewBB->getInstList();
705 InstList.push_back(new UnreachableInst(NewBB->getContext()));
706 return CloningDirector::StopCloningBB;
707}
708
709CloningDirector::CloningAction WinEHCleanupDirector::handleBeginCatch(
710 ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {
711 // Catch blocks within cleanup handlers will always be unreachable.
712 // We'll insert an unreachable instruction now, but it will be pruned
713 // before the cloning process is complete.
714 BasicBlock::InstListType &InstList = NewBB->getInstList();
715 InstList.push_back(new UnreachableInst(NewBB->getContext()));
716 return CloningDirector::StopCloningBB;
717}
718
719CloningDirector::CloningAction WinEHCleanupDirector::handleEndCatch(
720 ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {
721 // Catch blocks within cleanup handlers will always be unreachable.
722 // We'll insert an unreachable instruction now, but it will be pruned
723 // before the cloning process is complete.
724 BasicBlock::InstListType &InstList = NewBB->getInstList();
725 InstList.push_back(new UnreachableInst(NewBB->getContext()));
726 return CloningDirector::StopCloningBB;
727}
728
729CloningDirector::CloningAction WinEHCleanupDirector::handleTypeIdFor(
730 ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) {
731 // This causes a replacement that will collapse the landing pad CFG
732 // to just the cleanup code.
733 VMap[Inst] = ConstantInt::get(SelectorIDType, 0);
734 // Tell the caller not to clone this instruction.
735 return CloningDirector::SkipInstruction;
736}
737
738CloningDirector::CloningAction WinEHCleanupDirector::handleResume(
739 ValueToValueMapTy &VMap, const ResumeInst *Resume, BasicBlock *NewBB) {
740 ReturnInst::Create(NewBB->getContext(), nullptr, NewBB);
741
742 // We just added a terminator to the cloned block.
743 // Tell the caller to stop processing the current basic block so that
744 // the branch instruction will be skipped.
745 return CloningDirector::StopCloningBB;
746}
747
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000748WinEHFrameVariableMaterializer::WinEHFrameVariableMaterializer(
749 Function *OutlinedFn, FrameVarInfoMap &FrameVarInfo)
750 : FrameVarInfo(FrameVarInfo), Builder(OutlinedFn->getContext()) {
751 Builder.SetInsertPoint(&OutlinedFn->getEntryBlock());
752 // FIXME: Do something with the FrameVarMapped so that it is shared across the
753 // function.
754}
755
756Value *WinEHFrameVariableMaterializer::materializeValueFor(Value *V) {
Andrew Kaylor72029c62015-03-03 00:41:03 +0000757 // If we're asked to materialize a value that is an instruction, we
758 // temporarily create an alloca in the outlined function and add this
759 // to the FrameVarInfo map. When all the outlining is complete, we'll
760 // collect these into a structure, spilling non-alloca values in the
761 // parent frame as necessary, and replace these temporary allocas with
762 // GEPs referencing the frame allocation block.
763
764 // If the value is an alloca, the mapping is direct.
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000765 if (auto *AV = dyn_cast<AllocaInst>(V)) {
Andrew Kaylor72029c62015-03-03 00:41:03 +0000766 AllocaInst *NewAlloca = dyn_cast<AllocaInst>(AV->clone());
767 Builder.Insert(NewAlloca, AV->getName());
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000768 FrameVarInfo[AV].Allocas.push_back(NewAlloca);
769 return NewAlloca;
770 }
771
Andrew Kaylor72029c62015-03-03 00:41:03 +0000772 // For other types of instructions or arguments, we need an alloca based on
773 // the value's type and a load of the alloca. The alloca will be replaced
774 // by a GEP, but the load will stay. In the parent function, the value will
775 // be spilled to a location in the frame allocation block.
776 if (isa<Instruction>(V) || isa<Argument>(V)) {
777 AllocaInst *NewAlloca =
778 Builder.CreateAlloca(V->getType(), nullptr, "eh.temp.alloca");
779 FrameVarInfo[V].Allocas.push_back(NewAlloca);
780 LoadInst *NewLoad = Builder.CreateLoad(NewAlloca, V->getName() + ".reload");
781 return NewLoad;
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000782 }
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000783
Andrew Kaylor72029c62015-03-03 00:41:03 +0000784 // Don't materialize other values.
Andrew Kaylor1476e6d2015-02-24 20:49:35 +0000785 return nullptr;
786}