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<AllocaInst *, HandlerAllocas> FrameVarInfoMap; 50 51 class WinEHPrepare : public FunctionPass { 52 std::unique_ptr<FunctionPass> DwarfPrepare; 53 54 public: 55 static char ID; // Pass identification, replacement for typeid. 56 WinEHPrepare(const TargetMachine *TM = nullptr) 57 : FunctionPass(ID), DwarfPrepare(createDwarfEHPass(TM)) {} 58 59 bool runOnFunction(Function &Fn) override; 60 61 bool doFinalization(Module &M) override; 62 63 void getAnalysisUsage(AnalysisUsage &AU) const override; 64 65 const char *getPassName() const override { 66 return "Windows exception handling preparation"; 67 } 68 69 private: 70 bool prepareCPPEHHandlers(Function &F, 71 SmallVectorImpl<LandingPadInst *> &LPads); 72 bool outlineCatchHandler(Function *SrcFn, Constant *SelectorType, 73 LandingPadInst *LPad, CallInst *&EHAlloc, 74 AllocaInst *&EHObjPtr, FrameVarInfoMap &VarInfo); 75 }; 76 77 class WinEHFrameVariableMaterializer : public ValueMaterializer { 78 public: 79 WinEHFrameVariableMaterializer(Function *OutlinedFn, 80 FrameVarInfoMap &FrameVarInfo); 81 ~WinEHFrameVariableMaterializer() {} 82 83 virtual Value *materializeValueFor(Value *V) override; 84 85 private: 86 FrameVarInfoMap &FrameVarInfo; 87 IRBuilder<> Builder; 88 }; 89 90 class WinEHCatchDirector : public CloningDirector { 91 public: 92 WinEHCatchDirector(LandingPadInst *LPI, Function *CatchFn, Value *Selector, 93 Value *EHObj, FrameVarInfoMap &VarInfo) 94 : LPI(LPI), CurrentSelector(Selector->stripPointerCasts()), EHObj(EHObj), 95 Materializer(CatchFn, VarInfo), 96 SelectorIDType(Type::getInt32Ty(LPI->getContext())), 97 Int8PtrType(Type::getInt8PtrTy(LPI->getContext())) {} 98 99 CloningAction handleInstruction(ValueToValueMapTy &VMap, 100 const Instruction *Inst, 101 BasicBlock *NewBB) override; 102 103 ValueMaterializer *getValueMaterializer() override { return &Materializer; } 104 105 private: 106 LandingPadInst *LPI; 107 Value *CurrentSelector; 108 Value *EHObj; 109 WinEHFrameVariableMaterializer Materializer; 110 Type *SelectorIDType; 111 Type *Int8PtrType; 112 113 const Value *ExtractedEHPtr; 114 const Value *ExtractedSelector; 115 const Value *EHPtrStoreAddr; 116 const Value *SelectorStoreAddr; 117 }; 118 } // end anonymous namespace 119 120 char WinEHPrepare::ID = 0; 121 INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare", "Prepare Windows exceptions", 122 false, false) 123 124 FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) { 125 return new WinEHPrepare(TM); 126 } 127 128 static bool isMSVCPersonality(EHPersonality Pers) { 129 return Pers == EHPersonality::MSVC_Win64SEH || 130 Pers == EHPersonality::MSVC_CXX; 131 } 132 133 bool WinEHPrepare::runOnFunction(Function &Fn) { 134 SmallVector<LandingPadInst *, 4> LPads; 135 SmallVector<ResumeInst *, 4> Resumes; 136 for (BasicBlock &BB : Fn) { 137 if (auto *LP = BB.getLandingPadInst()) 138 LPads.push_back(LP); 139 if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator())) 140 Resumes.push_back(Resume); 141 } 142 143 // No need to prepare functions that lack landing pads. 144 if (LPads.empty()) 145 return false; 146 147 // Classify the personality to see what kind of preparation we need. 148 EHPersonality Pers = classifyEHPersonality(LPads.back()->getPersonalityFn()); 149 150 // Delegate through to the DWARF pass if this is unrecognized. 151 if (!isMSVCPersonality(Pers)) 152 return DwarfPrepare->runOnFunction(Fn); 153 154 // FIXME: This only returns true if the C++ EH handlers were outlined. 155 // When that code is complete, it should always return whatever 156 // prepareCPPEHHandlers returns. 157 if (Pers == EHPersonality::MSVC_CXX && prepareCPPEHHandlers(Fn, LPads)) 158 return true; 159 160 // FIXME: SEH Cleanups are unimplemented. Replace them with unreachable. 161 if (Resumes.empty()) 162 return false; 163 164 for (ResumeInst *Resume : Resumes) { 165 IRBuilder<>(Resume).CreateUnreachable(); 166 Resume->eraseFromParent(); 167 } 168 169 return true; 170 } 171 172 bool WinEHPrepare::doFinalization(Module &M) { 173 return DwarfPrepare->doFinalization(M); 174 } 175 176 void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const { 177 DwarfPrepare->getAnalysisUsage(AU); 178 } 179 180 bool WinEHPrepare::prepareCPPEHHandlers( 181 Function &F, SmallVectorImpl<LandingPadInst *> &LPads) { 182 // These containers are used to re-map frame variables that are used in 183 // outlined catch and cleanup handlers. They will be populated as the 184 // handlers are outlined. 185 FrameVarInfoMap FrameVarInfo; 186 SmallVector<CallInst *, 4> HandlerAllocs; 187 SmallVector<AllocaInst *, 4> HandlerEHObjPtrs; 188 189 bool HandlersOutlined = false; 190 191 for (LandingPadInst *LPad : LPads) { 192 // Look for evidence that this landingpad has already been processed. 193 bool LPadHasActionList = false; 194 BasicBlock *LPadBB = LPad->getParent(); 195 for (Instruction &Inst : LPadBB->getInstList()) { 196 // FIXME: Make this an intrinsic. 197 if (auto *Call = dyn_cast<CallInst>(&Inst)) 198 if (Call->getCalledFunction()->getName() == "llvm.eh.actions") { 199 LPadHasActionList = true; 200 break; 201 } 202 } 203 204 // If we've already outlined the handlers for this landingpad, 205 // there's nothing more to do here. 206 if (LPadHasActionList) 207 continue; 208 209 for (unsigned Idx = 0, NumClauses = LPad->getNumClauses(); Idx < NumClauses; 210 ++Idx) { 211 if (LPad->isCatch(Idx)) { 212 // Create a new instance of the handler data structure in the 213 // HandlerData vector. 214 CallInst *EHAlloc = nullptr; 215 AllocaInst *EHObjPtr = nullptr; 216 bool Outlined = outlineCatchHandler(&F, LPad->getClause(Idx), LPad, 217 EHAlloc, EHObjPtr, FrameVarInfo); 218 if (Outlined) { 219 HandlersOutlined = true; 220 // These values must be resolved after all handlers have been 221 // outlined. 222 if (EHAlloc) 223 HandlerAllocs.push_back(EHAlloc); 224 if (EHObjPtr) 225 HandlerEHObjPtrs.push_back(EHObjPtr); 226 } 227 } // End if (isCatch) 228 } // End for each clause 229 } // End for each landingpad 230 231 // If nothing got outlined, there is no more processing to be done. 232 if (!HandlersOutlined) 233 return false; 234 235 // FIXME: We will replace the landingpad bodies with llvm.eh.actions 236 // calls and indirect branches here and then delete blocks 237 // which are no longer reachable. That will get rid of the 238 // handlers that we have outlined. There is code below 239 // that looks for allocas with no uses in the parent function. 240 // That will only happen after the pruning is implemented. 241 242 // Remap the frame variables. 243 SmallVector<Type *, 2> StructTys; 244 StructTys.push_back(Type::getInt32Ty(F.getContext())); // EH state 245 StructTys.push_back(Type::getInt8PtrTy(F.getContext())); // EH object 246 247 // Start the index at two since we always have the above fields at 0 and 1. 248 int Idx = 2; 249 250 // FIXME: Sort the FrameVarInfo vector by the ParentAlloca size and alignment 251 // and add padding as necessary to provide the proper alignment. 252 253 // Map the alloca instructions to the corresponding index in the 254 // frame allocation structure. If any alloca is used only in a single 255 // handler and is not used in the parent frame after outlining, it will 256 // be assigned an index of -1, meaning the handler can keep its 257 // "temporary" alloca and the original alloca can be erased from the 258 // parent function. If we later encounter this alloca in a second 259 // handler, we will assign it a place in the frame allocation structure 260 // at that time. Since the instruction replacement doesn't happen until 261 // all the entries in the HandlerData have been processed this isn't a 262 // problem. 263 for (auto &VarInfoEntry : FrameVarInfo) { 264 AllocaInst *ParentAlloca = VarInfoEntry.first; 265 HandlerAllocas &AllocaInfo = VarInfoEntry.second; 266 267 // If the instruction still has uses in the parent function or if it is 268 // referenced by more than one handler, add it to the frame allocation 269 // structure. 270 if (ParentAlloca->getNumUses() != 0 || AllocaInfo.Allocas.size() > 1) { 271 Type *VarTy = ParentAlloca->getAllocatedType(); 272 StructTys.push_back(VarTy); 273 AllocaInfo.ParentFrameAllocationIndex = Idx++; 274 } else { 275 // If the variable is not used in the parent frame and it is only used 276 // in one handler, the alloca can be removed from the parent frame 277 // and the handler will keep its "temporary" alloca to define the value. 278 // An element index of -1 is used to indicate this condition. 279 AllocaInfo.ParentFrameAllocationIndex = -1; 280 } 281 } 282 283 // Having filled the StructTys vector and assigned an index to each element, 284 // we can now create the structure. 285 StructType *EHDataStructTy = StructType::create( 286 F.getContext(), StructTys, "struct." + F.getName().str() + ".ehdata"); 287 IRBuilder<> Builder(F.getParent()->getContext()); 288 289 // Create a frame allocation. 290 Module *M = F.getParent(); 291 LLVMContext &Context = M->getContext(); 292 BasicBlock *Entry = &F.getEntryBlock(); 293 Builder.SetInsertPoint(Entry->getFirstInsertionPt()); 294 Function *FrameAllocFn = 295 Intrinsic::getDeclaration(M, Intrinsic::frameallocate); 296 uint64_t EHAllocSize = M->getDataLayout()->getTypeAllocSize(EHDataStructTy); 297 Value *FrameAllocArgs[] = { 298 ConstantInt::get(Type::getInt32Ty(Context), EHAllocSize)}; 299 CallInst *FrameAlloc = 300 Builder.CreateCall(FrameAllocFn, FrameAllocArgs, "frame.alloc"); 301 302 Value *FrameEHData = Builder.CreateBitCast( 303 FrameAlloc, EHDataStructTy->getPointerTo(), "eh.data"); 304 305 // Now visit each handler that is using the structure and bitcast its EHAlloc 306 // value to be a pointer to the frame alloc structure. 307 DenseMap<Function *, Value *> EHDataMap; 308 for (CallInst *EHAlloc : HandlerAllocs) { 309 // The EHAlloc has no uses at this time, so we need to just insert the 310 // cast before the next instruction. There is always a next instruction. 311 BasicBlock::iterator II = EHAlloc; 312 ++II; 313 Builder.SetInsertPoint(cast<Instruction>(II)); 314 Value *EHData = Builder.CreateBitCast( 315 EHAlloc, EHDataStructTy->getPointerTo(), "eh.data"); 316 EHDataMap[EHAlloc->getParent()->getParent()] = EHData; 317 } 318 319 // Next, replace the place-holder EHObjPtr allocas with GEP instructions 320 // that pull the EHObjPtr from the frame alloc structure 321 for (AllocaInst *EHObjPtr : HandlerEHObjPtrs) { 322 Value *EHData = EHDataMap[EHObjPtr->getParent()->getParent()]; 323 Value *ElementPtr = Builder.CreateConstInBoundsGEP2_32(EHData, 0, 1); 324 EHObjPtr->replaceAllUsesWith(ElementPtr); 325 EHObjPtr->removeFromParent(); 326 ElementPtr->takeName(EHObjPtr); 327 delete EHObjPtr; 328 } 329 330 // Finally, replace all of the temporary allocas for frame variables used in 331 // the outlined handlers and the original frame allocas with GEP instructions 332 // that get the equivalent pointer from the frame allocation struct. 333 for (auto &VarInfoEntry : FrameVarInfo) { 334 AllocaInst *ParentAlloca = VarInfoEntry.first; 335 HandlerAllocas &AllocaInfo = VarInfoEntry.second; 336 int Idx = AllocaInfo.ParentFrameAllocationIndex; 337 338 // If we have an index of -1 for this instruction, it means it isn't used 339 // outside of this handler. In that case, we just keep the "temporary" 340 // alloca in the handler and erase the original alloca from the parent. 341 if (Idx == -1) { 342 ParentAlloca->eraseFromParent(); 343 } else { 344 // Otherwise, we replace the parent alloca and all outlined allocas 345 // which map to it with GEP instructions. 346 347 // First replace the original alloca. 348 Builder.SetInsertPoint(ParentAlloca); 349 Builder.SetCurrentDebugLocation(ParentAlloca->getDebugLoc()); 350 Value *ElementPtr = 351 Builder.CreateConstInBoundsGEP2_32(FrameEHData, 0, Idx); 352 ParentAlloca->replaceAllUsesWith(ElementPtr); 353 ParentAlloca->removeFromParent(); 354 ElementPtr->takeName(ParentAlloca); 355 delete ParentAlloca; 356 357 // Next replace all outlined allocas that are mapped to it. 358 for (AllocaInst *TempAlloca : AllocaInfo.Allocas) { 359 Value *EHData = EHDataMap[TempAlloca->getParent()->getParent()]; 360 // FIXME: Sink this GEP into the blocks where it is used. 361 Builder.SetInsertPoint(TempAlloca); 362 Builder.SetCurrentDebugLocation(TempAlloca->getDebugLoc()); 363 ElementPtr = Builder.CreateConstInBoundsGEP2_32(EHData, 0, Idx); 364 TempAlloca->replaceAllUsesWith(ElementPtr); 365 TempAlloca->removeFromParent(); 366 ElementPtr->takeName(TempAlloca); 367 delete TempAlloca; 368 } 369 } // end else of if (Idx == -1) 370 } // End for each FrameVarInfo entry. 371 372 return HandlersOutlined; 373 } 374 375 bool WinEHPrepare::outlineCatchHandler(Function *SrcFn, Constant *SelectorType, 376 LandingPadInst *LPad, CallInst *&EHAlloc, 377 AllocaInst *&EHObjPtr, 378 FrameVarInfoMap &VarInfo) { 379 Module *M = SrcFn->getParent(); 380 LLVMContext &Context = M->getContext(); 381 382 // Create a new function to receive the handler contents. 383 Type *Int8PtrType = Type::getInt8PtrTy(Context); 384 std::vector<Type *> ArgTys; 385 ArgTys.push_back(Int8PtrType); 386 ArgTys.push_back(Int8PtrType); 387 FunctionType *FnType = FunctionType::get(Int8PtrType, ArgTys, false); 388 Function *CatchHandler = Function::Create( 389 FnType, GlobalVariable::ExternalLinkage, SrcFn->getName() + ".catch", M); 390 391 // Generate a standard prolog to setup the frame recovery structure. 392 IRBuilder<> Builder(Context); 393 BasicBlock *Entry = BasicBlock::Create(Context, "catch.entry"); 394 CatchHandler->getBasicBlockList().push_front(Entry); 395 Builder.SetInsertPoint(Entry); 396 Builder.SetCurrentDebugLocation(LPad->getDebugLoc()); 397 398 // The outlined handler will be called with the parent's frame pointer as 399 // its second argument. To enable the handler to access variables from 400 // the parent frame, we use that pointer to get locate a special block 401 // of memory that was allocated using llvm.eh.allocateframe for this 402 // purpose. During the outlining process we will determine which frame 403 // variables are used in handlers and create a structure that maps these 404 // variables into the frame allocation block. 405 // 406 // The frame allocation block also contains an exception state variable 407 // used by the runtime and a pointer to the exception object pointer 408 // which will be filled in by the runtime for use in the handler. 409 Function *RecoverFrameFn = 410 Intrinsic::getDeclaration(M, Intrinsic::framerecover); 411 Value *RecoverArgs[] = {Builder.CreateBitCast(SrcFn, Int8PtrType, ""), 412 &(CatchHandler->getArgumentList().back())}; 413 EHAlloc = Builder.CreateCall(RecoverFrameFn, RecoverArgs, "eh.alloc"); 414 415 // This alloca is only temporary. We'll be replacing it once we know all the 416 // frame variables that need to go in the frame allocation structure. 417 EHObjPtr = Builder.CreateAlloca(Int8PtrType, 0, "eh.obj.ptr"); 418 419 // This will give us a raw pointer to the exception object, which 420 // corresponds to the formal parameter of the catch statement. If the 421 // handler uses this object, we will generate code during the outlining 422 // process to cast the pointer to the appropriate type and deference it 423 // as necessary. The un-outlined landing pad code represents the 424 // exception object as the result of the llvm.eh.begincatch call. 425 Value *EHObj = Builder.CreateLoad(EHObjPtr, false, "eh.obj"); 426 427 ValueToValueMapTy VMap; 428 429 // FIXME: Map other values referenced in the filter handler. 430 431 WinEHCatchDirector Director(LPad, CatchHandler, SelectorType, EHObj, VarInfo); 432 433 SmallVector<ReturnInst *, 8> Returns; 434 ClonedCodeInfo InlinedFunctionInfo; 435 436 BasicBlock::iterator II = LPad; 437 438 CloneAndPruneIntoFromInst(CatchHandler, SrcFn, ++II, VMap, 439 /*ModuleLevelChanges=*/false, Returns, "", 440 &InlinedFunctionInfo, 441 SrcFn->getParent()->getDataLayout(), &Director); 442 443 // Move all the instructions in the first cloned block into our entry block. 444 BasicBlock *FirstClonedBB = std::next(Function::iterator(Entry)); 445 Entry->getInstList().splice(Entry->end(), FirstClonedBB->getInstList()); 446 FirstClonedBB->eraseFromParent(); 447 448 return true; 449 } 450 451 CloningDirector::CloningAction WinEHCatchDirector::handleInstruction( 452 ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { 453 // Intercept instructions which extract values from the landing pad aggregate. 454 if (auto *Extract = dyn_cast<ExtractValueInst>(Inst)) { 455 if (Extract->getAggregateOperand() == LPI) { 456 assert(Extract->getNumIndices() == 1 && 457 "Unexpected operation: extracting both landing pad values"); 458 assert((*(Extract->idx_begin()) == 0 || *(Extract->idx_begin()) == 1) && 459 "Unexpected operation: extracting an unknown landing pad element"); 460 461 if (*(Extract->idx_begin()) == 0) { 462 // Element 0 doesn't directly corresponds to anything in the WinEH 463 // scheme. 464 // It will be stored to a memory location, then later loaded and finally 465 // the loaded value will be used as the argument to an 466 // llvm.eh.begincatch 467 // call. We're tracking it here so that we can skip the store and load. 468 ExtractedEHPtr = Inst; 469 } else { 470 // Element 1 corresponds to the filter selector. We'll map it to 1 for 471 // matching purposes, but it will also probably be stored to memory and 472 // reloaded, so we need to track the instuction so that we can map the 473 // loaded value too. 474 VMap[Inst] = ConstantInt::get(SelectorIDType, 1); 475 ExtractedSelector = Inst; 476 } 477 478 // Tell the caller not to clone this instruction. 479 return CloningDirector::SkipInstruction; 480 } 481 // Other extract value instructions just get cloned. 482 return CloningDirector::CloneInstruction; 483 } 484 485 if (auto *Store = dyn_cast<StoreInst>(Inst)) { 486 // Look for and suppress stores of the extracted landingpad values. 487 const Value *StoredValue = Store->getValueOperand(); 488 if (StoredValue == ExtractedEHPtr) { 489 EHPtrStoreAddr = Store->getPointerOperand(); 490 return CloningDirector::SkipInstruction; 491 } 492 if (StoredValue == ExtractedSelector) { 493 SelectorStoreAddr = Store->getPointerOperand(); 494 return CloningDirector::SkipInstruction; 495 } 496 497 // Any other store just gets cloned. 498 return CloningDirector::CloneInstruction; 499 } 500 501 if (auto *Load = dyn_cast<LoadInst>(Inst)) { 502 // Look for loads of (previously suppressed) landingpad values. 503 // The EHPtr load can be ignored (it should only be used as 504 // an argument to llvm.eh.begincatch), but the selector value 505 // needs to be mapped to a constant value of 1 to be used to 506 // simplify the branching to always flow to the current handler. 507 const Value *LoadAddr = Load->getPointerOperand(); 508 if (LoadAddr == EHPtrStoreAddr) { 509 VMap[Inst] = UndefValue::get(Int8PtrType); 510 return CloningDirector::SkipInstruction; 511 } 512 if (LoadAddr == SelectorStoreAddr) { 513 VMap[Inst] = ConstantInt::get(SelectorIDType, 1); 514 return CloningDirector::SkipInstruction; 515 } 516 517 // Any other loads just get cloned. 518 return CloningDirector::CloneInstruction; 519 } 520 521 if (match(Inst, m_Intrinsic<Intrinsic::eh_begincatch>())) { 522 // The argument to the call is some form of the first element of the 523 // landingpad aggregate value, but that doesn't matter. It isn't used 524 // here. 525 // The return value of this instruction, however, is used to access the 526 // EH object pointer. We have generated an instruction to get that value 527 // from the EH alloc block, so we can just map to that here. 528 VMap[Inst] = EHObj; 529 return CloningDirector::SkipInstruction; 530 } 531 if (match(Inst, m_Intrinsic<Intrinsic::eh_endcatch>())) { 532 auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst); 533 // It might be interesting to track whether or not we are inside a catch 534 // function, but that might make the algorithm more brittle than it needs 535 // to be. 536 537 // The end catch call can occur in one of two places: either in a 538 // landingpad 539 // block that is part of the catch handlers exception mechanism, or at the 540 // end of the catch block. If it occurs in a landing pad, we must skip it 541 // and continue so that the landing pad gets cloned. 542 // FIXME: This case isn't fully supported yet and shouldn't turn up in any 543 // of the test cases until it is. 544 if (IntrinCall->getParent()->isLandingPad()) 545 return CloningDirector::SkipInstruction; 546 547 // If an end catch occurs anywhere else the next instruction should be an 548 // unconditional branch instruction that we want to replace with a return 549 // to the the address of the branch target. 550 const BasicBlock *EndCatchBB = IntrinCall->getParent(); 551 const TerminatorInst *Terminator = EndCatchBB->getTerminator(); 552 const BranchInst *Branch = dyn_cast<BranchInst>(Terminator); 553 assert(Branch && Branch->isUnconditional()); 554 assert(std::next(BasicBlock::const_iterator(IntrinCall)) == 555 BasicBlock::const_iterator(Branch)); 556 557 ReturnInst::Create(NewBB->getContext(), 558 BlockAddress::get(Branch->getSuccessor(0)), NewBB); 559 560 // We just added a terminator to the cloned block. 561 // Tell the caller to stop processing the current basic block so that 562 // the branch instruction will be skipped. 563 return CloningDirector::StopCloningBB; 564 } 565 if (match(Inst, m_Intrinsic<Intrinsic::eh_typeid_for>())) { 566 auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst); 567 Value *Selector = IntrinCall->getArgOperand(0)->stripPointerCasts(); 568 // This causes a replacement that will collapse the landing pad CFG based 569 // on the filter function we intend to match. 570 if (Selector == CurrentSelector) 571 VMap[Inst] = ConstantInt::get(SelectorIDType, 1); 572 else 573 VMap[Inst] = ConstantInt::get(SelectorIDType, 0); 574 // Tell the caller not to clone this instruction. 575 return CloningDirector::SkipInstruction; 576 } 577 578 // Continue with the default cloning behavior. 579 return CloningDirector::CloneInstruction; 580 } 581 582 WinEHFrameVariableMaterializer::WinEHFrameVariableMaterializer( 583 Function *OutlinedFn, FrameVarInfoMap &FrameVarInfo) 584 : FrameVarInfo(FrameVarInfo), Builder(OutlinedFn->getContext()) { 585 Builder.SetInsertPoint(&OutlinedFn->getEntryBlock()); 586 // FIXME: Do something with the FrameVarMapped so that it is shared across the 587 // function. 588 } 589 590 Value *WinEHFrameVariableMaterializer::materializeValueFor(Value *V) { 591 // If we're asked to materialize an alloca variable, we temporarily 592 // create a matching alloca in the outlined function. When all the 593 // outlining is complete, we'll collect these into a structure and 594 // replace these temporary allocas with GEPs referencing the frame 595 // allocation block. 596 if (auto *AV = dyn_cast<AllocaInst>(V)) { 597 AllocaInst *NewAlloca = Builder.CreateAlloca( 598 AV->getAllocatedType(), AV->getArraySize(), AV->getName()); 599 FrameVarInfo[AV].Allocas.push_back(NewAlloca); 600 return NewAlloca; 601 } 602 603 // FIXME: Do PHI nodes need special handling? 604 605 // FIXME: Are there other cases we can handle better? GEP, ExtractValue, etc. 606 607 // FIXME: This doesn't work during cloning because it finds an instruction 608 // in the use list that isn't yet part of a basic block. 609 #if 0 610 // If we're asked to remap some other instruction, we'll need to 611 // spill it to an alloca variable in the parent function and add a 612 // temporary alloca in the outlined function to be processed as 613 // described above. 614 Instruction *Inst = dyn_cast<Instruction>(V); 615 if (Inst) { 616 AllocaInst *Spill = DemoteRegToStack(*Inst, true); 617 AllocaInst *NewAlloca = Builder.CreateAlloca(Spill->getAllocatedType(), 618 Spill->getArraySize()); 619 FrameVarMap[AV] = NewAlloca; 620 return NewAlloca; 621 } 622 #endif 623 624 return nullptr; 625 } 626