X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FWinEHPrepare.cpp;h=e4e63fddebb883ae7fd4c407b156859b4e882d97;hb=042dd34f9cb1fb17873116c7560f2f011c10a9b8;hp=db91c02ee461dcf7adb670b8e738b74c8700461a;hpb=018ed7b68b12e74a655a6ef00179455eda6e6e88;p=oota-llvm.git diff --git a/lib/CodeGen/WinEHPrepare.cpp b/lib/CodeGen/WinEHPrepare.cpp index db91c02ee46..e4e63fddebb 100644 --- a/lib/CodeGen/WinEHPrepare.cpp +++ b/lib/CodeGen/WinEHPrepare.cpp @@ -98,6 +98,8 @@ private: SetVector &EHReturnBlocks); void findCXXEHReturnPoints(Function &F, SetVector &EHReturnBlocks); + void getPossibleReturnTargets(Function *ParentF, Function *HandlerF, + SetVector &Targets); void completeNestedLandingPad(Function *ParentFn, LandingPadInst *OutlinedLPad, const LandingPadInst *OriginalLPad, @@ -700,6 +702,14 @@ bool WinEHPrepare::prepareExceptionHandlers( F.getEntryBlock().getFirstInsertionPt()); } + // This container stores the llvm.eh.recover and IndirectBr instructions + // that make up the body of each landing pad after it has been outlined. + // We need to defer the population of the target list for the indirectbr + // until all landing pads have been outlined so that we can handle the + // case of blocks in the target that are reached only from nested + // landing pads. + SmallVector, 4> LPadImpls; + for (LandingPadInst *LPad : LPads) { // Look for evidence that this landingpad has already been processed. bool LPadHasActionList = false; @@ -819,18 +829,28 @@ bool WinEHPrepare::prepareExceptionHandlers( CallInst *Recover = CallInst::Create(ActionIntrin, ActionArgs, "recover", LPadBB); - // Add an indirect branch listing possible successors of the catch handlers. - SetVector ReturnTargets; - for (ActionHandler *Action : Actions) { - if (auto *CatchAction = dyn_cast(Action)) { - const auto &CatchTargets = CatchAction->getReturnTargets(); - ReturnTargets.insert(CatchTargets.begin(), CatchTargets.end()); + if (isAsynchronousEHPersonality(Personality)) { + // SEH can create the target list directly, since catch handlers + // are not outlined. + SetVector ReturnTargets; + for (ActionHandler *Action : Actions) { + if (auto *CatchAction = dyn_cast(Action)) { + const auto &CatchTargets = CatchAction->getReturnTargets(); + ReturnTargets.insert(CatchTargets.begin(), CatchTargets.end()); + } } + IndirectBrInst *Branch = + IndirectBrInst::Create(Recover, ReturnTargets.size(), LPadBB); + for (BasicBlock *Target : ReturnTargets) + Branch->addDestination(Target); + } else { + // C++ EH must defer populating the targets to handle the case of + // targets that are reached indirectly through nested landing pads. + IndirectBrInst *Branch = + IndirectBrInst::Create(Recover, 0, LPadBB); + + LPadImpls.push_back(std::make_pair(Recover, Branch)); } - IndirectBrInst *Branch = - IndirectBrInst::Create(Recover, ReturnTargets.size(), LPadBB); - for (BasicBlock *Target : ReturnTargets) - Branch->addDestination(Target); } // End for each landingpad // If nothing got outlined, there is no more processing to be done. @@ -844,6 +864,45 @@ bool WinEHPrepare::prepareExceptionHandlers( completeNestedLandingPad(&F, LPadPair.first, LPadPair.second, FrameVarInfo); NestedLPtoOriginalLP.clear(); + // Populate the indirectbr instructions' target lists if we deferred + // doing so above. + SetVector CheckedTargets; + SmallVector, 4> ActionList; + for (auto &LPadImplPair : LPadImpls) { + IntrinsicInst *Recover = cast(LPadImplPair.first); + IndirectBrInst *Branch = LPadImplPair.second; + + // Get a list of handlers called by + parseEHActions(Recover, ActionList); + + // Add an indirect branch listing possible successors of the catch handlers. + SetVector ReturnTargets; + for (const auto &Action : ActionList) { + if (auto *CA = dyn_cast(Action.get())) { + Function *Handler = cast(CA->getHandlerBlockOrFunc()); + getPossibleReturnTargets(&F, Handler, ReturnTargets); + } + } + ActionList.clear(); + for (BasicBlock *Target : ReturnTargets) { + Branch->addDestination(Target); + // The target may be a block that we excepted to get pruned. + // If it is, it may contain a call to llvm.eh.endcatch. + if (CheckedTargets.insert(Target)) { + // Earlier preparations guarantee that all calls to llvm.eh.endcatch + // will be followed by an unconditional branch. + auto *Br = dyn_cast(Target->getTerminator()); + if (Br && Br->isUnconditional() && + Br != Target->getFirstNonPHIOrDbgOrLifetime()) { + Instruction *Prev = Br->getPrevNode(); + if (match(cast(Prev), m_Intrinsic())) + Prev->eraseFromParent(); + } + } + } + } + LPadImpls.clear(); + F.addFnAttr("wineh-parent", F.getName()); // Delete any blocks that were only used by handlers that were outlined above. @@ -934,6 +993,7 @@ bool WinEHPrepare::prepareExceptionHandlers( CleanupHandlerMap.clear(); HandlerToParentFP.clear(); DT = nullptr; + SEHExceptionCodeSlot = nullptr; return HandlersOutlined; } @@ -975,6 +1035,42 @@ void WinEHPrepare::promoteLandingPadValues(LandingPadInst *LPad) { RecursivelyDeleteTriviallyDeadInstructions(U); } +void WinEHPrepare::getPossibleReturnTargets(Function *ParentF, + Function *HandlerF, + SetVector &Targets) { + for (BasicBlock &BB : *HandlerF) { + // If the handler contains landing pads, check for any + // handlers that may return directly to a block in the + // parent function. + if (auto *LPI = BB.getLandingPadInst()) { + IntrinsicInst *Recover = cast(LPI->getNextNode()); + SmallVector, 4> ActionList; + parseEHActions(Recover, ActionList); + for (const auto &Action : ActionList) { + if (auto *CH = dyn_cast(Action.get())) { + Function *NestedF = cast(CH->getHandlerBlockOrFunc()); + getPossibleReturnTargets(ParentF, NestedF, Targets); + } + } + } + + auto *Ret = dyn_cast(BB.getTerminator()); + if (!Ret) + continue; + + // Handler functions must always return a block address. + BlockAddress *BA = cast(Ret->getReturnValue()); + + // If this is the handler for a nested landing pad, the + // return address may have been remapped to a block in the + // parent handler. We're not interested in those. + if (BA->getFunction() != ParentF) + continue; + + Targets.insert(BA->getBasicBlock()); + } +} + void WinEHPrepare::completeNestedLandingPad(Function *ParentFn, LandingPadInst *OutlinedLPad, const LandingPadInst *OriginalLPad, @@ -1004,10 +1100,10 @@ void WinEHPrepare::completeNestedLandingPad(Function *ParentFn, // Remap the exception variables into the outlined function. SmallVector ActionTargets; - SmallVector ActionList; + SmallVector, 4> ActionList; parseEHActions(EHActions, ActionList); - for (auto *Action : ActionList) { - auto *Catch = dyn_cast(Action); + for (const auto &Action : ActionList) { + auto *Catch = dyn_cast(Action.get()); if (!Catch) continue; // The dyn_cast to function here selects C++ catch handlers and skips @@ -1045,7 +1141,6 @@ void WinEHPrepare::completeNestedLandingPad(Function *ParentFn, ActionTargets.push_back(NewBA); } } - DeleteContainerPointers(ActionList); ActionList.clear(); OutlinedBB->getInstList().push_back(EHActions); @@ -1113,7 +1208,7 @@ static BasicBlock *createStubLandingPad(Function *Handler, // Insert a call to llvm.eh.actions so that we don't try to outline this lpad. Function *ActionIntrin = Intrinsic::getDeclaration(Handler->getParent(), Intrinsic::eh_actions); - Builder.CreateCall(ActionIntrin, "recover"); + Builder.CreateCall(ActionIntrin, {}, "recover"); LPad->setCleanup(true); Builder.CreateUnreachable(); return StubBB; @@ -1358,7 +1453,7 @@ void WinEHPrepare::processSEHCatchHandler(CatchHandler *CatchAction, IRBuilder<> Builder(HandlerBB->getFirstInsertionPt()); Function *EHCodeFn = Intrinsic::getDeclaration( StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode); - Value *Code = Builder.CreateCall(EHCodeFn, "sehcode"); + Value *Code = Builder.CreateCall(EHCodeFn, {}, "sehcode"); Code = Builder.CreateIntToPtr(Code, SEHExceptionCodeSlot->getAllocatedType()); Builder.CreateStore(Code, SEHExceptionCodeSlot); CatchAction->setHandlerBlockOrFunc(BlockAddress::get(HandlerBB)); @@ -1731,7 +1826,12 @@ Value *WinEHFrameVariableMaterializer::materializeValueFor(Value *V) { } if (isa(V) || isa(V)) { - errs() << "Failed to demote instruction used in exception handler:\n"; + Function *Parent = isa(V) + ? cast(V)->getParent()->getParent() + : cast(V)->getParent(); + errs() + << "Failed to demote instruction used in exception handler of function " + << GlobalValue::getRealLinkageName(Parent->getName()) << ":\n"; errs() << " " << *V << '\n'; report_fatal_error("WinEHPrepare failed to demote instruction"); } @@ -2220,8 +2320,9 @@ void WinEHPrepare::findCleanupHandlers(LandingPadActions &Actions, // This is a public function, declared in WinEHFuncInfo.h and is also // referenced by WinEHNumbering in FunctionLoweringInfo.cpp. -void llvm::parseEHActions(const IntrinsicInst *II, - SmallVectorImpl &Actions) { +void llvm::parseEHActions( + const IntrinsicInst *II, + SmallVectorImpl> &Actions) { for (unsigned I = 0, E = II->getNumArgOperands(); I != E;) { uint64_t ActionKind = cast(II->getArgOperand(I))->getZExtValue(); @@ -2231,16 +2332,17 @@ void llvm::parseEHActions(const IntrinsicInst *II, int64_t EHObjIndexVal = EHObjIndex->getSExtValue(); Constant *Handler = cast(II->getArgOperand(I + 3)); I += 4; - auto *CH = new CatchHandler(/*BB=*/nullptr, Selector, /*NextBB=*/nullptr); + auto CH = make_unique(/*BB=*/nullptr, Selector, + /*NextBB=*/nullptr); CH->setHandlerBlockOrFunc(Handler); CH->setExceptionVarIndex(EHObjIndexVal); - Actions.push_back(CH); + Actions.push_back(std::move(CH)); } else if (ActionKind == 0) { Constant *Handler = cast(II->getArgOperand(I + 1)); I += 2; - auto *CH = new CleanupHandler(/*BB=*/nullptr); + auto CH = make_unique(/*BB=*/nullptr); CH->setHandlerBlockOrFunc(Handler); - Actions.push_back(CH); + Actions.push_back(std::move(CH)); } else { llvm_unreachable("Expected either a catch or cleanup handler!"); }