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, FrameVarInfoMap &VarInfo); 77 }; 78 79 class WinEHFrameVariableMaterializer : public ValueMaterializer { 80 public: 81 WinEHFrameVariableMaterializer(Function *OutlinedFn, 82 FrameVarInfoMap &FrameVarInfo); 83 ~WinEHFrameVariableMaterializer() {} 84 85 virtual Value *materializeValueFor(Value *V) override; 86 87 private: 88 FrameVarInfoMap &FrameVarInfo; 89 IRBuilder<> Builder; 90 }; 91 92 class WinEHCloningDirectorBase : public CloningDirector { 93 public: 94 WinEHCloningDirectorBase(LandingPadInst *LPI, Function *HandlerFn, 95 FrameVarInfoMap &VarInfo) 96 : LPI(LPI), Materializer(HandlerFn, VarInfo), 97 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 104 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 117 ValueMaterializer *getValueMaterializer() override { return &Materializer; } 118 119 protected: 120 LandingPadInst *LPI; 121 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 }; 130 131 class WinEHCatchDirector : public WinEHCloningDirectorBase { 132 public: 133 WinEHCatchDirector(LandingPadInst *LPI, Function *CatchFn, Value *Selector, 134 FrameVarInfoMap &VarInfo) 135 : WinEHCloningDirectorBase(LPI, CatchFn, VarInfo), 136 CurrentSelector(Selector->stripPointerCasts()) {} 137 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 149 private: 150 Value *CurrentSelector; 151 }; 152 153 class WinEHCleanupDirector : public WinEHCloningDirectorBase { 154 public: 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 171 } // end anonymous namespace 172 173 char WinEHPrepare::ID = 0; 174 INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare", "Prepare Windows exceptions", 175 false, false) 176 177 FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) { 178 return new WinEHPrepare(TM); 179 } 180 181 static bool isMSVCPersonality(EHPersonality Pers) { 182 return Pers == EHPersonality::MSVC_Win64SEH || 183 Pers == EHPersonality::MSVC_CXX; 184 } 185 186 bool 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 225 bool WinEHPrepare::doFinalization(Module &M) { 226 return DwarfPrepare->doFinalization(M); 227 } 228 229 void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const { 230 DwarfPrepare->getAnalysisUsage(AU); 231 } 232 233 bool 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; 240 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; 267 bool Outlined = outlineHandler(Catch, &F, LPad->getClause(Idx), LPad, 268 EHAlloc, FrameVarInfo); 269 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); 275 } 276 } // End if (isCatch) 277 } // End for each clause 278 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; 287 bool Outlined = 288 outlineHandler(Cleanup, &F, nullptr, LPad, EHAlloc, FrameVarInfo); 289 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 297 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) { 331 Value *ParentVal = VarInfoEntry.first; 332 HandlerAllocas &AllocaInfo = VarInfoEntry.second; 333 334 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(); 354 StructTys.push_back(VarTy); 355 AllocaInfo.ParentFrameAllocationIndex = Idx++; 356 } 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 395 // 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. 398 Instruction *FrameEHDataInst = cast<Instruction>(FrameEHData); 399 BasicBlock::iterator II = FrameEHDataInst; 400 ++II; 401 Instruction *AllocaInsertPt = II; 402 for (auto &VarInfoEntry : FrameVarInfo) { 403 Value *ParentVal = VarInfoEntry.first; 404 HandlerAllocas &AllocaInfo = VarInfoEntry.second; 405 int Idx = AllocaInfo.ParentFrameAllocationIndex; 406 407 // 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 433 // 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); 450 if (ParentAlloca == AllocaInsertPt) 451 AllocaInsertPt = dyn_cast<Instruction>(ElementPtr); 452 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 472 bool WinEHPrepare::outlineHandler(HandlerType CatchOrCleanup, Function *SrcFn, 473 Constant *SelectorType, LandingPadInst *LPad, 474 CallInst *&EHAlloc, 475 FrameVarInfoMap &VarInfo) { 476 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); 484 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 } 495 496 // Generate a standard prolog to setup the frame recovery structure. 497 IRBuilder<> Builder(Context); 498 BasicBlock *Entry = BasicBlock::Create(Context, "entry"); 499 Handler->getBasicBlockList().push_front(Entry); 500 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, ""), 517 &(Handler->getArgumentList().back())}; 518 EHAlloc = Builder.CreateCall(RecoverFrameFn, RecoverArgs, "eh.alloc"); 519 520 std::unique_ptr<WinEHCloningDirectorBase> Director; 521 522 if (CatchOrCleanup == Catch) { 523 Director.reset( 524 new WinEHCatchDirector(LPad, Handler, SelectorType, VarInfo)); 525 } else { 526 Director.reset(new WinEHCleanupDirector(LPad, Handler, VarInfo)); 527 } 528 529 ValueToValueMapTy VMap; 530 531 // FIXME: Map other values referenced in the filter handler. 532 533 SmallVector<ReturnInst *, 8> Returns; 534 ClonedCodeInfo InlinedFunctionInfo; 535 536 BasicBlock::iterator II = LPad; 537 538 CloneAndPruneIntoFromInst( 539 Handler, SrcFn, ++II, VMap, 540 /*ModuleLevelChanges=*/false, Returns, "", &InlinedFunctionInfo, 541 &SrcFn->getParent()->getDataLayout(), Director.get()); 542 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 551 CloningDirector::CloningAction WinEHCloningDirectorBase::handleInstruction( 552 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 621 if (auto *Resume = dyn_cast<ResumeInst>(Inst)) 622 return handleResume(VMap, Resume, NewBB); 623 624 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); 630 631 // Continue with the default cloning behavior. 632 return CloningDirector::CloneInstruction; 633 } 634 635 CloningDirector::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. 640 // 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? 645 return CloningDirector::SkipInstruction; 646 } 647 648 CloningDirector::CloningAction 649 WinEHCatchDirector::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 685 CloningDirector::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 699 CloningDirector::CloningAction 700 WinEHCatchDirector::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 709 CloningDirector::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 719 CloningDirector::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 729 CloningDirector::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 738 CloningDirector::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 748 WinEHFrameVariableMaterializer::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 756 Value *WinEHFrameVariableMaterializer::materializeValueFor(Value *V) { 757 // 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. 765 if (auto *AV = dyn_cast<AllocaInst>(V)) { 766 AllocaInst *NewAlloca = dyn_cast<AllocaInst>(AV->clone()); 767 Builder.Insert(NewAlloca, AV->getName()); 768 FrameVarInfo[AV].Allocas.push_back(NewAlloca); 769 return NewAlloca; 770 } 771 772 // 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; 782 } 783 784 // Don't materialize other values. 785 return nullptr; 786 } 787