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 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 Value *ParentVal = VarInfoEntry.first; 265 HandlerAllocas &AllocaInfo = VarInfoEntry.second; 266 267 if (auto *ParentAlloca = dyn_cast<AllocaInst>(ParentVal)) { 268 // If the instruction still has uses in the parent function or if it is 269 // referenced by more than one handler, add it to the frame allocation 270 // structure. 271 if (ParentAlloca->getNumUses() != 0 || AllocaInfo.Allocas.size() > 1) { 272 Type *VarTy = ParentAlloca->getAllocatedType(); 273 StructTys.push_back(VarTy); 274 AllocaInfo.ParentFrameAllocationIndex = Idx++; 275 } else { 276 // If the variable is not used in the parent frame and it is only used 277 // in one handler, the alloca can be removed from the parent frame 278 // and the handler will keep its "temporary" alloca to define the value. 279 // An element index of -1 is used to indicate this condition. 280 AllocaInfo.ParentFrameAllocationIndex = -1; 281 } 282 } else { 283 // FIXME: Sink non-alloca values into the handler if they have no other 284 // uses in the parent function after outlining and are only used in 285 // one handler. 286 Type *VarTy = ParentVal->getType(); 287 StructTys.push_back(VarTy); 288 AllocaInfo.ParentFrameAllocationIndex = Idx++; 289 } 290 } 291 292 // Having filled the StructTys vector and assigned an index to each element, 293 // we can now create the structure. 294 StructType *EHDataStructTy = StructType::create( 295 F.getContext(), StructTys, "struct." + F.getName().str() + ".ehdata"); 296 IRBuilder<> Builder(F.getParent()->getContext()); 297 298 // Create a frame allocation. 299 Module *M = F.getParent(); 300 LLVMContext &Context = M->getContext(); 301 BasicBlock *Entry = &F.getEntryBlock(); 302 Builder.SetInsertPoint(Entry->getFirstInsertionPt()); 303 Function *FrameAllocFn = 304 Intrinsic::getDeclaration(M, Intrinsic::frameallocate); 305 uint64_t EHAllocSize = M->getDataLayout()->getTypeAllocSize(EHDataStructTy); 306 Value *FrameAllocArgs[] = { 307 ConstantInt::get(Type::getInt32Ty(Context), EHAllocSize)}; 308 CallInst *FrameAlloc = 309 Builder.CreateCall(FrameAllocFn, FrameAllocArgs, "frame.alloc"); 310 311 Value *FrameEHData = Builder.CreateBitCast( 312 FrameAlloc, EHDataStructTy->getPointerTo(), "eh.data"); 313 314 // Now visit each handler that is using the structure and bitcast its EHAlloc 315 // value to be a pointer to the frame alloc structure. 316 DenseMap<Function *, Value *> EHDataMap; 317 for (CallInst *EHAlloc : HandlerAllocs) { 318 // The EHAlloc has no uses at this time, so we need to just insert the 319 // cast before the next instruction. There is always a next instruction. 320 BasicBlock::iterator II = EHAlloc; 321 ++II; 322 Builder.SetInsertPoint(cast<Instruction>(II)); 323 Value *EHData = Builder.CreateBitCast( 324 EHAlloc, EHDataStructTy->getPointerTo(), "eh.data"); 325 EHDataMap[EHAlloc->getParent()->getParent()] = EHData; 326 } 327 328 // Next, replace the place-holder EHObjPtr allocas with GEP instructions 329 // that pull the EHObjPtr from the frame alloc structure 330 for (AllocaInst *EHObjPtr : HandlerEHObjPtrs) { 331 Value *EHData = EHDataMap[EHObjPtr->getParent()->getParent()]; 332 Builder.SetInsertPoint(EHObjPtr); 333 Value *ElementPtr = Builder.CreateConstInBoundsGEP2_32(EHData, 0, 1); 334 EHObjPtr->replaceAllUsesWith(ElementPtr); 335 EHObjPtr->removeFromParent(); 336 ElementPtr->takeName(EHObjPtr); 337 delete EHObjPtr; 338 } 339 340 // Finally, replace all of the temporary allocas for frame variables used in 341 // the outlined handlers and the original frame allocas with GEP instructions 342 // that get the equivalent pointer from the frame allocation struct. 343 Instruction *FrameEHDataInst = cast<Instruction>(FrameEHData); 344 BasicBlock::iterator II = FrameEHDataInst; 345 ++II; 346 Instruction *AllocaInsertPt = II; 347 for (auto &VarInfoEntry : FrameVarInfo) { 348 Value *ParentVal = VarInfoEntry.first; 349 HandlerAllocas &AllocaInfo = VarInfoEntry.second; 350 int Idx = AllocaInfo.ParentFrameAllocationIndex; 351 352 // If the mapped value isn't already an alloca, we need to spill it if it 353 // is a computed value or copy it if it is an argument. 354 AllocaInst *ParentAlloca = dyn_cast<AllocaInst>(ParentVal); 355 if (!ParentAlloca) { 356 if (auto *Arg = dyn_cast<Argument>(ParentVal)) { 357 // Lower this argument to a copy and then demote that to the stack. 358 // We can't just use the argument location because the handler needs 359 // it to be in the frame allocation block. 360 // Use 'select i8 true, %arg, undef' to simulate a 'no-op' instruction. 361 Value *TrueValue = ConstantInt::getTrue(Context); 362 Value *UndefValue = UndefValue::get(Arg->getType()); 363 Instruction *SI = 364 SelectInst::Create(TrueValue, Arg, UndefValue, 365 Arg->getName() + ".tmp", AllocaInsertPt); 366 Arg->replaceAllUsesWith(SI); 367 // Reset the select operand, because it was clobbered by the RAUW above. 368 SI->setOperand(1, Arg); 369 ParentAlloca = DemoteRegToStack(*SI, true, SI); 370 } else if (auto *PN = dyn_cast<PHINode>(ParentVal)) { 371 ParentAlloca = DemotePHIToStack(PN, AllocaInsertPt); 372 } else { 373 Instruction *ParentInst = cast<Instruction>(ParentVal); 374 ParentAlloca = DemoteRegToStack(*ParentInst, true, ParentInst); 375 } 376 } 377 378 // If we have an index of -1 for this instruction, it means it isn't used 379 // outside of this handler. In that case, we just keep the "temporary" 380 // alloca in the handler and erase the original alloca from the parent. 381 if (Idx == -1) { 382 ParentAlloca->eraseFromParent(); 383 } else { 384 // Otherwise, we replace the parent alloca and all outlined allocas 385 // which map to it with GEP instructions. 386 387 // First replace the original alloca. 388 Builder.SetInsertPoint(ParentAlloca); 389 Builder.SetCurrentDebugLocation(ParentAlloca->getDebugLoc()); 390 Value *ElementPtr = 391 Builder.CreateConstInBoundsGEP2_32(FrameEHData, 0, Idx); 392 ParentAlloca->replaceAllUsesWith(ElementPtr); 393 ParentAlloca->removeFromParent(); 394 ElementPtr->takeName(ParentAlloca); 395 if (ParentAlloca == AllocaInsertPt) 396 AllocaInsertPt = dyn_cast<Instruction>(ElementPtr); 397 delete ParentAlloca; 398 399 // Next replace all outlined allocas that are mapped to it. 400 for (AllocaInst *TempAlloca : AllocaInfo.Allocas) { 401 Value *EHData = EHDataMap[TempAlloca->getParent()->getParent()]; 402 // FIXME: Sink this GEP into the blocks where it is used. 403 Builder.SetInsertPoint(TempAlloca); 404 Builder.SetCurrentDebugLocation(TempAlloca->getDebugLoc()); 405 ElementPtr = Builder.CreateConstInBoundsGEP2_32(EHData, 0, Idx); 406 TempAlloca->replaceAllUsesWith(ElementPtr); 407 TempAlloca->removeFromParent(); 408 ElementPtr->takeName(TempAlloca); 409 delete TempAlloca; 410 } 411 } // end else of if (Idx == -1) 412 } // End for each FrameVarInfo entry. 413 414 return HandlersOutlined; 415 } 416 417 bool WinEHPrepare::outlineCatchHandler(Function *SrcFn, Constant *SelectorType, 418 LandingPadInst *LPad, CallInst *&EHAlloc, 419 AllocaInst *&EHObjPtr, 420 FrameVarInfoMap &VarInfo) { 421 Module *M = SrcFn->getParent(); 422 LLVMContext &Context = M->getContext(); 423 424 // Create a new function to receive the handler contents. 425 Type *Int8PtrType = Type::getInt8PtrTy(Context); 426 std::vector<Type *> ArgTys; 427 ArgTys.push_back(Int8PtrType); 428 ArgTys.push_back(Int8PtrType); 429 FunctionType *FnType = FunctionType::get(Int8PtrType, ArgTys, false); 430 Function *CatchHandler = Function::Create( 431 FnType, GlobalVariable::ExternalLinkage, SrcFn->getName() + ".catch", M); 432 433 // Generate a standard prolog to setup the frame recovery structure. 434 IRBuilder<> Builder(Context); 435 BasicBlock *Entry = BasicBlock::Create(Context, "catch.entry"); 436 CatchHandler->getBasicBlockList().push_front(Entry); 437 Builder.SetInsertPoint(Entry); 438 Builder.SetCurrentDebugLocation(LPad->getDebugLoc()); 439 440 // The outlined handler will be called with the parent's frame pointer as 441 // its second argument. To enable the handler to access variables from 442 // the parent frame, we use that pointer to get locate a special block 443 // of memory that was allocated using llvm.eh.allocateframe for this 444 // purpose. During the outlining process we will determine which frame 445 // variables are used in handlers and create a structure that maps these 446 // variables into the frame allocation block. 447 // 448 // The frame allocation block also contains an exception state variable 449 // used by the runtime and a pointer to the exception object pointer 450 // which will be filled in by the runtime for use in the handler. 451 Function *RecoverFrameFn = 452 Intrinsic::getDeclaration(M, Intrinsic::framerecover); 453 Value *RecoverArgs[] = {Builder.CreateBitCast(SrcFn, Int8PtrType, ""), 454 &(CatchHandler->getArgumentList().back())}; 455 EHAlloc = Builder.CreateCall(RecoverFrameFn, RecoverArgs, "eh.alloc"); 456 457 // This alloca is only temporary. We'll be replacing it once we know all the 458 // frame variables that need to go in the frame allocation structure. 459 EHObjPtr = Builder.CreateAlloca(Int8PtrType, 0, "eh.obj.ptr"); 460 461 // This will give us a raw pointer to the exception object, which 462 // corresponds to the formal parameter of the catch statement. If the 463 // handler uses this object, we will generate code during the outlining 464 // process to cast the pointer to the appropriate type and deference it 465 // as necessary. The un-outlined landing pad code represents the 466 // exception object as the result of the llvm.eh.begincatch call. 467 Value *EHObj = Builder.CreateLoad(EHObjPtr, false, "eh.obj"); 468 469 ValueToValueMapTy VMap; 470 471 // FIXME: Map other values referenced in the filter handler. 472 473 WinEHCatchDirector Director(LPad, CatchHandler, SelectorType, EHObj, VarInfo); 474 475 SmallVector<ReturnInst *, 8> Returns; 476 ClonedCodeInfo InlinedFunctionInfo; 477 478 BasicBlock::iterator II = LPad; 479 480 CloneAndPruneIntoFromInst(CatchHandler, SrcFn, ++II, VMap, 481 /*ModuleLevelChanges=*/false, Returns, "", 482 &InlinedFunctionInfo, 483 SrcFn->getParent()->getDataLayout(), &Director); 484 485 // Move all the instructions in the first cloned block into our entry block. 486 BasicBlock *FirstClonedBB = std::next(Function::iterator(Entry)); 487 Entry->getInstList().splice(Entry->end(), FirstClonedBB->getInstList()); 488 FirstClonedBB->eraseFromParent(); 489 490 return true; 491 } 492 493 CloningDirector::CloningAction WinEHCatchDirector::handleInstruction( 494 ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { 495 // Intercept instructions which extract values from the landing pad aggregate. 496 if (auto *Extract = dyn_cast<ExtractValueInst>(Inst)) { 497 if (Extract->getAggregateOperand() == LPI) { 498 assert(Extract->getNumIndices() == 1 && 499 "Unexpected operation: extracting both landing pad values"); 500 assert((*(Extract->idx_begin()) == 0 || *(Extract->idx_begin()) == 1) && 501 "Unexpected operation: extracting an unknown landing pad element"); 502 503 if (*(Extract->idx_begin()) == 0) { 504 // Element 0 doesn't directly corresponds to anything in the WinEH 505 // scheme. 506 // It will be stored to a memory location, then later loaded and finally 507 // the loaded value will be used as the argument to an 508 // llvm.eh.begincatch 509 // call. We're tracking it here so that we can skip the store and load. 510 ExtractedEHPtr = Inst; 511 } else { 512 // Element 1 corresponds to the filter selector. We'll map it to 1 for 513 // matching purposes, but it will also probably be stored to memory and 514 // reloaded, so we need to track the instuction so that we can map the 515 // loaded value too. 516 VMap[Inst] = ConstantInt::get(SelectorIDType, 1); 517 ExtractedSelector = Inst; 518 } 519 520 // Tell the caller not to clone this instruction. 521 return CloningDirector::SkipInstruction; 522 } 523 // Other extract value instructions just get cloned. 524 return CloningDirector::CloneInstruction; 525 } 526 527 if (auto *Store = dyn_cast<StoreInst>(Inst)) { 528 // Look for and suppress stores of the extracted landingpad values. 529 const Value *StoredValue = Store->getValueOperand(); 530 if (StoredValue == ExtractedEHPtr) { 531 EHPtrStoreAddr = Store->getPointerOperand(); 532 return CloningDirector::SkipInstruction; 533 } 534 if (StoredValue == ExtractedSelector) { 535 SelectorStoreAddr = Store->getPointerOperand(); 536 return CloningDirector::SkipInstruction; 537 } 538 539 // Any other store just gets cloned. 540 return CloningDirector::CloneInstruction; 541 } 542 543 if (auto *Load = dyn_cast<LoadInst>(Inst)) { 544 // Look for loads of (previously suppressed) landingpad values. 545 // The EHPtr load can be ignored (it should only be used as 546 // an argument to llvm.eh.begincatch), but the selector value 547 // needs to be mapped to a constant value of 1 to be used to 548 // simplify the branching to always flow to the current handler. 549 const Value *LoadAddr = Load->getPointerOperand(); 550 if (LoadAddr == EHPtrStoreAddr) { 551 VMap[Inst] = UndefValue::get(Int8PtrType); 552 return CloningDirector::SkipInstruction; 553 } 554 if (LoadAddr == SelectorStoreAddr) { 555 VMap[Inst] = ConstantInt::get(SelectorIDType, 1); 556 return CloningDirector::SkipInstruction; 557 } 558 559 // Any other loads just get cloned. 560 return CloningDirector::CloneInstruction; 561 } 562 563 if (match(Inst, m_Intrinsic<Intrinsic::eh_begincatch>())) { 564 // The argument to the call is some form of the first element of the 565 // landingpad aggregate value, but that doesn't matter. It isn't used 566 // here. 567 // The return value of this instruction, however, is used to access the 568 // EH object pointer. We have generated an instruction to get that value 569 // from the EH alloc block, so we can just map to that here. 570 VMap[Inst] = EHObj; 571 return CloningDirector::SkipInstruction; 572 } 573 if (match(Inst, m_Intrinsic<Intrinsic::eh_endcatch>())) { 574 auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst); 575 // It might be interesting to track whether or not we are inside a catch 576 // function, but that might make the algorithm more brittle than it needs 577 // to be. 578 579 // The end catch call can occur in one of two places: either in a 580 // landingpad 581 // block that is part of the catch handlers exception mechanism, or at the 582 // end of the catch block. If it occurs in a landing pad, we must skip it 583 // and continue so that the landing pad gets cloned. 584 // FIXME: This case isn't fully supported yet and shouldn't turn up in any 585 // of the test cases until it is. 586 if (IntrinCall->getParent()->isLandingPad()) 587 return CloningDirector::SkipInstruction; 588 589 // If an end catch occurs anywhere else the next instruction should be an 590 // unconditional branch instruction that we want to replace with a return 591 // to the the address of the branch target. 592 const BasicBlock *EndCatchBB = IntrinCall->getParent(); 593 const TerminatorInst *Terminator = EndCatchBB->getTerminator(); 594 const BranchInst *Branch = dyn_cast<BranchInst>(Terminator); 595 assert(Branch && Branch->isUnconditional()); 596 assert(std::next(BasicBlock::const_iterator(IntrinCall)) == 597 BasicBlock::const_iterator(Branch)); 598 599 ReturnInst::Create(NewBB->getContext(), 600 BlockAddress::get(Branch->getSuccessor(0)), NewBB); 601 602 // We just added a terminator to the cloned block. 603 // Tell the caller to stop processing the current basic block so that 604 // the branch instruction will be skipped. 605 return CloningDirector::StopCloningBB; 606 } 607 if (match(Inst, m_Intrinsic<Intrinsic::eh_typeid_for>())) { 608 auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst); 609 Value *Selector = IntrinCall->getArgOperand(0)->stripPointerCasts(); 610 // This causes a replacement that will collapse the landing pad CFG based 611 // on the filter function we intend to match. 612 if (Selector == CurrentSelector) 613 VMap[Inst] = ConstantInt::get(SelectorIDType, 1); 614 else 615 VMap[Inst] = ConstantInt::get(SelectorIDType, 0); 616 // Tell the caller not to clone this instruction. 617 return CloningDirector::SkipInstruction; 618 } 619 620 // Continue with the default cloning behavior. 621 return CloningDirector::CloneInstruction; 622 } 623 624 WinEHFrameVariableMaterializer::WinEHFrameVariableMaterializer( 625 Function *OutlinedFn, FrameVarInfoMap &FrameVarInfo) 626 : FrameVarInfo(FrameVarInfo), Builder(OutlinedFn->getContext()) { 627 Builder.SetInsertPoint(&OutlinedFn->getEntryBlock()); 628 // FIXME: Do something with the FrameVarMapped so that it is shared across the 629 // function. 630 } 631 632 Value *WinEHFrameVariableMaterializer::materializeValueFor(Value *V) { 633 // If we're asked to materialize a value that is an instruction, we 634 // temporarily create an alloca in the outlined function and add this 635 // to the FrameVarInfo map. When all the outlining is complete, we'll 636 // collect these into a structure, spilling non-alloca values in the 637 // parent frame as necessary, and replace these temporary allocas with 638 // GEPs referencing the frame allocation block. 639 640 // If the value is an alloca, the mapping is direct. 641 if (auto *AV = dyn_cast<AllocaInst>(V)) { 642 AllocaInst *NewAlloca = dyn_cast<AllocaInst>(AV->clone()); 643 Builder.Insert(NewAlloca, AV->getName()); 644 FrameVarInfo[AV].Allocas.push_back(NewAlloca); 645 return NewAlloca; 646 } 647 648 // For other types of instructions or arguments, we need an alloca based on 649 // the value's type and a load of the alloca. The alloca will be replaced 650 // by a GEP, but the load will stay. In the parent function, the value will 651 // be spilled to a location in the frame allocation block. 652 if (isa<Instruction>(V) || isa<Argument>(V)) { 653 AllocaInst *NewAlloca = 654 Builder.CreateAlloca(V->getType(), nullptr, "eh.temp.alloca"); 655 FrameVarInfo[V].Allocas.push_back(NewAlloca); 656 LoadInst *NewLoad = Builder.CreateLoad(NewAlloca, V->getName() + ".reload"); 657 return NewLoad; 658 } 659 660 // Don't materialize other values. 661 return nullptr; 662 } 663