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