From: Reid Kleckner Date: Thu, 27 Aug 2015 23:27:47 +0000 (+0000) Subject: [WinEH] Add some support for code generating catchpad X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=c0e64ada5c1ec6bf44319403fc94a2f3612c02ae [WinEH] Add some support for code generating catchpad We can now run 32-bit programs with empty catch bodies. The next step is to change PEI so that we get funclet prologues and epilogues. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@246235 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 82c762ed850..efd354921e8 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -165,6 +165,9 @@ public: unsigned CreateRegs(Type *Ty); unsigned InitializeRegForValue(const Value *V) { + // Tokens never live in vregs. + if (V->getType()->isTokenTy()) + return 0; unsigned &R = ValueMap[V]; assert(R == 0 && "Already initialized this value register!"); return R = CreateRegs(V->getType()); diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index cf70d25f36a..90e4432b8fb 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -591,6 +591,10 @@ namespace ISD { /// take a chain as input and return a chain. EH_LABEL, + CATCHRET, + + CLEANUPRET, + /// STACKSAVE - STACKSAVE has one operand, an input chain. It produces a /// value, the same type as the pointer type for the system, and an output /// chain. diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 8aac7b1fd13..3c8e32d0623 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -85,18 +85,21 @@ class MachineBasicBlock : public ilist_node { /// Alignment of the basic block. Zero if the basic block does not need to be /// aligned. The alignment is specified as log2(bytes). - unsigned Alignment; + unsigned Alignment = 0; /// Indicate that this basic block is entered via an exception handler. - bool IsLandingPad; + bool IsEHPad = false; /// Indicate that this basic block is potentially the target of an indirect /// branch. - bool AddressTaken; + bool AddressTaken = false; + + /// Indicate that this basic block is the entry block of an EH funclet. + bool IsEHFuncletEntry = false; /// \brief since getSymbol is a relatively heavy-weight operation, the symbol /// is only computed once and is cached. - mutable MCSymbol *CachedMCSymbol; + mutable MCSymbol *CachedMCSymbol = nullptr; // Intrusive list support MachineBasicBlock() {} @@ -352,16 +355,22 @@ public: /// Returns true if the block is a landing pad. That is this basic block is /// entered via an exception handler. - bool isLandingPad() const { return IsLandingPad; } + bool isEHPad() const { return IsEHPad; } /// Indicates the block is a landing pad. That is this basic block is entered /// via an exception handler. - void setIsLandingPad(bool V = true) { IsLandingPad = V; } + void setIsEHPad(bool V = true) { IsEHPad = V; } /// If this block has a successor that is a landing pad, return it. Otherwise /// return NULL. const MachineBasicBlock *getLandingPadSuccessor() const; + /// Returns true if this is the entry block of an EH funclet. + bool isEHFuncletEntry() const { return IsEHFuncletEntry; } + + /// Indicates if this is the entry block of an EH funclet. + void setIsEHFuncletEntry(bool V = true) { IsEHFuncletEntry = V; } + // Code Layout methods. /// Move 'this' block before or after the specified block. This only moves diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 4cdfe2463c9..974ab95cb0c 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -163,6 +163,7 @@ class MachineModuleInfo : public ImmutablePass { bool CallsEHReturn; bool CallsUnwindInit; + bool HasEHFunclets; /// DbgInfoAvailable - True if debugging information is available /// in this module. @@ -371,6 +372,12 @@ public: return LandingPads; } + bool hasEHFunclets() const { + return HasEHFunclets; + } + + void setHasEHFunclets(bool V) { HasEHFunclets = true; } + /// setCallSiteLandingPad - Map the landing pad's EH symbol to the call /// site indexes. void setCallSiteLandingPad(MCSymbol *Sym, ArrayRef Sites); diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index a011e4c338c..cae343debb6 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -264,6 +264,7 @@ private: /// personality specific tasks. Returns true if the block should be /// instruction selected, false if no code should be emitted for it. bool PrepareEHLandingPad(); + bool PrepareEHPad(); /// \brief Perform instruction selection on all basic blocks in the function. void SelectAllBasicBlocks(const Function &Fn); diff --git a/include/llvm/CodeGen/WinEHFuncInfo.h b/include/llvm/CodeGen/WinEHFuncInfo.h index 5c54c89f300..5517c812ccc 100644 --- a/include/llvm/CodeGen/WinEHFuncInfo.h +++ b/include/llvm/CodeGen/WinEHFuncInfo.h @@ -27,6 +27,7 @@ class InvokeInst; class IntrinsicInst; class LandingPadInst; class MCSymbol; +class MachineBasicBlock; class Value; enum ActionType { Catch, Cleanup }; @@ -123,6 +124,7 @@ struct WinEHHandlerType { GlobalVariable *TypeDescriptor; int CatchObjRecoverIdx; const Value *Handler; + MachineBasicBlock *HandlerMBB; }; struct WinEHTryBlockMapEntry { diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 994cabc7db9..db5041b19d0 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -451,6 +451,8 @@ def brcc : SDNode<"ISD::BR_CC" , SDTBrCC, [SDNPHasChain]>; def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>; def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>; def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>; +def catchret : SDNode<"ISD::CATCHRET" , SDTBr, [SDNPHasChain]>; + def trap : SDNode<"ISD::TRAP" , SDTNone, [SDNPHasChain, SDNPSideEffect]>; def debugtrap : SDNode<"ISD::DEBUGTRAP" , SDTNone, diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index e69febc6ad6..fdba2a92818 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2485,7 +2485,8 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const { } // Print the main label for the block. - if (MBB.pred_empty() || isBlockOnlyReachableByFallthrough(&MBB)) { + if (MBB.pred_empty() || + (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry())) { if (isVerbose()) { // NOTE: Want this comment at start of line, don't emit with AddComment. OutStreamer->emitRawComment(" BB#" + Twine(MBB.getNumber()) + ":", false); @@ -2523,7 +2524,7 @@ bool AsmPrinter:: isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { // If this is a landing pad, it isn't a fall through. If it has no preds, // then nothing falls through to it. - if (MBB->isLandingPad() || MBB->pred_empty()) + if (MBB->isEHPad() || MBB->pred_empty()) return false; // If there isn't exactly one predecessor, it can't be a fall through. diff --git a/lib/CodeGen/AsmPrinter/WinException.cpp b/lib/CodeGen/AsmPrinter/WinException.cpp index 4151101e22b..547dc4cbdc3 100644 --- a/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/lib/CodeGen/AsmPrinter/WinException.cpp @@ -62,6 +62,7 @@ void WinException::beginFunction(const MachineFunction *MF) { // If any landing pads survive, we need an EH table. bool hasLandingPads = !MMI->getLandingPads().empty(); + bool hasEHFunclets = MMI->hasEHFunclets(); const Function *F = MF->getFunction(); const Function *ParentF = MMI->getWinEHParent(F); @@ -78,19 +79,21 @@ void WinException::beginFunction(const MachineFunction *MF) { F->hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) && F->needsUnwindTableEntry(); - shouldEmitPersonality = forceEmitPersonality || (hasLandingPads && - PerEncoding != dwarf::DW_EH_PE_omit && Per); + shouldEmitPersonality = + forceEmitPersonality || ((hasLandingPads || hasEHFunclets) && + PerEncoding != dwarf::DW_EH_PE_omit && Per); unsigned LSDAEncoding = TLOF.getLSDAEncoding(); shouldEmitLSDA = shouldEmitPersonality && LSDAEncoding != dwarf::DW_EH_PE_omit; - // If we're not using CFI, we don't want the CFI or the personality. If - // WinEHPrepare outlined something, we should emit the LSDA. + // If we're not using CFI, we don't want the CFI or the personality, but we + // might want EH tables if we had EH pads. + // FIXME: If WinEHPrepare outlined something, we should emit the LSDA. Remove + // this once WinEHPrepare stops doing that. if (!Asm->MAI->usesWindowsCFI()) { - bool HasOutlinedChildren = - F->hasFnAttribute("wineh-parent") && F == ParentF; - shouldEmitLSDA = HasOutlinedChildren; + shouldEmitLSDA = + hasEHFunclets || (F->hasFnAttribute("wineh-parent") && F == ParentF); shouldEmitPersonality = false; return; } @@ -185,7 +188,10 @@ const MCExpr *WinException::create32bitRef(const MCSymbol *Value) { const MCExpr *WinException::create32bitRef(const Value *V) { if (!V) return MCConstantExpr::create(0, Asm->OutContext); - return create32bitRef(Asm->getSymbol(cast(V))); + // FIXME: Delete the GlobalValue case once the new IR is fully functional. + if (const auto *GV = dyn_cast(V)) + return create32bitRef(Asm->getSymbol(GV)); + return create32bitRef(MMI->getAddrLabelSymbol(cast(V))); } /// Emit the language-specific data that __C_specific_handler expects. This @@ -320,14 +326,17 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { extendIP2StateTable(MF, ParentF, FuncInfo); - // Defer emission until we've visited the parent function and all the catch - // handlers. Cleanups don't contribute to the ip2state table, so don't count - // them. - if (ParentF != F && !FuncInfo.CatchHandlerMaxState.count(F)) - return; - ++FuncInfo.NumIPToStateFuncsVisited; - if (FuncInfo.NumIPToStateFuncsVisited != FuncInfo.CatchHandlerMaxState.size()) - return; + if (!MMI->hasEHFunclets()) { + // Defer emission until we've visited the parent function and all the + // catch handlers. Cleanups don't contribute to the ip2state table, so + // don't count them. + if (ParentF != F && !FuncInfo.CatchHandlerMaxState.count(F)) + return; + ++FuncInfo.NumIPToStateFuncsVisited; + if (FuncInfo.NumIPToStateFuncsVisited != + FuncInfo.CatchHandlerMaxState.size()) + return; + } } else { FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(ParentLinkageName); emitEHRegistrationOffsetLabel(FuncInfo, ParentLinkageName); @@ -410,11 +419,13 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { HandlerMaps.push_back(HandlerMapXData); - int CatchHigh = -1; - for (WinEHHandlerType &HT : TBME.HandlerArray) - CatchHigh = - std::max(CatchHigh, - FuncInfo.CatchHandlerMaxState[cast(HT.Handler)]); + int CatchHigh = TBME.CatchHigh; + if (CatchHigh == -1) { + for (WinEHHandlerType &HT : TBME.HandlerArray) + CatchHigh = std::max( + CatchHigh, + FuncInfo.CatchHandlerMaxState[cast(HT.Handler)]); + } assert(TBME.TryLow <= TBME.TryHigh); OS.EmitIntValue(TBME.TryLow, 4); // TryLow @@ -456,7 +467,10 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { OS.EmitIntValue(HT.Adjectives, 4); // Adjectives OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); // Type OS.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset - OS.EmitValue(create32bitRef(HT.Handler), 4); // Handler + if (HT.HandlerMBB) // Handler + OS.EmitValue(create32bitRef(HT.HandlerMBB->getSymbol()), 4); + else + OS.EmitValue(create32bitRef(HT.Handler), 4); if (shouldEmitPersonality) { MCSymbol *ParentFrameOffset = diff --git a/lib/CodeGen/BranchFolding.cpp b/lib/CodeGen/BranchFolding.cpp index 260ab537053..9102a3da123 100644 --- a/lib/CodeGen/BranchFolding.cpp +++ b/lib/CodeGen/BranchFolding.cpp @@ -1001,7 +1001,7 @@ bool BranchFolder::TailMergeBlocks(MachineFunction &MF) { // Failing case: the only way IBB can be reached from PBB is via // exception handling. Happens for landing pads. Would be nice to have // a bit in the edge so we didn't have to do all this. - if (IBB->isLandingPad()) { + if (IBB->isEHPad()) { MachineFunction::iterator IP = PBB; IP++; MachineBasicBlock *PredNextBB = nullptr; if (IP != MF.end()) @@ -1178,13 +1178,13 @@ ReoptimizeBlock: // explicitly. Landing pads should not do this since the landing-pad table // points to this block. Blocks with their addresses taken shouldn't be // optimized away. - if (IsEmptyBlock(MBB) && !MBB->isLandingPad() && !MBB->hasAddressTaken()) { + if (IsEmptyBlock(MBB) && !MBB->isEHPad() && !MBB->hasAddressTaken()) { // Dead block? Leave for cleanup later. if (MBB->pred_empty()) return MadeChange; if (FallThrough == MF.end()) { // TODO: Simplify preds to not branch here if possible! - } else if (FallThrough->isLandingPad()) { + } else if (FallThrough->isEHPad()) { // Don't rewrite to a landing pad fallthough. That could lead to the case // where a BB jumps to more than one landing pad. // TODO: Is it ever worth rewriting predecessors which don't already @@ -1241,7 +1241,7 @@ ReoptimizeBlock: // AnalyzeBranch. if (PriorCond.empty() && !PriorTBB && MBB->pred_size() == 1 && PrevBB.succ_size() == 1 && - !MBB->hasAddressTaken() && !MBB->isLandingPad()) { + !MBB->hasAddressTaken() && !MBB->isEHPad()) { DEBUG(dbgs() << "\nMerging into block: " << PrevBB << "From MBB: " << *MBB); // Remove redundant DBG_VALUEs first. @@ -1472,7 +1472,7 @@ ReoptimizeBlock: // see if it has a fall-through into its successor. bool CurFallsThru = MBB->canFallThrough(); - if (!MBB->isLandingPad()) { + if (!MBB->isEHPad()) { // Check all the predecessors of this block. If one of them has no fall // throughs, move this block right after it. for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), @@ -1523,7 +1523,7 @@ ReoptimizeBlock: // fallthrough to happen. if (SuccBB != MBB && &*SuccPrev != MBB && !SuccPrev->canFallThrough() && !CurUnAnalyzable && - !SuccBB->isLandingPad()) { + !SuccBB->isEHPad()) { MBB->moveBefore(SuccBB); MadeChange = true; goto ReoptimizeBlock; diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index eaa4b5b238d..75e3a701d34 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -299,7 +299,7 @@ void LiveIntervals::computeLiveInRegUnits() { const MachineBasicBlock *MBB = MFI; // We only care about ABI blocks: Entry + landing pads. - if ((MFI != MF->begin() && !MBB->isLandingPad()) || MBB->livein_empty()) + if ((MFI != MF->begin() && !MBB->isEHPad()) || MBB->livein_empty()) continue; // Create phi-defs at Begin for all live-in registers. diff --git a/lib/CodeGen/LiveVariables.cpp b/lib/CodeGen/LiveVariables.cpp index 1f5f3047e63..6e843b0d6f9 100644 --- a/lib/CodeGen/LiveVariables.cpp +++ b/lib/CodeGen/LiveVariables.cpp @@ -598,7 +598,7 @@ void LiveVariables::runOnBlock(MachineBasicBlock *MBB, const unsigned NumRegs) { for (MachineBasicBlock::const_succ_iterator SI = MBB->succ_begin(), SE = MBB->succ_end(); SI != SE; ++SI) { MachineBasicBlock *SuccMBB = *SI; - if (SuccMBB->isLandingPad()) + if (SuccMBB->isEHPad()) continue; for (unsigned LI : SuccMBB->liveins()) { if (!TRI->isInAllocatableClass(LI)) diff --git a/lib/CodeGen/MIRParser/MIParser.cpp b/lib/CodeGen/MIRParser/MIParser.cpp index 83ba5a2c90b..c09f279a25f 100644 --- a/lib/CodeGen/MIRParser/MIParser.cpp +++ b/lib/CodeGen/MIRParser/MIParser.cpp @@ -368,7 +368,7 @@ bool MIParser::parseBasicBlockDefinition( MBB->setAlignment(Alignment); if (HasAddressTaken) MBB->setHasAddressTaken(); - MBB->setIsLandingPad(IsLandingPad); + MBB->setIsEHPad(IsLandingPad); return false; } diff --git a/lib/CodeGen/MIRPrinter.cpp b/lib/CodeGen/MIRPrinter.cpp index 297e1f813a0..bfcc56f680e 100644 --- a/lib/CodeGen/MIRPrinter.cpp +++ b/lib/CodeGen/MIRPrinter.cpp @@ -439,7 +439,7 @@ void MIPrinter::print(const MachineBasicBlock &MBB) { OS << "address-taken"; HasAttributes = true; } - if (MBB.isLandingPad()) { + if (MBB.isEHPad()) { OS << (HasAttributes ? ", " : " ("); OS << "landing-pad"; HasAttributes = true; diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp index c30b95a6b2d..b2bbe09176d 100644 --- a/lib/CodeGen/MachineBasicBlock.cpp +++ b/lib/CodeGen/MachineBasicBlock.cpp @@ -39,8 +39,7 @@ using namespace llvm; #define DEBUG_TYPE "codegen" MachineBasicBlock::MachineBasicBlock(MachineFunction &mf, const BasicBlock *bb) - : BB(bb), Number(-1), xParent(&mf), Alignment(0), IsLandingPad(false), - AddressTaken(false), CachedMCSymbol(nullptr) { + : BB(bb), Number(-1), xParent(&mf) { Insts.Parent = this; } @@ -203,7 +202,7 @@ const MachineBasicBlock *MachineBasicBlock::getLandingPadSuccessor() const { if (succ_size() > 2) return nullptr; for (const_succ_iterator I = succ_begin(), E = succ_end(); I != E; ++I) - if ((*I)->isLandingPad()) + if ((*I)->isEHPad()) return *I; return nullptr; } @@ -266,7 +265,7 @@ void MachineBasicBlock::print(raw_ostream &OS, ModuleSlotTracker &MST, LBB->printAsOperand(OS, /*PrintType=*/false, MST); Comma = ", "; } - if (isLandingPad()) { OS << Comma << "EH LANDING PAD"; Comma = ", "; } + if (isEHPad()) { OS << Comma << "EH LANDING PAD"; Comma = ", "; } if (hasAddressTaken()) { OS << Comma << "ADDRESS TAKEN"; Comma = ", "; } if (Alignment) OS << Comma << "Align " << Alignment << " (" << (1u << Alignment) @@ -338,7 +337,7 @@ MachineBasicBlock::addLiveIn(MCPhysReg PhysReg, const TargetRegisterClass *RC) { assert(getParent() && "MBB must be inserted in function"); assert(TargetRegisterInfo::isPhysicalRegister(PhysReg) && "Expected physreg"); assert(RC && "Register class is required"); - assert((isLandingPad() || this == &getParent()->front()) && + assert((isEHPad() || this == &getParent()->front()) && "Only the entry block and landing pads can have physreg live ins"); bool LiveIn = isLiveIn(PhysReg); @@ -396,7 +395,7 @@ void MachineBasicBlock::updateTerminator() { // its layout successor, insert a branch. First we have to locate the // only non-landing-pad successor, as that is the fallthrough block. for (succ_iterator SI = succ_begin(), SE = succ_end(); SI != SE; ++SI) { - if ((*SI)->isLandingPad()) + if ((*SI)->isEHPad()) continue; assert(!TBB && "Found more than one non-landing-pad successor!"); TBB = *SI; @@ -432,7 +431,7 @@ void MachineBasicBlock::updateTerminator() { // as the fallthrough successor. MachineBasicBlock *FallthroughBB = nullptr; for (succ_iterator SI = succ_begin(), SE = succ_end(); SI != SE; ++SI) { - if ((*SI)->isLandingPad() || *SI == TBB) + if ((*SI)->isEHPad() || *SI == TBB) continue; assert(!FallthroughBB && "Found more than one fallthrough successor."); FallthroughBB = *SI; @@ -662,7 +661,7 @@ MachineBasicBlock * MachineBasicBlock::SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P) { // Splitting the critical edge to a landing pad block is non-trivial. Don't do // it in this generic function. - if (Succ->isLandingPad()) + if (Succ->isEHPad()) return nullptr; MachineFunction *MF = getParent(); @@ -1046,7 +1045,7 @@ bool MachineBasicBlock::CorrectExtraCFGEdges(MachineBasicBlock *DestA, while (SI != succ_end()) { const MachineBasicBlock *MBB = *SI; if (!SeenMBBs.insert(MBB).second || - (MBB != DestA && MBB != DestB && !MBB->isLandingPad())) { + (MBB != DestA && MBB != DestB && !MBB->isEHPad())) { // This is a superfluous edge, remove it. SI = removeSuccessor(SI); Changed = true; diff --git a/lib/CodeGen/MachineBlockPlacement.cpp b/lib/CodeGen/MachineBlockPlacement.cpp index b77c803f77f..e515a89e782 100644 --- a/lib/CodeGen/MachineBlockPlacement.cpp +++ b/lib/CodeGen/MachineBlockPlacement.cpp @@ -678,7 +678,7 @@ MachineBlockPlacement::findBestLoopExit(MachineFunction &F, MachineLoop &L, uint32_t WeightScale = 0; uint32_t SumWeight = MBPI->getSumForBlock(MBB, WeightScale); for (MachineBasicBlock *Succ : MBB->successors()) { - if (Succ->isLandingPad()) + if (Succ->isEHPad()) continue; if (Succ == MBB) continue; diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index ebef22e462d..45501cbb01b 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -529,7 +529,7 @@ void MachineLICM::HoistRegionPostRA() { // If the header of the loop containing this basic block is a landing pad, // then don't try to hoist instructions out of this loop. const MachineLoop *ML = MLI->getLoopFor(BB); - if (ML && ML->getHeader()->isLandingPad()) continue; + if (ML && ML->getHeader()->isEHPad()) continue; // Conservatively treat live-in's as an external def. // FIXME: That means a reload that're reused in successor block(s) will not @@ -725,7 +725,7 @@ void MachineLICM::HoistOutOfLoop(MachineDomTreeNode *HeaderN) { // If the header of the loop containing this basic block is a landing pad, // then don't try to hoist instructions out of this loop. const MachineLoop *ML = MLI->getLoopFor(BB); - if (ML && ML->getHeader()->isLandingPad()) + if (ML && ML->getHeader()->isEHPad()) continue; // If this subregion is not in the top level loop at all, exit. diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp index 4d5bd83a032..6f9721a0d35 100644 --- a/lib/CodeGen/MachineModuleInfo.cpp +++ b/lib/CodeGen/MachineModuleInfo.cpp @@ -209,6 +209,7 @@ bool MachineModuleInfo::doInitialization(Module &M) { CurCallSite = 0; CallsEHReturn = false; CallsUnwindInit = false; + HasEHFunclets = false; DbgInfoAvailable = UsesVAFloatArgument = UsesMorestackAddr = false; // Always emit some info, by default "no personality" info. Personalities.push_back(nullptr); @@ -249,6 +250,7 @@ void MachineModuleInfo::EndFunction() { FilterEnds.clear(); CallsEHReturn = false; CallsUnwindInit = false; + HasEHFunclets = false; VariableDbgInfos.clear(); } diff --git a/lib/CodeGen/MachineSink.cpp b/lib/CodeGen/MachineSink.cpp index 1b9be50068a..f6b5f08036d 100644 --- a/lib/CodeGen/MachineSink.cpp +++ b/lib/CodeGen/MachineSink.cpp @@ -667,7 +667,7 @@ MachineBasicBlock *MachineSinking::FindSuccToSinkTo(MachineInstr *MI, // It's not safe to sink instructions to EH landing pad. Control flow into // landing pad is implicitly defined. - if (SuccToSinkTo && SuccToSinkTo->isLandingPad()) + if (SuccToSinkTo && SuccToSinkTo->isEHPad()) return nullptr; return SuccToSinkTo; diff --git a/lib/CodeGen/MachineVerifier.cpp b/lib/CodeGen/MachineVerifier.cpp index 078e5769f0a..6eb9d342ba2 100644 --- a/lib/CodeGen/MachineVerifier.cpp +++ b/lib/CodeGen/MachineVerifier.cpp @@ -508,7 +508,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) { // If this block has allocatable physical registers live-in, check that // it is an entry block or landing pad. for (unsigned LI : MBB->liveins()) { - if (isAllocatable(LI) && !MBB->isLandingPad() && + if (isAllocatable(LI) && !MBB->isEHPad() && MBB != MBB->getParent()->begin()) { report("MBB has allocable live-in, but isn't entry or landing-pad.", MBB); } @@ -519,7 +519,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) { SmallPtrSet LandingPadSuccs; for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(), E = MBB->succ_end(); I != E; ++I) { - if ((*I)->isLandingPad()) + if ((*I)->isEHPad()) LandingPadSuccs.insert(*I); if (!FunctionBlocks.count(*I)) report("MBB has successor that isn't part of the function.", MBB); @@ -1606,7 +1606,7 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR, assert(LiveInts->isLiveInToMBB(LR, MFI)); // We don't know how to track physregs into a landing pad. if (!TargetRegisterInfo::isVirtualRegister(Reg) && - MFI->isLandingPad()) { + MFI->isEHPad()) { if (&*MFI == EndMBB) break; ++MFI; diff --git a/lib/CodeGen/PHIElimination.cpp b/lib/CodeGen/PHIElimination.cpp index d3433018004..2c937926d0a 100644 --- a/lib/CodeGen/PHIElimination.cpp +++ b/lib/CodeGen/PHIElimination.cpp @@ -548,7 +548,7 @@ void PHIElimination::analyzePHINodes(const MachineFunction& MF) { bool PHIElimination::SplitPHIEdges(MachineFunction &MF, MachineBasicBlock &MBB, MachineLoopInfo *MLI) { - if (MBB.empty() || !MBB.front().isPHI() || MBB.isLandingPad()) + if (MBB.empty() || !MBB.front().isPHI() || MBB.isEHPad()) return false; // Quick exit for basic blocks without PHIs. const MachineLoop *CurLoop = MLI ? MLI->getLoopFor(&MBB) : nullptr; diff --git a/lib/CodeGen/PHIEliminationUtils.cpp b/lib/CodeGen/PHIEliminationUtils.cpp index 99bbad1cc28..4cabc3a8c1f 100644 --- a/lib/CodeGen/PHIEliminationUtils.cpp +++ b/lib/CodeGen/PHIEliminationUtils.cpp @@ -28,7 +28,7 @@ llvm::findPHICopyInsertPoint(MachineBasicBlock* MBB, MachineBasicBlock* SuccMBB, // Usually, we just want to insert the copy before the first terminator // instruction. However, for the edge going to a landing pad, we must insert // the copy before the call/invoke instruction. - if (!SuccMBB->isLandingPad()) + if (!SuccMBB->isEHPad()) return MBB->getFirstTerminator(); // Discover any defs/uses in this basic block. diff --git a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index ec3dab55464..c0d14c1780d 100644 --- a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -252,16 +252,17 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, // Mark landing pad blocks. SmallVector LPads; for (BB = Fn->begin(); BB != EB; ++BB) { - if (const auto *Invoke = dyn_cast(BB->getTerminator())) - MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad(); - if (BB->isLandingPad()) - LPads.push_back(BB->getLandingPadInst()); + if (BB->isEHPad()) + MBBMap[BB]->setIsEHPad(); + const Instruction *FNP = BB->getFirstNonPHI(); + if (const auto *LPI = dyn_cast(FNP)) + LPads.push_back(LPI); } // If this is an MSVC EH personality, we need to do a bit more work. - EHPersonality Personality = EHPersonality::Unknown; - if (Fn->hasPersonalityFn()) - Personality = classifyEHPersonality(Fn->getPersonalityFn()); + if (!Fn->hasPersonalityFn()) + return; + EHPersonality Personality = classifyEHPersonality(Fn->getPersonalityFn()); if (!isMSVCEHPersonality(Personality)) return; @@ -272,8 +273,13 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, WinEHFuncInfo &EHInfo = MMI.getWinEHFuncInfo(&fn); if (Personality == EHPersonality::MSVC_CXX) { + // Calculate state numbers and then map from funclet BBs to MBBs. const Function *WinEHParentFn = MMI.getWinEHParent(&fn); calculateWinCXXEHStateNumbers(WinEHParentFn, EHInfo); + for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) + for (WinEHHandlerType &H : TBME.HandlerArray) + if (const auto *BB = dyn_cast(H.Handler)) + H.HandlerMBB = MBBMap[BB]; } // Copy the state numbers to LandingPadInfo for the current function, which diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 48811bdea59..63328200f8d 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1158,30 +1158,56 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) { llvm_unreachable("Can't get register for value!"); } -void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) { - report_fatal_error("visitCleanupRet not yet implemented!"); -} +void SelectionDAGBuilder::visitCatchPad(const CatchPadInst &I) { + // Update machine-CFG edges. + MachineBasicBlock *PadMBB = FuncInfo.MBB; + MachineBasicBlock *CatchingMBB = FuncInfo.MBBMap[I.getNormalDest()]; + MachineBasicBlock *UnwindMBB = FuncInfo.MBBMap[I.getUnwindDest()]; + PadMBB->addSuccessor(CatchingMBB); + PadMBB->addSuccessor(UnwindMBB); -void SelectionDAGBuilder::visitCatchEndPad(const CatchEndPadInst &I) { - report_fatal_error("visitCatchEndPad not yet implemented!"); + CatchingMBB->setIsEHFuncletEntry(); + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); + MMI.setHasEHFunclets(true); } void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) { - report_fatal_error("visitCatchRet not yet implemented!"); -} + // Update machine-CFG edge. + MachineBasicBlock *PadMBB = FuncInfo.MBB; + MachineBasicBlock *TargetMBB = FuncInfo.MBBMap[I.getSuccessor()]; + PadMBB->addSuccessor(TargetMBB); -void SelectionDAGBuilder::visitCatchPad(const CatchPadInst &I) { - report_fatal_error("visitCatchPad not yet implemented!"); + // Create the terminator node. + SDValue Ret = DAG.getNode(ISD::CATCHRET, getCurSDLoc(), MVT::Other, + getControlRoot(), DAG.getBasicBlock(TargetMBB)); + DAG.setRoot(Ret); } -void SelectionDAGBuilder::visitTerminatePad(const TerminatePadInst &TPI) { - report_fatal_error("visitTerminatePad not yet implemented!"); +void SelectionDAGBuilder::visitCatchEndPad(const CatchEndPadInst &I) { + // If this unwinds to caller, we don't need a DAG node hanging around. + if (!I.hasUnwindDest()) + return; + + // Update machine-CFG edge. + MachineBasicBlock *PadMBB = FuncInfo.MBB; + MachineBasicBlock *UnwindMBB = FuncInfo.MBBMap[I.getUnwindDest()]; + PadMBB->addSuccessor(UnwindMBB); } void SelectionDAGBuilder::visitCleanupPad(const CleanupPadInst &CPI) { + MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); + MMI.setHasEHFunclets(true); report_fatal_error("visitCleanupPad not yet implemented!"); } +void SelectionDAGBuilder::visitCleanupRet(const CleanupReturnInst &I) { + report_fatal_error("visitCleanupRet not yet implemented!"); +} + +void SelectionDAGBuilder::visitTerminatePad(const TerminatePadInst &TPI) { + report_fatal_error("visitTerminatePad not yet implemented!"); +} + void SelectionDAGBuilder::visitRet(const ReturnInst &I) { const TargetLowering &TLI = DAG.getTargetLoweringInfo(); auto &DL = DAG.getDataLayout(); @@ -2021,7 +2047,7 @@ void SelectionDAGBuilder::visitResume(const ResumeInst &RI) { } void SelectionDAGBuilder::visitLandingPad(const LandingPadInst &LP) { - assert(FuncInfo.MBB->isLandingPad() && + assert(FuncInfo.MBB->isEHPad() && "Call to landingpad not in landing pad!"); MachineBasicBlock *MBB = FuncInfo.MBB; @@ -5094,7 +5120,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { assert(Reg && "cannot get exception code on this platform"); MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout()); const TargetRegisterClass *PtrRC = TLI.getRegClassFor(PtrVT); - assert(FuncInfo.MBB->isLandingPad() && "eh.exceptioncode in non-lpad"); + assert(FuncInfo.MBB->isEHPad() && "eh.exceptioncode in non-lpad"); unsigned VReg = FuncInfo.MBB->addLiveIn(Reg, PtrRC); SDValue N = DAG.getCopyFromReg(DAG.getEntryNode(), getCurSDLoc(), VReg, PtrVT); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp index 4c8658e51ca..a625e4973fd 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp @@ -278,6 +278,10 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::CALLSEQ_START: return "callseq_start"; case ISD::CALLSEQ_END: return "callseq_end"; + // EH instructions + case ISD::CATCHRET: return "catchret"; + case ISD::CLEANUPRET: return "cleanupret"; + // Other operators case ISD::LOAD: return "load"; case ISD::STORE: return "store"; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 7419ce547e0..be6ccb3ac61 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -19,6 +19,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/Analysis/CFG.h" +#include "llvm/Analysis/LibCallSemantics.h" #include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/FastISel.h" @@ -969,7 +970,7 @@ bool SelectionDAGISel::PrepareEHLandingPad() { InvokeBB->addSuccessor(ClauseBB); // Mark the clause as a landing pad or MI passes will delete it. - ClauseBB->setIsLandingPad(); + ClauseBB->setIsEHPad(); } } @@ -998,9 +999,9 @@ bool SelectionDAGISel::PrepareEHLandingPad() { static bool isFoldedOrDeadInstruction(const Instruction *I, FunctionLoweringInfo *FuncInfo) { return !I->mayWriteToMemory() && // Side-effecting instructions aren't folded. - !isa(I) && // Terminators aren't folded. + !isa(I) && // Terminators aren't folded. !isa(I) && // Debug instructions aren't folded. - !isa(I) && // Landingpad instructions aren't folded. + !I->isEHPad() && // EH pad instructions aren't folded. !FuncInfo->isExportedInst(I); // Exported instrs must be computed. } @@ -1163,6 +1164,7 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { if (!PrepareEHLandingPad()) continue; + // Before doing SelectionDAG ISel, see if FastISel has been requested. if (FastIS) { FastIS->startNewBlock(); @@ -1251,7 +1253,8 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) { // For the purpose of debugging, just abort. report_fatal_error("FastISel didn't select the entire block"); - if (!Inst->getType()->isVoidTy() && !Inst->use_empty()) { + if (!Inst->getType()->isVoidTy() && !Inst->getType()->isTokenTy() && + !Inst->use_empty()) { unsigned &R = FuncInfo->ValueMap[Inst]; if (!R) R = FuncInfo->CreateRegs(Inst->getType()); diff --git a/lib/CodeGen/WinEHPrepare.cpp b/lib/CodeGen/WinEHPrepare.cpp index 3cc9c395c22..df2d5db8c67 100644 --- a/lib/CodeGen/WinEHPrepare.cpp +++ b/lib/CodeGen/WinEHPrepare.cpp @@ -2608,7 +2608,8 @@ static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow, HT.TypeDescriptor = cast(CS->getAggregateElement(1)->stripPointerCasts()); } - HT.Handler = CPI->getParent(); + HT.Handler = CPI->getNormalDest(); + HT.HandlerMBB = nullptr; // FIXME: Pass CPI->getArgOperand(1). HT.CatchObjRecoverIdx = -1; TBME.HandlerArray.push_back(HT); @@ -2684,6 +2685,7 @@ void WinEHNumbering::createTryBlockMapEntry(int TryLow, int TryHigh, cast(CS->getAggregateElement(1)->stripPointerCasts()); } HT.Handler = cast(CH->getHandlerBlockOrFunc()); + HT.HandlerMBB = nullptr; HT.CatchObjRecoverIdx = CH->getExceptionVarIndex(); TBME.HandlerArray.push_back(HT); } diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index ea842a68020..d7ce7fc7552 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -6931,7 +6931,7 @@ void ARMTargetLowering::EmitSjLjDispatchBlock(MachineInstr *MI, MachineModuleInfo &MMI = MF->getMMI(); for (MachineFunction::iterator BB = MF->begin(), E = MF->end(); BB != E; ++BB) { - if (!BB->isLandingPad()) continue; + if (!BB->isEHPad()) continue; // FIXME: We should assert that the EH_LABEL is the first MI in the landing // pad. @@ -6979,7 +6979,7 @@ void ARMTargetLowering::EmitSjLjDispatchBlock(MachineInstr *MI, // Shove the dispatch's address into the return slot in the function context. MachineBasicBlock *DispatchBB = MF->CreateMachineBasicBlock(); - DispatchBB->setIsLandingPad(); + DispatchBB->setIsEHPad(); MachineBasicBlock *TrapBB = MF->CreateMachineBasicBlock(); unsigned trap_opcode; @@ -7245,7 +7245,7 @@ void ARMTargetLowering::EmitSjLjDispatchBlock(MachineInstr *MI, BB->succ_end()); while (!Successors.empty()) { MachineBasicBlock *SMBB = Successors.pop_back_val(); - if (SMBB->isLandingPad()) { + if (SMBB->isEHPad()) { BB->removeSuccessor(SMBB); MBBLPads.push_back(SMBB); } @@ -7293,7 +7293,7 @@ void ARMTargetLowering::EmitSjLjDispatchBlock(MachineInstr *MI, // landing pad now. for (SmallVectorImpl::iterator I = MBBLPads.begin(), E = MBBLPads.end(); I != E; ++I) - (*I)->setIsLandingPad(false); + (*I)->setIsEHPad(false); // The instruction is gone now. MI->eraseFromParent(); diff --git a/lib/Target/Hexagon/BitTracker.cpp b/lib/Target/Hexagon/BitTracker.cpp index 111d3b4d01f..ec08ccc629b 100644 --- a/lib/Target/Hexagon/BitTracker.cpp +++ b/lib/Target/Hexagon/BitTracker.cpp @@ -951,7 +951,7 @@ void BT::visitBranchesFrom(const MachineInstr *BI) { // be processed. for (succ_iterator I = B.succ_begin(), E = B.succ_end(); I != E; ++I) { const MachineBasicBlock *SB = *I; - if (SB->isLandingPad()) + if (SB->isEHPad()) Targets.insert(SB); } if (FallsThrough) { diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 88b54b5209d..c2e176c2c6a 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -405,7 +405,7 @@ bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* // If this is a landing pad, it isn't a fall through. If it has no preds, // then nothing falls through to it. - if (MBB->isLandingPad() || MBB->pred_empty()) + if (MBB->isEHPad() || MBB->pred_empty()) return false; // If there isn't exactly one predecessor, it can't be a fall through. diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index 664508fc7d7..c81555116d7 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -806,7 +806,7 @@ MachineBasicBlock *Filler::selectSuccBB(MachineBasicBlock &B) const { const MachineBasicBlock *Dst1) { return Prob.getEdgeWeight(&B, Dst0) < Prob.getEdgeWeight(&B, Dst1); }); - return S->isLandingPad() ? nullptr : S; + return S->isEHPad() ? nullptr : S; } std::pair diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 0f8736f311e..f9f79955828 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -407,6 +407,7 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, setOperationAction(ISD::SETCC , MVT::i64 , Custom); } setOperationAction(ISD::EH_RETURN , MVT::Other, Custom); + setOperationAction(ISD::CATCHRET , MVT::Other, Custom); // NOTE: EH_SJLJ_SETJMP/_LONGJMP supported here is NOT intended to support // SjLj exception handling but a light-weight setjmp/longjmp replacement to // support continuation, user-level threading, and etc.. As a result, no @@ -16664,6 +16665,25 @@ SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const { DAG.getRegister(StoreAddrReg, PtrVT)); } +SDValue X86TargetLowering::LowerCATCHRET(SDValue Op, SelectionDAG &DAG) const { + SDValue Chain = Op.getOperand(0); + SDValue Dest = Op.getOperand(1); + SDLoc DL(Op); + + MVT PtrVT = getPointerTy(DAG.getDataLayout()); + unsigned ReturnReg = (PtrVT == MVT::i64 ? X86::RAX : X86::EAX); + + // Load the address of the destination block. + MachineBasicBlock *DestMBB = cast(Dest)->getBasicBlock(); + SDValue BlockPtr = DAG.getMCSymbol(DestMBB->getSymbol(), PtrVT); + unsigned WrapperKind = + Subtarget->isPICStyleRIPRel() ? X86ISD::WrapperRIP : X86ISD::Wrapper; + SDValue WrappedPtr = DAG.getNode(WrapperKind, DL, PtrVT, BlockPtr); + Chain = DAG.getCopyToReg(Chain, DL, ReturnReg, WrappedPtr); + return DAG.getNode(X86ISD::CATCHRET, DL, MVT::Other, Chain, + DAG.getRegister(ReturnReg, PtrVT)); +} + SDValue X86TargetLowering::lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); @@ -18903,6 +18923,7 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { return LowerFRAME_TO_ARGS_OFFSET(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG); + case ISD::CATCHRET: return LowerCATCHRET(Op, DAG); case ISD::EH_SJLJ_SETJMP: return lowerEH_SJLJ_SETJMP(Op, DAG); case ISD::EH_SJLJ_LONGJMP: return lowerEH_SJLJ_LONGJMP(Op, DAG); case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG); @@ -19238,6 +19259,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::EH_SJLJ_SETJMP: return "X86ISD::EH_SJLJ_SETJMP"; case X86ISD::EH_SJLJ_LONGJMP: return "X86ISD::EH_SJLJ_LONGJMP"; case X86ISD::EH_RETURN: return "X86ISD::EH_RETURN"; + case X86ISD::CATCHRET: return "X86ISD::CATCHRET"; case X86ISD::TC_RETURN: return "X86ISD::TC_RETURN"; case X86ISD::FNSTCW16m: return "X86ISD::FNSTCW16m"; case X86ISD::FNSTSW16r: return "X86ISD::FNSTSW16r"; diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 824cd736ad7..69bb0e3b0e4 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -261,6 +261,8 @@ namespace llvm { // Exception Handling helpers. EH_RETURN, + CATCHRET, + // SjLj exception handling setjmp. EH_SJLJ_SETJMP, @@ -998,6 +1000,7 @@ namespace llvm { SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const; SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerCATCHRET(SDValue Op, SelectionDAG &DAG) const; SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const; SDValue lowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; diff --git a/lib/Target/X86/X86InstrCompiler.td b/lib/Target/X86/X86InstrCompiler.td index 28219dc7788..18c8d7d61f3 100644 --- a/lib/Target/X86/X86InstrCompiler.td +++ b/lib/Target/X86/X86InstrCompiler.td @@ -152,6 +152,15 @@ def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr), } +let isTerminator = 1, isBarrier = 1, hasCtrlDep = 1, isCodeGenOnly = 1 in { +def CATCHRET : I<0xC3, RawFrm, (outs), (ins GR32:$addr), + "ret{l}\t# CATCHRET", + [(X86catchret GR32:$addr)], IIC_RET>, Sched<[WriteJumpLd]>; +def CATCHRET64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr), + "ret{q}\t# CATCHRET", + [(X86catchret GR64:$addr)], IIC_RET>, Sched<[WriteJumpLd]>; +} + let hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1, usesCustomInserter = 1 in { def EH_SjLj_SetJmp32 : I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$buf), diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 9e61ba3aa17..5618c779608 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -205,6 +205,8 @@ def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR, def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET, [SDNPHasChain]>; +def X86catchret : SDNode<"X86ISD::CATCHRET", SDT_X86EHRET, [SDNPHasChain]>; + def X86eh_sjlj_setjmp : SDNode<"X86ISD::EH_SJLJ_SETJMP", SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisPtrTy<1>]>, diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp index 36c74023d7b..c190bbe722e 100644 --- a/lib/Target/X86/X86MCInstLower.cpp +++ b/lib/Target/X86/X86MCInstLower.cpp @@ -531,6 +531,12 @@ ReSimplify: break; } + case X86::CATCHRET: { + OutMI = MCInst(); + OutMI.setOpcode(getRetOpcode(AsmPrinter.getSubtarget())); + break; + } + // TAILJMPd, TAILJMPd64 - Lower to the correct jump instructions. case X86::TAILJMPr: case X86::TAILJMPd: diff --git a/lib/Target/X86/X86WinEHState.cpp b/lib/Target/X86/X86WinEHState.cpp index d039a0d4ca6..19f574ad746 100644 --- a/lib/Target/X86/X86WinEHState.cpp +++ b/lib/Target/X86/X86WinEHState.cpp @@ -471,6 +471,8 @@ int WinEHStatePass::escapeRegNode(Function &F) { void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo, Function &F, int BaseState) { + Function *RestoreFrame = + Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe); // Iterate all the instructions and emit state number stores. for (BasicBlock &BB : F) { for (Instruction &I : BB) { @@ -489,6 +491,14 @@ void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode, insertStateNumberStore(ParentRegNode, II, State); } } + + // Insert calls to llvm.x86.seh.restoreframe at catchret destinations. + if (auto *CR = dyn_cast(BB.getTerminator())) { + //llvm::errs() << "BB: " << BB << '\n'; + //llvm::errs() << "CR->getSuccessor(): " << *CR->getSuccessor() << '\n'; + IRBuilder<> Builder(CR->getSuccessor()->begin()); + Builder.CreateCall(RestoreFrame, {}); + } } } diff --git a/test/CodeGen/X86/win-catchpad.ll b/test/CodeGen/X86/win-catchpad.ll new file mode 100644 index 00000000000..607d948e3d1 --- /dev/null +++ b/test/CodeGen/X86/win-catchpad.ll @@ -0,0 +1,130 @@ +; RUN: llc -mtriple=i686-pc-windows-msvc < %s | FileCheck --check-prefix=X86 %s +; RUN: llc -mtriple=x86_64-pc-windows-msvc < %s | FileCheck --check-prefix=X64 %s + +; Loosely based on IR for this C++ source code: +; void f(int p); +; int main() { +; try { +; f(1); +; } catch (int) { +; f(2); +; } catch (...) { +; f(3); +; } +; } + +%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } +%eh.CatchableType = type { i32, i8*, i32, i32, i32, i32, i8* } +%eh.CatchableTypeArray.1 = type { i32, [1 x %eh.CatchableType*] } +%eh.ThrowInfo = type { i32, i8*, i8*, i8* } +%eh.CatchHandlerType = type { i32, i8* } + +$"\01??_R0H@8" = comdat any + +@"\01??_7type_info@@6B@" = external constant i8* +@"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat + +@llvm.eh.handlertype.H.0 = private unnamed_addr constant %eh.CatchHandlerType { i32 0, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) }, section "llvm.metadata" +@llvm.eh.handlertype.H.1 = private unnamed_addr constant %eh.CatchHandlerType { i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) }, section "llvm.metadata" + +declare void @f(i32 %p) +declare i32 @__CxxFrameHandler3(...) + +define i32 @try_catch_catch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { +entry: + invoke void @f(i32 1) + to label %try.cont unwind label %catch.dispatch + +catch.dispatch: ; preds = %entry + %0 = catchpad [%eh.CatchHandlerType* @llvm.eh.handlertype.H.0, i8* null] + to label %catch unwind label %catch.dispatch.2 + +catch: ; preds = %catch.dispatch + invoke void @f(i32 2) + to label %invoke.cont.2 unwind label %catchendblock + +invoke.cont.2: ; preds = %catch + catchret %0 to label %try.cont + +catch.dispatch.2: ; preds = %catch.dispatch + %1 = catchpad [%eh.CatchHandlerType* @llvm.eh.handlertype.H.0, i8* null] + to label %catch.2 unwind label %catchendblock + +catch.2: ; preds = %catch.dispatch.2 + invoke void @f(i32 3) + to label %invoke.cont.3 unwind label %catchendblock + +invoke.cont.3: ; preds = %catch.2 + catchret %1 to label %try.cont + +try.cont: ; preds = %entry, %invoke.cont.2, %invoke.cont.3 + ret i32 0 + +catchendblock: ; preds = %catch, %catch.2, %catch.dispatch.2 + catchendpad unwind to caller +} + +; X86-LABEL: _try_catch_catch: +; X86: movl $0, -{{[0-9]+}}(%ebp) +; X86: movl $1, (%esp) +; X86: calll _f +; X86: [[contbb:LBB0_[0-9]+]]: +; X86: movl -{{[0-9]+}}(%ebp), %esp +; X86: retl + +; X86: [[catch1bb:LBB0_[0-9]+]]: # %catch{{$}} +; X86: movl $1, -{{[0-9]+}}(%ebp) +; X86: movl $2, (%esp) +; X86: calll _f +; X86: movl $[[contbb]], %eax +; X86-NEXT: retl + +; X86: [[catch2bb:LBB0_[0-9]+]]: # %catch.2{{$}} +; X86: movl $1, -{{[0-9]+}}(%ebp) +; X86: movl $3, (%esp) +; X86: calll _f +; X86: movl $[[contbb]], %eax +; X86-NEXT: retl + +; X86: L__ehtable$try_catch_catch: +; X86: $handlerMap$0$try_catch_catch: +; X86: .long 0 +; X86: .long "??_R0H@8" +; X86: .long 0 +; X86: .long [[catch1bb]] +; X86: .long 0 +; X86: .long "??_R0H@8" +; X86: .long 0 +; X86: .long [[catch2bb]] + +; X64-LABEL: try_catch_catch: +; X64: movl $1, %ecx +; X64: callq f +; X64: [[contbb:\.LBB0_[0-9]+]]: +; X64: retq + +; X64: [[catch1bb:\.LBB0_[0-9]+]]: # %catch{{$}} +; X64: movl $2, %ecx +; X64: callq f +; X64: leaq [[contbb]](%rip), %rax +; X64: retq + +; X64: [[catch2bb:\.LBB0_[0-9]+]]: # %catch.2{{$}} +; X64: movl $3, %ecx +; X64: callq f +; X64: leaq [[contbb]](%rip), %rax +; X64: retq + +; FIXME: Get rid of these parent_frame_offset things below. They are leftover +; from our IR outlining strategy. +; X64: $handlerMap$0$try_catch_catch: +; X64: .long 0 +; X64: .long "??_R0H@8"@IMGREL +; X64: .long 0 +; X64: .long [[catch1bb]]@IMGREL +; X64 .long .Lcatch$parent_frame_offset +; X64: .long 0 +; X64: .long "??_R0H@8"@IMGREL +; X64: .long 0 +; X64: .long [[catch2bb]]@IMGREL +; X64 .long .Lcatch.2$parent_frame_offset