diff options
39 files changed, 108 insertions, 8039 deletions
diff --git a/llvm/include/llvm/CodeGen/WinEHFuncInfo.h b/llvm/include/llvm/CodeGen/WinEHFuncInfo.h index 773931ff7cd..89a75058247 100644 --- a/llvm/include/llvm/CodeGen/WinEHFuncInfo.h +++ b/llvm/include/llvm/CodeGen/WinEHFuncInfo.h @@ -33,99 +33,18 @@ class MCSymbol; class MachineBasicBlock; class Value; -enum ActionType { Catch, Cleanup }; - -class ActionHandler { -public: - ActionHandler(BasicBlock *BB, ActionType Type) - : StartBB(BB), Type(Type), EHState(-1), HandlerBlockOrFunc(nullptr) {} - - ActionType getType() const { return Type; } - BasicBlock *getStartBlock() const { return StartBB; } - - bool hasBeenProcessed() { return HandlerBlockOrFunc != nullptr; } - - void setHandlerBlockOrFunc(Constant *F) { HandlerBlockOrFunc = F; } - Constant *getHandlerBlockOrFunc() { return HandlerBlockOrFunc; } - - void setEHState(int State) { EHState = State; } - int getEHState() const { return EHState; } - -private: - BasicBlock *StartBB; - ActionType Type; - int EHState; - - // Can be either a BlockAddress or a Function depending on the EH personality. - Constant *HandlerBlockOrFunc; -}; - -class CatchHandler : public ActionHandler { -public: - CatchHandler(BasicBlock *BB, Constant *Selector, BasicBlock *NextBB) - : ActionHandler(BB, ActionType::Catch), Selector(Selector), - NextBB(NextBB), ExceptionObjectVar(nullptr), - ExceptionObjectIndex(-1) {} - - // Method for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ActionHandler *H) { - return H->getType() == ActionType::Catch; - } - - Constant *getSelector() const { return Selector; } - BasicBlock *getNextBB() const { return NextBB; } - - const Value *getExceptionVar() { return ExceptionObjectVar; } - TinyPtrVector<BasicBlock *> &getReturnTargets() { return ReturnTargets; } - - void setExceptionVar(const Value *Val) { ExceptionObjectVar = Val; } - void setExceptionVarIndex(int Index) { ExceptionObjectIndex = Index; } - int getExceptionVarIndex() const { return ExceptionObjectIndex; } - void setReturnTargets(TinyPtrVector<BasicBlock *> &Targets) { - ReturnTargets = Targets; - } - -private: - Constant *Selector; - BasicBlock *NextBB; - // While catch handlers are being outlined the ExceptionObjectVar field will - // be populated with the instruction in the parent frame that corresponds - // to the exception object (or nullptr if the catch does not use an - // exception object) and the ExceptionObjectIndex field will be -1. - // When the parseEHActions function is called to populate a vector of - // instances of this class, the ExceptionObjectVar field will be nullptr - // and the ExceptionObjectIndex will be the index of the exception object in - // the parent function's localescape block. - const Value *ExceptionObjectVar; - int ExceptionObjectIndex; - TinyPtrVector<BasicBlock *> ReturnTargets; -}; - -class CleanupHandler : public ActionHandler { -public: - CleanupHandler(BasicBlock *BB) : ActionHandler(BB, ActionType::Cleanup) {} - - // Method for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const ActionHandler *H) { - return H->getType() == ActionType::Cleanup; - } -}; - -void parseEHActions(const IntrinsicInst *II, - SmallVectorImpl<std::unique_ptr<ActionHandler>> &Actions); - -// The following structs respresent the .xdata for functions using C++ -// exceptions on Windows. +// The following structs respresent the .xdata tables for various +// Windows-related EH personalities. typedef PointerUnion<const BasicBlock *, MachineBasicBlock *> MBBOrBasicBlock; typedef PointerUnion<const Value *, const MachineBasicBlock *> ValueOrMBB; -struct WinEHUnwindMapEntry { +struct CxxUnwindMapEntry { int ToState; ValueOrMBB Cleanup; }; -/// Similar to WinEHUnwindMapEntry, but supports SEH filters. +/// Similar to CxxUnwindMapEntry, but supports SEH filters. struct SEHUnwindMapEntry { /// If unwinding continues through this handler, transition to the handler at /// this state. This indexes into SEHUnwindMap. @@ -174,13 +93,13 @@ struct WinEHFuncInfo { DenseMap<const CatchReturnInst *, const BasicBlock *> CatchRetSuccessorColorMap; DenseMap<MCSymbol *, std::pair<int, MCSymbol *>> InvokeToStateMap; - SmallVector<WinEHUnwindMapEntry, 4> UnwindMap; + SmallVector<CxxUnwindMapEntry, 4> CxxUnwindMap; SmallVector<WinEHTryBlockMapEntry, 4> TryBlockMap; SmallVector<SEHUnwindMapEntry, 4> SEHUnwindMap; SmallVector<ClrEHUnwindMapEntry, 4> ClrEHUnwindMap; int UnwindHelpFrameIdx = INT_MAX; - int getLastStateNumber() const { return UnwindMap.size() - 1; } + int getLastStateNumber() const { return CxxUnwindMap.size() - 1; } void addIPToStateRange(const BasicBlock *PadBB, MCSymbol *InvokeBegin, MCSymbol *InvokeEnd); diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index d40390ed3b4..fa43eb6a30e 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -429,13 +429,6 @@ def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty]>; -// eh.begincatch takes a pointer returned by a landingpad instruction and -// copies the exception object into the memory pointed to by the second -// parameter. If the second parameter is null, no copy occurs. -def int_eh_begincatch : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], - [NoCapture<0>, NoCapture<1>]>; -def int_eh_endcatch : Intrinsic<[], []>; - // eh.exceptionpointer returns the pointer to the exception caught by // the given `catchpad`. def int_eh_exceptionpointer : Intrinsic<[llvm_anyptr_ty], [llvm_token_ty], @@ -444,12 +437,6 @@ def int_eh_exceptionpointer : Intrinsic<[llvm_anyptr_ty], [llvm_token_ty], // Gets the exception code from a catchpad token. Only used on some platforms. def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], [llvm_token_ty], [IntrNoMem]>; -// Represents the list of actions to take when an exception is thrown. -def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>; - -// FIXME: Remove this when landing pad EH can be removed. -def int_eh_exceptioncode_old : Intrinsic<[llvm_i32_ty], [], [IntrReadMem]>; - // __builtin_unwind_init is an undocumented GCC intrinsic that causes all // callee-saved registers to be saved and restored (regardless of whether they // are used) in the calling function. It is used by libgcc_eh. diff --git a/llvm/lib/Analysis/Lint.cpp b/llvm/lib/Analysis/Lint.cpp index 15acc783f07..b63049c2591 100644 --- a/llvm/lib/Analysis/Lint.cpp +++ b/llvm/lib/Analysis/Lint.cpp @@ -345,13 +345,6 @@ void Lint::visitCallSite(CallSite CS) { visitMemoryReference(I, CS.getArgument(0), MemoryLocation::UnknownSize, 0, nullptr, MemRef::Read | MemRef::Write); break; - - case Intrinsic::eh_begincatch: - visitEHBeginCatch(II); - break; - case Intrinsic::eh_endcatch: - visitEHEndCatch(II); - break; } } @@ -511,187 +504,6 @@ void Lint::visitShl(BinaryOperator &I) { "Undefined result: Shift count out of range", &I); } -static bool -allPredsCameFromLandingPad(BasicBlock *BB, - SmallSet<BasicBlock *, 4> &VisitedBlocks) { - VisitedBlocks.insert(BB); - if (BB->isLandingPad()) - return true; - // If we find a block with no predecessors, the search failed. - if (pred_empty(BB)) - return false; - for (BasicBlock *Pred : predecessors(BB)) { - if (VisitedBlocks.count(Pred)) - continue; - if (!allPredsCameFromLandingPad(Pred, VisitedBlocks)) - return false; - } - return true; -} - -static bool -allSuccessorsReachEndCatch(BasicBlock *BB, BasicBlock::iterator InstBegin, - IntrinsicInst **SecondBeginCatch, - SmallSet<BasicBlock *, 4> &VisitedBlocks) { - VisitedBlocks.insert(BB); - for (BasicBlock::iterator I = InstBegin, E = BB->end(); I != E; ++I) { - IntrinsicInst *IC = dyn_cast<IntrinsicInst>(I); - if (IC && IC->getIntrinsicID() == Intrinsic::eh_endcatch) - return true; - // If we find another begincatch while looking for an endcatch, - // that's also an error. - if (IC && IC->getIntrinsicID() == Intrinsic::eh_begincatch) { - *SecondBeginCatch = IC; - return false; - } - } - - // If we reach a block with no successors while searching, the - // search has failed. - if (succ_empty(BB)) - return false; - // Otherwise, search all of the successors. - for (BasicBlock *Succ : successors(BB)) { - if (VisitedBlocks.count(Succ)) - continue; - if (!allSuccessorsReachEndCatch(Succ, Succ->begin(), SecondBeginCatch, - VisitedBlocks)) - return false; - } - return true; -} - -void Lint::visitEHBeginCatch(IntrinsicInst *II) { - // The checks in this function make a potentially dubious assumption about - // the CFG, namely that any block involved in a catch is only used for the - // catch. This will very likely be true of IR generated by a front end, - // but it may cease to be true, for example, if the IR is run through a - // pass which combines similar blocks. - // - // In general, if we encounter a block the isn't dominated by the catch - // block while we are searching the catch block's successors for a call - // to end catch intrinsic, then it is possible that it will be legal for - // a path through this block to never reach a call to llvm.eh.endcatch. - // An analogous statement could be made about our search for a landing - // pad among the catch block's predecessors. - // - // What is actually required is that no path is possible at runtime that - // reaches a call to llvm.eh.begincatch without having previously visited - // a landingpad instruction and that no path is possible at runtime that - // calls llvm.eh.begincatch and does not subsequently call llvm.eh.endcatch - // (mentally adjusting for the fact that in reality these calls will be - // removed before code generation). - // - // Because this is a lint check, we take a pessimistic approach and warn if - // the control flow is potentially incorrect. - - SmallSet<BasicBlock *, 4> VisitedBlocks; - BasicBlock *CatchBB = II->getParent(); - - // The begin catch must occur in a landing pad block or all paths - // to it must have come from a landing pad. - Assert(allPredsCameFromLandingPad(CatchBB, VisitedBlocks), - "llvm.eh.begincatch may be reachable without passing a landingpad", - II); - - // Reset the visited block list. - VisitedBlocks.clear(); - - IntrinsicInst *SecondBeginCatch = nullptr; - - // This has to be called before it is asserted. Otherwise, the first assert - // below can never be hit. - bool EndCatchFound = allSuccessorsReachEndCatch( - CatchBB, std::next(static_cast<BasicBlock::iterator>(II)), - &SecondBeginCatch, VisitedBlocks); - Assert( - SecondBeginCatch == nullptr, - "llvm.eh.begincatch may be called a second time before llvm.eh.endcatch", - II, SecondBeginCatch); - Assert(EndCatchFound, - "Some paths from llvm.eh.begincatch may not reach llvm.eh.endcatch", - II); -} - -static bool allPredCameFromBeginCatch( - BasicBlock *BB, BasicBlock::reverse_iterator InstRbegin, - IntrinsicInst **SecondEndCatch, SmallSet<BasicBlock *, 4> &VisitedBlocks) { - VisitedBlocks.insert(BB); - // Look for a begincatch in this block. - for (BasicBlock::reverse_iterator RI = InstRbegin, RE = BB->rend(); RI != RE; - ++RI) { - IntrinsicInst *IC = dyn_cast<IntrinsicInst>(&*RI); - if (IC && IC->getIntrinsicID() == Intrinsic::eh_begincatch) - return true; - // If we find another end catch before we find a begin catch, that's - // an error. - if (IC && IC->getIntrinsicID() == Intrinsic::eh_endcatch) { - *SecondEndCatch = IC; - return false; - } - // If we encounter a landingpad instruction, the search failed. - if (isa<LandingPadInst>(*RI)) - return false; - } - // If while searching we find a block with no predeccesors, - // the search failed. - if (pred_empty(BB)) - return false; - // Search any predecessors we haven't seen before. - for (BasicBlock *Pred : predecessors(BB)) { - if (VisitedBlocks.count(Pred)) - continue; - if (!allPredCameFromBeginCatch(Pred, Pred->rbegin(), SecondEndCatch, - VisitedBlocks)) - return false; - } - return true; -} - -void Lint::visitEHEndCatch(IntrinsicInst *II) { - // The check in this function makes a potentially dubious assumption about - // the CFG, namely that any block involved in a catch is only used for the - // catch. This will very likely be true of IR generated by a front end, - // but it may cease to be true, for example, if the IR is run through a - // pass which combines similar blocks. - // - // In general, if we encounter a block the isn't post-dominated by the - // end catch block while we are searching the end catch block's predecessors - // for a call to the begin catch intrinsic, then it is possible that it will - // be legal for a path to reach the end catch block without ever having - // called llvm.eh.begincatch. - // - // What is actually required is that no path is possible at runtime that - // reaches a call to llvm.eh.endcatch without having previously visited - // a call to llvm.eh.begincatch (mentally adjusting for the fact that in - // reality these calls will be removed before code generation). - // - // Because this is a lint check, we take a pessimistic approach and warn if - // the control flow is potentially incorrect. - - BasicBlock *EndCatchBB = II->getParent(); - - // Alls paths to the end catch call must pass through a begin catch call. - - // If llvm.eh.begincatch wasn't called in the current block, we'll use this - // lambda to recursively look for it in predecessors. - SmallSet<BasicBlock *, 4> VisitedBlocks; - IntrinsicInst *SecondEndCatch = nullptr; - - // This has to be called before it is asserted. Otherwise, the first assert - // below can never be hit. - bool BeginCatchFound = - allPredCameFromBeginCatch(EndCatchBB, BasicBlock::reverse_iterator(II), - &SecondEndCatch, VisitedBlocks); - Assert( - SecondEndCatch == nullptr, - "llvm.eh.endcatch may be called a second time after llvm.eh.begincatch", - II, SecondEndCatch); - Assert(BeginCatchFound, - "llvm.eh.endcatch may be reachable without passing llvm.eh.begincatch", - II); -} - static bool isZero(Value *V, const DataLayout &DL, DominatorTree *DT, AssumptionCache *AC) { // Assume undef could be zero. diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp index 63be0daa708..adc47650235 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp @@ -418,7 +418,7 @@ invoke_ranges(WinEHFuncInfo &EHInfo, const MachineBasicBlock &MBB) { /// imagerel32 LabelStart; /// imagerel32 LabelEnd; /// imagerel32 FilterOrFinally; // One means catch-all. -/// imagerel32 ExceptOrNull; // Zero means __finally. +/// imagerel32 LabelLPad; // Zero means __finally. /// } Entries[NumEntries]; /// }; void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) { @@ -426,153 +426,69 @@ void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) { MCContext &Ctx = Asm->OutContext; WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(MF->getFunction()); - if (!FuncInfo.SEHUnwindMap.empty()) { - // Remember what state we were in the last time we found a begin try label. - // This allows us to coalesce many nearby invokes with the same state into - // one entry. - int LastEHState = -1; - MCSymbol *LastBeginLabel = nullptr; - MCSymbol *LastEndLabel = nullptr; - - // Use the assembler to compute the number of table entries through label - // difference and division. - MCSymbol *TableBegin = - Ctx.createTempSymbol("lsda_begin", /*AlwaysAddSuffix=*/true); - MCSymbol *TableEnd = - Ctx.createTempSymbol("lsda_end", /*AlwaysAddSuffix=*/true); - const MCExpr *LabelDiff = - MCBinaryExpr::createSub(MCSymbolRefExpr::create(TableEnd, Ctx), - MCSymbolRefExpr::create(TableBegin, Ctx), Ctx); - const MCExpr *EntrySize = MCConstantExpr::create(16, Ctx); - const MCExpr *EntryCount = - MCBinaryExpr::createDiv(LabelDiff, EntrySize, Ctx); - OS.EmitValue(EntryCount, 4); - - OS.EmitLabel(TableBegin); - - // Iterate over all the invoke try ranges. Unlike MSVC, LLVM currently only - // models exceptions from invokes. LLVM also allows arbitrary reordering of - // the code, so our tables end up looking a bit different. Rather than - // trying to match MSVC's tables exactly, we emit a denormalized table. For - // each range of invokes in the same state, we emit table entries for all - // the actions that would be taken in that state. This means our tables are - // slightly bigger, which is OK. - for (const auto &MBB : *MF) { - // Break out before we enter into a finally funclet. - // FIXME: We need to emit separate EH tables for cleanups. - if (MBB.isEHFuncletEntry() && &MBB != MF->begin()) - break; - - for (InvokeRange &I : invoke_ranges(FuncInfo, MBB)) { - // If this invoke is in the same state as the last invoke and there were - // no non-throwing calls between it, extend the range to include both - // and continue. - if (!I.SawPotentiallyThrowing && I.State == LastEHState) { - LastEndLabel = I.EndLabel; - continue; - } - // If this invoke ends a previous one, emit all the actions for this - // state. - if (LastEHState != -1) - emitSEHActionsForRange(FuncInfo, LastBeginLabel, LastEndLabel, - LastEHState); + // Remember what state we were in the last time we found a begin try label. + // This allows us to coalesce many nearby invokes with the same state into + // one entry. + int LastEHState = -1; + MCSymbol *LastBeginLabel = nullptr; + MCSymbol *LastEndLabel = nullptr; + + // Use the assembler to compute the number of table entries through label + // difference and division. + MCSymbol *TableBegin = + Ctx.createTempSymbol("lsda_begin", /*AlwaysAddSuffix=*/true); + MCSymbol *TableEnd = + Ctx.createTempSymbol("lsda_end", /*AlwaysAddSuffix=*/true); + const MCExpr *LabelDiff = + MCBinaryExpr::createSub(MCSymbolRefExpr::create(TableEnd, Ctx), + MCSymbolRefExpr::create(TableBegin, Ctx), Ctx); + const MCExpr *EntrySize = MCConstantExpr::create(16, Ctx); + const MCExpr *EntryCount = MCBinaryExpr::createDiv(LabelDiff, EntrySize, Ctx); + OS.EmitValue(EntryCount, 4); + + OS.EmitLabel(TableBegin); + + // Iterate over all the invoke try ranges. Unlike MSVC, LLVM currently only + // models exceptions from invokes. LLVM also allows arbitrary reordering of + // the code, so our tables end up looking a bit different. Rather than + // trying to match MSVC's tables exactly, we emit a denormalized table. For + // each range of invokes in the same state, we emit table entries for all + // the actions that would be taken in that state. This means our tables are + // slightly bigger, which is OK. + for (const auto &MBB : *MF) { + // Break out before we enter into a finally funclet. + // FIXME: We need to emit separate EH tables for cleanups. + if (MBB.isEHFuncletEntry() && &MBB != MF->begin()) + break; - LastBeginLabel = I.BeginLabel; + for (InvokeRange &I : invoke_ranges(FuncInfo, MBB)) { + // If this invoke is in the same state as the last invoke and there were + // no non-throwing calls between it, extend the range to include both + // and continue. + if (!I.SawPotentiallyThrowing && I.State == LastEHState) { LastEndLabel = I.EndLabel; - LastEHState = I.State; + continue; } - } - if (LastEndLabel) - emitSEHActionsForRange(FuncInfo, LastBeginLabel, LastEndLabel, - LastEHState); + // If this invoke ends a previous one, emit all the actions for this + // state. + if (LastEHState != -1) + emitSEHActionsForRange(FuncInfo, LastBeginLabel, LastEndLabel, + LastEHState); - OS.EmitLabel(TableEnd); - return; + LastBeginLabel = I.BeginLabel; + LastEndLabel = I.EndLabel; + LastEHState = I.State; + } } - // Simplifying assumptions for first implementation: - // - Cleanups are not implemented. - // - Filters are not implemented. - - // The Itanium LSDA table sorts similar landing pads together to simplify the - // actions table, but we don't need that. - const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); - SmallVector<const LandingPadInfo *, 64> LandingPads; - LandingPads.reserve(PadInfos.size()); - for (const auto &LP : PadInfos) - LandingPads.push_back(&LP); - - // Compute label ranges for call sites as we would for the Itanium LSDA, but - // use an all zero action table because we aren't using these actions. - SmallVector<unsigned, 64> FirstActions; - FirstActions.resize(LandingPads.size()); - SmallVector<CallSiteEntry, 64> CallSites; - computeCallSiteTable(CallSites, LandingPads, FirstActions); - - MCSymbol *EHFuncBeginSym = Asm->getFunctionBegin(); - MCSymbol *EHFuncEndSym = Asm->getFunctionEnd(); - - // Emit the number of table entries. - unsigned NumEntries = 0; - for (const CallSiteEntry &CSE : CallSites) { - if (!CSE.LPad) - continue; // Ignore gaps. - NumEntries += CSE.LPad->SEHHandlers.size(); - } - OS.EmitIntValue(NumEntries, 4); + // Hitting the end of the function causes us to emit the range for the + // previous invoke. + if (LastEndLabel) + emitSEHActionsForRange(FuncInfo, LastBeginLabel, LastEndLabel, LastEHState); - // If there are no actions, we don't need to iterate again. - if (NumEntries == 0) - return; - - // Emit the four-label records for each call site entry. The table has to be - // sorted in layout order, and the call sites should already be sorted. - for (const CallSiteEntry &CSE : CallSites) { - // Ignore gaps. Unlike the Itanium model, unwinding through a frame without - // an EH table entry will propagate the exception rather than terminating - // the program. - if (!CSE.LPad) - continue; - const LandingPadInfo *LPad = CSE.LPad; - - // Compute the label range. We may reuse the function begin and end labels - // rather than forming new ones. - const MCExpr *Begin = - create32bitRef(CSE.BeginLabel ? CSE.BeginLabel : EHFuncBeginSym); - const MCExpr *End; - if (CSE.EndLabel) { - // The interval is half-open, so we have to add one to include the return - // address of the last invoke in the range. - End = getLabelPlusOne(CSE.EndLabel); - } else { - End = create32bitRef(EHFuncEndSym); - } - - // Emit an entry for each action. - for (SEHHandler Handler : LPad->SEHHandlers) { - OS.EmitValue(Begin, 4); - OS.EmitValue(End, 4); - - // Emit the filter or finally function pointer, if present. Otherwise, - // emit '1' to indicate a catch-all. - const Function *F = Handler.FilterOrFinally; - if (F) - OS.EmitValue(create32bitRef(Asm->getSymbol(F)), 4); - else - OS.EmitIntValue(1, 4); - - // Emit the recovery address, if present. Otherwise, this must be a - // finally. - const BlockAddress *BA = Handler.RecoverBA; - if (BA) - OS.EmitValue( - create32bitRef(Asm->GetBlockAddressSymbol(BA)), 4); - else - OS.EmitIntValue(0, 4); - } - } + OS.EmitLabel(TableEnd); } void WinException::emitSEHActionsForRange(WinEHFuncInfo &FuncInfo, @@ -583,12 +499,6 @@ void WinException::emitSEHActionsForRange(WinEHFuncInfo &FuncInfo, assert(BeginLabel && EndLabel); while (State != -1) { - // struct Entry { - // imagerel32 LabelStart; - // imagerel32 LabelEnd; - // imagerel32 FilterOrFinally; // One means catch-all. - // imagerel32 ExceptOrNull; // Zero means __finally. - // }; SEHUnwindMapEntry &UME = FuncInfo.SEHUnwindMap[State]; const MCExpr *FilterOrFinally; const MCExpr *ExceptOrNull; @@ -641,7 +551,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { MCSymbol *UnwindMapXData = nullptr; MCSymbol *TryBlockMapXData = nullptr; MCSymbol *IPToStateXData = nullptr; - if (!FuncInfo.UnwindMap.empty()) + if (!FuncInfo.CxxUnwindMap.empty()) UnwindMapXData = Asm->OutContext.getOrCreateSymbol( Twine("$stateUnwindMap$", FuncLinkageName)); if (!FuncInfo.TryBlockMap.empty()) @@ -669,7 +579,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { OS.EmitValueToAlignment(4); OS.EmitLabel(FuncInfoXData); OS.EmitIntValue(0x19930522, 4); // MagicNumber - OS.EmitIntValue(FuncInfo.UnwindMap.size(), 4); // MaxState + OS.EmitIntValue(FuncInfo.CxxUnwindMap.size(), 4); // MaxState OS.EmitValue(create32bitRef(UnwindMapXData), 4); // UnwindMap OS.EmitIntValue(FuncInfo.TryBlockMap.size(), 4); // NumTryBlocks OS.EmitValue(create32bitRef(TryBlockMapXData), 4); // TryBlockMap @@ -686,7 +596,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { // }; if (UnwindMapXData) { OS.EmitLabel(UnwindMapXData); - for (const WinEHUnwindMapEntry &UME : FuncInfo.UnwindMap) { + for (const CxxUnwindMapEntry &UME : FuncInfo.CxxUnwindMap) { MCSymbol *CleanupSym = getMCSymbolForMBBOrGV(Asm, UME.Cleanup); OS.EmitIntValue(UME.ToState, 4); // ToState OS.EmitValue(create32bitRef(CleanupSym), 4); // Action @@ -719,7 +629,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { assert(0 <= TBME.TryLow && "bad trymap interval"); assert(TBME.TryLow <= TBME.TryHigh && "bad trymap interval"); assert(TBME.TryHigh < TBME.CatchHigh && "bad trymap interval"); - assert(TBME.CatchHigh < int(FuncInfo.UnwindMap.size()) && + assert(TBME.CatchHigh < int(FuncInfo.CxxUnwindMap.size()) && "bad trymap interval"); OS.EmitIntValue(TBME.TryLow, 4); // TryLow @@ -903,66 +813,15 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) { BaseState = -2; } - if (!FuncInfo.SEHUnwindMap.empty()) { - for (SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) { - MCSymbol *ExceptOrFinally = - UME.Handler.get<MachineBasicBlock *>()->getSymbol(); - // -1 is usually the base state for "unwind to caller", but for - // _except_handler4 it's -2. Do that replacement here if necessary. - int ToState = UME.ToState == -1 ? BaseState : UME.ToState; - OS.EmitIntValue(ToState, 4); // ToState - OS.EmitValue(create32bitRef(UME.Filter), 4); // Filter - OS.EmitValue(create32bitRef(ExceptOrFinally), 4); // Except/Finally - } - return; - } - // FIXME: The following code is for the old landingpad-based SEH - // implementation. Remove it when possible. - - // Build a list of pointers to LandingPadInfos and then sort by WinEHState. - const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); - SmallVector<const LandingPadInfo *, 4> LPads; - LPads.reserve((PadInfos.size())); - for (const LandingPadInfo &LPInfo : PadInfos) - LPads.push_back(&LPInfo); - std::sort(LPads.begin(), LPads.end(), - [](const LandingPadInfo *L, const LandingPadInfo *R) { - return L->WinEHState < R->WinEHState; - }); - - // For each action in each lpad, emit one of these: - // struct ScopeTableEntry { - // int32_t EnclosingLevel; - // int32_t (__cdecl *Filter)(); - // void *HandlerOrFinally; - // }; - // - // The "outermost" action will use BaseState as its enclosing level. Each - // other action will refer to the previous state as its enclosing level. - int CurState = 0; - for (const LandingPadInfo *LPInfo : LPads) { - int EnclosingLevel = BaseState; - assert(CurState + int(LPInfo->SEHHandlers.size()) - 1 == - LPInfo->WinEHState && - "gaps in the SEH scope table"); - for (auto I = LPInfo->SEHHandlers.rbegin(), E = LPInfo->SEHHandlers.rend(); - I != E; ++I) { - const SEHHandler &Handler = *I; - const BlockAddress *BA = Handler.RecoverBA; - const Function *F = Handler.FilterOrFinally; - assert(F && "cannot catch all in 32-bit SEH without filter function"); - const MCExpr *FilterOrNull = - create32bitRef(BA ? Asm->getSymbol(F) : nullptr); - const MCExpr *ExceptOrFinally = create32bitRef( - BA ? Asm->GetBlockAddressSymbol(BA) : Asm->getSymbol(F)); - - OS.EmitIntValue(EnclosingLevel, 4); - OS.EmitValue(FilterOrNull, 4); - OS.EmitValue(ExceptOrFinally, 4); - - // The next state unwinds to this state. - EnclosingLevel = CurState; - CurState++; - } + assert(!FuncInfo.SEHUnwindMap.empty()); + for (SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) { + MCSymbol *ExceptOrFinally = + UME.Handler.get<MachineBasicBlock *>()->getSymbol(); + // -1 is usually the base state for "unwind to caller", but for + // _except_handler4 it's -2. Do that replacement here if necessary. + int ToState = UME.ToState == -1 ? BaseState : UME.ToState; + OS.EmitIntValue(ToState, 4); // ToState + OS.EmitValue(create32bitRef(UME.Filter), 4); // Filter + OS.EmitValue(create32bitRef(ExceptOrFinally), 4); // Except/Finally } } diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp index 13b097cfc60..1e2f2fb0429 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -1103,13 +1103,6 @@ bool FastISel::selectIntrinsicCall(const IntrinsicInst *II) { // The donothing intrinsic does, well, nothing. case Intrinsic::donothing: return true; - case Intrinsic::eh_actions: { - unsigned ResultReg = getRegForValue(UndefValue::get(II->getType())); - if (!ResultReg) - return false; - updateValueMap(II, ResultReg); - return true; - } case Intrinsic::dbg_declare: { const DbgDeclareInst *DI = cast<DbgDeclareInst>(II); assert(DI->getVariable() && "Missing variable"); diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index cf2d84f9a11..d9b32d92c8e 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -283,11 +283,6 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, if (!isFuncletEHPersonality(Personality)) return; - if (Personality == EHPersonality::MSVC_Win64SEH || - Personality == EHPersonality::MSVC_X86SEH) { - addSEHHandlersForLPads(LPads); - } - // Calculate state numbers if we haven't already. WinEHFuncInfo &EHInfo = MMI.getWinEHFuncInfo(&fn); const Function *WinEHParentFn = MMI.getWinEHParent(&fn); @@ -313,7 +308,7 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, H.Handler = MBBMap[BB]; } } - for (WinEHUnwindMapEntry &UME : EHInfo.UnwindMap) + for (CxxUnwindMapEntry &UME : EHInfo.CxxUnwindMap) if (UME.Cleanup) if (const auto *BB = dyn_cast<BasicBlock>(UME.Cleanup.get<const Value *>())) UME.Cleanup = MBBMap[BB]; @@ -345,44 +340,6 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, } } -void FunctionLoweringInfo::addSEHHandlersForLPads( - ArrayRef<const LandingPadInst *> LPads) { - MachineModuleInfo &MMI = MF->getMMI(); - - // Iterate over all landing pads with llvm.eh.actions calls. - for (const LandingPadInst *LP : LPads) { - const IntrinsicInst *ActionsCall = - dyn_cast<IntrinsicInst>(LP->getNextNode()); - if (!ActionsCall || - ActionsCall->getIntrinsicID() != Intrinsic::eh_actions) - continue; - - // Parse the llvm.eh.actions call we found. - MachineBasicBlock *LPadMBB = MBBMap[LP->getParent()]; - SmallVector<std::unique_ptr<ActionHandler>, 4> Actions; - parseEHActions(ActionsCall, Actions); - - // Iterate EH actions from most to least precedence, which means - // iterating in reverse. - for (auto I = Actions.rbegin(), E = Actions.rend(); I != E; ++I) { - ActionHandler *Action = I->get(); - if (auto *CH = dyn_cast<CatchHandler>(Action)) { - const auto *Filter = - dyn_cast<Function>(CH->getSelector()->stripPointerCasts()); - assert((Filter || CH->getSelector()->isNullValue()) && - "expected function or catch-all"); - const auto *RecoverBA = - cast<BlockAddress>(CH->getHandlerBlockOrFunc()); - MMI.addSEHCatchHandler(LPadMBB, Filter, RecoverBA); - } else { - assert(isa<CleanupHandler>(Action)); - const auto *Fini = cast<Function>(Action->getHandlerBlockOrFunc()); - MMI.addSEHCleanupHandler(LPadMBB, Fini); - } - } - } -} - /// clear - Clear out all the function-specific state. This returns this /// FunctionLoweringInfo to an empty state, ready to be used for a /// different function. diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 9e315194c98..071317c5a53 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5152,9 +5152,6 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { } case Intrinsic::clear_cache: return TLI.getClearCacheBuiltinName(); - case Intrinsic::eh_actions: - setValue(&I, DAG.getUNDEF(TLI.getPointerTy(DAG.getDataLayout()))); - return nullptr; case Intrinsic::donothing: // ignore return nullptr; @@ -5238,22 +5235,6 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { return nullptr; } - case Intrinsic::eh_begincatch: - case Intrinsic::eh_endcatch: - llvm_unreachable("begin/end catch intrinsics not lowered in codegen"); - case Intrinsic::eh_exceptioncode_old: { - unsigned Reg = TLI.getExceptionPointerRegister(); - assert(Reg && "cannot get exception code on this platform"); - MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout()); - const TargetRegisterClass *PtrRC = TLI.getRegClassFor(PtrVT); - 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); - N = DAG.getZExtOrTrunc(N, getCurSDLoc(), MVT::i32); - setValue(&I, N); - return nullptr; - } case Intrinsic::eh_exceptionpointer: case Intrinsic::eh_exceptioncode: { diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 0df05683b4f..2a25131dbad 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -973,43 +973,6 @@ bool SelectionDAGISel::PrepareEHLandingPad() { BuildMI(*MBB, FuncInfo->InsertPt, SDB->getCurDebugLoc(), II) .addSym(Label); - // If this personality function uses funclets, we need to split the landing - // pad into several BBs. - const Constant *Personality = MF->getFunction()->getPersonalityFn(); - if (const auto *PF = dyn_cast<Function>(Personality->stripPointerCasts())) - MF->getMMI().addPersonality(PF); - EHPersonality PersonalityType = classifyEHPersonality(Personality); - - if (isFuncletEHPersonality(PersonalityType)) { - SmallVector<MachineBasicBlock *, 4> ClauseBBs; - const IntrinsicInst *ActionsCall = - dyn_cast<IntrinsicInst>(LLVMBB->getFirstInsertionPt()); - // Get all invoke BBs that unwind to this landingpad. - SmallVector<MachineBasicBlock *, 4> InvokeBBs(MBB->pred_begin(), - MBB->pred_end()); - if (ActionsCall && ActionsCall->getIntrinsicID() == Intrinsic::eh_actions) { - // If this is a call to llvm.eh.actions followed by indirectbr, then we've - // run WinEHPrepare, and we should remove this block from the machine CFG. - // Mark the targets of the indirectbr as landingpads instead. - for (const BasicBlock *LLVMSucc : successors(LLVMBB)) { - MachineBasicBlock *ClauseBB = FuncInfo->MBBMap[LLVMSucc]; - // Add the edge from the invoke to the clause. - for (MachineBasicBlock *InvokeBB : InvokeBBs) - InvokeBB->addSuccessor(ClauseBB); - - // Mark the clause as a landing pad or MI passes will delete it. - ClauseBB->setIsEHPad(); - } - } - - // Remove the edge from the invoke to the lpad. - for (MachineBasicBlock *InvokeBB : InvokeBBs) - InvokeBB->removeSuccessor(MBB); - - // Don't select instructions for the landingpad. - return false; - } - // Mark exception register as live in. if (unsigned Reg = TLI->getExceptionPointerRegister()) FuncInfo->ExceptionPointerVirtReg = MBB->addLiveIn(Reg, PtrRC); diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index 11a7edec48f..5affb3f0924 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -63,27 +63,6 @@ static cl::opt<bool> DisableCleanups( namespace { -// This map is used to model frame variable usage during outlining, to -// construct a structure type to hold the frame variables in a frame -// allocation block, and to remap the frame variable allocas (including -// spill locations as needed) to GEPs that get the variable from the -// frame allocation structure. -typedef MapVector<Value *, TinyPtrVector<AllocaInst *>> FrameVarInfoMap; - -// TinyPtrVector cannot hold nullptr, so we need our own sentinel that isn't -// quite null. -AllocaInst *getCatchObjectSentinel() { - return static_cast<AllocaInst *>(nullptr) + 1; -} - -typedef SmallSet<BasicBlock *, 4> VisitedBlockSet; - -class LandingPadActions; -class LandingPadMap; - -typedef DenseMap<const BasicBlock *, CatchHandler *> CatchHandlerMapTy; -typedef DenseMap<const BasicBlock *, CleanupHandler *> CleanupHandlerMapTy; - class WinEHPrepare : public FunctionPass { public: static char ID; // Pass identification, replacement for typeid. @@ -104,36 +83,6 @@ public: } private: - bool prepareExceptionHandlers(Function &F, - SmallVectorImpl<LandingPadInst *> &LPads); - void identifyEHBlocks(Function &F, SmallVectorImpl<LandingPadInst *> &LPads); - void promoteLandingPadValues(LandingPadInst *LPad); - void demoteValuesLiveAcrossHandlers(Function &F, - SmallVectorImpl<LandingPadInst *> &LPads); - void findSEHEHReturnPoints(Function &F, - SetVector<BasicBlock *> &EHReturnBlocks); - void findCXXEHReturnPoints(Function &F, - SetVector<BasicBlock *> &EHReturnBlocks); - void getPossibleReturnTargets(Function *ParentF, Function *HandlerF, - SetVector<BasicBlock*> &Targets); - void completeNestedLandingPad(Function *ParentFn, - LandingPadInst *OutlinedLPad, - const LandingPadInst *OriginalLPad, - FrameVarInfoMap &VarInfo); - Function *createHandlerFunc(Function *ParentFn, Type *RetTy, - const Twine &Name, Module *M, Value *&ParentFP); - bool outlineHandler(ActionHandler *Action, Function *SrcFn, - LandingPadInst *LPad, BasicBlock *StartBB, - FrameVarInfoMap &VarInfo); - void addStubInvokeToHandlerIfNeeded(Function *Handler); - - void mapLandingPadBlocks(LandingPadInst *LPad, LandingPadActions &Actions); - CatchHandler *findCatchHandler(BasicBlock *BB, BasicBlock *&NextBB, - VisitedBlockSet &VisitedBlocks); - void findCleanupHandlers(LandingPadActions &Actions, BasicBlock *StartBB, - BasicBlock *EndBB); - - void processSEHCatchHandler(CatchHandler *Handler, BasicBlock *StartBB); void insertPHIStores(PHINode *OriginalPHI, AllocaInst *SpillSlot); void insertPHIStore(BasicBlock *PredBlock, Value *PredVal, AllocaInst *SpillSlot, @@ -159,236 +108,13 @@ private: Triple TheTriple; // All fields are reset by runOnFunction. - DominatorTree *DT = nullptr; - const TargetLibraryInfo *LibInfo = nullptr; EHPersonality Personality = EHPersonality::Unknown; - CatchHandlerMapTy CatchHandlerMap; - CleanupHandlerMapTy CleanupHandlerMap; - DenseMap<const LandingPadInst *, LandingPadMap> LPadMaps; - SmallPtrSet<BasicBlock *, 4> NormalBlocks; - SmallPtrSet<BasicBlock *, 4> EHBlocks; - SetVector<BasicBlock *> EHReturnBlocks; - - // This maps landing pad instructions found in outlined handlers to - // the landing pad instruction in the parent function from which they - // were cloned. The cloned/nested landing pad is used as the key - // because the landing pad may be cloned into multiple handlers. - // This map will be used to add the llvm.eh.actions call to the nested - // landing pads after all handlers have been outlined. - DenseMap<LandingPadInst *, const LandingPadInst *> NestedLPtoOriginalLP; - - // This maps blocks in the parent function which are destinations of - // catch handlers to cloned blocks in (other) outlined handlers. This - // handles the case where a nested landing pads has a catch handler that - // returns to a handler function rather than the parent function. - // The original block is used as the key here because there should only - // ever be one handler function from which the cloned block is not pruned. - // The original block will be pruned from the parent function after all - // handlers have been outlined. This map will be used to adjust the - // return instructions of handlers which return to the block that was - // outlined into a handler. This is done after all handlers have been - // outlined but before the outlined code is pruned from the parent function. - DenseMap<const BasicBlock *, BasicBlock *> LPadTargetBlocks; - - // Map from outlined handler to call to parent local address. Only used for - // 32-bit EH. - DenseMap<Function *, Value *> HandlerToParentFP; - - AllocaInst *SEHExceptionCodeSlot = nullptr; std::map<BasicBlock *, std::set<BasicBlock *>> BlockColors; std::map<BasicBlock *, std::set<BasicBlock *>> FuncletBlocks; std::map<BasicBlock *, std::set<BasicBlock *>> FuncletChildren; }; -class WinEHFrameVariableMaterializer : public ValueMaterializer { -public: - WinEHFrameVariableMaterializer(Function *OutlinedFn, Value *ParentFP, - FrameVarInfoMap &FrameVarInfo); - ~WinEHFrameVariableMaterializer() override {} - - Value *materializeValueFor(Value *V) override; - - void escapeCatchObject(Value *V); - -private: - FrameVarInfoMap &FrameVarInfo; - IRBuilder<> Builder; -}; - -class LandingPadMap { -public: - LandingPadMap() : OriginLPad(nullptr) {} - void mapLandingPad(const LandingPadInst *LPad); - - bool isInitialized() { return OriginLPad != nullptr; } - - bool isOriginLandingPadBlock(const BasicBlock *BB) const; - bool isLandingPadSpecificInst(const Instruction *Inst) const; - - void remapEHValues(ValueToValueMapTy &VMap, Value *EHPtrValue, - Value *SelectorValue) const; - -private: - const LandingPadInst *OriginLPad; - // We will normally only see one of each of these instructions, but - // if more than one occurs for some reason we can handle that. - TinyPtrVector<const ExtractValueInst *> ExtractedEHPtrs; - TinyPtrVector<const ExtractValueInst *> ExtractedSelectors; -}; - -class WinEHCloningDirectorBase : public CloningDirector { -public: - WinEHCloningDirectorBase(Function *HandlerFn, Value *ParentFP, - FrameVarInfoMap &VarInfo, LandingPadMap &LPadMap) - : Materializer(HandlerFn, ParentFP, VarInfo), - SelectorIDType(Type::getInt32Ty(HandlerFn->getContext())), - Int8PtrType(Type::getInt8PtrTy(HandlerFn->getContext())), - LPadMap(LPadMap), ParentFP(ParentFP) {} - - CloningAction handleInstruction(ValueToValueMapTy &VMap, - const Instruction *Inst, - BasicBlock *NewBB) override; - - virtual CloningAction handleBeginCatch(ValueToValueMapTy &VMap, - const Instruction *Inst, - BasicBlock *NewBB) = 0; - virtual CloningAction handleEndCatch(ValueToValueMapTy &VMap, - const Instruction *Inst, - BasicBlock *NewBB) = 0; - virtual CloningAction handleTypeIdFor(ValueToValueMapTy &VMap, - const Instruction *Inst, - BasicBlock *NewBB) = 0; - virtual CloningAction handleIndirectBr(ValueToValueMapTy &VMap, - const IndirectBrInst *IBr, - BasicBlock *NewBB) = 0; - virtual CloningAction handleInvoke(ValueToValueMapTy &VMap, - const InvokeInst *Invoke, - BasicBlock *NewBB) = 0; - virtual CloningAction handleResume(ValueToValueMapTy &VMap, - const ResumeInst *Resume, - BasicBlock *NewBB) = 0; - virtual CloningAction handleCompare(ValueToValueMapTy &VMap, - const CmpInst *Compare, - BasicBlock *NewBB) = 0; - virtual CloningAction handleLandingPad(ValueToValueMapTy &VMap, - const LandingPadInst *LPad, - BasicBlock *NewBB) = 0; - - ValueMaterializer *getValueMaterializer() override { return &Materializer; } - -protected: - WinEHFrameVariableMaterializer Materializer; - Type *SelectorIDType; - Type *Int8PtrType; - LandingPadMap &LPadMap; - - /// The value representing the parent frame pointer. - Value *ParentFP; -}; - -class WinEHCatchDirector : public WinEHCloningDirectorBase { -public: - WinEHCatchDirector( - Function *CatchFn, Value *ParentFP, Value *Selector, - FrameVarInfoMap &VarInfo, LandingPadMap &LPadMap, - DenseMap<LandingPadInst *, const LandingPadInst *> &NestedLPads, - DominatorTree *DT, SmallPtrSetImpl<BasicBlock *> &EHBlocks) - : WinEHCloningDirectorBase(CatchFn, ParentFP, VarInfo, LPadMap), - CurrentSelector(Selector->stripPointerCasts()), - ExceptionObjectVar(nullptr), NestedLPtoOriginalLP(NestedLPads), - DT(DT), EHBlocks(EHBlocks) {} - - CloningAction handleBeginCatch(ValueToValueMapTy &VMap, - const Instruction *Inst, - BasicBlock *NewBB) override; - CloningAction handleEndCatch(ValueToValueMapTy &VMap, const Instruction *Inst, - BasicBlock *NewBB) override; - CloningAction handleTypeIdFor(ValueToValueMapTy &VMap, - const Instruction *Inst, - BasicBlock *NewBB) override; - CloningAction handleIndirectBr(ValueToValueMapTy &VMap, - const IndirectBrInst *IBr, - BasicBlock *NewBB) override; - CloningAction handleInvoke(ValueToValueMapTy &VMap, const InvokeInst *Invoke, - BasicBlock *NewBB) override; - CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume, - BasicBlock *NewBB) override; - CloningAction handleCompare(ValueToValueMapTy &VMap, const CmpInst *Compare, - BasicBlock *NewBB) override; - CloningAction handleLandingPad(ValueToValueMapTy &VMap, - const LandingPadInst *LPad, - BasicBlock *NewBB) override; - - Value *getExceptionVar() { return ExceptionObjectVar; } - TinyPtrVector<BasicBlock *> &getReturnTargets() { return ReturnTargets; } - -private: - Value *CurrentSelector; - - Value *ExceptionObjectVar; - TinyPtrVector<BasicBlock *> ReturnTargets; - - // This will be a reference to the field of the same name in the WinEHPrepare - // object which instantiates this WinEHCatchDirector object. - DenseMap<LandingPadInst *, const LandingPadInst *> &NestedLPtoOriginalLP; - DominatorTree *DT; - SmallPtrSetImpl<BasicBlock *> &EHBlocks; -}; - -class WinEHCleanupDirector : public WinEHCloningDirectorBase { -public: - WinEHCleanupDirector(Function *CleanupFn, Value *ParentFP, - FrameVarInfoMap &VarInfo, LandingPadMap &LPadMap) - : WinEHCloningDirectorBase(CleanupFn, ParentFP, VarInfo, - LPadMap) {} - - CloningAction handleBeginCatch(ValueToValueMapTy &VMap, - const Instruction *Inst, - BasicBlock *NewBB) override; - CloningAction handleEndCatch(ValueToValueMapTy &VMap, const Instruction *Inst, - BasicBlock *NewBB) override; - CloningAction handleTypeIdFor(ValueToValueMapTy &VMap, - const Instruction *Inst, - BasicBlock *NewBB) override; - CloningAction handleIndirectBr(ValueToValueMapTy &VMap, - const IndirectBrInst *IBr, - BasicBlock *NewBB) override; - CloningAction handleInvoke(ValueToValueMapTy &VMap, const InvokeInst *Invoke, - BasicBlock *NewBB) override; - CloningAction handleResume(ValueToValueMapTy &VMap, const ResumeInst *Resume, - BasicBlock *NewBB) override; - CloningAction handleCompare(ValueToValueMapTy &VMap, const CmpInst *Compare, - BasicBlock *NewBB) override; - CloningAction handleLandingPad(ValueToValueMapTy &VMap, - const LandingPadInst *LPad, - BasicBlock *NewBB) override; -}; - -class LandingPadActions { -public: - LandingPadActions() : HasCleanupHandlers(false) {} - - void insertCatchHandler(CatchHandler *Action) { Actions.push_back(Action); } - void insertCleanupHandler(CleanupHandler *Action) { - Actions.push_back(Action); - HasCleanupHandlers = true; - } - - bool includesCleanup() const { return HasCleanupHandlers; } - - SmallVectorImpl<ActionHandler *> &actions() { return Actions; } - SmallVectorImpl<ActionHandler *>::iterator begin() { return Actions.begin(); } - SmallVectorImpl<ActionHandler *>::iterator end() { return Actions.end(); } - -private: - // Note that this class does not own the ActionHandler objects in this vector. - // The ActionHandlers are owned by the CatchHandlerMap and CleanupHandlerMap - // in the WinEHPrepare class. - SmallVector<ActionHandler *, 4> Actions; - bool HasCleanupHandlers; -}; - } // end anonymous namespace char WinEHPrepare::ID = 0; @@ -399,27 +125,19 @@ FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) { return new WinEHPrepare(TM); } -static bool -findExceptionalConstructs(Function &Fn, - SmallVectorImpl<LandingPadInst *> &LPads, - SmallVectorImpl<ResumeInst *> &Resumes, - SmallVectorImpl<BasicBlock *> &EntryBlocks) { - bool ForExplicitEH = false; +static void findFuncletEntryPoints(Function &Fn, + SmallVectorImpl<BasicBlock *> &EntryBlocks) { + EntryBlocks.push_back(&Fn.getEntryBlock()); for (BasicBlock &BB : Fn) { Instruction *First = BB.getFirstNonPHI(); - if (auto *LP = dyn_cast<LandingPadInst>(First)) { - LPads.push_back(LP); - } else if (First->isEHPad()) { - if (!ForExplicitEH) - EntryBlocks.push_back(&Fn.getEntryBlock()); - if (!isa<CatchEndPadInst>(First) && !isa<CleanupEndPadInst>(First)) - EntryBlocks.push_back(&BB); - ForExplicitEH = true; - } - if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator())) - Resumes.push_back(Resume); + if (!First->isEHPad()) + continue; + assert(!isa<LandingPadInst>(First) && + "landingpad cannot be used with funclet EH personality"); + // Find EH pad blocks that represent funclet start points. + if (!isa<CatchEndPadInst>(First) && !isa<CleanupEndPadInst>(First)) + EntryBlocks.push_back(&BB); } - return ForExplicitEH; } bool WinEHPrepare::runOnFunction(Function &Fn) { @@ -442,25 +160,9 @@ bool WinEHPrepare::runOnFunction(Function &Fn) { // not. removeUnreachableBlocks(Fn); - SmallVector<LandingPadInst *, 4> LPads; - SmallVector<ResumeInst *, 4> Resumes; SmallVector<BasicBlock *, 4> EntryBlocks; - bool ForExplicitEH = - findExceptionalConstructs(Fn, LPads, Resumes, EntryBlocks); - - if (ForExplicitEH) - return prepareExplicitEH(Fn, EntryBlocks); - - // No need to prepare functions that lack landing pads. - if (LPads.empty()) - return false; - - DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); - LibInfo = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); - - // If there were any landing pads, prepareExceptionHandlers will make changes. - prepareExceptionHandlers(Fn, LPads); - return true; + findFuncletEntryPoints(Fn, EntryBlocks); + return prepareExplicitEH(Fn, EntryBlocks); } bool WinEHPrepare::doFinalization(Module &M) { return false; } @@ -470,2140 +172,12 @@ void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired<TargetLibraryInfoWrapperPass>(); } -static bool isSelectorDispatch(BasicBlock *BB, BasicBlock *&CatchHandler, - Constant *&Selector, BasicBlock *&NextBB); - -// Finds blocks reachable from the starting set Worklist. Does not follow unwind -// edges or blocks listed in StopPoints. -static void findReachableBlocks(SmallPtrSetImpl<BasicBlock *> &ReachableBBs, - SetVector<BasicBlock *> &Worklist, - const SetVector<BasicBlock *> *StopPoints) { - while (!Worklist.empty()) { - BasicBlock *BB = Worklist.pop_back_val(); - - // Don't cross blocks that we should stop at. - if (StopPoints && StopPoints->count(BB)) - continue; - - if (!ReachableBBs.insert(BB).second) - continue; // Already visited. - - // Don't follow unwind edges of invokes. - if (auto *II = dyn_cast<InvokeInst>(BB->getTerminator())) { - Worklist.insert(II->getNormalDest()); - continue; - } - - // Otherwise, follow all successors. - Worklist.insert(succ_begin(BB), succ_end(BB)); - } -} - -// Attempt to find an instruction where a block can be split before -// a call to llvm.eh.begincatch and its operands. If the block -// begins with the begincatch call or one of its adjacent operands -// the block will not be split. -static Instruction *findBeginCatchSplitPoint(BasicBlock *BB, - IntrinsicInst *II) { - // If the begincatch call is already the first instruction in the block, - // don't split. - Instruction *FirstNonPHI = BB->getFirstNonPHI(); - if (II == FirstNonPHI) - return nullptr; - - // If either operand is in the same basic block as the instruction and - // isn't used by another instruction before the begincatch call, include it - // in the split block. - auto *Op0 = dyn_cast<Instruction>(II->getOperand(0)); - auto *Op1 = dyn_cast<Instruction>(II->getOperand(1)); - - Instruction *I = II->getPrevNode(); - Instruction *LastI = II; - - while (I == Op0 || I == Op1) { - // If the block begins with one of the operands and there are no other - // instructions between the operand and the begincatch call, don't split. - if (I == FirstNonPHI) - return nullptr; - - LastI = I; - I = I->getPrevNode(); - } - - // If there is at least one instruction in the block before the begincatch - // call and its operands, split the block at either the begincatch or - // its operand. - return LastI; -} - -/// Find all points where exceptional control rejoins normal control flow via -/// llvm.eh.endcatch. Add them to the normal bb reachability worklist. -void WinEHPrepare::findCXXEHReturnPoints( - Function &F, SetVector<BasicBlock *> &EHReturnBlocks) { - for (auto BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) { - BasicBlock *BB = &*BBI; - for (Instruction &I : *BB) { - if (match(&I, m_Intrinsic<Intrinsic::eh_begincatch>())) { - Instruction *SplitPt = - findBeginCatchSplitPoint(BB, cast<IntrinsicInst>(&I)); - if (SplitPt) { - // Split the block before the llvm.eh.begincatch call to allow - // cleanup and catch code to be distinguished later. - // Do not update BBI because we still need to process the - // portion of the block that we are splitting off. - SplitBlock(BB, SplitPt, DT); - break; - } - } - if (match(&I, m_Intrinsic<Intrinsic::eh_endcatch>())) { - // Split the block after the call to llvm.eh.endcatch if there is - // anything other than an unconditional branch, or if the successor - // starts with a phi. - auto *Br = dyn_cast<BranchInst>(I.getNextNode()); - if (!Br || !Br->isUnconditional() || - isa<PHINode>(Br->getSuccessor(0)->begin())) { - DEBUG(dbgs() << "splitting block " << BB->getName() - << " with llvm.eh.endcatch\n"); - BBI = SplitBlock(BB, I.getNextNode(), DT)->getIterator(); - } - // The next BB is normal control flow. - EHReturnBlocks.insert(BB->getTerminator()->getSuccessor(0)); - break; - } - } - } -} - -static bool isCatchAllLandingPad(const BasicBlock *BB) { - const LandingPadInst *LP = BB->getLandingPadInst(); - if (!LP) - return false; - unsigned N = LP->getNumClauses(); - return (N > 0 && LP->isCatch(N - 1) && - isa<ConstantPointerNull>(LP->getClause(N - 1))); -} - -/// Find all points where exceptions control rejoins normal control flow via -/// selector dispatch. -void WinEHPrepare::findSEHEHReturnPoints( - Function &F, SetVector<BasicBlock *> &EHReturnBlocks) { - for (auto BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) { - BasicBlock *BB = &*BBI; - // If the landingpad is a catch-all, treat the whole lpad as if it is - // reachable from normal control flow. - // FIXME: This is imprecise. We need a better way of identifying where a - // catch-all starts and cleanups stop. As far as LLVM is concerned, there - // is no difference. - if (isCatchAllLandingPad(BB)) { - EHReturnBlocks.insert(BB); - continue; - } - - BasicBlock *CatchHandler; - BasicBlock *NextBB; - Constant *Selector; - if (isSelectorDispatch(BB, CatchHandler, Selector, NextBB)) { - // Split the edge if there are multiple predecessors. This creates a place - // where we can insert EH recovery code. - if (!CatchHandler->getSinglePredecessor()) { - DEBUG(dbgs() << "splitting EH return edge from " << BB->getName() - << " to " << CatchHandler->getName() << '\n'); - CatchHandler = SplitCriticalEdge( - BB, std::find(succ_begin(BB), succ_end(BB), CatchHandler)); - BBI = CatchHandler->getIterator(); - } - EHReturnBlocks.insert(CatchHandler); - } - } -} - -void WinEHPrepare::identifyEHBlocks(Function &F, - SmallVectorImpl<LandingPadInst *> &LPads) { - DEBUG(dbgs() << "Demoting values live across exception handlers in function " - << F.getName() << '\n'); - - // Build a set of all non-exceptional blocks and exceptional blocks. - // - Non-exceptional blocks are blocks reachable from the entry block while - // not following invoke unwind edges. - // - Exceptional blocks are blocks reachable from landingpads. Analysis does - // not follow llvm.eh.endcatch blocks, which mark a transition from - // exceptional to normal control. - - if (Personality == EHPersonality::MSVC_CXX) - findCXXEHReturnPoints(F, EHReturnBlocks); - else - findSEHEHReturnPoints(F, EHReturnBlocks); - - DEBUG({ - dbgs() << "identified the following blocks as EH return points:\n"; - for (BasicBlock *BB : EHReturnBlocks) - dbgs() << " " << BB->getName() << '\n'; - }); - -// Join points should not have phis at this point, unless they are a -// landingpad, in which case we will demote their phis later. -#ifndef NDEBUG - for (BasicBlock *BB : EHReturnBlocks) - assert((BB->isLandingPad() || !isa<PHINode>(BB->begin())) && - "non-lpad EH return block has phi"); -#endif - - // Normal blocks are the blocks reachable from the entry block and all EH - // return points. - SetVector<BasicBlock *> Worklist; - Worklist = EHReturnBlocks; - Worklist.insert(&F.getEntryBlock()); - findReachableBlocks(NormalBlocks, Worklist, nullptr); - DEBUG({ - dbgs() << "marked the following blocks as normal:\n"; - for (BasicBlock *BB : NormalBlocks) - dbgs() << " " << BB->getName() << '\n'; - }); - - // Exceptional blocks are the blocks reachable from landingpads that don't - // cross EH return points. - Worklist.clear(); - for (auto *LPI : LPads) - Worklist.insert(LPI->getParent()); - findReachableBlocks(EHBlocks, Worklist, &EHReturnBlocks); - DEBUG({ - dbgs() << "marked the following blocks as exceptional:\n"; - for (BasicBlock *BB : EHBlocks) - dbgs() << " " << BB->getName() << '\n'; - }); - -} - -/// Ensure that all values live into and out of exception handlers are stored -/// in memory. -/// FIXME: This falls down when values are defined in one handler and live into -/// another handler. For example, a cleanup defines a value used only by a -/// catch handler. -void WinEHPrepare::demoteValuesLiveAcrossHandlers( - Function &F, SmallVectorImpl<LandingPadInst *> &LPads) { - DEBUG(dbgs() << "Demoting values live across exception handlers in function " - << F.getName() << '\n'); - - // identifyEHBlocks() should have been called before this function. - assert(!NormalBlocks.empty()); - - // Try to avoid demoting EH pointer and selector values. They get in the way - // of our pattern matching. - SmallPtrSet<Instruction *, 10> EHVals; - for (BasicBlock &BB : F) { - LandingPadInst *LP = BB.getLandingPadInst(); - if (!LP) - continue; - EHVals.insert(LP); - for (User *U : LP->users()) { - auto *EI = dyn_cast<ExtractValueInst>(U); - if (!EI) - continue; - EHVals.insert(EI); - for (User *U2 : EI->users()) { - if (auto *PN = dyn_cast<PHINode>(U2)) - EHVals.insert(PN); - } - } - } - - SetVector<Argument *> ArgsToDemote; - SetVector<Instruction *> InstrsToDemote; - for (BasicBlock &BB : F) { - bool IsNormalBB = NormalBlocks.count(&BB); - bool IsEHBB = EHBlocks.count(&BB); - if (!IsNormalBB && !IsEHBB) - continue; // Blocks that are neither normal nor EH are unreachable. - for (Instruction &I : BB) { - for (Value *Op : I.operands()) { - // Don't demote static allocas, constants, and labels. - if (isa<Constant>(Op) || isa<BasicBlock>(Op) || isa<InlineAsm>(Op)) - continue; - auto *AI = dyn_cast<AllocaInst>(Op); - if (AI && AI->isStaticAlloca()) - continue; - - if (auto *Arg = dyn_cast<Argument>(Op)) { - if (IsEHBB) { - DEBUG(dbgs() << "Demoting argument " << *Arg - << " used by EH instr: " << I << "\n"); - ArgsToDemote.insert(Arg); - } - continue; - } - - // Don't demote EH values. - auto *OpI = cast<Instruction>(Op); - if (EHVals.count(OpI)) - continue; - - BasicBlock *OpBB = OpI->getParent(); - // If a value is produced and consumed in the same BB, we don't need to - // demote it. - if (OpBB == &BB) - continue; - bool IsOpNormalBB = NormalBlocks.count(OpBB); - bool IsOpEHBB = EHBlocks.count(OpBB); - if (IsNormalBB != IsOpNormalBB || IsEHBB != IsOpEHBB) { - DEBUG({ - dbgs() << "Demoting instruction live in-out from EH:\n"; - dbgs() << "Instr: " << *OpI << '\n'; - dbgs() << "User: " << I << '\n'; - }); - InstrsToDemote.insert(OpI); - } - } - } - } - - // Demote values live into and out of handlers. - // FIXME: This demotion is inefficient. We should insert spills at the point - // of definition, insert one reload in each handler that uses the value, and - // insert reloads in the BB used to rejoin normal control flow. - Instruction *AllocaInsertPt = &*F.getEntryBlock().getFirstInsertionPt(); - for (Instruction *I : InstrsToDemote) - DemoteRegToStack(*I, false, AllocaInsertPt); - - // Demote arguments separately, and only for uses in EH blocks. - for (Argument *Arg : ArgsToDemote) { - auto *Slot = new AllocaInst(Arg->getType(), nullptr, - Arg->getName() + ".reg2mem", AllocaInsertPt); - SmallVector<User *, 4> Users(Arg->user_begin(), Arg->user_end()); - for (User *U : Users) { - auto *I = dyn_cast<Instruction>(U); - if (I && EHBlocks.count(I->getParent())) { - auto *Reload = new LoadInst(Slot, Arg->getName() + ".reload", false, I); - U->replaceUsesOfWith(Arg, Reload); - } - } - new StoreInst(Arg, Slot, AllocaInsertPt); - } - - // Demote landingpad phis, as the landingpad will be removed from the machine - // CFG. - for (LandingPadInst *LPI : LPads) { - BasicBlock *BB = LPI->getParent(); - while (auto *Phi = dyn_cast<PHINode>(BB->begin())) - DemotePHIToStack(Phi, AllocaInsertPt); - } - - DEBUG(dbgs() << "Demoted " << InstrsToDemote.size() << " instructions and " - << ArgsToDemote.size() << " arguments for WinEHPrepare\n\n"); -} - -bool WinEHPrepare::prepareExceptionHandlers( - Function &F, SmallVectorImpl<LandingPadInst *> &LPads) { - // Don't run on functions that are already prepared. - for (LandingPadInst *LPad : LPads) { - BasicBlock *LPadBB = LPad->getParent(); - for (Instruction &Inst : *LPadBB) - if (match(&Inst, m_Intrinsic<Intrinsic::eh_actions>())) - return false; - } - - identifyEHBlocks(F, LPads); - demoteValuesLiveAcrossHandlers(F, LPads); - - // These containers are used to re-map frame variables that are used in - // outlined catch and cleanup handlers. They will be populated as the - // handlers are outlined. - FrameVarInfoMap FrameVarInfo; - - bool HandlersOutlined = false; - - Module *M = F.getParent(); - LLVMContext &Context = M->getContext(); - - // Create a new function to receive the handler contents. - PointerType *Int8PtrType = Type::getInt8PtrTy(Context); - Type *Int32Type = Type::getInt32Ty(Context); - Function *ActionIntrin = Intrinsic::getDeclaration(M, Intrinsic::eh_actions); - - if (isAsynchronousEHPersonality(Personality)) { - // FIXME: Switch the ehptr type to i32 and then switch this. - SEHExceptionCodeSlot = - new AllocaInst(Int8PtrType, nullptr, "seh_exception_code", - &*F.getEntryBlock().getFirstInsertionPt()); - } - - // In order to handle the case where one outlined catch handler returns - // to a block within another outlined catch handler that would otherwise - // be unreachable, we need to outline the nested landing pad before we - // outline the landing pad which encloses it. - if (!isAsynchronousEHPersonality(Personality)) - std::sort(LPads.begin(), LPads.end(), - [this](LandingPadInst *const &L, LandingPadInst *const &R) { - return DT->properlyDominates(R->getParent(), L->getParent()); - }); - - // 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<std::pair<CallInst*, IndirectBrInst *>, 4> LPadImpls; - - for (LandingPadInst *LPad : LPads) { - // Look for evidence that this landingpad has already been processed. - bool LPadHasActionList = false; - BasicBlock *LPadBB = LPad->getParent(); - for (Instruction &Inst : *LPadBB) { - if (match(&Inst, m_Intrinsic<Intrinsic::eh_actions>())) { - LPadHasActionList = true; - break; - } - } - - // If we've already outlined the handlers for this landingpad, - // there's nothing more to do here. - if (LPadHasActionList) - continue; - - // If either of the values in the aggregate returned by the landing pad is - // extracted and stored to memory, promote the stored value to a register. - promoteLandingPadValues(LPad); - - LandingPadActions Actions; - mapLandingPadBlocks(LPad, Actions); - - HandlersOutlined |= !Actions.actions().empty(); - for (ActionHandler *Action : Actions) { - if (Action->hasBeenProcessed()) - continue; - BasicBlock *StartBB = Action->getStartBlock(); - - // SEH doesn't do any outlining for catches. Instead, pass the handler - // basic block addr to llvm.eh.actions and list the block as a return - // target. - if (isAsynchronousEHPersonality(Personality)) { - if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) { - processSEHCatchHandler(CatchAction, StartBB); - continue; - } - } - - outlineHandler(Action, &F, LPad, StartBB, FrameVarInfo); - } - - // Split the block after the landingpad instruction so that it is just a - // call to llvm.eh.actions followed by indirectbr. - assert(!isa<PHINode>(LPadBB->begin()) && "lpad phi not removed"); - SplitBlock(LPadBB, LPad->getNextNode(), DT); - // Erase the branch inserted by the split so we can insert indirectbr. - LPadBB->getTerminator()->eraseFromParent(); - - // Replace all extracted values with undef and ultimately replace the - // landingpad with undef. - SmallVector<Instruction *, 4> SEHCodeUses; - SmallVector<Instruction *, 4> EHUndefs; - for (User *U : LPad->users()) { - auto *E = dyn_cast<ExtractValueInst>(U); - if (!E) - continue; - assert(E->getNumIndices() == 1 && - "Unexpected operation: extracting both landing pad values"); - unsigned Idx = *E->idx_begin(); - assert((Idx == 0 || Idx == 1) && "unexpected index"); - if (Idx == 0 && isAsynchronousEHPersonality(Personality)) - SEHCodeUses.push_back(E); - else - EHUndefs.push_back(E); - } - for (Instruction *E : EHUndefs) { - E->replaceAllUsesWith(UndefValue::get(E->getType())); - E->eraseFromParent(); - } - LPad->replaceAllUsesWith(UndefValue::get(LPad->getType())); - - // Rewrite uses of the exception pointer to loads of an alloca. - while (!SEHCodeUses.empty()) { - Instruction *E = SEHCodeUses.pop_back_val(); - SmallVector<Use *, 4> Uses; - for (Use &U : E->uses()) - Uses.push_back(&U); - for (Use *U : Uses) { - auto *I = cast<Instruction>(U->getUser()); - if (isa<ResumeInst>(I)) - continue; - if (auto *Phi = dyn_cast<PHINode>(I)) - SEHCodeUses.push_back(Phi); - else - U->set(new LoadInst(SEHExceptionCodeSlot, "sehcode", false, I)); - } - E->replaceAllUsesWith(UndefValue::get(E->getType())); - E->eraseFromParent(); - } - - // Add a call to describe the actions for this landing pad. - std::vector<Value *> ActionArgs; - for (ActionHandler *Action : Actions) { - // Action codes from docs are: 0 cleanup, 1 catch. - if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) { - ActionArgs.push_back(ConstantInt::get(Int32Type, 1)); - ActionArgs.push_back(CatchAction->getSelector()); - // Find the frame escape index of the exception object alloca in the - // parent. - int FrameEscapeIdx = -1; - Value *EHObj = const_cast<Value *>(CatchAction->getExceptionVar()); - if (EHObj && !isa<ConstantPointerNull>(EHObj)) { - auto I = FrameVarInfo.find(EHObj); - assert(I != FrameVarInfo.end() && - "failed to map llvm.eh.begincatch var"); - FrameEscapeIdx = std::distance(FrameVarInfo.begin(), I); - } - ActionArgs.push_back(ConstantInt::get(Int32Type, FrameEscapeIdx)); - } else { - ActionArgs.push_back(ConstantInt::get(Int32Type, 0)); - } - ActionArgs.push_back(Action->getHandlerBlockOrFunc()); - } - CallInst *Recover = - CallInst::Create(ActionIntrin, ActionArgs, "recover", LPadBB); - - SetVector<BasicBlock *> ReturnTargets; - for (ActionHandler *Action : Actions) { - if (auto *CatchAction = dyn_cast<CatchHandler>(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); - - if (!isAsynchronousEHPersonality(Personality)) { - // C++ EH must repopulate the targets later to handle the case of - // targets that are reached indirectly through nested landing pads. - LPadImpls.push_back(std::make_pair(Recover, Branch)); - } - - } // End for each landingpad - - // If nothing got outlined, there is no more processing to be done. - if (!HandlersOutlined) - return false; - - // Replace any nested landing pad stubs with the correct action handler. - // This must be done before we remove unreachable blocks because it - // cleans up references to outlined blocks that will be deleted. - for (auto &LPadPair : NestedLPtoOriginalLP) - completeNestedLandingPad(&F, LPadPair.first, LPadPair.second, FrameVarInfo); - NestedLPtoOriginalLP.clear(); - - // Update the indirectbr instructions' target lists if necessary. - SetVector<BasicBlock*> CheckedTargets; - SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList; - for (auto &LPadImplPair : LPadImpls) { - IntrinsicInst *Recover = cast<IntrinsicInst>(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<BasicBlock *> ReturnTargets; - for (const auto &Action : ActionList) { - if (auto *CA = dyn_cast<CatchHandler>(Action.get())) { - Function *Handler = cast<Function>(CA->getHandlerBlockOrFunc()); - getPossibleReturnTargets(&F, Handler, ReturnTargets); - } - } - ActionList.clear(); - // Clear any targets we already knew about. - for (unsigned int I = 0, E = Branch->getNumDestinations(); I < E; ++I) { - BasicBlock *KnownTarget = Branch->getDestination(I); - if (ReturnTargets.count(KnownTarget)) - ReturnTargets.remove(KnownTarget); - } - 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<BranchInst>(Target->getTerminator()); - if (Br && Br->isUnconditional() && - Br != Target->getFirstNonPHIOrDbgOrLifetime()) { - Instruction *Prev = Br->getPrevNode(); - if (match(cast<Value>(Prev), m_Intrinsic<Intrinsic::eh_endcatch>())) - Prev->eraseFromParent(); - } - } - } - } - LPadImpls.clear(); - - F.addFnAttr("wineh-parent", F.getName()); - - // Delete any blocks that were only used by handlers that were outlined above. - removeUnreachableBlocks(F); - - BasicBlock *Entry = &F.getEntryBlock(); - IRBuilder<> Builder(F.getParent()->getContext()); - Builder.SetInsertPoint(Entry, Entry->getFirstInsertionPt()); - - Function *FrameEscapeFn = - Intrinsic::getDeclaration(M, Intrinsic::localescape); - Function *RecoverFrameFn = - Intrinsic::getDeclaration(M, Intrinsic::localrecover); - SmallVector<Value *, 8> AllocasToEscape; - - // Scan the entry block for an existing call to llvm.localescape. We need to - // keep escaping those objects. - for (Instruction &I : F.front()) { - auto *II = dyn_cast<IntrinsicInst>(&I); - if (II && II->getIntrinsicID() == Intrinsic::localescape) { - auto Args = II->arg_operands(); - AllocasToEscape.append(Args.begin(), Args.end()); - II->eraseFromParent(); - break; - } - } - - // Finally, replace all of the temporary allocas for frame variables used in - // the outlined handlers with calls to llvm.localrecover. - for (auto &VarInfoEntry : FrameVarInfo) { - Value *ParentVal = VarInfoEntry.first; - TinyPtrVector<AllocaInst *> &Allocas = VarInfoEntry.second; - AllocaInst *ParentAlloca = cast<AllocaInst>(ParentVal); - - // FIXME: We should try to sink unescaped allocas from the parent frame into - // the child frame. If the alloca is escaped, we have to use the lifetime - // markers to ensure that the alloca is only live within the child frame. - - // Add this alloca to the list of things to escape. - AllocasToEscape.push_back(ParentAlloca); - - // Next replace all outlined allocas that are mapped to it. - for (AllocaInst *TempAlloca : Allocas) { - if (TempAlloca == getCatchObjectSentinel()) - continue; // Skip catch parameter sentinels. - Function *HandlerFn = TempAlloca->getParent()->getParent(); - llvm::Value *FP = HandlerToParentFP[HandlerFn]; - assert(FP); - - // FIXME: Sink this localrecover into the blocks where it is used. - Builder.SetInsertPoint(TempAlloca); - Builder.SetCurrentDebugLocation(TempAlloca->getDebugLoc()); - Value *RecoverArgs[] = { - Builder.CreateBitCast(&F, Int8PtrType, ""), FP, - llvm::ConstantInt::get(Int32Type, AllocasToEscape.size() - 1)}; - Instruction *RecoveredAlloca = - Builder.CreateCall(RecoverFrameFn, RecoverArgs); - - // Add a pointer bitcast if the alloca wasn't an i8. - if (RecoveredAlloca->getType() != TempAlloca->getType()) { - RecoveredAlloca->setName(Twine(TempAlloca->getName()) + ".i8"); - RecoveredAlloca = cast<Instruction>( - Builder.CreateBitCast(RecoveredAlloca, TempAlloca->getType())); - } - TempAlloca->replaceAllUsesWith(RecoveredAlloca); - TempAlloca->removeFromParent(); - RecoveredAlloca->takeName(TempAlloca); - delete TempAlloca; - } - } // End for each FrameVarInfo entry. - - // Insert 'call void (...)* @llvm.localescape(...)' at the end of the entry - // block. - Builder.SetInsertPoint(&F.getEntryBlock().back()); - Builder.CreateCall(FrameEscapeFn, AllocasToEscape); - - if (SEHExceptionCodeSlot) { - if (isAllocaPromotable(SEHExceptionCodeSlot)) { - SmallPtrSet<BasicBlock *, 4> UserBlocks; - for (User *U : SEHExceptionCodeSlot->users()) { - if (auto *Inst = dyn_cast<Instruction>(U)) - UserBlocks.insert(Inst->getParent()); - } - PromoteMemToReg(SEHExceptionCodeSlot, *DT); - // After the promotion, kill off dead instructions. - for (BasicBlock *BB : UserBlocks) - SimplifyInstructionsInBlock(BB, LibInfo); - } - } - - // Clean up the handler action maps we created for this function - DeleteContainerSeconds(CatchHandlerMap); - CatchHandlerMap.clear(); - DeleteContainerSeconds(CleanupHandlerMap); - CleanupHandlerMap.clear(); - HandlerToParentFP.clear(); - DT = nullptr; - LibInfo = nullptr; - SEHExceptionCodeSlot = nullptr; - EHBlocks.clear(); - NormalBlocks.clear(); - EHReturnBlocks.clear(); - - return HandlersOutlined; -} - -void WinEHPrepare::promoteLandingPadValues(LandingPadInst *LPad) { - // If the return values of the landing pad instruction are extracted and - // stored to memory, we want to promote the store locations to reg values. - SmallVector<AllocaInst *, 2> EHAllocas; - - // The landingpad instruction returns an aggregate value. Typically, its - // value will be passed to a pair of extract value instructions and the - // results of those extracts are often passed to store instructions. - // In unoptimized code the stored value will often be loaded and then stored - // again. - for (auto *U : LPad->users()) { - ExtractValueInst *Extract = dyn_cast<ExtractValueInst>(U); - if (!Extract) - continue; - - for (auto *EU : Extract->users()) { - if (auto *Store = dyn_cast<StoreInst>(EU)) { - auto *AV = cast<AllocaInst>(Store->getPointerOperand()); - EHAllocas.push_back(AV); - } - } - } - - // We can't do this without a dominator tree. - assert(DT); - - if (!EHAllocas.empty()) { - PromoteMemToReg(EHAllocas, *DT); - EHAllocas.clear(); - } - - // After promotion, some extracts may be trivially dead. Remove them. - SmallVector<Value *, 4> Users(LPad->user_begin(), LPad->user_end()); - for (auto *U : Users) - RecursivelyDeleteTriviallyDeadInstructions(U); -} - -void WinEHPrepare::getPossibleReturnTargets(Function *ParentF, - Function *HandlerF, - SetVector<BasicBlock*> &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<IntrinsicInst>(LPI->getNextNode()); - SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList; - parseEHActions(Recover, ActionList); - for (const auto &Action : ActionList) { - if (auto *CH = dyn_cast<CatchHandler>(Action.get())) { - Function *NestedF = cast<Function>(CH->getHandlerBlockOrFunc()); - getPossibleReturnTargets(ParentF, NestedF, Targets); - } - } - } - - auto *Ret = dyn_cast<ReturnInst>(BB.getTerminator()); - if (!Ret) - continue; - - // Handler functions must always return a block address. - BlockAddress *BA = cast<BlockAddress>(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, - FrameVarInfoMap &FrameVarInfo) { - // Get the nested block and erase the unreachable instruction that was - // temporarily inserted as its terminator. - LLVMContext &Context = ParentFn->getContext(); - BasicBlock *OutlinedBB = OutlinedLPad->getParent(); - // If the nested landing pad was outlined before the landing pad that enclosed - // it, it will already be in outlined form. In that case, we just need to see - // if the returns and the enclosing branch instruction need to be updated. - IndirectBrInst *Branch = - dyn_cast<IndirectBrInst>(OutlinedBB->getTerminator()); - if (!Branch) { - // If the landing pad wasn't in outlined form, it should be a stub with - // an unreachable terminator. - assert(isa<UnreachableInst>(OutlinedBB->getTerminator())); - OutlinedBB->getTerminator()->eraseFromParent(); - // That should leave OutlinedLPad as the last instruction in its block. - assert(&OutlinedBB->back() == OutlinedLPad); - } - - // The original landing pad will have already had its action intrinsic - // built by the outlining loop. We need to clone that into the outlined - // location. It may also be necessary to add references to the exception - // variables to the outlined handler in which this landing pad is nested - // and remap return instructions in the nested handlers that should return - // to an address in the outlined handler. - Function *OutlinedHandlerFn = OutlinedBB->getParent(); - BasicBlock::const_iterator II = OriginalLPad->getIterator(); - ++II; - // The instruction after the landing pad should now be a call to eh.actions. - const Instruction *Recover = &*II; - const IntrinsicInst *EHActions = cast<IntrinsicInst>(Recover); - - // Remap the return target in the nested handler. - SmallVector<BlockAddress *, 4> ActionTargets; - SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList; - parseEHActions(EHActions, ActionList); - for (const auto &Action : ActionList) { - auto *Catch = dyn_cast<CatchHandler>(Action.get()); - if (!Catch) - continue; - // The dyn_cast to function here selects C++ catch handlers and skips - // SEH catch handlers. - auto *Handler = dyn_cast<Function>(Catch->getHandlerBlockOrFunc()); - if (!Handler) - continue; - // Visit all the return instructions, looking for places that return - // to a location within OutlinedHandlerFn. - for (BasicBlock &NestedHandlerBB : *Handler) { - auto *Ret = dyn_cast<ReturnInst>(NestedHandlerBB.getTerminator()); - if (!Ret) - continue; - - // Handler functions must always return a block address. - BlockAddress *BA = cast<BlockAddress>(Ret->getReturnValue()); - // The original target will have been in the main parent function, - // but if it is the address of a block that has been outlined, it - // should be a block that was outlined into OutlinedHandlerFn. - assert(BA->getFunction() == ParentFn); - - // Ignore targets that aren't part of an outlined handler function. - if (!LPadTargetBlocks.count(BA->getBasicBlock())) - continue; - - // If the return value is the address ofF a block that we - // previously outlined into the parent handler function, replace - // the return instruction and add the mapped target to the list - // of possible return addresses. - BasicBlock *MappedBB = LPadTargetBlocks[BA->getBasicBlock()]; - assert(MappedBB->getParent() == OutlinedHandlerFn); - BlockAddress *NewBA = BlockAddress::get(OutlinedHandlerFn, MappedBB); - Ret->eraseFromParent(); - ReturnInst::Create(Context, NewBA, &NestedHandlerBB); - ActionTargets.push_back(NewBA); - } - } - ActionList.clear(); - - if (Branch) { - // If the landing pad was already in outlined form, just update its targets. - for (unsigned int I = Branch->getNumDestinations(); I > 0; --I) - Branch->removeDestination(I); - // Add the previously collected action targets. - for (auto *Target : ActionTargets) - Branch->addDestination(Target->getBasicBlock()); - } else { - // If the landing pad was previously stubbed out, fill in its outlined form. - IntrinsicInst *NewEHActions = cast<IntrinsicInst>(EHActions->clone()); - OutlinedBB->getInstList().push_back(NewEHActions); - - // Insert an indirect branch into the outlined landing pad BB. - IndirectBrInst *IBr = IndirectBrInst::Create(NewEHActions, 0, OutlinedBB); - // Add the previously collected action targets. - for (auto *Target : ActionTargets) - IBr->addDestination(Target->getBasicBlock()); - } -} - -// This function examines a block to determine whether the block ends with a -// conditional branch to a catch handler based on a selector comparison. -// This function is used both by the WinEHPrepare::findSelectorComparison() and -// WinEHCleanupDirector::handleTypeIdFor(). -static bool isSelectorDispatch(BasicBlock *BB, BasicBlock *&CatchHandler, - Constant *&Selector, BasicBlock *&NextBB) { - ICmpInst::Predicate Pred; - BasicBlock *TBB, *FBB; - Value *LHS, *RHS; - - if (!match(BB->getTerminator(), - m_Br(m_ICmp(Pred, m_Value(LHS), m_Value(RHS)), TBB, FBB))) - return false; - - if (!match(LHS, - m_Intrinsic<Intrinsic::eh_typeid_for>(m_Constant(Selector))) && - !match(RHS, m_Intrinsic<Intrinsic::eh_typeid_for>(m_Constant(Selector)))) - return false; - - if (Pred == CmpInst::ICMP_EQ) { - CatchHandler = TBB; - NextBB = FBB; - return true; - } - - if (Pred == CmpInst::ICMP_NE) { - CatchHandler = FBB; - NextBB = TBB; - return true; - } - - return false; -} - -static bool isCatchBlock(BasicBlock *BB) { - for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg()->getIterator(), - IE = BB->end(); - II != IE; ++II) { - if (match(cast<Value>(II), m_Intrinsic<Intrinsic::eh_begincatch>())) - return true; - } - return false; -} - -static BasicBlock *createStubLandingPad(Function *Handler) { - // FIXME: Finish this! - LLVMContext &Context = Handler->getContext(); - BasicBlock *StubBB = BasicBlock::Create(Context, "stub"); - Handler->getBasicBlockList().push_back(StubBB); - IRBuilder<> Builder(StubBB); - LandingPadInst *LPad = Builder.CreateLandingPad( - llvm::StructType::get(Type::getInt8PtrTy(Context), - Type::getInt32Ty(Context), nullptr), - 0); - // 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"); - LPad->setCleanup(true); - Builder.CreateUnreachable(); - return StubBB; -} - -// Cycles through the blocks in an outlined handler function looking for an -// invoke instruction and inserts an invoke of llvm.donothing with an empty -// landing pad if none is found. The code that generates the .xdata tables for -// the handler needs at least one landing pad to identify the parent function's -// personality. -void WinEHPrepare::addStubInvokeToHandlerIfNeeded(Function *Handler) { - ReturnInst *Ret = nullptr; - UnreachableInst *Unreached = nullptr; - for (BasicBlock &BB : *Handler) { - TerminatorInst *Terminator = BB.getTerminator(); - // If we find an invoke, there is nothing to be done. - auto *II = dyn_cast<InvokeInst>(Terminator); - if (II) - return; - // If we've already recorded a return instruction, keep looking for invokes. - if (!Ret) - Ret = dyn_cast<ReturnInst>(Terminator); - // If we haven't recorded an unreachable instruction, try this terminator. - if (!Unreached) - Unreached = dyn_cast<UnreachableInst>(Terminator); - } - - // If we got this far, the handler contains no invokes. We should have seen - // at least one return or unreachable instruction. We'll insert an invoke of - // llvm.donothing ahead of that instruction. - assert(Ret || Unreached); - TerminatorInst *Term; - if (Ret) - Term = Ret; - else - Term = Unreached; - BasicBlock *OldRetBB = Term->getParent(); - BasicBlock *NewRetBB = SplitBlock(OldRetBB, Term, DT); - // SplitBlock adds an unconditional branch instruction at the end of the - // parent block. We want to replace that with an invoke call, so we can - // erase it now. - OldRetBB->getTerminator()->eraseFromParent(); - BasicBlock *StubLandingPad = createStubLandingPad(Handler); - Function *F = - Intrinsic::getDeclaration(Handler->getParent(), Intrinsic::donothing); - InvokeInst::Create(F, NewRetBB, StubLandingPad, None, "", OldRetBB); -} - -// FIXME: Consider sinking this into lib/Target/X86 somehow. TargetLowering -// usually doesn't build LLVM IR, so that's probably the wrong place. -Function *WinEHPrepare::createHandlerFunc(Function *ParentFn, Type *RetTy, - const Twine &Name, Module *M, - Value *&ParentFP) { - // x64 uses a two-argument prototype where the parent FP is the second - // argument. x86 uses no arguments, just the incoming EBP value. - LLVMContext &Context = M->getContext(); - Type *Int8PtrType = Type::getInt8PtrTy(Context); - FunctionType *FnType; - if (TheTriple.getArch() == Triple::x86_64) { - Type *ArgTys[2] = {Int8PtrType, Int8PtrType}; - FnType = FunctionType::get(RetTy, ArgTys, false); - } else { - FnType = FunctionType::get(RetTy, None, false); - } - - Function *Handler = - Function::Create(FnType, GlobalVariable::InternalLinkage, Name, M); - BasicBlock *Entry = BasicBlock::Create(Context, "entry"); - Handler->getBasicBlockList().push_front(Entry); - if (TheTriple.getArch() == Triple::x86_64) { - ParentFP = &(Handler->getArgumentList().back()); - } else { - assert(M); - Function *FrameAddressFn = - Intrinsic::getDeclaration(M, Intrinsic::frameaddress); - Function *RecoverFPFn = - Intrinsic::getDeclaration(M, Intrinsic::x86_seh_recoverfp); - IRBuilder<> Builder(&Handler->getEntryBlock()); - Value *EBP = - Builder.CreateCall(FrameAddressFn, {Builder.getInt32(1)}, "ebp"); - Value *ParentI8Fn = Builder.CreateBitCast(ParentFn, Int8PtrType); - ParentFP = Builder.CreateCall(RecoverFPFn, {ParentI8Fn, EBP}); - } - return Handler; -} - -bool WinEHPrepare::outlineHandler(ActionHandler *Action, Function *SrcFn, - LandingPadInst *LPad, BasicBlock *StartBB, - FrameVarInfoMap &VarInfo) { - Module *M = SrcFn->getParent(); - LLVMContext &Context = M->getContext(); - Type *Int8PtrType = Type::getInt8PtrTy(Context); - - // Create a new function to receive the handler contents. - Value *ParentFP; - Function *Handler; - if (Action->getType() == Catch) { - Handler = createHandlerFunc(SrcFn, Int8PtrType, SrcFn->getName() + ".catch", M, - ParentFP); - } else { - Handler = createHandlerFunc(SrcFn, Type::getVoidTy(Context), - SrcFn->getName() + ".cleanup", M, ParentFP); - } - Handler->setPersonalityFn(SrcFn->getPersonalityFn()); - HandlerToParentFP[Handler] = ParentFP; - Handler->addFnAttr("wineh-parent", SrcFn->getName()); - BasicBlock *Entry = &Handler->getEntryBlock(); - - // Generate a standard prolog to setup the frame recovery structure. - IRBuilder<> Builder(Context); - Builder.SetInsertPoint(Entry); - Builder.SetCurrentDebugLocation(LPad->getDebugLoc()); - - std::unique_ptr<WinEHCloningDirectorBase> Director; - - ValueToValueMapTy VMap; - - LandingPadMap &LPadMap = LPadMaps[LPad]; - if (!LPadMap.isInitialized()) - LPadMap.mapLandingPad(LPad); - if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) { - Constant *Sel = CatchAction->getSelector(); - Director.reset(new WinEHCatchDirector(Handler, ParentFP, Sel, VarInfo, - LPadMap, NestedLPtoOriginalLP, DT, - EHBlocks)); - LPadMap.remapEHValues(VMap, UndefValue::get(Int8PtrType), - ConstantInt::get(Type::getInt32Ty(Context), 1)); - } else { - Director.reset( - new WinEHCleanupDirector(Handler, ParentFP, VarInfo, LPadMap)); - LPadMap.remapEHValues(VMap, UndefValue::get(Int8PtrType), - UndefValue::get(Type::getInt32Ty(Context))); - } - - SmallVector<ReturnInst *, 8> Returns; - ClonedCodeInfo OutlinedFunctionInfo; - - // If the start block contains PHI nodes, we need to map them. - BasicBlock::iterator II = StartBB->begin(); - while (auto *PN = dyn_cast<PHINode>(II)) { - bool Mapped = false; - // Look for PHI values that we have already mapped (such as the selector). - for (Value *Val : PN->incoming_values()) { - if (VMap.count(Val)) { - VMap[PN] = VMap[Val]; - Mapped = true; - } - } - // If we didn't find a match for this value, map it as an undef. - if (!Mapped) { - VMap[PN] = UndefValue::get(PN->getType()); - } - ++II; - } - - // The landing pad value may be used by PHI nodes. It will ultimately be - // eliminated, but we need it in the map for intermediate handling. - VMap[LPad] = UndefValue::get(LPad->getType()); - - // Skip over PHIs and, if applicable, landingpad instructions. - II = StartBB->getFirstInsertionPt(); - - CloneAndPruneIntoFromInst(Handler, SrcFn, &*II, VMap, - /*ModuleLevelChanges=*/false, Returns, "", - &OutlinedFunctionInfo, Director.get()); - - // Move all the instructions in the cloned "entry" block into our entry block. - // Depending on how the parent function was laid out, the block that will - // correspond to the outlined entry block may not be the first block in the - // list. We can recognize it, however, as the cloned block which has no - // predecessors. Any other block wouldn't have been cloned if it didn't - // have a predecessor which was also cloned. - Function::iterator ClonedIt = std::next(Function::iterator(Entry)); - while (!pred_empty(&*ClonedIt)) - ++ClonedIt; - assert(ClonedIt != Entry->getParent()->end()); - BasicBlock *ClonedEntryBB = &*ClonedIt; - Entry->getInstList().splice(Entry->end(), ClonedEntryBB->getInstList()); - ClonedEntryBB->eraseFromParent(); - - // Make sure we can identify the handler's personality later. - addStubInvokeToHandlerIfNeeded(Handler); - - if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) { - WinEHCatchDirector *CatchDirector = - reinterpret_cast<WinEHCatchDirector *>(Director.get()); - CatchAction->setExceptionVar(CatchDirector->getExceptionVar()); - CatchAction->setReturnTargets(CatchDirector->getReturnTargets()); - - // Look for blocks that are not part of the landing pad that we just - // outlined but terminate with a call to llvm.eh.endcatch and a - // branch to a block that is in the handler we just outlined. - // These blocks will be part of a nested landing pad that intends to - // return to an address in this handler. This case is best handled - // after both landing pads have been outlined, so for now we'll just - // save the association of the blocks in LPadTargetBlocks. The - // return instructions which are created from these branches will be - // replaced after all landing pads have been outlined. - for (const auto MapEntry : VMap) { - // VMap maps all values and blocks that were just cloned, but dead - // blocks which were pruned will map to nullptr. - if (!isa<BasicBlock>(MapEntry.first) || MapEntry.second == nullptr) - continue; - const BasicBlock *MappedBB = cast<BasicBlock>(MapEntry.first); - for (auto *Pred : predecessors(const_cast<BasicBlock *>(MappedBB))) { - auto *Branch = dyn_cast<BranchInst>(Pred->getTerminator()); - if (!Branch || !Branch->isUnconditional() || Pred->size() <= 1) - continue; - BasicBlock::iterator II = - const_cast<BranchInst *>(Branch)->getIterator(); - --II; - if (match(cast<Value>(II), m_Intrinsic<Intrinsic::eh_endcatch>())) { - // This would indicate that a nested landing pad wants to return - // to a block that is outlined into two different handlers. - assert(!LPadTargetBlocks.count(MappedBB)); - LPadTargetBlocks[MappedBB] = cast<BasicBlock>(MapEntry.second); - } - } - } - } // End if (CatchAction) - - Action->setHandlerBlockOrFunc(Handler); - - return true; -} - -/// This BB must end in a selector dispatch. All we need to do is pass the -/// handler block to llvm.eh.actions and list it as a possible indirectbr -/// target. -void WinEHPrepare::processSEHCatchHandler(CatchHandler *CatchAction, - BasicBlock *StartBB) { - BasicBlock *HandlerBB; - BasicBlock *NextBB; - Constant *Selector; - bool Res = isSelectorDispatch(StartBB, HandlerBB, Selector, NextBB); - if (Res) { - // If this was EH dispatch, this must be a conditional branch to the handler - // block. - // FIXME: Handle instructions in the dispatch block. Currently we drop them, - // leading to crashes if some optimization hoists stuff here. - assert(CatchAction->getSelector() && HandlerBB && - "expected catch EH dispatch"); - } else { - // This must be a catch-all. Split the block after the landingpad. - assert(CatchAction->getSelector()->isNullValue() && "expected catch-all"); - HandlerBB = SplitBlock(StartBB, &*StartBB->getFirstInsertionPt(), DT); - } - IRBuilder<> Builder(&*HandlerBB->getFirstInsertionPt()); - Function *EHCodeFn = Intrinsic::getDeclaration( - StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode_old); - Value *Code = Builder.CreateCall(EHCodeFn, {}, "sehcode"); - Code = Builder.CreateIntToPtr(Code, SEHExceptionCodeSlot->getAllocatedType()); - Builder.CreateStore(Code, SEHExceptionCodeSlot); - CatchAction->setHandlerBlockOrFunc(BlockAddress::get(HandlerBB)); - TinyPtrVector<BasicBlock *> Targets(HandlerBB); - CatchAction->setReturnTargets(Targets); -} - -void LandingPadMap::mapLandingPad(const LandingPadInst *LPad) { - // Each instance of this class should only ever be used to map a single - // landing pad. - assert(OriginLPad == nullptr || OriginLPad == LPad); - - // If the landing pad has already been mapped, there's nothing more to do. - if (OriginLPad == LPad) - return; - - OriginLPad = LPad; - - // The landingpad instruction returns an aggregate value. Typically, its - // value will be passed to a pair of extract value instructions and the - // results of those extracts will have been promoted to reg values before - // this routine is called. - for (auto *U : LPad->users()) { - const ExtractValueInst *Extract = dyn_cast<ExtractValueInst>(U); - if (!Extract) - continue; - assert(Extract->getNumIndices() == 1 && - "Unexpected operation: extracting both landing pad values"); - unsigned int Idx = *(Extract->idx_begin()); - assert((Idx == 0 || Idx == 1) && - "Unexpected operation: extracting an unknown landing pad element"); - if (Idx == 0) { - ExtractedEHPtrs.push_back(Extract); - } else if (Idx == 1) { - ExtractedSelectors.push_back(Extract); - } - } -} - -bool LandingPadMap::isOriginLandingPadBlock(const BasicBlock *BB) const { - return BB->getLandingPadInst() == OriginLPad; -} - -bool LandingPadMap::isLandingPadSpecificInst(const Instruction *Inst) const { - if (Inst == OriginLPad) - return true; - for (auto *Extract : ExtractedEHPtrs) { - if (Inst == Extract) - return true; - } - for (auto *Extract : ExtractedSelectors) { - if (Inst == Extract) - return true; - } - return false; -} - -void LandingPadMap::remapEHValues(ValueToValueMapTy &VMap, Value *EHPtrValue, - Value *SelectorValue) const { - // Remap all landing pad extract instructions to the specified values. - for (auto *Extract : ExtractedEHPtrs) - VMap[Extract] = EHPtrValue; - for (auto *Extract : ExtractedSelectors) - VMap[Extract] = SelectorValue; -} - -static bool isLocalAddressCall(const Value *V) { - return match(const_cast<Value *>(V), m_Intrinsic<Intrinsic::localaddress>()); -} - -CloningDirector::CloningAction WinEHCloningDirectorBase::handleInstruction( - ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { - // If this is one of the boilerplate landing pad instructions, skip it. - // The instruction will have already been remapped in VMap. - if (LPadMap.isLandingPadSpecificInst(Inst)) - return CloningDirector::SkipInstruction; - - // Nested landing pads that have not already been outlined will be cloned as - // stubs, with just the landingpad instruction and an unreachable instruction. - // When all landingpads have been outlined, we'll replace this with the - // llvm.eh.actions call and indirect branch created when the landing pad was - // outlined. - if (auto *LPad = dyn_cast<LandingPadInst>(Inst)) { - return handleLandingPad(VMap, LPad, NewBB); - } - - // Nested landing pads that have already been outlined will be cloned in their - // outlined form, but we need to intercept the ibr instruction to filter out - // targets that do not return to the handler we are outlining. - if (auto *IBr = dyn_cast<IndirectBrInst>(Inst)) { - return handleIndirectBr(VMap, IBr, NewBB); - } - - if (auto *Invoke = dyn_cast<InvokeInst>(Inst)) - return handleInvoke(VMap, Invoke, NewBB); - - if (auto *Resume = dyn_cast<ResumeInst>(Inst)) - return handleResume(VMap, Resume, NewBB); - - if (auto *Cmp = dyn_cast<CmpInst>(Inst)) - return handleCompare(VMap, Cmp, NewBB); - - if (match(Inst, m_Intrinsic<Intrinsic::eh_begincatch>())) - return handleBeginCatch(VMap, Inst, NewBB); - if (match(Inst, m_Intrinsic<Intrinsic::eh_endcatch>())) - return handleEndCatch(VMap, Inst, NewBB); - if (match(Inst, m_Intrinsic<Intrinsic::eh_typeid_for>())) - return handleTypeIdFor(VMap, Inst, NewBB); - - // When outlining llvm.localaddress(), remap that to the second argument, - // which is the FP of the parent. - if (isLocalAddressCall(Inst)) { - VMap[Inst] = ParentFP; - return CloningDirector::SkipInstruction; - } - - // Continue with the default cloning behavior. - return CloningDirector::CloneInstruction; -} - -CloningDirector::CloningAction WinEHCatchDirector::handleLandingPad( - ValueToValueMapTy &VMap, const LandingPadInst *LPad, BasicBlock *NewBB) { - // If the instruction after the landing pad is a call to llvm.eh.actions - // the landing pad has already been outlined. In this case, we should - // clone it because it may return to a block in the handler we are - // outlining now that would otherwise be unreachable. The landing pads - // are sorted before outlining begins to enable this case to work - // properly. - const Instruction *NextI = LPad->getNextNode(); - if (match(NextI, m_Intrinsic<Intrinsic::eh_actions>())) - return CloningDirector::CloneInstruction; - - // If the landing pad hasn't been outlined yet, the landing pad we are - // outlining now does not dominate it and so it cannot return to a block - // in this handler. In that case, we can just insert a stub landing - // pad now and patch it up later. - Instruction *NewInst = LPad->clone(); - if (LPad->hasName()) - NewInst->setName(LPad->getName()); - // Save this correlation for later processing. - NestedLPtoOriginalLP[cast<LandingPadInst>(NewInst)] = LPad; - VMap[LPad] = NewInst; - BasicBlock::InstListType &InstList = NewBB->getInstList(); - InstList.push_back(NewInst); - InstList.push_back(new UnreachableInst(NewBB->getContext())); - return CloningDirector::StopCloningBB; -} - -CloningDirector::CloningAction WinEHCatchDirector::handleBeginCatch( - ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { - // The argument to the call is some form of the first element of the - // landingpad aggregate value, but that doesn't matter. It isn't used - // here. - // The second argument is an outparameter where the exception object will be - // stored. Typically the exception object is a scalar, but it can be an - // aggregate when catching by value. - // FIXME: Leave something behind to indicate where the exception object lives - // for this handler. Should it be part of llvm.eh.actions? - assert(ExceptionObjectVar == nullptr && "Multiple calls to " - "llvm.eh.begincatch found while " - "outlining catch handler."); - ExceptionObjectVar = Inst->getOperand(1)->stripPointerCasts(); - if (isa<ConstantPointerNull>(ExceptionObjectVar)) - return CloningDirector::SkipInstruction; - assert(cast<AllocaInst>(ExceptionObjectVar)->isStaticAlloca() && - "catch parameter is not static alloca"); - Materializer.escapeCatchObject(ExceptionObjectVar); - return CloningDirector::SkipInstruction; -} - -CloningDirector::CloningAction -WinEHCatchDirector::handleEndCatch(ValueToValueMapTy &VMap, - const Instruction *Inst, BasicBlock *NewBB) { - auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst); - // It might be interesting to track whether or not we are inside a catch - // function, but that might make the algorithm more brittle than it needs - // to be. - - // The end catch call can occur in one of two places: either in a - // landingpad block that is part of the catch handlers exception mechanism, - // or at the end of the catch block. However, a catch-all handler may call - // end catch from the original landing pad. If the call occurs in a nested - // landing pad block, we must skip it and continue so that the landing pad - // gets cloned. - auto *ParentBB = IntrinCall->getParent(); - if (ParentBB->isLandingPad() && !LPadMap.isOriginLandingPadBlock(ParentBB)) - return CloningDirector::SkipInstruction; - - // If an end catch occurs anywhere else we want to terminate the handler - // with a return to the code that follows the endcatch call. If the - // next instruction is not an unconditional branch, we need to split the - // block to provide a clear target for the return instruction. - BasicBlock *ContinueBB; - auto Next = std::next(BasicBlock::const_iterator(IntrinCall)); - const BranchInst *Branch = dyn_cast<BranchInst>(Next); - if (!Branch || !Branch->isUnconditional()) { - // We're interrupting the cloning process at this location, so the - // const_cast we're doing here will not cause a problem. - ContinueBB = SplitBlock(const_cast<BasicBlock *>(ParentBB), - const_cast<Instruction *>(cast<Instruction>(Next))); - } else { - ContinueBB = Branch->getSuccessor(0); - } - - ReturnInst::Create(NewBB->getContext(), BlockAddress::get(ContinueBB), NewBB); - ReturnTargets.push_back(ContinueBB); - - // We just added a terminator to the cloned block. - // Tell the caller to stop processing the current basic block so that - // the branch instruction will be skipped. - return CloningDirector::StopCloningBB; -} - -CloningDirector::CloningAction WinEHCatchDirector::handleTypeIdFor( - ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { - auto *IntrinCall = dyn_cast<IntrinsicInst>(Inst); - Value *Selector = IntrinCall->getArgOperand(0)->stripPointerCasts(); - // This causes a replacement that will collapse the landing pad CFG based - // on the filter function we intend to match. - if (Selector == CurrentSelector) - VMap[Inst] = ConstantInt::get(SelectorIDType, 1); - else - VMap[Inst] = ConstantInt::get(SelectorIDType, 0); - // Tell the caller not to clone this instruction. - return CloningDirector::SkipInstruction; -} - -CloningDirector::CloningAction WinEHCatchDirector::handleIndirectBr( - ValueToValueMapTy &VMap, - const IndirectBrInst *IBr, - BasicBlock *NewBB) { - // If this indirect branch is not part of a landing pad block, just clone it. - const BasicBlock *ParentBB = IBr->getParent(); - if (!ParentBB->isLandingPad()) - return CloningDirector::CloneInstruction; - - // If it is part of a landing pad, we want to filter out target blocks - // that are not part of the handler we are outlining. - const LandingPadInst *LPad = ParentBB->getLandingPadInst(); - - // Save this correlation for later processing. - NestedLPtoOriginalLP[cast<LandingPadInst>(VMap[LPad])] = LPad; - - // We should only get here for landing pads that have already been outlined. - assert(match(LPad->getNextNode(), m_Intrinsic<Intrinsic::eh_actions>())); - - // Copy the indirectbr, but only include targets that were previously - // identified as EH blocks and are dominated by the nested landing pad. - SetVector<const BasicBlock *> ReturnTargets; - for (int I = 0, E = IBr->getNumDestinations(); I < E; ++I) { - auto *TargetBB = IBr->getDestination(I); - if (EHBlocks.count(const_cast<BasicBlock*>(TargetBB)) && - DT->dominates(ParentBB, TargetBB)) { - DEBUG(dbgs() << " Adding destination " << TargetBB->getName() << "\n"); - ReturnTargets.insert(TargetBB); - } - } - IndirectBrInst *NewBranch = - IndirectBrInst::Create(const_cast<Value *>(IBr->getAddress()), - ReturnTargets.size(), NewBB); - for (auto *Target : ReturnTargets) - NewBranch->addDestination(const_cast<BasicBlock*>(Target)); - - // The operands and targets of the branch instruction are remapped later - // because it is a terminator. Tell the cloning code to clone the - // blocks we just added to the target list. - return CloningDirector::CloneSuccessors; -} - -CloningDirector::CloningAction -WinEHCatchDirector::handleInvoke(ValueToValueMapTy &VMap, - const InvokeInst *Invoke, BasicBlock *NewBB) { - return CloningDirector::CloneInstruction; -} - -CloningDirector::CloningAction -WinEHCatchDirector::handleResume(ValueToValueMapTy &VMap, - const ResumeInst *Resume, BasicBlock *NewBB) { - // Resume instructions shouldn't be reachable from catch handlers. - // We still need to handle it, but it will be pruned. - BasicBlock::InstListType &InstList = NewBB->getInstList(); - InstList.push_back(new UnreachableInst(NewBB->getContext())); - return CloningDirector::StopCloningBB; -} - -CloningDirector::CloningAction -WinEHCatchDirector::handleCompare(ValueToValueMapTy &VMap, - const CmpInst *Compare, BasicBlock *NewBB) { - const IntrinsicInst *IntrinCall = nullptr; - if (match(Compare->getOperand(0), m_Intrinsic<Intrinsic::eh_typeid_for>())) { - IntrinCall = dyn_cast<IntrinsicInst>(Compare->getOperand(0)); - } else if (match(Compare->getOperand(1), - m_Intrinsic<Intrinsic::eh_typeid_for>())) { - IntrinCall = dyn_cast<IntrinsicInst>(Compare->getOperand(1)); - } - if (IntrinCall) { - Value *Selector = IntrinCall->getArgOperand(0)->stripPointerCasts(); - // This causes a replacement that will collapse the landing pad CFG based - // on the filter function we intend to match. - if (Selector == CurrentSelector->stripPointerCasts()) { - VMap[Compare] = ConstantInt::get(SelectorIDType, 1); - } else { - VMap[Compare] = ConstantInt::get(SelectorIDType, 0); - } - return CloningDirector::SkipInstruction; - } - return CloningDirector::CloneInstruction; -} - -CloningDirector::CloningAction WinEHCleanupDirector::handleLandingPad( - ValueToValueMapTy &VMap, const LandingPadInst *LPad, BasicBlock *NewBB) { - // The MS runtime will terminate the process if an exception occurs in a - // cleanup handler, so we shouldn't encounter landing pads in the actual - // cleanup code, but they may appear in catch blocks. Depending on where - // we started cloning we may see one, but it will get dropped during dead - // block pruning. - Instruction *NewInst = new UnreachableInst(NewBB->getContext()); - VMap[LPad] = NewInst; - BasicBlock::InstListType &InstList = NewBB->getInstList(); - InstList.push_back(NewInst); - return CloningDirector::StopCloningBB; -} - -CloningDirector::CloningAction WinEHCleanupDirector::handleBeginCatch( - ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { - // Cleanup code may flow into catch blocks or the catch block may be part - // of a branch that will be optimized away. We'll insert a return - // instruction now, but it may be pruned before the cloning process is - // complete. - ReturnInst::Create(NewBB->getContext(), nullptr, NewBB); - return CloningDirector::StopCloningBB; -} - -CloningDirector::CloningAction WinEHCleanupDirector::handleEndCatch( - ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { - // Cleanup handlers nested within catch handlers may begin with a call to - // eh.endcatch. We can just ignore that instruction. - return CloningDirector::SkipInstruction; -} - -CloningDirector::CloningAction WinEHCleanupDirector::handleTypeIdFor( - ValueToValueMapTy &VMap, const Instruction *Inst, BasicBlock *NewBB) { - // If we encounter a selector comparison while cloning a cleanup handler, - // we want to stop cloning immediately. Anything after the dispatch - // will be outlined into a different handler. - BasicBlock *CatchHandler; - Constant *Selector; - BasicBlock *NextBB; - if (isSelectorDispatch(const_cast<BasicBlock *>(Inst->getParent()), - CatchHandler, Selector, NextBB)) { - ReturnInst::Create(NewBB->getContext(), nullptr, NewBB); - return CloningDirector::StopCloningBB; - } - // If eg.typeid.for is called for any other reason, it can be ignored. - VMap[Inst] = ConstantInt::get(SelectorIDType, 0); - return CloningDirector::SkipInstruction; -} - -CloningDirector::CloningAction WinEHCleanupDirector::handleIndirectBr( - ValueToValueMapTy &VMap, - const IndirectBrInst *IBr, - BasicBlock *NewBB) { - // No special handling is required for cleanup cloning. - return CloningDirector::CloneInstruction; -} - -CloningDirector::CloningAction WinEHCleanupDirector::handleInvoke( - ValueToValueMapTy &VMap, const InvokeInst *Invoke, BasicBlock *NewBB) { - // All invokes in cleanup handlers can be replaced with calls. - SmallVector<Value *, 16> CallArgs(Invoke->op_begin(), Invoke->op_end() - 3); - // Insert a normal call instruction... - CallInst *NewCall = - CallInst::Create(const_cast<Value *>(Invoke->getCalledValue()), CallArgs, - Invoke->getName(), NewBB); - NewCall->setCallingConv(Invoke->getCallingConv()); - NewCall->setAttributes(Invoke->getAttributes()); - NewCall->setDebugLoc(Invoke->getDebugLoc()); - VMap[Invoke] = NewCall; - - // Remap the operands. - llvm::RemapInstruction(NewCall, VMap, RF_None, nullptr, &Materializer); - - // Insert an unconditional branch to the normal destination. - BranchInst::Create(Invoke->getNormalDest(), NewBB); - - // The unwind destination won't be cloned into the new function, so - // we don't need to clean up its phi nodes. - - // We just added a terminator to the cloned block. - // Tell the caller to stop processing the current basic block. - return CloningDirector::CloneSuccessors; -} - -CloningDirector::CloningAction WinEHCleanupDirector::handleResume( - ValueToValueMapTy &VMap, const ResumeInst *Resume, BasicBlock *NewBB) { - ReturnInst::Create(NewBB->getContext(), nullptr, NewBB); - - // We just added a terminator to the cloned block. - // Tell the caller to stop processing the current basic block so that - // the branch instruction will be skipped. - return CloningDirector::StopCloningBB; -} - -CloningDirector::CloningAction -WinEHCleanupDirector::handleCompare(ValueToValueMapTy &VMap, - const CmpInst *Compare, BasicBlock *NewBB) { - if (match(Compare->getOperand(0), m_Intrinsic<Intrinsic::eh_typeid_for>()) || - match(Compare->getOperand(1), m_Intrinsic<Intrinsic::eh_typeid_for>())) { - VMap[Compare] = ConstantInt::get(SelectorIDType, 1); - return CloningDirector::SkipInstruction; - } - return CloningDirector::CloneInstruction; -} - -WinEHFrameVariableMaterializer::WinEHFrameVariableMaterializer( - Function *OutlinedFn, Value *ParentFP, FrameVarInfoMap &FrameVarInfo) - : FrameVarInfo(FrameVarInfo), Builder(OutlinedFn->getContext()) { - BasicBlock *EntryBB = &OutlinedFn->getEntryBlock(); - - // New allocas should be inserted in the entry block, but after the parent FP - // is established if it is an instruction. - BasicBlock::iterator InsertPoint = EntryBB->getFirstInsertionPt(); - if (auto *FPInst = dyn_cast<Instruction>(ParentFP)) - InsertPoint = std::next(FPInst->getIterator()); - Builder.SetInsertPoint(EntryBB, InsertPoint); -} - -Value *WinEHFrameVariableMaterializer::materializeValueFor(Value *V) { - // If we're asked to materialize a static alloca, we temporarily create an - // alloca in the outlined function and add this to the FrameVarInfo map. When - // all the outlining is complete, we'll replace these temporary allocas with - // calls to llvm.localrecover. - if (auto *AV = dyn_cast<AllocaInst>(V)) { - assert(AV->isStaticAlloca() && - "cannot materialize un-demoted dynamic alloca"); - AllocaInst *NewAlloca = dyn_cast<AllocaInst>(AV->clone()); - Builder.Insert(NewAlloca, AV->getName()); - FrameVarInfo[AV].push_back(NewAlloca); - return NewAlloca; - } - - if (isa<Instruction>(V) || isa<Argument>(V)) { - Function *Parent = isa<Instruction>(V) - ? cast<Instruction>(V)->getParent()->getParent() - : cast<Argument>(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"); - } - - // Don't materialize other values. - return nullptr; -} - -void WinEHFrameVariableMaterializer::escapeCatchObject(Value *V) { - // Catch parameter objects have to live in the parent frame. When we see a use - // of a catch parameter, add a sentinel to the multimap to indicate that it's - // used from another handler. This will prevent us from trying to sink the - // alloca into the handler and ensure that the catch parameter is present in - // the call to llvm.localescape. - FrameVarInfo[V].push_back(getCatchObjectSentinel()); -} - -// This function maps the catch and cleanup handlers that are reachable from the -// specified landing pad. The landing pad sequence will have this basic shape: -// -// <cleanup handler> -// <selector comparison> -// <catch handler> -// <cleanup handler> -// <selector comparison> -// <catch handler> -// <cleanup handler> -// ... -// -// Any of the cleanup slots may be absent. The cleanup slots may be occupied by -// any arbitrary control flow, but all paths through the cleanup code must -// eventually reach the next selector comparison and no path can skip to a -// different selector comparisons, though some paths may terminate abnormally. -// Therefore, we will use a depth first search from the start of any given -// cleanup block and stop searching when we find the next selector comparison. -// -// If the landingpad instruction does not have a catch clause, we will assume -// that any instructions other than selector comparisons and catch handlers can -// be ignored. In practice, these will only be the boilerplate instructions. -// -// The catch handlers may also have any control structure, but we are only -// interested in the start of the catch handlers, so we don't need to actually -// follow the flow of the catch handlers. The start of the catch handlers can -// be located from the compare instructions, but they can be skipped in the -// flow by following the contrary branch. -void WinEHPrepare::mapLandingPadBlocks(LandingPadInst *LPad, - LandingPadActions &Actions) { - unsigned int NumClauses = LPad->getNumClauses(); - unsigned int HandlersFound = 0; - BasicBlock *BB = LPad->getParent(); - - DEBUG(dbgs() << "Mapping landing pad: " << BB->getName() << "\n"); - - if (NumClauses == 0) { - findCleanupHandlers(Actions, BB, nullptr); - return; - } - - VisitedBlockSet VisitedBlocks; - - while (HandlersFound != NumClauses) { - BasicBlock *NextBB = nullptr; - - // Skip over filter clauses. - if (LPad->isFilter(HandlersFound)) { - ++HandlersFound; - continue; - } - - // See if the clause we're looking for is a catch-all. - // If so, the catch begins immediately. - Constant *ExpectedSelector = - LPad->getClause(HandlersFound)->stripPointerCasts(); - if (isa<ConstantPointerNull>(ExpectedSelector)) { - // The catch all must occur last. - assert(HandlersFound == NumClauses - 1); - - // There can be additional selector dispatches in the call chain that we - // need to ignore. - BasicBlock *CatchBlock = nullptr; - Constant *Selector; - while (BB && isSelectorDispatch(BB, CatchBlock, Selector, NextBB)) { - DEBUG(dbgs() << " Found extra catch dispatch in block " - << CatchBlock->getName() << "\n"); - BB = NextBB; - } - - // Add the catch handler to the action list. - CatchHandler *Action = nullptr; - if (CatchHandlerMap.count(BB) && CatchHandlerMap[BB] != nullptr) { - // If the CatchHandlerMap already has an entry for this BB, re-use it. - Action = CatchHandlerMap[BB]; - assert(Action->getSelector() == ExpectedSelector); - } else { - // We don't expect a selector dispatch, but there may be a call to - // llvm.eh.begincatch, which separates catch handling code from - // cleanup code in the same control flow. This call looks for the - // begincatch intrinsic. - Action = findCatchHandler(BB, NextBB, VisitedBlocks); - if (Action) { - // For C++ EH, check if there is any interesting cleanup code before - // we begin the catch. This is important because cleanups cannot - // rethrow exceptions but code called from catches can. For SEH, it - // isn't important if some finally code before a catch-all is executed - // out of line or after recovering from the exception. - if (Personality == EHPersonality::MSVC_CXX) - findCleanupHandlers(Actions, BB, BB); - } else { - // If an action was not found, it means that the control flows - // directly into the catch-all handler and there is no cleanup code. - // That's an expected situation and we must create a catch action. - // Since this is a catch-all handler, the selector won't actually - // appear in the code anywhere. ExpectedSelector here is the constant - // null ptr that we got from the landing pad instruction. - Action = new CatchHandler(BB, ExpectedSelector, nullptr); - CatchHandlerMap[BB] = Action; - } - } - Actions.insertCatchHandler(Action); - DEBUG(dbgs() << " Catch all handler at block " << BB->getName() << "\n"); - ++HandlersFound; - - // Once we reach a catch-all, don't expect to hit a resume instruction. - BB = nullptr; - break; - } - - CatchHandler *CatchAction = findCatchHandler(BB, NextBB, VisitedBlocks); - assert(CatchAction); - - // See if there is any interesting code executed before the dispatch. - findCleanupHandlers(Actions, BB, CatchAction->getStartBlock()); - - // When the source program contains multiple nested try blocks the catch - // handlers can get strung together in such a way that we can encounter - // a dispatch for a selector that we've already had a handler for. - if (CatchAction->getSelector()->stripPointerCasts() == ExpectedSelector) { - ++HandlersFound; - - // Add the catch handler to the action list. - DEBUG(dbgs() << " Found catch dispatch in block " - << CatchAction->getStartBlock()->getName() << "\n"); - Actions.insertCatchHandler(CatchAction); - } else { - // Under some circumstances optimized IR will flow unconditionally into a - // handler block without checking the selector. This can only happen if - // the landing pad has a catch-all handler and the handler for the - // preceding catch clause is identical to the catch-call handler - // (typically an empty catch). In this case, the handler must be shared - // by all remaining clauses. - if (isa<ConstantPointerNull>( - CatchAction->getSelector()->stripPointerCasts())) { - DEBUG(dbgs() << " Applying early catch-all handler in block " - << CatchAction->getStartBlock()->getName() - << " to all remaining clauses.\n"); - Actions.insertCatchHandler(CatchAction); - return; - } - - DEBUG(dbgs() << " Found extra catch dispatch in block " - << CatchAction->getStartBlock()->getName() << "\n"); - } - - // Move on to the block after the catch handler. - BB = NextBB; - } - - // If we didn't wind up in a catch-all, see if there is any interesting code - // executed before the resume. - findCleanupHandlers(Actions, BB, BB); - - // It's possible that some optimization moved code into a landingpad that - // wasn't - // previously being used for cleanup. If that happens, we need to execute - // that - // extra code from a cleanup handler. - if (Actions.includesCleanup() && !LPad->isCleanup()) - LPad->setCleanup(true); -} - -// This function searches starting with the input block for the next -// block that terminates with a branch whose condition is based on a selector -// comparison. This may be the input block. See the mapLandingPadBlocks -// comments for a discussion of control flow assumptions. -// -CatchHandler *WinEHPrepare::findCatchHandler(BasicBlock *BB, - BasicBlock *&NextBB, - VisitedBlockSet &VisitedBlocks) { - // See if we've already found a catch handler use it. - // Call count() first to avoid creating a null entry for blocks - // we haven't seen before. - if (CatchHandlerMap.count(BB) && CatchHandlerMap[BB] != nullptr) { - CatchHandler *Action = cast<CatchHandler>(CatchHandlerMap[BB]); - NextBB = Action->getNextBB(); - return Action; - } - - // VisitedBlocks applies only to the current search. We still - // need to consider blocks that we've visited while mapping other - // landing pads. - VisitedBlocks.insert(BB); - - BasicBlock *CatchBlock = nullptr; - Constant *Selector = nullptr; - - // If this is the first time we've visited this block from any landing pad - // look to see if it is a selector dispatch block. - if (!CatchHandlerMap.count(BB)) { - if (isSelectorDispatch(BB, CatchBlock, Selector, NextBB)) { - CatchHandler *Action = new CatchHandler(BB, Selector, NextBB); - CatchHandlerMap[BB] = Action; - return Action; - } - // If we encounter a block containing an llvm.eh.begincatch before we - // find a selector dispatch block, the handler is assumed to be - // reached unconditionally. This happens for catch-all blocks, but - // it can also happen for other catch handlers that have been combined - // with the catch-all handler during optimization. - if (isCatchBlock(BB)) { - PointerType *Int8PtrTy = Type::getInt8PtrTy(BB->getContext()); - Constant *NullSelector = ConstantPointerNull::get(Int8PtrTy); - CatchHandler *Action = new CatchHandler(BB, NullSelector, nullptr); - CatchHandlerMap[BB] = Action; - return Action; - } - } - - // Visit each successor, looking for the dispatch. - // FIXME: We expect to find the dispatch quickly, so this will probably - // work better as a breadth first search. - for (BasicBlock *Succ : successors(BB)) { - if (VisitedBlocks.count(Succ)) - continue; - - CatchHandler *Action = findCatchHandler(Succ, NextBB, VisitedBlocks); - if (Action) - return Action; - } - return nullptr; -} - -// These are helper functions to combine repeated code from findCleanupHandlers. -static void createCleanupHandler(LandingPadActions &Actions, - CleanupHandlerMapTy &CleanupHandlerMap, - BasicBlock *BB) { - CleanupHandler *Action = new CleanupHandler(BB); - CleanupHandlerMap[BB] = Action; - Actions.insertCleanupHandler(Action); - DEBUG(dbgs() << " Found cleanup code in block " - << Action->getStartBlock()->getName() << "\n"); -} - -static CallSite matchOutlinedFinallyCall(BasicBlock *BB, - Instruction *MaybeCall) { - // Look for finally blocks that Clang has already outlined for us. - // %fp = call i8* @llvm.localaddress() - // call void @"fin$parent"(iN 1, i8* %fp) - if (isLocalAddressCall(MaybeCall) && MaybeCall != BB->getTerminator()) - MaybeCall = MaybeCall->getNextNode(); - CallSite FinallyCall(MaybeCall); - if (!FinallyCall || FinallyCall.arg_size() != 2) - return CallSite(); - if (!match(FinallyCall.getArgument(0), m_SpecificInt(1))) - return CallSite(); - if (!isLocalAddressCall(FinallyCall.getArgument(1))) - return CallSite(); - return FinallyCall; -} - -static BasicBlock *followSingleUnconditionalBranches(BasicBlock *BB) { - // Skip single ubr blocks. - while (BB->getFirstNonPHIOrDbg() == BB->getTerminator()) { - auto *Br = dyn_cast<BranchInst>(BB->getTerminator()); - if (Br && Br->isUnconditional()) - BB = Br->getSuccessor(0); - else - return BB; - } - return BB; -} - -// This function searches starting with the input block for the next block that -// contains code that is not part of a catch handler and would not be eliminated -// during handler outlining. -// -void WinEHPrepare::findCleanupHandlers(LandingPadActions &Actions, - BasicBlock *StartBB, BasicBlock *EndBB) { - // Here we will skip over the following: - // - // landing pad prolog: - // - // Unconditional branches - // - // Selector dispatch - // - // Resume pattern - // - // Anything else marks the start of an interesting block - - BasicBlock *BB = StartBB; - // Anything other than an unconditional branch will kick us out of this loop - // one way or another. - while (BB) { - BB = followSingleUnconditionalBranches(BB); - // If we've already scanned this block, don't scan it again. If it is - // a cleanup block, there will be an action in the CleanupHandlerMap. - // If we've scanned it and it is not a cleanup block, there will be a - // nullptr in the CleanupHandlerMap. If we have not scanned it, there will - // be no entry in the CleanupHandlerMap. We must call count() first to - // avoid creating a null entry for blocks we haven't scanned. - if (CleanupHandlerMap.count(BB)) { - if (auto *Action = CleanupHandlerMap[BB]) { - Actions.insertCleanupHandler(Action); - DEBUG(dbgs() << " Found cleanup code in block " - << Action->getStartBlock()->getName() << "\n"); - // FIXME: This cleanup might chain into another, and we need to discover - // that. - return; - } else { - // Here we handle the case where the cleanup handler map contains a - // value for this block but the value is a nullptr. This means that - // we have previously analyzed the block and determined that it did - // not contain any cleanup code. Based on the earlier analysis, we - // know the block must end in either an unconditional branch, a - // resume or a conditional branch that is predicated on a comparison - // with a selector. Either the resume or the selector dispatch - // would terminate the search for cleanup code, so the unconditional - // branch is the only case for which we might need to continue - // searching. - BasicBlock *SuccBB = followSingleUnconditionalBranches(BB); - if (SuccBB == BB || SuccBB == EndBB) - return; - BB = SuccBB; - continue; - } - } - - // Create an entry in the cleanup handler map for this block. Initially - // we create an entry that says this isn't a cleanup block. If we find - // cleanup code, the caller will replace this entry. - CleanupHandlerMap[BB] = nullptr; - - TerminatorInst *Terminator = BB->getTerminator(); - - // Landing pad blocks have extra instructions we need to accept. - LandingPadMap *LPadMap = nullptr; - if (BB->isLandingPad()) { - LandingPadInst *LPad = BB->getLandingPadInst(); - LPadMap = &LPadMaps[LPad]; - if (!LPadMap->isInitialized()) - LPadMap->mapLandingPad(LPad); - } - - // Look for the bare resume pattern: - // %lpad.val1 = insertvalue { i8*, i32 } undef, i8* %exn, 0 - // %lpad.val2 = insertvalue { i8*, i32 } %lpad.val1, i32 %sel, 1 - // resume { i8*, i32 } %lpad.val2 - if (auto *Resume = dyn_cast<ResumeInst>(Terminator)) { - InsertValueInst *Insert1 = nullptr; - InsertValueInst *Insert2 = nullptr; - Value *ResumeVal = Resume->getOperand(0); - // If the resume value isn't a phi or landingpad value, it should be a - // series of insertions. Identify them so we can avoid them when scanning - // for cleanups. - if (!isa<PHINode>(ResumeVal) && !isa<LandingPadInst>(ResumeVal)) { - Insert2 = dyn_cast<InsertValueInst>(ResumeVal); - if (!Insert2) - return createCleanupHandler(Actions, CleanupHandlerMap, BB); - Insert1 = dyn_cast<InsertValueInst>(Insert2->getAggregateOperand()); - if (!Insert1) - return createCleanupHandler(Actions, CleanupHandlerMap, BB); - } - for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg()->getIterator(), - IE = BB->end(); - II != IE; ++II) { - Instruction *Inst = &*II; - if (LPadMap && LPadMap->isLandingPadSpecificInst(Inst)) - continue; - if (Inst == Insert1 || Inst == Insert2 || Inst == Resume) - continue; - if (!Inst->hasOneUse() || - (Inst->user_back() != Insert1 && Inst->user_back() != Insert2)) { - return createCleanupHandler(Actions, CleanupHandlerMap, BB); - } - } - return; - } - - BranchInst *Branch = dyn_cast<BranchInst>(Terminator); - if (Branch && Branch->isConditional()) { - // Look for the selector dispatch. - // %2 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIf to i8*)) - // %matches = icmp eq i32 %sel, %2 - // br i1 %matches, label %catch14, label %eh.resume - CmpInst *Compare = dyn_cast<CmpInst>(Branch->getCondition()); - if (!Compare || !Compare->isEquality()) - return createCleanupHandler(Actions, CleanupHandlerMap, BB); - for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg()->getIterator(), - IE = BB->end(); - II != IE; ++II) { - Instruction *Inst = &*II; - if (LPadMap && LPadMap->isLandingPadSpecificInst(Inst)) - continue; - if (Inst == Compare || Inst == Branch) - continue; - if (match(Inst, m_Intrinsic<Intrinsic::eh_typeid_for>())) - continue; - return createCleanupHandler(Actions, CleanupHandlerMap, BB); - } - // The selector dispatch block should always terminate our search. - assert(BB == EndBB); - return; - } - - if (isAsynchronousEHPersonality(Personality)) { - // If this is a landingpad block, split the block at the first non-landing - // pad instruction. - Instruction *MaybeCall = BB->getFirstNonPHIOrDbg(); - if (LPadMap) { - while (MaybeCall != BB->getTerminator() && - LPadMap->isLandingPadSpecificInst(MaybeCall)) - MaybeCall = MaybeCall->getNextNode(); - } - - // Look for outlined finally calls on x64, since those happen to match the - // prototype provided by the runtime. - if (TheTriple.getArch() == Triple::x86_64) { - if (CallSite FinallyCall = matchOutlinedFinallyCall(BB, MaybeCall)) { - Function *Fin = FinallyCall.getCalledFunction(); - assert(Fin && "outlined finally call should be direct"); - auto *Action = new CleanupHandler(BB); - Action->setHandlerBlockOrFunc(Fin); - Actions.insertCleanupHandler(Action); - CleanupHandlerMap[BB] = Action; - DEBUG(dbgs() << " Found frontend-outlined finally call to " - << Fin->getName() << " in block " - << Action->getStartBlock()->getName() << "\n"); - - // Split the block if there were more interesting instructions and - // look for finally calls in the normal successor block. - BasicBlock *SuccBB = BB; - if (FinallyCall.getInstruction() != BB->getTerminator() && - FinallyCall.getInstruction()->getNextNode() != - BB->getTerminator()) { - SuccBB = - SplitBlock(BB, FinallyCall.getInstruction()->getNextNode(), DT); - } else { - if (FinallyCall.isInvoke()) { - SuccBB = cast<InvokeInst>(FinallyCall.getInstruction()) - ->getNormalDest(); - } else { - SuccBB = BB->getUniqueSuccessor(); - assert(SuccBB && - "splitOutlinedFinallyCalls didn't insert a branch"); - } - } - BB = SuccBB; - if (BB == EndBB) - return; - continue; - } - } - } - - // Anything else is either a catch block or interesting cleanup code. - for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg()->getIterator(), - IE = BB->end(); - II != IE; ++II) { - Instruction *Inst = &*II; - if (LPadMap && LPadMap->isLandingPadSpecificInst(Inst)) - continue; - // Unconditional branches fall through to this loop. - if (Inst == Branch) - continue; - // If this is a catch block, there is no cleanup code to be found. - if (match(Inst, m_Intrinsic<Intrinsic::eh_begincatch>())) - return; - // If this a nested landing pad, it may contain an endcatch call. - if (match(Inst, m_Intrinsic<Intrinsic::eh_endcatch>())) - return; - // Anything else makes this interesting cleanup code. - return createCleanupHandler(Actions, CleanupHandlerMap, BB); - } - - // Only unconditional branches in empty blocks should get this far. - assert(Branch && Branch->isUnconditional()); - if (BB == EndBB) - return; - BB = Branch->getSuccessor(0); - } -} - -// 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<std::unique_ptr<ActionHandler>> &Actions) { - assert(II->getIntrinsicID() == Intrinsic::eh_actions && - "attempted to parse non eh.actions intrinsic"); - for (unsigned I = 0, E = II->getNumArgOperands(); I != E;) { - uint64_t ActionKind = - cast<ConstantInt>(II->getArgOperand(I))->getZExtValue(); - if (ActionKind == /*catch=*/1) { - auto *Selector = cast<Constant>(II->getArgOperand(I + 1)); - ConstantInt *EHObjIndex = cast<ConstantInt>(II->getArgOperand(I + 2)); - int64_t EHObjIndexVal = EHObjIndex->getSExtValue(); - Constant *Handler = cast<Constant>(II->getArgOperand(I + 3)); - I += 4; - auto CH = make_unique<CatchHandler>(/*BB=*/nullptr, Selector, - /*NextBB=*/nullptr); - CH->setHandlerBlockOrFunc(Handler); - CH->setExceptionVarIndex(EHObjIndexVal); - Actions.push_back(std::move(CH)); - } else if (ActionKind == 0) { - Constant *Handler = cast<Constant>(II->getArgOperand(I + 1)); - I += 2; - auto CH = make_unique<CleanupHandler>(/*BB=*/nullptr); - CH->setHandlerBlockOrFunc(Handler); - Actions.push_back(std::move(CH)); - } else { - llvm_unreachable("Expected either a catch or cleanup handler!"); - } - } - std::reverse(Actions.begin(), Actions.end()); -} - static int addUnwindMapEntry(WinEHFuncInfo &FuncInfo, int ToState, const Value *V) { - WinEHUnwindMapEntry UME; + CxxUnwindMapEntry UME; UME.ToState = ToState; UME.Cleanup = V; - FuncInfo.UnwindMap.push_back(UME); + FuncInfo.CxxUnwindMap.push_back(UME); return FuncInfo.getLastStateNumber(); } @@ -3120,15 +694,10 @@ void WinEHPrepare::colorFunclets(Function &F, void llvm::calculateCatchReturnSuccessorColors(const Function *Fn, WinEHFuncInfo &FuncInfo) { - SmallVector<LandingPadInst *, 4> LPads; - SmallVector<ResumeInst *, 4> Resumes; SmallVector<BasicBlock *, 4> EntryBlocks; // colorFunclets needs the set of EntryBlocks, get them using - // findExceptionalConstructs. - bool ForExplicitEH = findExceptionalConstructs(const_cast<Function &>(*Fn), - LPads, Resumes, EntryBlocks); - if (!ForExplicitEH) - return; + // findFuncletEntryPoints. + findFuncletEntryPoints(const_cast<Function &>(*Fn), EntryBlocks); std::map<BasicBlock *, std::set<BasicBlock *>> BlockColors; std::map<BasicBlock *, std::set<BasicBlock *>> FuncletBlocks; diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp index 993879e399b..ed909c58e9b 100644 --- a/llvm/lib/Target/X86/X86WinEHState.cpp +++ b/llvm/lib/Target/X86/X86WinEHState.cpp @@ -429,14 +429,27 @@ void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) { } void WinEHStatePass::addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo) { - calculateWinCXXEHStateNumbers(&F, FuncInfo); + // Set up RegNodeEscapeIndex + int RegNodeEscapeIndex = escapeRegNode(F); + FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex; - // The base state for the parent is -1. + calculateWinCXXEHStateNumbers(&F, FuncInfo); addStateStoresToFunclet(RegNode, FuncInfo, F, -1); +} - // Set up RegNodeEscapeIndex +/// Assign every distinct landingpad a unique state number for SEH. Unlike C++ +/// EH, we can use this very simple algorithm while C++ EH cannot because catch +/// handlers aren't outlined and the runtime doesn't have to figure out which +/// catch handler frame to unwind to. +void WinEHStatePass::addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo) { + // Remember and return the index that we used. We save it in WinEHFuncInfo so + // that we can lower llvm.x86.seh.recoverfp later in filter functions without + // too much trouble. int RegNodeEscapeIndex = escapeRegNode(F); FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex; + + calculateSEHStateNumbers(&F, FuncInfo); + addStateStoresToFunclet(RegNode, FuncInfo, F, -1); } /// Escape RegNode so that we can access it from child handlers. Find the call @@ -503,92 +516,6 @@ void WinEHStatePass::addStateStoresToFunclet(Value *ParentRegNode, } } -/// Assign every distinct landingpad a unique state number for SEH. Unlike C++ -/// EH, we can use this very simple algorithm while C++ EH cannot because catch -/// handlers aren't outlined and the runtime doesn't have to figure out which -/// catch handler frame to unwind to. -/// FIXME: __finally blocks are outlined, so this approach may break down there. -void WinEHStatePass::addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo) { - // Remember and return the index that we used. We save it in WinEHFuncInfo so - // that we can lower llvm.x86.seh.recoverfp later in filter functions without - // too much trouble. - int RegNodeEscapeIndex = escapeRegNode(F); - FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex; - - // If this funciton uses the new EH IR, use the explicit state numbering - // algorithm and return early. - bool UsesLPads = false; - for (BasicBlock &BB : F) { - if (BB.isLandingPad()) { - UsesLPads = true; - break; - } - } - if (!UsesLPads) { - calculateSEHStateNumbers(&F, FuncInfo); - addStateStoresToFunclet(RegNode, FuncInfo, F, -1); - return; - } - // FIXME: Delete the rest of this code and clean things up when new EH is - // done. - - // Iterate all the instructions and emit state number stores. - int CurState = 0; - SmallPtrSet<BasicBlock *, 4> ExceptBlocks; - for (BasicBlock &BB : F) { - for (auto I = BB.begin(), E = BB.end(); I != E; ++I) { - if (auto *CI = dyn_cast<CallInst>(I)) { - auto *Intrin = dyn_cast<IntrinsicInst>(CI); - if (Intrin) { - // Calls that "don't throw" are considered to be able to throw asynch - // exceptions, but intrinsics cannot. - continue; - } - insertStateNumberStore(RegNode, CI, -1); - } else if (auto *II = dyn_cast<InvokeInst>(I)) { - // Look up the state number of the landingpad this unwinds to. - LandingPadInst *LPI = II->getUnwindDest()->getLandingPadInst(); - auto InsertionPair = - FuncInfo.EHPadStateMap.insert(std::make_pair(LPI, CurState)); - auto Iter = InsertionPair.first; - int &State = Iter->second; - bool Inserted = InsertionPair.second; - if (Inserted) { - // Each action consumes a state number. - auto *EHActions = cast<IntrinsicInst>(LPI->getNextNode()); - SmallVector<std::unique_ptr<ActionHandler>, 4> ActionList; - parseEHActions(EHActions, ActionList); - assert(!ActionList.empty()); - CurState += ActionList.size(); - State += ActionList.size() - 1; - - // Remember all the __except block targets. - for (auto &Handler : ActionList) { - if (auto *CH = dyn_cast<CatchHandler>(Handler.get())) { - auto *BA = cast<BlockAddress>(CH->getHandlerBlockOrFunc()); -#ifndef NDEBUG - for (BasicBlock *Pred : predecessors(BA->getBasicBlock())) - assert(Pred->isLandingPad() && - "WinEHPrepare failed to split block"); -#endif - ExceptBlocks.insert(BA->getBasicBlock()); - } - } - } - insertStateNumberStore(RegNode, II, State); - } - } - } - - // Insert llvm.x86.seh.restoreframe() into each __except block. - Function *RestoreFrame = - Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe); - for (BasicBlock *ExceptBB : ExceptBlocks) { - IRBuilder<> Builder(ExceptBB->begin()); - Builder.CreateCall(RestoreFrame, {}); - } -} - void WinEHStatePass::insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State) { IRBuilder<> Builder(IP); diff --git a/llvm/test/Analysis/Lint/cppeh-catch-intrinsics.ll b/llvm/test/Analysis/Lint/cppeh-catch-intrinsics.ll deleted file mode 100644 index 19480a2f60f..00000000000 --- a/llvm/test/Analysis/Lint/cppeh-catch-intrinsics.ll +++ /dev/null @@ -1,278 +0,0 @@ -; RUN: opt -lint -disable-output < %s 2>&1 | FileCheck %s - -; This test is meant to prove that the Verifier is able to identify a variety -; of errors with the llvm.eh.begincatch and llvm.eh.endcatch intrinsics. -; See cppeh-catch-intrinsics-clean for correct uses. - -target triple = "x86_64-pc-windows-msvc" - -declare void @llvm.eh.begincatch(i8*, i8*) - -declare void @llvm.eh.endcatch() - -@_ZTIi = external constant i8* - -; Function Attrs: uwtable -define void @test_missing_endcatch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: Some paths from llvm.eh.begincatch may not reach llvm.eh.endcatch -; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn, i8* null) -entry: - invoke void @_Z9may_throwv() - to label %try.cont unwind label %lpad - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn = extractvalue { i8*, i32 } %0, 0 - %sel = extractvalue { i8*, i32 } %0, 1 - %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matches = icmp eq i32 %sel, %1 - br i1 %matches, label %catch, label %eh.resume - -catch: ; preds = %lpad - call void @llvm.eh.begincatch(i8* %exn, i8* null) - call void @_Z10handle_intv() - br label %invoke.cont2 - -invoke.cont2: ; preds = %catch - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %entry - ret void - -eh.resume: ; preds = %catch.dispatch - resume { i8*, i32 } %0 -} - -; Function Attrs: uwtable -define void @test_missing_begincatch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: llvm.eh.endcatch may be reachable without passing llvm.eh.begincatch -; CHECK-NEXT: call void @llvm.eh.endcatch() -entry: - invoke void @_Z9may_throwv() - to label %try.cont unwind label %lpad - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn = extractvalue { i8*, i32 } %0, 0 - %sel = extractvalue { i8*, i32 } %0, 1 - %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matches = icmp eq i32 %sel, %1 - br i1 %matches, label %catch, label %eh.resume - -catch: ; preds = %lpad - call void @_Z10handle_intv() - br label %invoke.cont2 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %entry - ret void - -eh.resume: ; preds = %catch.dispatch - resume { i8*, i32 } %0 -} - -; Function Attrs: uwtable -define void @test_multiple_begin() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: llvm.eh.begincatch may be called a second time before llvm.eh.endcatch -; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn, i8* null) -; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn, i8* null) -entry: - invoke void @_Z9may_throwv() - to label %try.cont unwind label %lpad - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn = extractvalue { i8*, i32 } %0, 0 - %sel = extractvalue { i8*, i32 } %0, 1 - %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matches = icmp eq i32 %sel, %1 - br i1 %matches, label %catch, label %eh.resume - -catch: ; preds = %lpad - call void @llvm.eh.begincatch(i8* %exn, i8* null) - call void @_Z10handle_intv() - br label %invoke.cont2 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.begincatch(i8* %exn, i8* null) - call void @llvm.eh.endcatch() - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %entry - ret void - -eh.resume: ; preds = %catch.dispatch - resume { i8*, i32 } %0 -} - -; Function Attrs: uwtable -define void @test_multiple_end() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: llvm.eh.endcatch may be called a second time after llvm.eh.begincatch -; CHECK-NEXT: call void @llvm.eh.endcatch() -; CHECK-NEXT: call void @llvm.eh.endcatch() -entry: - invoke void @_Z9may_throwv() - to label %try.cont unwind label %lpad - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn = extractvalue { i8*, i32 } %0, 0 - %sel = extractvalue { i8*, i32 } %0, 1 - %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matches = icmp eq i32 %sel, %1 - br i1 %matches, label %catch, label %eh.resume - -catch: ; preds = %lpad - call void @llvm.eh.begincatch(i8* %exn, i8* null) - call void @_Z10handle_intv() - call void @llvm.eh.endcatch() - br label %invoke.cont2 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %entry - ret void - -eh.resume: ; preds = %catch.dispatch - resume { i8*, i32 } %0 -} - - -; Function Attrs: uwtable -define void @test_begincatch_without_lpad() { -; CHECK: llvm.eh.begincatch may be reachable without passing a landingpad -; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn, i8* null) -entry: - %exn = alloca i8 - call void @llvm.eh.begincatch(i8* %exn, i8* null) - call void @_Z10handle_intv() - br label %invoke.cont2 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %entry - ret void -} - -; Function Attrs: uwtable -define void @test_branch_to_begincatch_with_no_lpad(i32 %fake.sel) personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: llvm.eh.begincatch may be reachable without passing a landingpad -; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn2, i8* null) -entry: - %fake.exn = alloca i8 - invoke void @_Z9may_throwv() - to label %catch unwind label %lpad - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn = extractvalue { i8*, i32 } %0, 0 - %sel = extractvalue { i8*, i32 } %0, 1 - %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matches = icmp eq i32 %sel, %1 - br i1 %matches, label %catch, label %eh.resume - - invoke void @_Z9may_throwv() - to label %try.cont unwind label %lpad - -catch: ; preds = %lpad, %entry - %exn2 = phi i8* [%exn, %lpad], [%fake.exn, %entry] - %sel2 = phi i32 [%sel, %lpad], [%fake.sel, %entry] - call void @llvm.eh.begincatch(i8* %exn2, i8* null) - call void @_Z10handle_intv() - %matches1 = icmp eq i32 %sel2, 0 - br i1 %matches1, label %invoke.cont2, label %invoke.cont3 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() - br label %try.cont - -invoke.cont3: ; preds = %catch - call void @llvm.eh.endcatch() - br label %eh.resume - -try.cont: ; preds = %invoke.cont2 - ret void - -eh.resume: ; preds = %catch.dispatch - %lpad.val = insertvalue { i8*, i32 } undef, i32 0, 1 - resume { i8*, i32 } %lpad.val -} - -; Function Attrs: uwtable -define void @test_branch_missing_endcatch() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: Some paths from llvm.eh.begincatch may not reach llvm.eh.endcatch -; CHECK-NEXT: call void @llvm.eh.begincatch(i8* %exn2, i8* null) -entry: - invoke void @_Z9may_throwv() - to label %invoke.cont unwind label %lpad - -invoke.cont: - invoke void @_Z9may_throwv() - to label %invoke.cont unwind label %lpad1 - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn = extractvalue { i8*, i32 } %0, 0 - %sel = extractvalue { i8*, i32 } %0, 1 - %1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matches = icmp eq i32 %sel, %1 - br i1 %matches, label %catch, label %eh.resume - - invoke void @_Z9may_throwv() - to label %try.cont unwind label %lpad - -lpad1: ; preds = %entry - %l1.0 = landingpad { i8*, i32 } - cleanup - catch i8* bitcast (i8** @_ZTIi to i8*) - %exn1 = extractvalue { i8*, i32 } %l1.0, 0 - %sel1 = extractvalue { i8*, i32 } %l1.0, 1 - %l1.1 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) - %matchesl1 = icmp eq i32 %sel1, %l1.1 - br i1 %matchesl1, label %catch, label %eh.resume - -catch: ; preds = %lpad, %lpad1 - %exn2 = phi i8* [%exn, %lpad], [%exn1, %lpad1] - %sel2 = phi i32 [%sel, %lpad], [%sel1, %lpad1] - call void @llvm.eh.begincatch(i8* %exn2, i8* null) - call void @_Z10handle_intv() - %matches1 = icmp eq i32 %sel2, 0 - br i1 %matches1, label %invoke.cont2, label %invoke.cont3 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() - br label %try.cont - -invoke.cont3: ; preds = %catch - br label %eh.resume - -try.cont: ; preds = %invoke.cont2, %entry - ret void - -eh.resume: ; preds = %catch.dispatch - %lpad.val = insertvalue { i8*, i32 } undef, i32 0, 1 - resume { i8*, i32 } %lpad.val -} - -declare void @_Z9may_throwv() - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) - -declare void @_Z10handle_intv() - diff --git a/llvm/test/CodeGen/WinEH/cppeh-alloca-sink.ll b/llvm/test/CodeGen/WinEH/cppeh-alloca-sink.ll deleted file mode 100644 index f215dca2ddd..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-alloca-sink.ll +++ /dev/null @@ -1,180 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test describes two difficult cases in sinking allocas into child frames. -; We don't currently do this optimization, but we'll need to tweak these tests -; when we do. - -; This test is based on the following code: -; -; // In this case we can sink the alloca from the parent into the catch because -; // the lifetime is limited to the catch. -; extern "C" void may_throw(); -; extern "C" void sink_alloca_to_catch() { -; try { -; may_throw(); -; } catch (int) { -; volatile int only_used_in_catch = 42; -; } -; } -; -; // In this case we cannot. The variable should live as long as the parent -; // frame lives. -; extern "C" void use_catch_var(int *); -; extern "C" void dont_sink_alloca_to_catch(int n) { -; int live_in_out_catch = 0; -; while (n > 0) { -; try { -; may_throw(); -; } catch (int) { -; use_catch_var(&live_in_out_catch); -; } -; n--; -; } -; } - -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -declare void @may_throw() #1 -declare i32 @__CxxFrameHandler3(...) -declare i32 @llvm.eh.typeid.for(i8*) #2 -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #3 -declare void @llvm.eh.endcatch() #3 - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x 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" - -; Function Attrs: uwtable -define void @sink_alloca_to_catch() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %0 = alloca i32 - %only_used_in_catch = alloca i32, align 4 - invoke void @may_throw() - to label %try.cont unwind label %lpad - -lpad: ; preds = %entry - %1 = landingpad { i8*, i32 } - catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0 - %2 = extractvalue { i8*, i32 } %1, 1 - %3 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*)) #3 - %matches = icmp eq i32 %2, %3 - br i1 %matches, label %catch, label %eh.resume - -catch: ; preds = %lpad - %4 = extractvalue { i8*, i32 } %1, 0 - call void @llvm.eh.begincatch(i8* %4, i8* null) #3 - store volatile i32 42, i32* %only_used_in_catch, align 4 - tail call void @llvm.eh.endcatch() #3 - br label %try.cont - -try.cont: ; preds = %entry, %catch - ret void - -eh.resume: ; preds = %lpad - resume { i8*, i32 } %1 -} - -; CHECK-LABEL: define void @sink_alloca_to_catch() -; CHECK: call void (...) @llvm.localescape(i32* %only_used_in_catch) - -declare void @use_catch_var(i32*) #1 - -; Function Attrs: uwtable -define void @dont_sink_alloca_to_catch(i32 %n) #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %0 = alloca i32 - %n.addr = alloca i32, align 4 - %live_in_out_catch = alloca i32, align 4 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - store i32 %n, i32* %n.addr, align 4 - br label %while.cond - -while.cond: ; preds = %try.cont, %entry - %1 = load i32, i32* %n.addr, align 4 - %cmp = icmp sgt i32 %1, 0 - br i1 %cmp, label %while.body, label %while.end - -while.body: ; preds = %while.cond - invoke void @may_throw() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %while.body - br label %try.cont - -lpad: ; preds = %while.body - %2 = landingpad { i8*, i32 } - catch i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*) - %3 = extractvalue { i8*, i32 } %2, 0 - store i8* %3, i8** %exn.slot - %4 = extractvalue { i8*, i32 } %2, 1 - store i32 %4, i32* %ehselector.slot - br label %catch.dispatch - -catch.dispatch: ; preds = %lpad - %sel = load i32, i32* %ehselector.slot - %5 = call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*)) #3 - %matches = icmp eq i32 %sel, %5 - br i1 %matches, label %catch, label %eh.resume - -catch: ; preds = %catch.dispatch - %exn = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn, i8* null) #3 - invoke void @use_catch_var(i32* %live_in_out_catch) - to label %invoke.cont2 unwind label %lpad1 - -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() #3 - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %invoke.cont - %6 = load i32, i32* %0 - %7 = load i32, i32* %n.addr, align 4 - %dec = add nsw i32 %7, -1 - store i32 %dec, i32* %n.addr, align 4 - br label %while.cond - -lpad1: ; preds = %catch - %8 = landingpad { i8*, i32 } - cleanup - %9 = extractvalue { i8*, i32 } %8, 0 - store i8* %9, i8** %exn.slot - %10 = extractvalue { i8*, i32 } %8, 1 - store i32 %10, i32* %ehselector.slot - call void @llvm.eh.endcatch() #3 - br label %eh.resume - -while.end: ; preds = %while.cond - ret void - -eh.resume: ; preds = %lpad1, %catch.dispatch - %exn3 = load i8*, i8** %exn.slot - %sel4 = load i32, i32* %ehselector.slot - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn3, 0 - %lpad.val5 = insertvalue { i8*, i32 } %lpad.val, i32 %sel4, 1 - resume { i8*, i32 } %lpad.val5 -} - -; CHECK-LABEL: define void @dont_sink_alloca_to_catch(i32 %n) -; CHECK: call void (...) @llvm.localescape(i32* %live_in_out_catch) - -; CHECK-LABEL: define internal i8* @sink_alloca_to_catch.catch(i8*, i8*) -; CHECK: %only_used_in_catch.i8 = call i8* @llvm.localrecover({{.*}}, i32 0) -; CHECK: %only_used_in_catch = bitcast - -; CHECK-LABEL: define internal i8* @dont_sink_alloca_to_catch.catch(i8*, i8*) -; CHECK: %live_in_out_catch.i8 = call i8* @llvm.localrecover({{.*}}, i32 0) -; CHECK: %live_in_out_catch = bitcast - - - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nounwind readnone } -attributes #3 = { nounwind } diff --git a/llvm/test/CodeGen/WinEH/cppeh-catch-all-win32.ll b/llvm/test/CodeGen/WinEH/cppeh-catch-all-win32.ll deleted file mode 100644 index b2e84b90d69..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-catch-all-win32.ll +++ /dev/null @@ -1,86 +0,0 @@ -; RUN: opt -winehprepare -S -o - < %s | FileCheck %s - -; This test is based on the following code: -; -; extern "C" void may_throw(); -; extern "C" void handle_exception(); -; extern "C" void test() { -; try { -; may_throw(); -; } catch (...) { -; handle_exception(); -; } -; } - -target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" -target triple = "i686-pc-windows-msvc" - -; The function entry in this case remains unchanged. -; CHECK: define void @test() -; CHECK: entry: -; CHECK: invoke void @may_throw() -; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]*]] - -define void @test() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - invoke void @may_throw() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - br label %try.cont - -; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: catch i8* null -; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* ()* @test.catch) -; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont] - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* null - %1 = extractvalue { i8*, i32 } %0, 0 - store i8* %1, i8** %exn.slot - %2 = extractvalue { i8*, i32 } %0, 1 - store i32 %2, i32* %ehselector.slot - br label %catch - -; CHECK-NOT: catch: -; CHECK-NOT: @handle_exception() - -catch: ; preds = %lpad - %exn = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn, i8* null) #1 - call void @handle_exception() - call void @llvm.eh.endcatch() #1 - br label %try.cont - -try.cont: ; preds = %catch, %invoke.cont - ret void - -; CHECK: } -} - -; CHECK: define internal i8* @test.catch() -; CHECK: call i8* @llvm.frameaddress(i32 1) -; CHECK: call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @test to i8*), i8* %{{.*}}) -; CHECK: call void @handle_exception() -; CHECK: ret i8* blockaddress(@test, %try.cont) -; CHECK: } - - -declare void @may_throw() #0 - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #1 - -declare void @handle_exception() #0 - -; Function Attrs: nounwind -declare void @llvm.eh.endcatch() #1 - -attributes #0 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind } diff --git a/llvm/test/CodeGen/WinEH/cppeh-catch-and-throw.ll b/llvm/test/CodeGen/WinEH/cppeh-catch-and-throw.ll deleted file mode 100644 index d604b86deb3..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-catch-and-throw.ll +++ /dev/null @@ -1,143 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test is based on the following code: -; -; class Obj { -; public: -; ~Obj(); -; }; -; -; void test(void) -; { -; try { -; Obj o; -; throw 1; -; } catch (...) { -; throw; -; } -; } - -; ModuleID = 'cppeh-catch-and-throw.cpp' -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } -%eh.CatchableType = type { i32, i32, i32, i32, i32, i32, i32 } -%eh.CatchableTypeArray.1 = type { i32, [1 x i32] } -%eh.ThrowInfo = type { i32, i32, i32, i32 } -%class.Obj = type { i8 } - -$"\01??_R0H@8" = comdat any - -$"_CT??_R0H@84" = comdat any - -$_CTA1H = comdat any - -$_TI1H = 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 -@__ImageBase = external constant i8 -@"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 -1, i32 0, i32 4, i32 0 }, section ".xdata", comdat -@_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableType* @"_CT??_R0H@84" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32)] }, section ".xdata", comdat -@_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableTypeArray.1* @_CTA1H to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, section ".xdata", comdat - -; This is just a minimal check to verify that main was handled by WinEHPrepare. -; CHECK: define void @"\01?test@@YAXXZ"() -; CHECK: entry: -; CHECK: call void (...) @llvm.localescape -; CHECK: invoke void @_CxxThrowException -; CHECK: } - -; Function Attrs: uwtable -define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %o = alloca %class.Obj, align 1 - %tmp = alloca i32, align 4 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - store i32 1, i32* %tmp - %0 = bitcast i32* %tmp to i8* - invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* @_TI1H) #3 - to label %unreachable unwind label %lpad - -lpad: ; preds = %entry - %1 = landingpad { i8*, i32 } - catch i8* null - %2 = extractvalue { i8*, i32 } %1, 0 - store i8* %2, i8** %exn.slot - %3 = extractvalue { i8*, i32 } %1, 1 - store i32 %3, i32* %ehselector.slot - call void @"\01??1Obj@@QEAA@XZ"(%class.Obj* %o) #2 - br label %catch - -catch: ; preds = %lpad - %exn = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn, i8* null) #2 - invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #3 - to label %unreachable unwind label %lpad1 - -lpad1: ; preds = %catch - %4 = landingpad { i8*, i32 } - cleanup - %5 = extractvalue { i8*, i32 } %4, 0 - store i8* %5, i8** %exn.slot - %6 = extractvalue { i8*, i32 } %4, 1 - store i32 %6, i32* %ehselector.slot - call void @llvm.eh.endcatch() #2 - br label %eh.resume - -try.cont: ; No predecessors! - ret void - -eh.resume: ; preds = %lpad1 - %exn2 = load i8*, i8** %exn.slot - %sel = load i32, i32* %ehselector.slot - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn2, 0 - %lpad.val3 = insertvalue { i8*, i32 } %lpad.val, i32 %sel, 1 - resume { i8*, i32 } %lpad.val3 - -unreachable: ; preds = %catch, %entry - unreachable -} - -; Verify that we inserted a stub invoke into the outlined cleanup handler. -; -; CHECK-LABEL: define internal void @"\01?test@@YAXXZ.cleanup"(i8*, i8*) -; CHECK: entry: -; CHECK: call i8* @llvm.localrecover -; CHECK: call void @"\01??1Obj@@QEAA@XZ" -; CHECK: invoke void @llvm.donothing() -; CHECK: to label %[[SPLIT_LABEL:.+]] unwind label %[[LPAD_LABEL:.+]] -; -; CHECK: [[SPLIT_LABEL]] -; -; CHECK: [[LPAD_LABEL]] -; CHECK: landingpad { i8*, i32 } -; CHECK: cleanup -; CHECK: unreachable -; CHECK: } - -declare void @_CxxThrowException(i8*, %eh.ThrowInfo*) - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind -declare void @"\01??1Obj@@QEAA@XZ"(%class.Obj*) #1 - -; Function Attrs: nounwind -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #2 - -; Function Attrs: nounwind -declare void @llvm.eh.endcatch() #2 - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nounwind } -attributes #3 = { noreturn } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 (trunk 235214) (llvm/trunk 235213)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-catch-scalar.ll b/llvm/test/CodeGen/WinEH/cppeh-catch-scalar.ll deleted file mode 100644 index 3b5ab746d63..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-catch-scalar.ll +++ /dev/null @@ -1,126 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test is based on the following code: -; -; void test() -; { -; try { -; may_throw(); -; } catch (int i) { -; handle_int(i); -; } -; } -; -; Parts of the IR have been hand-edited to simplify the test case. -; The full IR will be restored when Windows C++ EH support is complete. - -;ModuleID = 'cppeh-catch-scalar.cpp' -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -@_ZTIi = external constant i8* - -; The function entry will be rewritten like this. -; CHECK: define void @_Z4testv() -; CHECK: entry: -; CHECK: [[I_PTR:\%.+]] = alloca i32, align 4 -; CHECK: call void (...) @llvm.localescape(i32* [[I_PTR]]) -; CHECK: invoke void @_Z9may_throwv() -; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]*]] - -; Function Attrs: uwtable -define void @_Z4testv() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - %i = alloca i32, align 4 - invoke void @_Z9may_throwv() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - br label %try.cont - -; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) -; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i8** @_ZTIi to i8*), i32 0, i8* (i8*, i8*)* @_Z4testv.catch) -; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont] - -lpad: ; preds = %entry - %tmp = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIi to i8*) - %tmp1 = extractvalue { i8*, i32 } %tmp, 0 - store i8* %tmp1, i8** %exn.slot - %tmp2 = extractvalue { i8*, i32 } %tmp, 1 - store i32 %tmp2, i32* %ehselector.slot - br label %catch.dispatch - -; CHECK-NOT: catch-dispatch: - -catch.dispatch: ; preds = %lpad - %sel = load i32, i32* %ehselector.slot - %tmp3 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #3 - %matches = icmp eq i32 %sel, %tmp3 - br i1 %matches, label %catch, label %eh.resume - -; CHECK-NOT: catch: - -catch: ; preds = %catch.dispatch - %exn11 = load i8*, i8** %exn.slot - %i.i8 = bitcast i32* %i to i8* - call void @llvm.eh.begincatch(i8* %exn11, i8* %i.i8) #3 - %tmp7 = load i32, i32* %i, align 4 - call void @_Z10handle_inti(i32 %tmp7) - br label %invoke.cont2 - -; CHECK-NOT: invoke.cont2: - -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() #3 - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %invoke.cont - ret void - -; CHECK-NOT: eh.resume: - -eh.resume: ; preds = %catch.dispatch - %exn3 = load i8*, i8** %exn.slot - %sel4 = load i32, i32* %ehselector.slot - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn3, 0 - %lpad.val5 = insertvalue { i8*, i32 } %lpad.val, i32 %sel4, 1 - resume { i8*, i32 } %lpad.val5 - -; CHECK: } -} - -; CHECK: define internal i8* @_Z4testv.catch(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_I:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @_Z4testv to i8*), i8* %1, i32 0) -; CHECK: [[I_PTR1:\%.+]] = bitcast i8* [[RECOVER_I]] to i32* -; CHECK: [[TMP:\%.+]] = load i32, i32* [[I_PTR1]], align 4 -; CHECK: call void @_Z10handle_inti(i32 [[TMP]]) -; CHECK: ret i8* blockaddress(@_Z4testv, %try.cont) -; CHECK: } - -declare void @_Z9may_throwv() #1 - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #2 - -declare void @llvm.eh.begincatch(i8*, i8*) - -declare void @llvm.eh.endcatch() - -declare void @_Z10handle_inti(i32) #1 - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nounwind readnone } -attributes #3 = { nounwind } - -!llvm.ident = !{!0} - -!0 = !{!"clang version 3.7.0 (trunk 227474) (llvm/trunk 227508)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-catch-unwind.ll b/llvm/test/CodeGen/WinEH/cppeh-catch-unwind.ll deleted file mode 100644 index 8fdda9bbc02..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-catch-unwind.ll +++ /dev/null @@ -1,240 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test was generated from the following source: -; -; void test() { -; try { -; SomeClass obj; -; may_throw(); -; try { -; may_throw(); -; } catch (int) { -; handle_exception(); -; } -; } catch (int) { -; handle_exception(); -; } -; } -; -; The code above was compiled with the -O2 option. - -; ModuleID = 'catch-unwind.cpp' -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } -%class.SomeClass = type { 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 - - -; CHECK-LABEL: define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: entry: -; CHECK: [[OBJ_PTR:\%.+]] = alloca %class.SomeClass -; CHECK: [[TMP0:\%.+]] = alloca i32, align 4 -; CHECK: [[TMP1:\%.+]] = alloca i32, align 4 -; CHECK: call void (...) @llvm.localescape(i32* [[TMP1]], %class.SomeClass* [[OBJ_PTR]], i32* [[TMP0]]) -; CHECK: %call = invoke %class.SomeClass* @"\01??0SomeClass@@QEAA@XZ"(%class.SomeClass* %obj) -; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]*]] - -; Function Attrs: uwtable -define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %obj = alloca %class.SomeClass, align 1 - %0 = alloca i32, align 4 - %1 = alloca i32, align 4 - %call = invoke %class.SomeClass* @"\01??0SomeClass@@QEAA@XZ"(%class.SomeClass* %obj) - to label %invoke.cont unwind label %lpad - -; CHECK: invoke.cont: -; CHECK: invoke void @"\01?may_throw@@YAXXZ"() -; CHECK: to label %invoke.cont2 unwind label %[[LPAD1_LABEL:lpad[0-9]*]] - -invoke.cont: ; preds = %entry - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont2 unwind label %lpad1 - -; CHECK: invoke.cont2: -; CHECK: invoke void @"\01?may_throw@@YAXXZ"() -; CHECK: to label %try.cont unwind label %[[LPAD3_LABEL:lpad[0-9]*]] - -invoke.cont2: ; preds = %invoke.cont - invoke void @"\01?may_throw@@YAXXZ"() - to label %try.cont unwind label %lpad3 - -; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry -; CHECK: [[LPAD_VAL:\%.+]] = landingpad { i8*, i32 } -; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) -; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch") -; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont15] - -lpad: ; preds = %entry - %2 = landingpad { i8*, i32 } - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) - %3 = extractvalue { i8*, i32 } %2, 0 - %4 = extractvalue { i8*, i32 } %2, 1 - br label %catch.dispatch7 - -; CHECK: [[LPAD1_LABEL]]:{{[ ]+}}; preds = %invoke.cont -; CHECK: [[LPAD1_VAL:\%.+]] = landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) -; CHECK-NEXT: [[RECOVER1:\%.+]] = call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @"\01?test@@YAXXZ.cleanup", i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch") -; CHECK-NEXT: indirectbr i8* [[RECOVER1]], [label %try.cont15] - -lpad1: ; preds = %invoke.cont - %5 = landingpad { i8*, i32 } - cleanup - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) - %6 = extractvalue { i8*, i32 } %5, 0 - %7 = extractvalue { i8*, i32 } %5, 1 - br label %ehcleanup - -; CHECK: [[LPAD3_LABEL]]:{{[ ]+}}; preds = %invoke.cont2 -; CHECK: [[LPAD3_VAL:\%.+]] = landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) -; CHECK-NEXT: [[RECOVER3:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch.1", i32 0, void (i8*, i8*)* @"\01?test@@YAXXZ.cleanup") -; CHECK-NEXT: indirectbr i8* [[RECOVER3]], [label %try.cont, label %try.cont15] - -lpad3: ; preds = %invoke.cont2 - %8 = landingpad { i8*, i32 } - cleanup - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) - %9 = extractvalue { i8*, i32 } %8, 0 - %10 = extractvalue { i8*, i32 } %8, 1 - %11 = call i32 @llvm.eh.typeid.for(i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)) #3 - %matches = icmp eq i32 %10, %11 - br i1 %matches, label %catch, label %ehcleanup - -; CHECK-NOT: catch: -catch: ; preds = %lpad3 - %12 = bitcast i32* %0 to i8* - call void @llvm.eh.begincatch(i8* %9, i8* %12) #3 - invoke void @"\01?handle_exception@@YAXXZ"() - to label %invoke.cont6 unwind label %lpad5 - -; CHECK-NOT: invoke.cont6: -invoke.cont6: ; preds = %catch - call void @llvm.eh.endcatch() #3 - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %invoke.cont6 - call void @"\01??1SomeClass@@QEAA@XZ"(%class.SomeClass* %obj) #3 - br label %try.cont15 - -; CHECK-NOT: lpad5: -lpad5: ; preds = %catch - %13 = landingpad { i8*, i32 } - cleanup - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) - %14 = extractvalue { i8*, i32 } %13, 0 - %15 = extractvalue { i8*, i32 } %13, 1 - call void @llvm.eh.endcatch() #3 - br label %ehcleanup - -; CHECK-NOT: ehcleanup -ehcleanup: ; preds = %lpad5, %lpad3, %lpad1 - %exn.slot.0 = phi i8* [ %14, %lpad5 ], [ %9, %lpad3 ], [ %6, %lpad1 ] - %ehselector.slot.0 = phi i32 [ %15, %lpad5 ], [ %10, %lpad3 ], [ %7, %lpad1 ] - call void @"\01??1SomeClass@@QEAA@XZ"(%class.SomeClass* %obj) #3 - br label %catch.dispatch7 - -; CHECK-NOT: catch.dispatch7: -catch.dispatch7: ; preds = %ehcleanup, %lpad - %exn.slot.1 = phi i8* [ %exn.slot.0, %ehcleanup ], [ %3, %lpad ] - %ehselector.slot.1 = phi i32 [ %ehselector.slot.0, %ehcleanup ], [ %4, %lpad ] - %16 = call i32 @llvm.eh.typeid.for(i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)) #3 - %matches9 = icmp eq i32 %ehselector.slot.1, %16 - br i1 %matches9, label %catch10, label %eh.resume - -; CHECK-NOT: catch10: -catch10: ; preds = %catch.dispatch7 - %17 = bitcast i32* %1 to i8* - call void @llvm.eh.begincatch(i8* %exn.slot.1, i8* %17) #3 - call void @"\01?handle_exception@@YAXXZ"() - br label %invoke.cont13 - -; CHECK-NOT: invoke.cont13: -invoke.cont13: ; preds = %catch10 - call void @llvm.eh.endcatch() #3 - br label %try.cont15 - -try.cont15: ; preds = %invoke.cont13, %try.cont - ret void - -; CHECK-NOT: eh.resume -eh.resume: ; preds = %catch.dispatch7 - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn.slot.1, 0 - %lpad.val18 = insertvalue { i8*, i32 } %lpad.val, i32 %ehselector.slot.1, 1 - resume { i8*, i32 } %lpad.val18 - -; CHECK: } -} - -; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_TMP1:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0) -; CHECK: [[TMP1_PTR:\%.+]] = bitcast i8* [[RECOVER_TMP1]] to i32* -; CHECK: call void @"\01?handle_exception@@YAXXZ"() -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont15) -; CHECK: } - -; CHECK-LABEL: define internal void @"\01?test@@YAXXZ.cleanup"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_OBJ:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 1) -; CHECK: [[OBJ_PTR:\%.+]] = bitcast i8* %obj.i8 to %class.SomeClass* -; CHECK: call void @"\01??1SomeClass@@QEAA@XZ"(%class.SomeClass* [[OBJ_PTR]]) -; CHECK: ret void -; CHECK: } - -; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch.1"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_TMP0:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 2) -; CHECK: [[TMP0_PTR:\%.+]] = bitcast i8* [[RECOVER_TMP0]] to i32* -; CHECK: invoke void @"\01?handle_exception@@YAXXZ"() -; CHECK: to label %invoke.cont6 unwind label %[[LPAD5_LABEL:lpad[0-9]+]] -; -; CHECK: invoke.cont6: ; preds = %entry -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont) -; -; CHECK: [[LPAD5_LABEL]]:{{[ ]+}}; preds = %entry -; CHECK: [[LPAD5_VAL:\%.+]] = landingpad { i8*, i32 } -; CHECK: cleanup -; CHECK: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) -; CHECK: } - -declare %class.SomeClass* @"\01??0SomeClass@@QEAA@XZ"(%class.SomeClass* returned) #1 - -declare i32 @__CxxFrameHandler3(...) - -declare void @"\01?may_throw@@YAXXZ"() #1 - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #2 - -; Function Attrs: nounwind -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #3 - -declare void @"\01?handle_exception@@YAXXZ"() #1 - -; Function Attrs: nounwind -declare void @llvm.eh.endcatch() #3 - -; Function Attrs: nounwind -declare void @"\01??1SomeClass@@QEAA@XZ"(%class.SomeClass*) #4 - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nounwind readnone } -attributes #3 = { nounwind } -attributes #4 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 (trunk 232069) (llvm/trunk 232070)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-cleanup-invoke.ll b/llvm/test/CodeGen/WinEH/cppeh-cleanup-invoke.ll deleted file mode 100644 index 7e5f659f2a4..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-cleanup-invoke.ll +++ /dev/null @@ -1,91 +0,0 @@ -; RUN: opt -winehprepare -S < %s | FileCheck %s - -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -; Modified based on this code: -; struct HasDtor { -; ~HasDtor(); -; }; -; extern "C" void may_throw(); -; int main() { -; try { -; HasDtor o; -; may_throw(); -; } catch (int) { -; } -; } - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } -%eh.CatchHandlerType = type { i32, i8* } -%struct.HasDtor = type { 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" - -define i32 @main() personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %o = alloca %struct.HasDtor, align 1 - invoke void @may_throw() - to label %invoke.cont2 unwind label %lpad1 - -invoke.cont2: ; preds = %invoke.cont - call void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* %o) - br label %try.cont - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0 - %1 = extractvalue { i8*, i32 } %0, 0 - %2 = extractvalue { i8*, i32 } %0, 1 - br label %catch.dispatch - -lpad1: ; preds = %invoke.cont - %3 = landingpad { i8*, i32 } - cleanup - catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0 - %4 = extractvalue { i8*, i32 } %3, 0 - %5 = extractvalue { i8*, i32 } %3, 1 - invoke void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* %o) - to label %catch.dispatch unwind label %lpad - -catch.dispatch: ; preds = %lpad1, %lpad - %exn.slot.0 = phi i8* [ %4, %lpad1 ], [ %1, %lpad ] - %ehselector.slot.0 = phi i32 [ %5, %lpad1 ], [ %2, %lpad ] - %6 = call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*)) - %matches = icmp eq i32 %ehselector.slot.0, %6 - br i1 %matches, label %catch, label %eh.resume - -catch: ; preds = %catch.dispatch - call void @llvm.eh.begincatch(i8* %exn.slot.0, i8* null) - call void @llvm.eh.endcatch() - br label %try.cont - -try.cont: ; preds = %catch, %invoke.cont2 - ret i32 0 - -eh.resume: ; preds = %catch.dispatch - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn.slot.0, 0 - %lpad.val5 = insertvalue { i8*, i32 } %lpad.val, i32 %ehselector.slot.0, 1 - resume { i8*, i32 } %lpad.val5 -} - -; CHECK-LABEL: define i32 @main() -; CHECK: @llvm.eh.actions(i32 0, void (i8*, i8*)* @main.cleanup, i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*), i32 -1, i8* (i8*, i8*)* @main.catch) - -; CHECK-LABEL: define internal void @main.cleanup(i8*, i8*) -; CHECK: call void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* %{{.*}}) -; CHECK: ret void - -declare void @may_throw() - -declare i32 @__CxxFrameHandler3(...) - -declare void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor*) - -declare i32 @llvm.eh.typeid.for(i8*) -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) -declare void @llvm.eh.endcatch() diff --git a/llvm/test/CodeGen/WinEH/cppeh-demote-liveout.ll b/llvm/test/CodeGen/WinEH/cppeh-demote-liveout.ll deleted file mode 100644 index 309952bfc94..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-demote-liveout.ll +++ /dev/null @@ -1,72 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S < %s | FileCheck %s - -; Notionally based on this C++ source: -; int liveout_catch(int p) { -; int val = p + 1; -; try { -; might_throw(); -; } catch (int) { -; val++; -; } -; return val; -; } - -declare void @llvm.eh.begincatch(i8*, i8*) -declare void @llvm.eh.endcatch() -declare void @might_throw() -declare i32 @__CxxFrameHandler3(...) -declare i32 @llvm.eh.typeid.for(i8*) - -@typeinfo.int = external global i32 - -define i32 @liveout_catch(i32 %p) personality i32 (...)* @__CxxFrameHandler3 { -entry: - %val.entry = add i32 %p, 1 - invoke void @might_throw() - to label %ret unwind label %lpad - -lpad: - %ehvals = landingpad { i8*, i32 } - cleanup - catch i32* @typeinfo.int - %ehptr = extractvalue { i8*, i32 } %ehvals, 0 - %sel = extractvalue { i8*, i32 } %ehvals, 1 - %int_sel = call i32 @llvm.eh.typeid.for(i8* bitcast (i32* @typeinfo.int to i8*)) - %match = icmp eq i32 %sel, %int_sel - br i1 %match, label %catchit, label %resume - -catchit: - call void @llvm.eh.begincatch(i8* %ehptr, i8* null) - %val.lpad = add i32 %val.entry, 1 - call void @llvm.eh.endcatch() - br label %ret - -ret: - %rv = phi i32 [%val.entry, %entry], [%val.lpad, %catchit] - ret i32 %rv - -resume: - resume {i8*, i32} %ehvals -} - -; CHECK-LABEL: define i32 @liveout_catch(i32 %p) -; CHECK: %val.entry = add i32 %p, 1 -; CHECK-NEXT: store i32 %val.entry, i32* %val.entry.reg2mem -; CHECK: invoke void @might_throw() -; -; CHECK: landingpad -; CHECK: indirectbr i8* {{.*}}, [label %catchit.split] -; -; CHECK: catchit.split: -; CHECK: load i32, i32* %val.lpad.reg2mem -; CHECK: br label %ret -; -; CHECK: ret: -; CHECK: %rv = phi i32 [ {{.*}}, %entry ], [ {{.*}}, %catchit.split ] -; CHECK: ret i32 - -; CHECK-LABEL: define internal i8* @liveout_catch.catch(i8*, i8*) -; CHECK: %[[val:[^ ]*]] = load i32, i32* -; CHECK-NEXT: %[[val_lpad:[^ ]*]] = add i32 %[[val]], 1 -; CHECK-NEXT: store i32 %[[val_lpad]], i32* -; CHECK: ret i8* blockaddress(@liveout_catch, %catchit.split) diff --git a/llvm/test/CodeGen/WinEH/cppeh-frame-vars.ll b/llvm/test/CodeGen/WinEH/cppeh-frame-vars.ll deleted file mode 100644 index c2dbd8ecab6..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-frame-vars.ll +++ /dev/null @@ -1,272 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test is based on the following code: -; -; struct SomeData { -; int a; -; int b; -; }; -; -; void may_throw(); -; void does_not_throw(int i); -; void dump(int *, int, SomeData&); -; -; void test() { -; int NumExceptions = 0; -; int ExceptionVal[10]; -; SomeData Data = { 0, 0 }; -; -; for (int i = 0; i < 10; ++i) { -; try { -; may_throw(); -; Data.a += i; -; } -; catch (int e) { -; ExceptionVal[NumExceptions] = e; -; ++NumExceptions; -; if (e == i) -; Data.b += e; -; else -; Data.a += e; -; } -; does_not_throw(NumExceptions); -; } -; dump(ExceptionVal, NumExceptions, Data); -; } - -; ModuleID = 'cppeh-frame-vars.cpp' -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } -%struct.SomeData = type { i32, i32 } - -$"\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 - -; The function entry should be rewritten like this. -; CHECK: define void @"\01?test@@YAXXZ"() -; CHECK: entry: -; CHECK: [[NUMEXCEPTIONS_PTR:\%.+]] = alloca i32, align 4 -; CHECK: [[EXCEPTIONVAL_PTR:\%.+]] = alloca [10 x i32], align 16 -; CHECK: [[DATA_PTR:\%.+]] = alloca %struct.SomeData, align 4 -; CHECK: [[I_PTR:\%.+]] = alloca i32, align 4 -; CHECK: [[E_PTR:\%.+]] = alloca i32, align 4 -; CHECK: store i32 0, i32* [[NUMEXCEPTIONS_PTR]], align 4 -; CHECK: [[TMP:\%.+]] = bitcast %struct.SomeData* [[DATA_PTR]] to i8* -; CHECK: call void @llvm.memset(i8* [[TMP]], i8 0, i64 8, i32 4, i1 false) -; CHECK: store i32 0, i32* [[I_PTR]], align 4 -; CHECK: call void (...) @llvm.localescape(i32* [[E_PTR]], i32* [[NUMEXCEPTIONS_PTR]], [10 x i32]* [[EXCEPTIONVAL_PTR]], i32* [[I_PTR]], %struct.SomeData* [[DATA_PTR]]) -; CHECK: br label %for.cond - -; Function Attrs: uwtable -define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %NumExceptions = alloca i32, align 4 - %ExceptionVal = alloca [10 x i32], align 16 - %Data = alloca %struct.SomeData, align 4 - %i = alloca i32, align 4 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - %e = alloca i32, align 4 - store i32 0, i32* %NumExceptions, align 4 - %tmp = bitcast %struct.SomeData* %Data to i8* - call void @llvm.memset(i8* %tmp, i8 0, i64 8, i32 4, i1 false) - store i32 0, i32* %i, align 4 - br label %for.cond - -for.cond: ; preds = %for.inc, %entry - %tmp1 = load i32, i32* %i, align 4 - %cmp = icmp slt i32 %tmp1, 10 - br i1 %cmp, label %for.body, label %for.end - -; CHECK: for.body: -; CHECK: invoke void @"\01?may_throw@@YAXXZ"() -; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]*]] - -for.body: ; preds = %for.cond - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %for.body - %tmp2 = load i32, i32* %i, align 4 - %a = getelementptr inbounds %struct.SomeData, %struct.SomeData* %Data, i32 0, i32 0 - %tmp3 = load i32, i32* %a, align 4 - %add = add nsw i32 %tmp3, %tmp2 - store i32 %add, i32* %a, align 4 - br label %try.cont - -; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %for.body -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) -; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch") -; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont] - -lpad: ; preds = %for.body - %tmp4 = landingpad { i8*, i32 } - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) - %tmp5 = extractvalue { i8*, i32 } %tmp4, 0 - store i8* %tmp5, i8** %exn.slot - %tmp6 = extractvalue { i8*, i32 } %tmp4, 1 - store i32 %tmp6, i32* %ehselector.slot - br label %catch.dispatch - -; CHECK-NOT: catch.dispatch: - -catch.dispatch: ; preds = %lpad - %sel = load i32, i32* %ehselector.slot - %tmp7 = call i32 @llvm.eh.typeid.for(i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)) #1 - %matches = icmp eq i32 %sel, %tmp7 - br i1 %matches, label %catch, label %eh.resume - -; CHECK-NOT: catch: - -catch: ; preds = %catch.dispatch - %exn = load i8*, i8** %exn.slot - %e.i8 = bitcast i32* %e to i8* - call void @llvm.eh.begincatch(i8* %exn, i8* %e.i8) #1 - %tmp11 = load i32, i32* %e, align 4 - %tmp12 = load i32, i32* %NumExceptions, align 4 - %idxprom = sext i32 %tmp12 to i64 - %arrayidx = getelementptr inbounds [10 x i32], [10 x i32]* %ExceptionVal, i32 0, i64 %idxprom - store i32 %tmp11, i32* %arrayidx, align 4 - %tmp13 = load i32, i32* %NumExceptions, align 4 - %inc = add nsw i32 %tmp13, 1 - store i32 %inc, i32* %NumExceptions, align 4 - %tmp14 = load i32, i32* %e, align 4 - %tmp15 = load i32, i32* %i, align 4 - %cmp1 = icmp eq i32 %tmp14, %tmp15 - br i1 %cmp1, label %if.then, label %if.else - -; CHECK-NOT: if.then: - -if.then: ; preds = %catch - %tmp16 = load i32, i32* %e, align 4 - %b = getelementptr inbounds %struct.SomeData, %struct.SomeData* %Data, i32 0, i32 1 - %tmp17 = load i32, i32* %b, align 4 - %add2 = add nsw i32 %tmp17, %tmp16 - store i32 %add2, i32* %b, align 4 - br label %if.end - -; CHECK-NOT: if.else: - -if.else: ; preds = %catch - %tmp18 = load i32, i32* %e, align 4 - %a3 = getelementptr inbounds %struct.SomeData, %struct.SomeData* %Data, i32 0, i32 0 - %tmp19 = load i32, i32* %a3, align 4 - %add4 = add nsw i32 %tmp19, %tmp18 - store i32 %add4, i32* %a3, align 4 - br label %if.end - -; CHECK-NOT: if.end: - -if.end: ; preds = %if.else, %if.then - call void @llvm.eh.endcatch() #1 - br label %try.cont - -try.cont: ; preds = %if.end, %invoke.cont - %tmp20 = load i32, i32* %NumExceptions, align 4 - call void @"\01?does_not_throw@@YAXH@Z"(i32 %tmp20) - br label %for.inc - -for.inc: ; preds = %try.cont - %tmp21 = load i32, i32* %i, align 4 - %inc5 = add nsw i32 %tmp21, 1 - store i32 %inc5, i32* %i, align 4 - br label %for.cond - -for.end: ; preds = %for.cond - %tmp22 = load i32, i32* %NumExceptions, align 4 - %arraydecay = getelementptr inbounds [10 x i32], [10 x i32]* %ExceptionVal, i32 0, i32 0 - call void @"\01?dump@@YAXPEAHHAEAUSomeData@@@Z"(i32* %arraydecay, i32 %tmp22, %struct.SomeData* dereferenceable(8) %Data) - ret void - -; CHECK-NOT: eh.resume: - -eh.resume: ; preds = %catch.dispatch - %exn6 = load i8*, i8** %exn.slot - %sel7 = load i32, i32* %ehselector.slot - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn6, 0 - %lpad.val8 = insertvalue { i8*, i32 } %lpad.val, i32 %sel7, 1 - resume { i8*, i32 } %lpad.val8 - -; CHECK: } -} - -; The following catch handler should be outlined. -; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_E:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0) -; CHECK: [[E_PTR1:\%.+]] = bitcast i8* [[RECOVER_E]] to i32* -; CHECK: [[RECOVER_NUMEXCEPTIONS:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 1) -; CHECK: [[NUMEXCEPTIONS_PTR1:\%.+]] = bitcast i8* [[RECOVER_NUMEXCEPTIONS]] to i32* -; CHECK: [[RECOVER_EXCEPTIONVAL:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 2) -; CHECK: [[EXCEPTIONVAL_PTR1:\%.+]] = bitcast i8* [[RECOVER_EXCEPTIONVAL]] to [10 x i32]* -; CHECK: [[RECOVER_I:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 3) -; CHECK: [[I_PTR1:\%.+]] = bitcast i8* [[RECOVER_I]] to i32* -; CHECK: [[RECOVER_DATA:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 4) -; CHECK: [[DATA_PTR1:\%.+]] = bitcast i8* [[RECOVER_DATA]] to %struct.SomeData* -; CHECK: [[TMP:\%.+]] = load i32, i32* [[E_PTR1]], align 4 -; CHECK: [[TMP1:\%.+]] = load i32, i32* [[NUMEXCEPTIONS_PTR]], align 4 -; CHECK: [[IDXPROM:\%.+]] = sext i32 [[TMP1]] to i64 -; CHECK: [[ARRAYIDX:\%.+]] = getelementptr inbounds [10 x i32], [10 x i32]* [[EXCEPTIONVAL_PTR1]], i32 0, i64 [[IDXPROM]] -; CHECK: store i32 [[TMP]], i32* [[ARRAYIDX]], align 4 -; CHECK: [[TMP2:\%.+]] = load i32, i32* [[NUMEXCEPTIONS_PTR1]], align 4 -; CHECK: [[INC:\%.+]] = add nsw i32 [[TMP2]], 1 -; CHECK: store i32 [[INC]], i32* [[NUMEXCEPTIONS_PTR]], align 4 -; CHECK: [[TMP3:\%.+]] = load i32, i32* [[E_PTR1]], align 4 -; CHECK: [[TMP4:\%.+]] = load i32, i32* [[I_PTR1]], align 4 -; CHECK: [[CMP:\%.+]] = icmp eq i32 [[TMP3]], [[TMP4]] -; CHECK: br i1 [[CMP]], label %if.then, label %if.else -; -; CHECK: if.then: ; preds = %entry -; CHECK: [[TMP5:\%.+]] = load i32, i32* [[E_PTR1]], align 4 -; CHECK: [[B_PTR:\%.+]] = getelementptr inbounds %struct.SomeData, %struct.SomeData* [[DATA_PTR1]], i32 0, i32 1 -; CHECK: [[TMP6:\%.+]] = load i32, i32* [[B_PTR]], align 4 -; CHECK: %add2 = add nsw i32 [[TMP6]], [[TMP5]] -; CHECK: store i32 [[ADD:\%.+]], i32* [[B_PTR]], align 4 -; CHECK: br label %if.end -; -; CHECK: if.else: ; preds = %entry -; CHECK: [[TMP7:\%.+]] = load i32, i32* %e, align 4 -; CHECK: [[A3:\%.+]] = getelementptr inbounds %struct.SomeData, %struct.SomeData* %Data, i32 0, i32 0 -; CHECK: [[TMP8:\%.+]] = load i32, i32* %a3, align 4 -; CHECK: [[ADD1:\%.+]] = add nsw i32 [[TMP8]], [[TMP7]] -; CHECK: store i32 [[ADD1]], i32* [[A3]], align 4 -; CHECK: br label %if.end -; -; CHECK: if.end: ; preds = %if.else, %if.then -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont) -; CHECK: } - - -; Function Attrs: nounwind -declare void @llvm.memset(i8* nocapture, i8, i64, i32, i1) #1 - -declare void @"\01?may_throw@@YAXXZ"() #2 - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #3 - -declare void @llvm.eh.begincatch(i8*, i8*) - -declare void @llvm.eh.endcatch() - -declare void @"\01?does_not_throw@@YAXH@Z"(i32) #2 - -declare void @"\01?dump@@YAXPEAHHAEAUSomeData@@@Z"(i32*, i32, %struct.SomeData* dereferenceable(8)) #2 - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind } -attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #3 = { nounwind readnone } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 (trunk 228868)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-inalloca.ll b/llvm/test/CodeGen/WinEH/cppeh-inalloca.ll deleted file mode 100644 index 649c5e72e2d..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-inalloca.ll +++ /dev/null @@ -1,194 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test is built from the following code: -; struct A { -; A(int a); -; A(const A &o); -; ~A(); -; int a; -; }; -; -; void may_throw(); -; -; int test(A a) { -; try { -; may_throw(); -; } -; catch (int e) { -; return a.a + e; -; } -; return 0; -; } -; -; The test was built for a 32-bit Windows target and then the reference to -; the inalloca instruction was manually sunk into the landingpad. - -; ModuleID = 'cppeh-inalloca.cpp' - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } -%struct.A = type { i32 } - -$"\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 - -; The function entry should be rewritten like this. -; CHECK: define i32 @"\01?test@@YAHUA@@@Z"(<{ %struct.A }>* inalloca) -; CHECK: entry: -; CHECK: [[TMP_REGMEM:\%.+]] = alloca <{ %struct.A }>* -; CHECK: store <{ %struct.A }>* %0, <{ %struct.A }>** [[TMP_REGMEM]] -; CHECK: [[RETVAL:\%.+]] = alloca i32, align 4 -; CHECK: [[E_PTR:\%.+]] = alloca i32, align 4 -; CHECK: [[CLEANUP_SLOT:\%.+]] = alloca i32 -; CHECK: call void (...) @llvm.localescape(i32* %e, <{ %struct.A }>** [[TMP_REGMEM]], i32* [[RETVAL]], i32* [[CLEANUP_SLOT]]) -; CHECK: invoke void @"\01?may_throw@@YAXXZ"() -; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]*]] - -define i32 @"\01?test@@YAHUA@@@Z"(<{ %struct.A }>* inalloca) #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %retval = alloca i32, align 4 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - %e = alloca i32, align 4 - %cleanup.dest.slot = alloca i32 - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - br label %try.cont - -; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) -; CHECK-NEXT: [[RECOVER:\%recover.*]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAHUA@@@Z.catch", i32 0, void (i8*, i8*)* @"\01?test@@YAHUA@@@Z.cleanup") -; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %cleanup] - -lpad: ; preds = %entry - %1 = landingpad { i8*, i32 } - cleanup - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) - %2 = extractvalue { i8*, i32 } %1, 0 - store i8* %2, i8** %exn.slot - %3 = extractvalue { i8*, i32 } %1, 1 - store i32 %3, i32* %ehselector.slot - br label %catch.dispatch - -; CHECK-NOT: catch.dispatch: - -catch.dispatch: ; preds = %lpad - %sel = load i32, i32* %ehselector.slot - %4 = call i32 @llvm.eh.typeid.for(i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)) #3 - %matches = icmp eq i32 %sel, %4 - br i1 %matches, label %catch, label %ehcleanup - -; CHECK-NOT: catch: - -catch: ; preds = %catch.dispatch - %exn = load i8*, i8** %exn.slot - %e.i8 = bitcast i32* %e to i8* - call void @llvm.eh.begincatch(i8* %exn, i8* %e.i8) #3 - %a = getelementptr inbounds <{ %struct.A }>, <{ %struct.A }>* %0, i32 0, i32 0 - %a1 = getelementptr inbounds %struct.A, %struct.A* %a, i32 0, i32 0 - %tmp8 = load i32, i32* %a1, align 4 - %tmp9 = load i32, i32* %e, align 4 - %add = add nsw i32 %tmp8, %tmp9 - store i32 %add, i32* %retval - store i32 1, i32* %cleanup.dest.slot - call void @llvm.eh.endcatch() #3 - br label %cleanup - -try.cont: ; preds = %invoke.cont - store i32 0, i32* %retval - store i32 1, i32* %cleanup.dest.slot - br label %cleanup - -; The cleanup block should be re-written like this. -; CHECK: cleanup:{{[ ]+}}; preds = %[[LPAD_LABEL]], %try.cont -; CHECK: %a2 = getelementptr inbounds <{ %struct.A }>, <{ %struct.A }>* %0, i32 0, i32 0 -; CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %a2) -; CHECK: [[TMP1:\%.+]] = load i32, i32* [[RETVAL]] -; CHECK: ret i32 [[TMP1]] - -cleanup: ; preds = %try.cont, %catch - %a2 = getelementptr inbounds <{ %struct.A }>, <{ %struct.A }>* %0, i32 0, i32 0 - call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %a2) #3 - %tmp10 = load i32, i32* %retval - ret i32 %tmp10 - -; CHECK-NOT: ehcleanup: - -ehcleanup: ; preds = %catch.dispatch - %a3 = getelementptr inbounds <{ %struct.A }>, <{ %struct.A }>* %0, i32 0, i32 0 - call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %a3) #3 - br label %eh.resume - -; CHECK-NOT: eh.resume: - -eh.resume: ; preds = %ehcleanup - %exn2 = load i8*, i8** %exn.slot - %sel3 = load i32, i32* %ehselector.slot - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn2, 0 - %lpad.val4 = insertvalue { i8*, i32 } %lpad.val, i32 %sel3, 1 - resume { i8*, i32 } %lpad.val4 - -; CHECK: } -} - -; The following catch handler should be outlined. -; CHECK: define internal i8* @"\01?test@@YAHUA@@@Z.catch"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_E:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1, i32 0) -; CHECK: [[E_PTR:\%.+]] = bitcast i8* [[RECOVER_E]] to i32* -; CHECK: [[RECOVER_EH_TEMP:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1, i32 1) -; CHECK: [[EH_TEMP:\%.+]] = bitcast i8* [[RECOVER_EH_TEMP]] to <{ %struct.A }>** -; CHECK: [[RECOVER_RETVAL:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1, i32 2) -; CHECK: [[RETVAL1:\%.+]] = bitcast i8* [[RECOVER_RETVAL]] to i32* -; CHECK: [[RECOVER_CLEANUPSLOT:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1, i32 3) -; CHECK: [[CLEANUPSLOT1:\%.+]] = bitcast i8* [[RECOVER_CLEANUPSLOT]] to i32* -; CHECK: [[E_I8PTR:\%.+]] = bitcast i32* [[E_PTR]] to i8* -; CHECK: [[TMP_RELOAD:\%.+]] = load <{ %struct.A }>*, <{ %struct.A }>** [[EH_TEMP]] -; CHECK: [[RECOVER_A:\%.+]] = getelementptr inbounds <{ %struct.A }>, <{ %struct.A }>* [[TMP_RELOAD]], i32 0, i32 0 -; CHECK: [[A1:\%.+]] = getelementptr inbounds %struct.A, %struct.A* [[RECOVER_A]], i32 0, i32 0 -; CHECK: [[TMP2:\%.+]] = load i32, i32* [[A1]], align 4 -; CHECK: [[TMP3:\%.+]] = load i32, i32* [[E_PTR]], align 4 -; CHECK: [[ADD:\%.+]] = add nsw i32 [[TMP2]], [[TMP3]] -; CHECK: store i32 [[ADD]], i32* [[RETVAL1]] -; CHECK: store i32 1, i32* [[CLEANUPSLOT1]] -; CHECK: ret i8* blockaddress(@"\01?test@@YAHUA@@@Z", %cleanup) -; CHECK: } - -; The following cleanup handler should be outlined. -; CHECK: define internal void @"\01?test@@YAHUA@@@Z.cleanup"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_EH_TEMP1:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (i32 (<{ %struct.A }>*)* @"\01?test@@YAHUA@@@Z" to i8*), i8* %1, i32 1) -; CHECK: [[EH_TEMP1:\%.+]] = bitcast i8* [[RECOVER_EH_TEMP]] to <{ %struct.A }>** -; CHECK: [[TMP_RELOAD1:\%.+]] = load <{ %struct.A }>*, <{ %struct.A }>** [[EH_TEMP1]] -; CHECK: [[A3:\%.+]] = getelementptr inbounds <{ %struct.A }>, <{ %struct.A }>* [[TMP_RELOAD1]], i32 0, i32 0 -; CHECK: call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* [[A3]]) -; CHECK: ret void -; CHECK: } - -declare void @"\01?may_throw@@YAXXZ"() #0 - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #1 - -declare void @llvm.eh.begincatch(i8*, i8*) - -declare void @llvm.eh.endcatch() - -; Function Attrs: nounwind -declare x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A*) #2 - -attributes #0 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind readnone } -attributes #2 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #3 = { nounwind } - -!llvm.ident = !{!0} - -!0 = !{!"clang version 3.7.0 (trunk 228868)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-min-unwind.ll b/llvm/test/CodeGen/WinEH/cppeh-min-unwind.ll deleted file mode 100644 index 98d6d6fcacb..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-min-unwind.ll +++ /dev/null @@ -1,99 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test was generated from the following source: -; -; class SomeClass { -; public: -; SomeClass(); -; ~SomeClass(); -; }; -; -; void test() { -; SomeClass obj; -; may_throw(); -; } - - -; ModuleID = 'min-unwind.cpp' -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%class.SomeClass = type { [28 x i32] } - -; The function entry should be rewritten like this. -; CHECK: define void @_Z4testv() -; CHECK: entry: -; CHECK: [[OBJ_PTR:\%.+]] = alloca %class.SomeClass, align 4 -; CHECK: call void @_ZN9SomeClassC1Ev(%class.SomeClass* [[OBJ_PTR]]) -; CHECK: call void (...) @llvm.localescape(%class.SomeClass* [[OBJ_PTR]]) -; CHECK: invoke void @_Z9may_throwv() -; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]*]] - -; Function Attrs: uwtable -define void @_Z4testv() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %obj = alloca %class.SomeClass, align 4 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - call void @_ZN9SomeClassC1Ev(%class.SomeClass* %obj) - invoke void @_Z9may_throwv() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - call void @_ZN9SomeClassD1Ev(%class.SomeClass* %obj) - ret void - -; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @_Z4testv.cleanup) -; CHECK-NEXT: indirectbr i8* [[RECOVER]], [] - -lpad: ; preds = %entry - %tmp = landingpad { i8*, i32 } - cleanup - %tmp1 = extractvalue { i8*, i32 } %tmp, 0 - store i8* %tmp1, i8** %exn.slot - %tmp2 = extractvalue { i8*, i32 } %tmp, 1 - store i32 %tmp2, i32* %ehselector.slot - call void @_ZN9SomeClassD1Ev(%class.SomeClass* %obj) - br label %eh.resume - -; CHECK-NOT: eh.resume: - -eh.resume: ; preds = %lpad - %exn = load i8*, i8** %exn.slot - %sel = load i32, i32* %ehselector.slot - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn, 0 - %lpad.val2 = insertvalue { i8*, i32 } %lpad.val, i32 %sel, 1 - resume { i8*, i32 } %lpad.val2 - -; CHECK: } -} - -; This cleanup handler should be outlined. -; CHECK: define internal void @_Z4testv.cleanup(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_OBJ:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @_Z4testv to i8*), i8* %1, i32 0) -; CHECK: [[OBJ_PTR1:\%.+]] = bitcast i8* [[RECOVER_OBJ]] to %class.SomeClass* -; CHECK: call void @_ZN9SomeClassD1Ev(%class.SomeClass* [[OBJ_PTR1]]) -; CHECK: ret void -; CHECK: } - -declare void @_ZN9SomeClassC1Ev(%class.SomeClass*) #1 - -declare void @_Z9may_throwv() #1 - -declare i32 @__CxxFrameHandler3(...) - -declare void @_ZN9SomeClassD1Ev(%class.SomeClass*) #1 - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { noinline noreturn nounwind } -attributes #3 = { noreturn nounwind } -attributes #4 = { nounwind } - -!llvm.ident = !{!0} - -!0 = !{!"clang version 3.7.0 (trunk 226027)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-mixed-catch-and-cleanup.ll b/llvm/test/CodeGen/WinEH/cppeh-mixed-catch-and-cleanup.ll deleted file mode 100644 index c69633f17e2..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-mixed-catch-and-cleanup.ll +++ /dev/null @@ -1,106 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test is based on the following code: -; -; void test() -; { -; try { -; Obj o; -; may_throw(); -; } catch (...) { -; } -; } -; -; The purpose of this test is to verify that we create separate catch and -; cleanup handlers. When compiling for the C++ 11 standard, this isn't -; strictly necessary, since calling the destructor from the catch handler -; would be logically equivalent to calling it from a cleanup handler. -; However, if the -std=c++98 option is used, an exception in the cleanup -; code should terminate the process (the MSVCRT runtime will do that) but -; if the destructor is called from the catch handler, it wouldn't terminate -; the process - - -; ModuleID = 'cppeh-mixed-catch-and-cleanup.cpp' -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%class.Obj = type { i8 } - -; This just verifies that the function was processed by WinEHPrepare. -; -; CHECK-LABEL: define void @"\01?test@@YAXXZ"() -; CHECK: entry: -; CHECK: call void (...) @llvm.localescape -; CHECK: } - -; Function Attrs: nounwind uwtable -define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %o = alloca %class.Obj, align 1 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - call void @"\01??1Obj@@QEAA@XZ"(%class.Obj* %o) #3 - br label %try.cont - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* null - %1 = extractvalue { i8*, i32 } %0, 0 - store i8* %1, i8** %exn.slot - %2 = extractvalue { i8*, i32 } %0, 1 - store i32 %2, i32* %ehselector.slot - call void @"\01??1Obj@@QEAA@XZ"(%class.Obj* %o) #3 - %exn = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn, i8* null) #3 - call void @llvm.eh.endcatch() #3 - br label %try.cont - -try.cont: ; preds = %catch, %invoke.cont - ret void -} - -; Verify that a cleanup handler was created and that it calls ~Obj(). -; CHECK-LABEL: define internal void @"\01?test@@YAXXZ.cleanup"(i8*, i8*) -; CHECK: entry: -; CHECK: @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0) -; CHECK: call void @"\01??1Obj@@QEAA@XZ" -; CHECK: ret void -; CHECK: } - -; Verify that a catch handler was created and that it does not call ~Obj(). -; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*) -; CHECK: entry: -; CHECK-NOT: call void @"\01??1Obj@@QEAA@XZ" -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont) -; CHECK: } - - - -declare void @"\01?may_throw@@YAXXZ"() #1 - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind -declare void @"\01??1Obj@@QEAA@XZ"(%class.Obj*) #2 - -; Function Attrs: nounwind -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #3 - -; Function Attrs: nounwind -declare void @llvm.eh.endcatch() #3 - -attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #3 = { nounwind } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 (trunk 235779) (llvm/trunk 235769)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-multi-catch.ll b/llvm/test/CodeGen/WinEH/cppeh-multi-catch.ll deleted file mode 100644 index 266cdea20cd..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-multi-catch.ll +++ /dev/null @@ -1,226 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test is based on the following code: -; -; void test() -; { -; try { -; may_throw(); -; } catch (int i) { -; handle_int(i); -; } catch (long long ll) { -; handle_long_long(ll); -; } catch (SomeClass &obj) { -; handle_obj(&obj); -; } catch (...) { -; handle_exception(); -; } -; } -; -; The catch handlers were edited to insert 'ret void' after the endcatch call. - -; ModuleID = 'catch-with-type.cpp' -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } -%eh.HandlerMapEntry = type { i32, i32 } -%rtti.TypeDescriptor3 = type { i8**, i8*, [4 x i8] } -%rtti.TypeDescriptor15 = type { i8**, i8*, [16 x i8] } -%class.SomeClass = type { i8 } - -$"\01??_R0H@8" = comdat any - -$"\01??_R0_J@8" = comdat any - -$"\01??_R0?AVSomeClass@@@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 -@__ImageBase = external constant i8 -@llvm.eh.handlermapentry.H = private unnamed_addr constant %eh.HandlerMapEntry { i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, section "llvm.metadata" -@"\01??_R0_J@8" = linkonce_odr global %rtti.TypeDescriptor3 { i8** @"\01??_7type_info@@6B@", i8* null, [4 x i8] c"._J\00" }, comdat -@llvm.eh.handlermapentry._J = private unnamed_addr constant %eh.HandlerMapEntry { i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor3* @"\01??_R0_J@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, section "llvm.metadata" -@"\01??_R0?AVSomeClass@@@8" = linkonce_odr global %rtti.TypeDescriptor15 { i8** @"\01??_7type_info@@6B@", i8* null, [16 x i8] c".?AVSomeClass@@\00" }, comdat -@"llvm.eh.handlermapentry.reference.?AVSomeClass@@" = private unnamed_addr constant %eh.HandlerMapEntry { i32 8, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor15* @"\01??_R0?AVSomeClass@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, section "llvm.metadata" - - -; CHECK: define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -; CHECK: entry: -; CHECK: [[OBJ_PTR:\%.+]] = alloca %class.SomeClass*, align 8 -; CHECK: [[LL_PTR:\%.+]] = alloca i64, align 8 -; CHECK: [[I_PTR:\%.+]] = alloca i32, align 4 -; CHECK: call void (...) @llvm.localescape(i32* [[I_PTR]], i64* [[LL_PTR]], %class.SomeClass** [[OBJ_PTR]]) -; CHECK: invoke void @"\01?may_throw@@YAXXZ"() -; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]*]] - -; Function Attrs: uwtable -define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - %obj = alloca %class.SomeClass*, align 8 - %ll = alloca i64, align 8 - %i = alloca i32, align 4 - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - br label %try.cont - -; CHECK: [[LPAD_LABEL]]:{{[ ]+}}; preds = %entry -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: catch %eh.HandlerMapEntry* @llvm.eh.handlermapentry.H -; CHECK-NEXT: catch %eh.HandlerMapEntry* @llvm.eh.handlermapentry._J -; CHECK-NEXT: catch %eh.HandlerMapEntry* @"llvm.eh.handlermapentry.reference.?AVSomeClass@@" -; CHECK-NEXT: catch i8* null -; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions( -; CHECK-SAME: i32 1, i8* bitcast (%eh.HandlerMapEntry* @llvm.eh.handlermapentry.H to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch", -; CHECK-SAME: i32 1, i8* bitcast (%eh.HandlerMapEntry* @llvm.eh.handlermapentry._J to i8*), i32 1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch.1", -; CHECK-SAME: i32 1, i8* bitcast (%eh.HandlerMapEntry* @"llvm.eh.handlermapentry.reference.?AVSomeClass@@" to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch.2", -; CHECK-SAME: i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch.3") -; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %ret] - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch %eh.HandlerMapEntry* @llvm.eh.handlermapentry.H - catch %eh.HandlerMapEntry* @llvm.eh.handlermapentry._J - catch %eh.HandlerMapEntry* @"llvm.eh.handlermapentry.reference.?AVSomeClass@@" - catch i8* null - %1 = extractvalue { i8*, i32 } %0, 0 - store i8* %1, i8** %exn.slot - %2 = extractvalue { i8*, i32 } %0, 1 - store i32 %2, i32* %ehselector.slot - br label %catch.dispatch - -; CHECK-NOT: catch.dispatch: -catch.dispatch: ; preds = %lpad - %sel = load i32, i32* %ehselector.slot - %3 = call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.HandlerMapEntry* @llvm.eh.handlermapentry.H to i8*)) #3 - %matches = icmp eq i32 %sel, %3 - br i1 %matches, label %catch14, label %catch.fallthrough - -ret: - ret void - -; CHECK-NOT: catch14: -; CHECK: ret: -; CHECK-NEXT: ret void -catch14: ; preds = %catch.dispatch - %exn15 = load i8*, i8** %exn.slot - %4 = bitcast i32* %i to i8* - call void @llvm.eh.begincatch(i8* %exn15, i8* %4) #3 - %5 = load i32, i32* %i, align 4 - call void @"\01?handle_int@@YAXH@Z"(i32 %5) - call void @llvm.eh.endcatch() #3 - br label %ret - -try.cont: ; preds = %invoke.cont - br label %ret - -; CHECK-NOT: catch.fallthrough: -catch.fallthrough: ; preds = %catch.dispatch - %6 = call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.HandlerMapEntry* @llvm.eh.handlermapentry._J to i8*)) #3 - %matches1 = icmp eq i32 %sel, %6 - br i1 %matches1, label %catch10, label %catch.fallthrough2 - -; CHECK-NOT: catch10: -catch10: ; preds = %catch.fallthrough - %exn11 = load i8*, i8** %exn.slot - %7 = bitcast i64* %ll to i8* - call void @llvm.eh.begincatch(i8* %exn11, i8* %7) #3 - %8 = load i64, i64* %ll, align 8 - call void @"\01?handle_long_long@@YAX_J@Z"(i64 %8) - call void @llvm.eh.endcatch() #3 - br label %ret - -; CHECK-NOT: catch.fallthrough2: -catch.fallthrough2: ; preds = %catch.fallthrough - %9 = call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.HandlerMapEntry* @"llvm.eh.handlermapentry.reference.?AVSomeClass@@" to i8*)) #3 - %matches3 = icmp eq i32 %sel, %9 - br i1 %matches3, label %catch6, label %catch - -; CHECK-NOT: catch6: -catch6: ; preds = %catch.fallthrough2 - %exn7 = load i8*, i8** %exn.slot - %10 = bitcast %class.SomeClass** %obj to i8* - call void @llvm.eh.begincatch(i8* %exn7, i8* %10) #3 - %11 = load %class.SomeClass*, %class.SomeClass** %obj, align 8 - call void @"\01?handle_obj@@YAXPEAVSomeClass@@@Z"(%class.SomeClass* %11) - call void @llvm.eh.endcatch() #3 - br label %ret - -; CHECK-NOT: catch: -catch: ; preds = %catch.fallthrough2 - %exn = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn, i8* null) #3 - call void @"\01?handle_exception@@YAXXZ"() call void @llvm.eh.endcatch() #3 - br label %ret -; CHECK: } -} - -; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_I:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0) -; CHECK: [[I_PTR:\%.+]] = bitcast i8* [[RECOVER_I]] to i32* -; CHECK: [[TMP1:\%.+]] = load i32, i32* [[I_PTR]], align 4 -; CHECK: call void @"\01?handle_int@@YAXH@Z"(i32 [[TMP1]]) -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %ret) -; CHECK: } - -; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch.1"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_LL:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 1) -; CHECK: [[LL_PTR:\%.+]] = bitcast i8* [[RECOVER_LL]] to i64* -; CHECK: [[TMP2:\%.+]] = load i64, i64* [[LL_PTR]], align 8 -; CHECK: call void @"\01?handle_long_long@@YAX_J@Z"(i64 [[TMP2]]) -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %ret) -; CHECK: } - -; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch.2"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_OBJ:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 2) -; CHECK: [[OBJ_PTR:\%.+]] = bitcast i8* [[RECOVER_OBJ]] to %class.SomeClass** -; CHECK: [[TMP3:\%.+]] = load %class.SomeClass*, %class.SomeClass** [[OBJ_PTR]], align 8 -; CHECK: call void @"\01?handle_obj@@YAXPEAVSomeClass@@@Z"(%class.SomeClass* [[TMP3]]) -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %ret) -; CHECK: } - -; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch.3"(i8*, i8*) -; CHECK: entry: -; CHECK: call void @"\01?handle_exception@@YAXXZ"() -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %ret) -; CHECK: } - - -declare void @"\01?may_throw@@YAXXZ"() #1 - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #2 - -; Function Attrs: nounwind -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #3 - -declare void @"\01?handle_exception@@YAXXZ"() #1 - -; Function Attrs: nounwind -declare void @llvm.eh.endcatch() #3 - -declare void @"\01?handle_obj@@YAXPEAVSomeClass@@@Z"(%class.SomeClass*) #1 - -declare void @"\01?handle_long_long@@YAX_J@Z"(i64) #1 - -declare void @"\01?handle_int@@YAXH@Z"(i32) #1 - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nounwind readnone } -attributes #3 = { nounwind } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 (trunk 233155) (llvm/trunk 233153)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-nested-1.ll b/llvm/test/CodeGen/WinEH/cppeh-nested-1.ll deleted file mode 100644 index d525d8a1a67..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-nested-1.ll +++ /dev/null @@ -1,194 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test is based on the following code: -; -;void test() -;{ -; try { -; try { -; may_throw(); -; } catch (int i) { -; handle_int(i); -; } -; } catch (float f) { -; handle_float(f); -; } -; done(); -;} - -; ModuleID = 'cppeh-nested-1.cpp' -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } - -$"\01??_R0M@8" = comdat any - -$"\01??_R0H@8" = comdat any - -@"\01??_7type_info@@6B@" = external constant i8* -@"\01??_R0M@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".M\00" }, comdat -@"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat - -; CHECK: define void @"\01?test@@YAXXZ"() -; CHECK: entry: -; CHECK: %i = alloca i32, align 4 -; CHECK: %f = alloca float, align 4 -; CHECK: call void (...) @llvm.localescape(float* %f, i32* %i) -; CHECK: invoke void @"\01?may_throw@@YAXXZ"() -; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]*]] - -; Function Attrs: uwtable -define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - %i = alloca i32, align 4 - %f = alloca float, align 4 - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - br label %try.cont - -; CHECK: [[LPAD_LABEL]]: -; CHECK: landingpad { i8*, i32 } -; CHECK: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) -; CHECK: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*) -; CHECK: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch.1", i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch") -; CHECK: indirectbr i8* [[RECOVER]], [label %try.cont, label %try.cont10] - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*) - %1 = extractvalue { i8*, i32 } %0, 0 - store i8* %1, i8** %exn.slot - %2 = extractvalue { i8*, i32 } %0, 1 - store i32 %2, i32* %ehselector.slot - br label %catch.dispatch - -; CHECK-NOT: catch.dispatch: -catch.dispatch: ; preds = %lpad - %sel = load i32, i32* %ehselector.slot - %3 = call i32 @llvm.eh.typeid.for(i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)) #3 - %matches = icmp eq i32 %sel, %3 - br i1 %matches, label %catch, label %catch.dispatch3 - -; CHECK-NOT: catch: -catch: ; preds = %catch.dispatch - %exn = load i8*, i8** %exn.slot - %4 = bitcast i32* %i to i8* - call void @llvm.eh.begincatch(i8* %exn, i8* %4) #3 - %5 = load i32, i32* %i, align 4 - invoke void @"\01?handle_int@@YAXH@Z"(i32 %5) - to label %invoke.cont2 unwind label %lpad1 - -; CHECK-NOT: invoke.cont2: -invoke.cont2: ; preds = %catch - call void @llvm.eh.endcatch() #3 - br label %try.cont - -try.cont: ; preds = %invoke.cont2, %invoke.cont - br label %try.cont10 - -; CHECK-NOT: lpad1: -lpad1: ; preds = %catch - %6 = landingpad { i8*, i32 } - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*) - %7 = extractvalue { i8*, i32 } %6, 0 - store i8* %7, i8** %exn.slot - %8 = extractvalue { i8*, i32 } %6, 1 - store i32 %8, i32* %ehselector.slot - call void @llvm.eh.endcatch() #3 - br label %catch.dispatch3 - -; CHECK-NOT: catch.dispatch3: -catch.dispatch3: ; preds = %lpad1, %catch.dispatch - %sel4 = load i32, i32* %ehselector.slot - %9 = call i32 @llvm.eh.typeid.for(i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*)) #3 - %matches5 = icmp eq i32 %sel4, %9 - br i1 %matches5, label %catch6, label %eh.resume - -; CHECK-NOT: catch6: -catch6: ; preds = %catch.dispatch3 - %exn7 = load i8*, i8** %exn.slot - %10 = bitcast float* %f to i8* - call void @llvm.eh.begincatch(i8* %exn7, i8* %10) #3 - %11 = load float, float* %f, align 4 - call void @"\01?handle_float@@YAXM@Z"(float %11) - call void @llvm.eh.endcatch() #3 - br label %try.cont10 - -try.cont10: ; preds = %catch6, %try.cont - call void @"\01?done@@YAXXZ"() - ret void - -; CHECK-NOT: eh.resume: -eh.resume: ; %catch.dispatch3 - %exn11 = load i8*, i8** %exn.slot - %sel12 = load i32, i32* %ehselector.slot - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn11, 0 - %lpad.val13 = insertvalue { i8*, i32 } %lpad.val, i32 %sel12, 1 - resume { i8*, i32 } %lpad.val13 -; CHECK: } -} - -; CHECK: define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_F1:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0) -; CHECK: [[F_PTR1:\%.+]] = bitcast i8* [[RECOVER_F1]] to float* -; CHECK: [[TMP2:\%.+]] = load float, float* [[F_PTR1]], align 4 -; CHECK: call void @"\01?handle_float@@YAXM@Z"(float [[TMP2]]) -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont10) -; CHECK: } - -; CHECK: define internal i8* @"\01?test@@YAXXZ.catch.1"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_I:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 1) -; CHECK: [[I_PTR:\%.+]] = bitcast i8* [[RECOVER_I]] to i32* -; CHECK: [[TMP1:\%.+]] = load i32, i32* [[I_PTR]], align 4 -; CHECK: invoke void @"\01?handle_int@@YAXH@Z"(i32 [[TMP1]]) -; CHECK: to label %invoke.cont2 unwind label %[[LPAD1_LABEL:lpad[0-9]*]] -; -; CHECK: invoke.cont2: -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont) -; -; CHECK: [[LPAD1_LABEL]]:{{[ ]+}}; preds = %entry -; CHECK: [[LPAD1_VAL:\%.+]] = landingpad { i8*, i32 } -; CHECK: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*) -; CHECK: [[RECOVER1:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch") -; CHECK: indirectbr i8* [[RECOVER1]], [] -; -; CHECK: } - - -declare void @"\01?may_throw@@YAXXZ"() #1 - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #2 - -; Function Attrs: nounwind -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #3 - -declare void @"\01?handle_int@@YAXH@Z"(i32) #1 - -; Function Attrs: nounwind -declare void @llvm.eh.endcatch() #3 - -declare void @"\01?handle_float@@YAXM@Z"(float) #1 - -declare void @"\01?done@@YAXXZ"() #1 - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nounwind readnone } -attributes #3 = { nounwind } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 (trunk 232069) (llvm/trunk 232070)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-nested-2.ll b/llvm/test/CodeGen/WinEH/cppeh-nested-2.ll deleted file mode 100644 index 2764e7478c7..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-nested-2.ll +++ /dev/null @@ -1,324 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test is based on the following code: -; -; class Inner { -; public: -; Inner(); -; ~Inner(); -; }; -; class Outer { -; public: -; Outer(); -; ~Outer(); -; }; -; void test() { -; try { -; Outer outer; -; try { -; Inner inner; -; may_throw(); -; } catch (int i) { -; handle_int(i); -; } -; } catch (float f) { -; handle_float(f); -; } -; done(); -; } - -; ModuleID = 'nested-2.cpp' -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%class.Outer = type { i8 } -%class.Inner = type { i8 } - -@_ZTIf = external constant i8* -@_ZTIi = external constant i8* - -; The function entry should be rewritten like this. -; CHECK: define void @_Z4testv() -; CHECK: entry: -; CHECK: %outer = alloca %class.Outer, align 1 -; CHECK: %inner = alloca %class.Inner, align 1 -; CHECK: %i = alloca i32, align 4 -; CHECK: %f = alloca float, align 4 -; CHECK: call void (...) @llvm.localescape(float* %f, i32* %i, %class.Outer* %outer, %class.Inner* %inner) -; CHECK: invoke void @_ZN5OuterC1Ev(%class.Outer* %outer) -; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]*]] - -; Function Attrs: uwtable -define void @_Z4testv() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %outer = alloca %class.Outer, align 1 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - %inner = alloca %class.Inner, align 1 - %i = alloca i32, align 4 - %f = alloca float, align 4 - invoke void @_ZN5OuterC1Ev(%class.Outer* %outer) - to label %invoke.cont unwind label %lpad - -; CHECK: invoke.cont: -; CHECK: invoke void @_ZN5InnerC1Ev(%class.Inner* %inner) -; CHECK: to label %invoke.cont2 unwind label %[[LPAD1_LABEL:lpad[0-9]*]] - -invoke.cont: ; preds = %entry - invoke void @_ZN5InnerC1Ev(%class.Inner* %inner) - to label %invoke.cont2 unwind label %lpad1 - -; CHECK: invoke.cont2: -; CHECK: invoke void @_Z9may_throwv() -; CHECK: to label %invoke.cont4 unwind label %[[LPAD3_LABEL:lpad[0-9]*]] - -invoke.cont2: ; preds = %invoke.cont - invoke void @_Z9may_throwv() - to label %invoke.cont4 unwind label %lpad3 - -; CHECK: invoke.cont4: -; CHECK: invoke void @_ZN5InnerD1Ev(%class.Inner* %inner) -; CHECK: to label %invoke.cont5 unwind label %[[LPAD1_LABEL]] - -invoke.cont4: ; preds = %invoke.cont2 - invoke void @_ZN5InnerD1Ev(%class.Inner* %inner) - to label %invoke.cont5 unwind label %lpad1 - -; CHECK: invoke.cont5: -; CHECK: br label %try.cont - -invoke.cont5: ; preds = %invoke.cont4 - br label %try.cont - -; CHECK: [[LPAD_LABEL]]: -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIf to i8*) -; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i8** @_ZTIf to i8*), i32 0, i8* (i8*, i8*)* @_Z4testv.catch) -; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont19] - -lpad: ; preds = %try.cont, %entry - %tmp = landingpad { i8*, i32 } - catch i8* bitcast (i8** @_ZTIf to i8*) - %tmp1 = extractvalue { i8*, i32 } %tmp, 0 - store i8* %tmp1, i8** %exn.slot - %tmp2 = extractvalue { i8*, i32 } %tmp, 1 - store i32 %tmp2, i32* %ehselector.slot - br label %catch.dispatch11 - -; CHECK: [[LPAD1_LABEL]]: -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) -; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIf to i8*) -; CHECK-NEXT: [[RECOVER1:\%.+]] = call i8* (...) @llvm.eh.actions( -; CHECK-SAME: i32 1, i8* bitcast (i8** @_ZTIi to i8*), i32 1, i8* (i8*, i8*)* @_Z4testv.catch.1, -; CHECK-SAME: i32 0, void (i8*, i8*)* @_Z4testv.cleanup, -; CHECK-SAME: i32 1, i8* bitcast (i8** @_ZTIf to i8*), i32 0, i8* (i8*, i8*)* @_Z4testv.catch) -; CHECK-NEXT: indirectbr i8* [[RECOVER1]], [label %try.cont, label %try.cont19] - -lpad1: ; preds = %invoke.cont4, %invoke.cont - %tmp3 = landingpad { i8*, i32 } - cleanup - catch i8* bitcast (i8** @_ZTIi to i8*) - catch i8* bitcast (i8** @_ZTIf to i8*) - %tmp4 = extractvalue { i8*, i32 } %tmp3, 0 - store i8* %tmp4, i8** %exn.slot - %tmp5 = extractvalue { i8*, i32 } %tmp3, 1 - store i32 %tmp5, i32* %ehselector.slot - br label %catch.dispatch - -; CHECK: [[LPAD3_LABEL]]: -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIi to i8*) -; CHECK-NEXT: catch i8* bitcast (i8** @_ZTIf to i8*) -; CHECK-NEXT: [[RECOVER3:\%.+]] = call i8* (...) @llvm.eh.actions( -; CHECK-SAME: i32 0, void (i8*, i8*)* @_Z4testv.cleanup.2, -; CHECK-SAME: i32 1, i8* bitcast (i8** @_ZTIi to i8*), i32 1, i8* (i8*, i8*)* @_Z4testv.catch.1, -; CHECK-SAME: i32 0, void (i8*, i8*)* @_Z4testv.cleanup, -; CHECK-SAME: i32 1, i8* bitcast (i8** @_ZTIf to i8*), i32 0, i8* (i8*, i8*)* @_Z4testv.catch) -; CHECK-NEXT: indirectbr i8* [[RECOVER3]], [label %try.cont, label %try.cont19] - -lpad3: ; preds = %invoke.cont2 - %tmp6 = landingpad { i8*, i32 } - cleanup - catch i8* bitcast (i8** @_ZTIi to i8*) - catch i8* bitcast (i8** @_ZTIf to i8*) - %tmp7 = extractvalue { i8*, i32 } %tmp6, 0 - store i8* %tmp7, i8** %exn.slot - %tmp8 = extractvalue { i8*, i32 } %tmp6, 1 - store i32 %tmp8, i32* %ehselector.slot - call void @_ZN5InnerD1Ev(%class.Inner* %inner) - br label %catch.dispatch - -; CHECK-NOT: catch.dispatch: - -catch.dispatch: ; preds = %lpad3, %lpad1 - %sel = load i32, i32* %ehselector.slot - %tmp9 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) #4 - %matches = icmp eq i32 %sel, %tmp9 - br i1 %matches, label %catch, label %ehcleanup - -; CHECK-NOT: catch: - -catch: ; preds = %catch.dispatch - %exn = load i8*, i8** %exn.slot - %i.i8 = bitcast i32* %i to i8* - call void @llvm.eh.begincatch(i8* %exn, i8* %i.i8) #4 - %tmp13 = load i32, i32* %i, align 4 - invoke void @_Z10handle_inti(i32 %tmp13) - to label %invoke.cont8 unwind label %lpad7 - -; CHECK-NOT: invoke.cont8: - -invoke.cont8: ; preds = %catch - call void @llvm.eh.endcatch() #4 - br label %try.cont - -; CHECK: try.cont: -; CHECK: invoke void @_ZN5OuterD1Ev(%class.Outer* %outer) -; CHECK: to label %invoke.cont9 unwind label %[[LPAD_LABEL]] - -try.cont: ; preds = %invoke.cont8, %invoke.cont5 - invoke void @_ZN5OuterD1Ev(%class.Outer* %outer) - to label %invoke.cont9 unwind label %lpad - -invoke.cont9: ; preds = %try.cont - br label %try.cont19 - -; CHECK-NOT: lpad7: - -lpad7: ; preds = %catch - %tmp14 = landingpad { i8*, i32 } - cleanup - catch i8* bitcast (i8** @_ZTIf to i8*) - %tmp15 = extractvalue { i8*, i32 } %tmp14, 0 - store i8* %tmp15, i8** %exn.slot - %tmp16 = extractvalue { i8*, i32 } %tmp14, 1 - store i32 %tmp16, i32* %ehselector.slot - call void @llvm.eh.endcatch() #4 - br label %ehcleanup - -; CHECK-NOT: ehcleanup: ; preds = %lpad7, %catch.dispatch - -ehcleanup: ; preds = %lpad7, %catch.dispatch - call void @_ZN5OuterD1Ev(%class.Outer* %outer) - br label %catch.dispatch11 - -; CHECK-NOT: catch.dispatch11: - -catch.dispatch11: ; preds = %ehcleanup, %lpad - %sel12 = load i32, i32* %ehselector.slot - %tmp17 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIf to i8*)) #4 - %matches13 = icmp eq i32 %sel12, %tmp17 - br i1 %matches13, label %catch14, label %eh.resume - -; CHECK-NOT: catch14: - -catch14: ; preds = %catch.dispatch11 - %exn15 = load i8*, i8** %exn.slot - %f.i8 = bitcast float* %f to i8* - call void @llvm.eh.begincatch(i8* %exn15, i8* %f.i8) #4 - %tmp21 = load float, float* %f, align 4 - call void @_Z12handle_floatf(float %tmp21) - call void @llvm.eh.endcatch() #4 - br label %try.cont19 - -try.cont19: ; preds = %catch14, %invoke.cont9 - call void @_Z4donev() - ret void - -; CHECK-NOT: eh.resume: - -eh.resume: ; preds = %catch.dispatch11 - %exn20 = load i8*, i8** %exn.slot - %sel21 = load i32, i32* %ehselector.slot - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn20, 0 - %lpad.val22 = insertvalue { i8*, i32 } %lpad.val, i32 %sel21, 1 - resume { i8*, i32 } %lpad.val22 - -; CHECK: } -} - -; This catch handler should be outlined. -; CHECK: define internal i8* @_Z4testv.catch(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_F:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @_Z4testv to i8*), i8* %1, i32 0) -; CHECK: [[F_PTR:\%.+]] = bitcast i8* [[RECOVER_F]] to float* -; CHECK: [[TMP:\%.+]] = load float, float* [[F_PTR]], align 4 -; CHECK: call void @_Z12handle_floatf(float [[TMP]]) -; CHECK: ret i8* blockaddress(@_Z4testv, %try.cont19) -; CHECK: } - -; This catch handler should be outlined. -; CHECK: define internal i8* @_Z4testv.catch.1(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_I:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @_Z4testv to i8*), i8* %1, i32 1) -; CHECK: [[I_PTR:\%.+]] = bitcast i8* [[RECOVER_I]] to i32* -; CHECK: [[TMP1:\%.+]] = load i32, i32* [[I_PTR]], align 4 -; CHECK: invoke void @_Z10handle_inti(i32 [[TMP1]]) -; CHECK: to label %invoke.cont8 unwind label %[[LPAD7_LABEL:lpad[0-9]*]] -; -; CHECK: invoke.cont8: ; preds = %entry -; CHECK: ret i8* blockaddress(@_Z4testv, %try.cont) -; -; CHECK: [[LPAD7_LABEL]]:{{[ ]+}}; preds = %entry -; CHECK: [[LPAD7_VAL:\%.+]] = landingpad { i8*, i32 } -; (FIXME) The nested handler body isn't being populated yet. -; CHECK: } - -; This cleanup handler should be outlined. -; CHECK: define internal void @_Z4testv.cleanup(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_OUTER:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @_Z4testv to i8*), i8* %1, i32 2) -; CHECK: [[OUTER_PTR:\%.+]] = bitcast i8* [[RECOVER_OUTER]] to %class.Outer* -; CHECK: call void @_ZN5OuterD1Ev(%class.Outer* [[OUTER_PTR]]) -; CHECK: ret void -; CHECK: } - -; This cleanup handler should be outlined. -; CHECK: define internal void @_Z4testv.cleanup.2(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_INNER:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @_Z4testv to i8*), i8* %1, i32 3) -; CHECK: [[INNER_PTR:\%.+]] = bitcast i8* [[RECOVER_INNER]] to %class.Inner* -; CHECK: call void @_ZN5InnerD1Ev(%class.Inner* [[INNER_PTR]]) -; CHECK: ret void -; CHECK: } - - - -declare void @_ZN5OuterC1Ev(%class.Outer*) #1 - -declare i32 @__CxxFrameHandler3(...) - -declare void @_ZN5InnerC1Ev(%class.Inner*) #1 - -declare void @_Z9may_throwv() #1 - -declare void @_ZN5InnerD1Ev(%class.Inner*) #1 - -declare void @llvm.eh.begincatch(i8*, i8*) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #3 - -declare void @_Z10handle_inti(i32) #1 - -declare void @llvm.eh.endcatch() - -declare void @_ZN5OuterD1Ev(%class.Outer*) #1 - -declare void @_Z12handle_floatf(float) #1 - -declare void @_Z4donev() #1 - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { noinline noreturn nounwind } -attributes #3 = { nounwind readnone } -attributes #4 = { nounwind } -attributes #5 = { noreturn nounwind } - -!llvm.ident = !{!0} - -!0 = !{!"clang version 3.7.0 (trunk 226027)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-nested-3.ll b/llvm/test/CodeGen/WinEH/cppeh-nested-3.ll deleted file mode 100644 index 88759f406fb..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-nested-3.ll +++ /dev/null @@ -1,260 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test is based on the following code: -; -;void test() -;{ -; try { -; try { -; may_throw(); -; } catch (int i) { -; try { -; may_throw(); -; } -; catch (int j) { -; i = j; -; } -; handle_int(i); -; } -; } catch (float f) { -; handle_float(f); -; } -; done(); -;} - -; ModuleID = 'cppeh-nested-3.cpp' -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } - -$"\01??_R0M@8" = comdat any - -$"\01??_R0H@8" = comdat any - -@"\01??_7type_info@@6B@" = external constant i8* -@"\01??_R0M@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".M\00" }, comdat -@"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat - -; CHECK: define void @"\01?test@@YAXXZ"() -; CHECK: entry: -; CHECK: %i = alloca i32, align 4 -; CHECK: %j = alloca i32, align 4 -; CHECK: %f = alloca float, align 4 -; CHECK: call void (...) @llvm.localescape(i32* %j, i32* %i, float* %f) -; CHECK: invoke void @"\01?may_throw@@YAXXZ"() -; CHECK: to label %invoke.cont unwind label %[[LPAD_LABEL:lpad[0-9]*]] - -; Function Attrs: uwtable -define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - %i = alloca i32, align 4 - %j = alloca i32, align 4 - %f = alloca float, align 4 - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - br label %try.cont10 - -; CHECK: [[LPAD_LABEL]]: -; CHECK: landingpad { i8*, i32 } -; CHECK: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) -; CHECK: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*) -; CHECK: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch.2", i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch.1") -; CHECK: indirectbr i8* [[RECOVER]], [label %try.cont10, label %try.cont19] - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*) - %1 = extractvalue { i8*, i32 } %0, 0 - store i8* %1, i8** %exn.slot - %2 = extractvalue { i8*, i32 } %0, 1 - store i32 %2, i32* %ehselector.slot - br label %catch.dispatch - -; CHECK-NOT: catch.dispatch: -catch.dispatch: ; preds = %lpad - %sel = load i32, i32* %ehselector.slot - %3 = call i32 @llvm.eh.typeid.for(i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)) #3 - %matches = icmp eq i32 %sel, %3 - br i1 %matches, label %catch, label %catch.dispatch11 - -; CHECK-NOT: catch: -catch: ; preds = %catch.dispatch - %exn = load i8*, i8** %exn.slot - %4 = bitcast i32* %i to i8* - call void @llvm.eh.begincatch(i8* %exn, i8* %4) #3 - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont2 unwind label %lpad1 - -; CHECK-NOT: invoke.cont2: -invoke.cont2: ; preds = %catch - br label %try.cont - -; CHECK-NOT: lpad1: -lpad1: ; preds = %catch - %5 = landingpad { i8*, i32 } - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*) - %6 = extractvalue { i8*, i32 } %5, 0 - store i8* %6, i8** %exn.slot - %7 = extractvalue { i8*, i32 } %5, 1 - store i32 %7, i32* %ehselector.slot - br label %catch.dispatch3 - -; CHECK-NOT: catch.dispatch3: -catch.dispatch3: ; preds = %lpad1 - %sel4 = load i32, i32* %ehselector.slot - %8 = call i32 @llvm.eh.typeid.for(i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)) #3 - %matches5 = icmp eq i32 %sel4, %8 - br i1 %matches5, label %catch6, label %catch.dispatch11 - -; CHECK-NOT: catch6: -catch6: ; preds = %catch.dispatch3 - %exn7 = load i8*, i8** %exn.slot - %9 = bitcast i32* %j to i8* - call void @llvm.eh.begincatch(i8* %exn7, i8* %9) #3 - %10 = load i32, i32* %j, align 4 - store i32 %10, i32* %i, align 4 - call void @llvm.eh.endcatch() #3 - br label %try.cont - -; CHECK-NOT: try.cont: -try.cont: ; preds = %catch6, %invoke.cont2 - %11 = load i32, i32* %i, align 4 - invoke void @"\01?handle_int@@YAXH@Z"(i32 %11) - to label %invoke.cont9 unwind label %lpad8 - -; CHECK-NOT: invoke.cont9: -invoke.cont9: ; preds = %try.cont - call void @llvm.eh.endcatch() #3 - br label %try.cont10 - -try.cont10: ; preds = %invoke.cont9, %invoke.cont - br label %try.cont19 - -; CHECK-NOT: lpad8: -lpad8: ; preds = %try.cont - %12 = landingpad { i8*, i32 } - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*) - %13 = extractvalue { i8*, i32 } %12, 0 - store i8* %13, i8** %exn.slot - %14 = extractvalue { i8*, i32 } %12, 1 - store i32 %14, i32* %ehselector.slot - call void @llvm.eh.endcatch() #3 - br label %catch.dispatch11 - -; CHECK-NOT: catch.dispatch11: -catch.dispatch11: ; preds = %lpad8, %catch.dispatch3, %catch.dispatch - %sel12 = load i32, i32* %ehselector.slot - %15 = call i32 @llvm.eh.typeid.for(i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*)) #3 - %matches13 = icmp eq i32 %sel12, %15 - br i1 %matches13, label %catch14, label %eh.resume - -; CHECK-NOT: catch14: -catch14: ; preds = %catch.dispatch11 - %exn15 = load i8*, i8** %exn.slot - %16 = bitcast float* %f to i8* - call void @llvm.eh.begincatch(i8* %exn15, i8* %16) #3 - %17 = load float, float* %f, align 4 - call void @"\01?handle_float@@YAXM@Z"(float %17) - call void @llvm.eh.endcatch() #3 - br label %try.cont19 - -try.cont19: ; preds = %catch14, %try.cont10 - call void @"\01?done@@YAXXZ"() - ret void - -; CHECK-NOT: eh.resume: -eh.resume: ; preds = %lpad16, %catch.dispatch11 - %exn20 = load i8*, i8** %exn.slot - %sel21 = load i32, i32* %ehselector.slot - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn20, 0 - %lpad.val22 = insertvalue { i8*, i32 } %lpad.val, i32 %sel21, 1 - resume { i8*, i32 } %lpad.val22 -; CHECK: } -} - -; CHECK: define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_J:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0) -; CHECK: [[J_PTR:\%.+]] = bitcast i8* [[RECOVER_J]] to i32* -; CHECK: [[RECOVER_I1:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 1) -; CHECK: [[I_PTR1:\%.+]] = bitcast i8* [[RECOVER_I1]] to i32* -; CHECK: [[TMP3:\%.+]] = load i32, i32* [[J_PTR]], align 4 -; CHECK: store i32 [[TMP3]], i32* [[I_PTR1]] -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ.catch.2", %invoke.cont2) -; CHECK: } - -; CHECK: define internal i8* @"\01?test@@YAXXZ.catch.1"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_F:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 2) -; CHECK: [[F_PTR:\%.+]] = bitcast i8* [[RECOVER_F]] to float* -; CHECK: [[TMP2:\%.+]] = load float, float* [[F_PTR]], align 4 -; CHECK: call void @"\01?handle_float@@YAXM@Z"(float [[TMP2]]) -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont19) -; CHECK: } - -; CHECK: define internal i8* @"\01?test@@YAXXZ.catch.2"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_I:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 1) -; CHECK: [[I_PTR:\%.+]] = bitcast i8* [[RECOVER_I]] to i32* -; CHECK: invoke void @"\01?may_throw@@YAXXZ"() -; CHECK: to label %invoke.cont2 unwind label %[[LPAD1_LABEL:lpad[0-9]*]] -; -; CHECK: invoke.cont2: ; preds = %[[LPAD1_LABEL]], %entry -; CHECK: [[TMP1:\%.+]] = load i32, i32* [[I_PTR]], align 4 -; CHECK: invoke void @"\01?handle_int@@YAXH@Z"(i32 [[TMP1]]) -; CHECK: to label %invoke.cont9 unwind label %[[LPAD8_LABEL:lpad[0-9]*]] -; -; CHECK: [[LPAD1_LABEL]]:{{[ ]+}}; preds = %entry -; CHECK: [[LPAD1_VAL:\%.+]] = landingpad { i8*, i32 } -; CHECK: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) -; CHECK: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*) -; CHECK: [[RECOVER1:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch", i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch.1") -; CHECK: indirectbr i8* [[RECOVER1]], [label %invoke.cont2] -; -; CHECK: invoke.cont9: -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont10) -; -; CHECK: [[LPAD8_LABEL]]:{{[ ]+}}; preds = %invoke.cont2 -; CHECK: [[LPAD8_VAL:\%.+]] = landingpad { i8*, i32 } -; CHECK: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*) -; CHECK: [[RECOVER2:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0M@8" to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch.1") -; CHECK: indirectbr i8* [[RECOVER2]], [] -; -; CHECK: } - -declare void @"\01?may_throw@@YAXXZ"() #1 - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #2 - -; Function Attrs: nounwind -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #3 - -; Function Attrs: nounwind -declare void @llvm.eh.endcatch() #3 - -declare void @"\01?handle_int@@YAXH@Z"(i32) #1 - -declare void @"\01?handle_float@@YAXM@Z"(float) #1 - -declare void @"\01?done@@YAXXZ"() #1 - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nounwind readnone } -attributes #3 = { nounwind } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 (trunk 232069) (llvm/trunk 232070)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-nested-rethrow.ll b/llvm/test/CodeGen/WinEH/cppeh-nested-rethrow.ll deleted file mode 100644 index 53f532c8eb1..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-nested-rethrow.ll +++ /dev/null @@ -1,212 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test was generated from the following code. -; -; void test1() { -; try { -; try { -; throw 1; -; } catch(...) { throw; } -; } catch (...) { } -; } -; void test2() { -; try { -; throw 1; -; } catch(...) { -; try { -; throw; -; } catch (...) {} -; } -; } -; -; These two functions result in functionally equivalent code, but the last -; catch block contains a call to llvm.eh.endcatch that tripped up processing -; during development. -; -; The main purpose of this test is to verify that we can correctly -; handle the case of nested landing pads that return directly to a block in -; the parent function. - -; ModuleID = 'cppeh-nested-rethrow.cpp' -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } -%eh.CatchableType = type { i32, i32, i32, i32, i32, i32, i32 } -%eh.CatchableTypeArray.1 = type { i32, [1 x i32] } -%eh.ThrowInfo = type { i32, i32, i32, i32 } - -$"\01??_R0H@8" = comdat any - -$"_CT??_R0H@84" = comdat any - -$_CTA1H = comdat any - -$_TI1H = 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 -@__ImageBase = external constant i8 -@"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 -1, i32 0, i32 4, i32 0 }, section ".xdata", comdat -@_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableType* @"_CT??_R0H@84" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32)] }, section ".xdata", comdat -@_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableTypeArray.1* @_CTA1H to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, section ".xdata", comdat - -; CHECK-LABEL: define void @"\01?test1@@YAXXZ"() -; CHECK: entry: -; CHECK: call void (...) @llvm.localescape - -; Function Attrs: nounwind uwtable -define void @"\01?test1@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %tmp = alloca i32, align 4 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - store i32 1, i32* %tmp - %0 = bitcast i32* %tmp to i8* - invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* @_TI1H) #2 - to label %unreachable unwind label %lpad - -lpad: ; preds = %entry - %1 = landingpad { i8*, i32 } - catch i8* null - %2 = extractvalue { i8*, i32 } %1, 0 - store i8* %2, i8** %exn.slot - %3 = extractvalue { i8*, i32 } %1, 1 - store i32 %3, i32* %ehselector.slot - br label %catch - -catch: ; preds = %lpad - %exn = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn, i8* null) #1 - invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #2 - to label %unreachable unwind label %lpad1 - -lpad1: ; preds = %catch - %4 = landingpad { i8*, i32 } - catch i8* null - %5 = extractvalue { i8*, i32 } %4, 0 - store i8* %5, i8** %exn.slot - %6 = extractvalue { i8*, i32 } %4, 1 - store i32 %6, i32* %ehselector.slot - br label %catch2 - -catch2: ; preds = %lpad1 - %exn3 = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn3, i8* null) #1 - call void @llvm.eh.endcatch() #1 - br label %try.cont.4 - -; This block should not be eliminated. -; CHECK: try.cont.4: -try.cont.4: ; preds = %catch2, %try.cont - ret void - -try.cont: ; No predecessors! - br label %try.cont.4 - -unreachable: ; preds = %catch, %entry - unreachable -; CHECK: } -} - -declare void @_CxxThrowException(i8*, %eh.ThrowInfo*) - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #1 - -; Function Attrs: nounwind -declare void @llvm.eh.endcatch() #1 - -; CHECK-LABEL: define void @"\01?test2@@YAXXZ"() -; CHECK: entry: -; CHECK: call void (...) @llvm.localescape - -; Function Attrs: nounwind uwtable -define void @"\01?test2@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %tmp = alloca i32, align 4 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - store i32 1, i32* %tmp - %0 = bitcast i32* %tmp to i8* - invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* @_TI1H) #2 - to label %unreachable unwind label %lpad - -lpad: ; preds = %entry - %1 = landingpad { i8*, i32 } - catch i8* null - %2 = extractvalue { i8*, i32 } %1, 0 - store i8* %2, i8** %exn.slot - %3 = extractvalue { i8*, i32 } %1, 1 - store i32 %3, i32* %ehselector.slot - br label %catch - -catch: ; preds = %lpad - %exn = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn, i8* null) #1 - invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #2 - to label %unreachable unwind label %lpad1 - -lpad1: ; preds = %catch - %4 = landingpad { i8*, i32 } - catch i8* null - %5 = extractvalue { i8*, i32 } %4, 0 - store i8* %5, i8** %exn.slot - %6 = extractvalue { i8*, i32 } %4, 1 - store i32 %6, i32* %ehselector.slot - br label %catch2 - -catch2: ; preds = %lpad1 - %exn3 = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn3, i8* null) #1 - call void @llvm.eh.endcatch() #1 - br label %try.cont - -; This block should not be eliminated. -; CHECK: try.cont: -; The endcatch call should be eliminated. -; CHECK-NOT: call void @llvm.eh.endcatch() -try.cont: ; preds = %catch2 - call void @llvm.eh.endcatch() #1 - br label %try.cont.4 - -try.cont.4: ; preds = %try.cont - ret void - -unreachable: ; preds = %catch, %entry - unreachable -; CHECK: } -} - -; The outlined test1.catch handler should return to a valid block address. -; CHECK-LABEL: define internal i8* @"\01?test1@@YAXXZ.catch"(i8*, i8*) -; CHECK-NOT: ret i8* inttoptr (i32 1 to i8*) -; CHECK: } - -; The outlined test1.catch1 handler should not contain a return instruction. -; CHECK-LABEL: define internal i8* @"\01?test1@@YAXXZ.catch.1"(i8*, i8*) -; CHECK-NOT: ret -; CHECK: } - -; The outlined test2.catch handler should return to a valid block address. -; CHECK-LABEL: define internal i8* @"\01?test2@@YAXXZ.catch"(i8*, i8*) -; CHECK-NOT: ret i8* inttoptr (i32 1 to i8*) -; CHECK: } - -; The outlined test2.catch2 handler should not contain a return instruction. -; CHECK-LABEL: define internal i8* @"\01?test2@@YAXXZ.catch.2"(i8*, i8*) -; CHECK-NOT: ret -; CHECK: } - - -attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind } -attributes #2 = { noreturn } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 (trunk 236059)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll b/llvm/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll deleted file mode 100644 index 7b474c9d38a..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-nonalloca-frame-values.ll +++ /dev/null @@ -1,278 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test is based on the following code: -; -; struct SomeData { -; int a; -; int b; -; }; -; -; void may_throw(); -; void does_not_throw(int i); -; void dump(int *, int, SomeData&); -; -; void test() { -; int NumExceptions = 0; -; int ExceptionVal[10]; -; SomeData Data = { 0, 0 }; -; -; for (int i = 0; i < 10; ++i) { -; try { -; may_throw(); -; Data.a += i; -; } -; catch (int e) { -; ExceptionVal[NumExceptions] = e; -; ++NumExceptions; -; if (e == i) -; Data.b += e; -; else -; Data.a += e; -; } -; does_not_throw(NumExceptions); -; } -; dump(ExceptionVal, NumExceptions, Data); -; } -; -; Unlike the cppeh-frame-vars.ll test, this test was generated using -O2 -; optimization, which results in non-alloca values being used in the -; catch handler. - -; ModuleID = 'cppeh-frame-vars.cpp' -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } -%struct.SomeData = type { i32, i32 } - -$"\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 - -; The function entry should be rewritten like this. -; CHECK: define void @"\01?test@@YAXXZ"() -; CHECK: entry: -; CHECK: [[NUMEXCEPTIONS_REGMEM:\%.+]] = alloca i32 -; CHECK: [[I_REGMEM:\%.+]] = alloca i32 -; CHECK: [[B_REGMEM:\%.+]] = alloca i32* -; CHECK: [[A_REGMEM:\%.+]] = alloca i32* -; CHECK: [[E_PTR:\%.+]] = alloca i32, align 4 -; CHECK: [[EXCEPTIONVAL:\%.+]] = alloca [10 x i32], align 16 -; CHECK: [[DATA_PTR:\%.+]] = alloca i64, align 8 -; CHECK: [[TMPCAST:\%.+]] = bitcast i64* [[DATA_PTR]] to %struct.SomeData* -; CHECK: [[TMP:\%.+]] = bitcast [10 x i32]* [[EXCEPTIONVAL]] to i8* -; CHECK: call void @llvm.lifetime.start(i64 40, i8* [[TMP]]) -; CHECK: store i64 0, i64* [[DATA_PTR]], align 8 -; CHECK: [[A_PTR:\%.+]] = bitcast i64* [[DATA_PTR]] to i32* -; CHECK: store i32* [[A_PTR]], i32** [[A_REGMEM]] -; CHECK: [[B_PTR:\%.+]] = getelementptr inbounds %struct.SomeData, %struct.SomeData* [[TMPCAST]], i64 0, i32 1 -; CHECK: store i32* [[B_PTR]], i32** [[B_REGMEM]] -; CHECK: call void (...) @llvm.localescape(i32* %e, i32* %NumExceptions.020.reg2mem, [10 x i32]* [[EXCEPTIONVAL]], i32* %inc.reg2mem, i32* [[I_REGMEM]], i32** [[A_REGMEM]], i32** [[B_REGMEM]]) -; CHECK: br label %for.body - -; Function Attrs: uwtable -define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %e = alloca i32, align 4 - %ExceptionVal = alloca [10 x i32], align 16 - %Data = alloca i64, align 8 - %tmpcast = bitcast i64* %Data to %struct.SomeData* - %0 = bitcast [10 x i32]* %ExceptionVal to i8* - call void @llvm.lifetime.start(i64 40, i8* %0) #1 - store i64 0, i64* %Data, align 8 - %a = bitcast i64* %Data to i32* - %b = getelementptr inbounds %struct.SomeData, %struct.SomeData* %tmpcast, i64 0, i32 1 - br label %for.body - -; CHECK: for.body: -; CHECK: [[NUMEXCEPTIONS_PHI:\%.*]] = phi i32 [ 0, %entry ], [ {{\%NumExceptions.*}}, %try.cont ] -; CHECK: [[I_PHI:\%.*]] = phi i32 [ 0, %entry ], [ {{\%inc.*}}, %try.cont ] -; CHECK: store i32 [[I_PHI]], i32* [[I_REGMEM]] -; CHECK: store i32 [[NUMEXCEPTIONS_PHI]], i32* [[NUMEXCEPTIONS_REGMEM]] -; CHECK: invoke void @"\01?may_throw@@YAXXZ"() -for.body: ; preds = %entry, %try.cont - %NumExceptions.020 = phi i32 [ 0, %entry ], [ %NumExceptions.1, %try.cont ] - %i.019 = phi i32 [ 0, %entry ], [ %inc5, %try.cont ] - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont unwind label %lpad - -; CHECK: invoke.cont: ; preds = %for.body -; CHECK: [[A_RELOAD:\%.+]] = load i32*, i32** [[A_REGMEM]] -; CHECK: [[TMP1:\%.+]] = load i32, i32* [[A_RELOAD]], align 8 -; CHECK: [[I_RELOAD:\%.+]] = load i32, i32* [[I_REGMEM]] -; CHECK: [[ADD:\%.+]] = add nsw i32 [[TMP1]], [[I_RELOAD]] -; CHECK: [[A_RELOAD1:\%.+]] = load i32*, i32** [[A_REGMEM]] -; CHECK: [[NUMEXCEPTIONS_RELOAD:\%.+]] = load i32, i32* [[NUMEXCEPTIONS_REGMEM]] -; CHECK: br label %try.cont -invoke.cont: ; preds = %for.body - %1 = load i32, i32* %a, align 8, !tbaa !2 - %add = add nsw i32 %1, %i.019 - store i32 %add, i32* %a, align 8, !tbaa !2 - br label %try.cont - -; CHECK: [[LPAD_LABEL:lpad[0-9]*]]:{{[ ]+}}; preds = %for.body -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) -; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch") -; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %[[SPLIT_RECOVER_BB:.*]]] - -lpad: ; preds = %for.body - %2 = landingpad { i8*, i32 } - catch i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) - %3 = extractvalue { i8*, i32 } %2, 1 - %4 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*)) #1 - %matches = icmp eq i32 %3, %4 - br i1 %matches, label %catch, label %eh.resume - -; CHECK-NOT: catch: - -catch: ; preds = %lpad - %5 = extractvalue { i8*, i32 } %2, 0 - %e.i8 = bitcast i32* %e to i8* - call void @llvm.eh.begincatch(i8* %5, i8* %e.i8) #1 - %tmp8 = load i32, i32* %e, align 4, !tbaa !7 - %idxprom = sext i32 %NumExceptions.020 to i64 - %arrayidx = getelementptr inbounds [10 x i32], [10 x i32]* %ExceptionVal, i64 0, i64 %idxprom - store i32 %tmp8, i32* %arrayidx, align 4, !tbaa !7 - %inc = add nsw i32 %NumExceptions.020, 1 - %cmp1 = icmp eq i32 %tmp8, %i.019 - br i1 %cmp1, label %if.then, label %if.else - -if.then: ; preds = %catch - %tmp9 = load i32, i32* %b, align 4, !tbaa !8 - %add2 = add nsw i32 %tmp9, %i.019 - store i32 %add2, i32* %b, align 4, !tbaa !8 - br label %if.end - -; CHECK-NOT: if.else: - -if.else: ; preds = %catch - %tmp10 = load i32, i32* %a, align 8, !tbaa !2 - %add4 = add nsw i32 %tmp10, %tmp8 - store i32 %add4, i32* %a, align 8, !tbaa !2 - br label %if.end - -; CHECK-NOT: if.end: -; CHECK: [[SPLIT_RECOVER_BB]]: -; CHECK: [[INC_RELOAD:\%.*]] = load i32, i32* -; CHECK: br label %try.cont - -if.end: ; preds = %if.else, %if.then - tail call void @llvm.eh.endcatch() #1 - br label %try.cont - -; CHECK: try.cont:{{[ ]+}}; preds = %[[SPLIT_RECOVER_BB]], %invoke.cont -; CHECK: [[NUMEXCEPTIONS_PHI:\%.*]] = phi i32 [ [[NUMEXCEPTIONS_RELOAD]], %invoke.cont ], [ [[INC_RELOAD]], %[[SPLIT_RECOVER_BB]] ] -; CHECK: tail call void @"\01?does_not_throw@@YAXH@Z"(i32 [[NUMEXCEPTIONS_PHI]]) -; CHECK: [[I_RELOAD:\%.+]] = load i32, i32* [[I_REGMEM]] -; CHECK: [[INC:\%.+]] = add nuw nsw i32 [[I_RELOAD]], 1 -; CHECK: [[CMP:\%.+]] = icmp slt i32 [[INC]], 10 -; CHECK: br i1 [[CMP]], label %for.body, label %for.end - -try.cont: ; preds = %if.end, %invoke.cont - %NumExceptions.1 = phi i32 [ %NumExceptions.020, %invoke.cont ], [ %inc, %if.end ] - tail call void @"\01?does_not_throw@@YAXH@Z"(i32 %NumExceptions.1) - %inc5 = add nuw nsw i32 %i.019, 1 - %cmp = icmp slt i32 %inc5, 10 - br i1 %cmp, label %for.body, label %for.end - -for.end: ; preds = %try.cont - %NumExceptions.1.lcssa = phi i32 [ %NumExceptions.1, %try.cont ] - %arraydecay = getelementptr inbounds [10 x i32], [10 x i32]* %ExceptionVal, i64 0, i64 0 - call void @"\01?dump@@YAXPEAHHAEAUSomeData@@@Z"(i32* %arraydecay, i32 %NumExceptions.1.lcssa, %struct.SomeData* dereferenceable(8) %tmpcast) - call void @llvm.lifetime.end(i64 40, i8* %0) #1 - ret void - -eh.resume: ; preds = %lpad - %.lcssa = phi { i8*, i32 } [ %2, %lpad ] - resume { i8*, i32 } %.lcssa -} - -; The following catch handler should be outlined. -; CHECK: define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*) -; CHECK: entry: -; CHECK: [[RECOVER_E:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0) -; CHECK: [[E_PTR:\%.+]] = bitcast i8* [[RECOVER_E]] to i32* -; CHECK: [[RECOVER_NUMEXCEPTIONS:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 1) -; CHECK: [[NUMEXCEPTIONS_REGMEM:\%.+]] = bitcast i8* [[RECOVER_NUMEXCEPTIONS]] to i32* -; CHECK: [[RECOVER_EXCEPTIONVAL:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 2) -; CHECK: [[EXCEPTIONVAL:\%.+]] = bitcast i8* [[RECOVER_EXCEPTIONVAL]] to [10 x i32]* -; CHECK: [[RECOVER_INC:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 3) -; CHECK: [[INC_REGMEM:\%.+]] = bitcast i8* [[RECOVER_INC]] to i32* -; CHECK: [[RECOVER_I:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 4) -; CHECK: [[I_REGMEM:\%.+]] = bitcast i8* [[RECOVER_I]] to i32* -; CHECK: [[RECOVER_A:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 5) -; CHECK: [[A_REGMEM:\%.+]] = bitcast i8* [[RECOVER_A]] to i32** -; CHECK: [[RECOVER_B:\%.+]] = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 6) -; CHECK: [[B_REGMEM:\%.+]] = bitcast i8* [[RECOVER_B]] to i32** -; CHECK: [[E_I8PTR:\%.+]] = bitcast i32* [[E_PTR]] to i8* -; CHECK: [[TMP:\%.+]] = load i32, i32* [[E_PTR]], align 4 -; CHECK: [[NUMEXCEPTIONS_RELOAD:\%.+]] = load i32, i32* [[NUMEXCEPTIONS_REGMEM]] -; CHECK: [[IDXPROM:\%.+]] = sext i32 [[NUMEXCEPTIONS_RELOAD]] to i64 -; CHECK: [[ARRAYIDX:\%.+]] = getelementptr inbounds [10 x i32], [10 x i32]* [[EXCEPTIONVAL]], i64 0, i64 [[IDXPROM]] -; CHECK: store i32 [[TMP]], i32* [[ARRAYIDX]], align 4 -; CHECK: [[NUMEXCEPTIONS_RELOAD:\%.+]] = load i32, i32* [[NUMEXCEPTIONS_REGMEM]] -; CHECK: [[INC:\%.+]] = add nsw i32 [[NUMEXCEPTIONS_RELOAD]], 1 -; CHECK: [[CMP:\%.+]] = icmp eq i32 [[TMP]], [[I_RELOAD]] -; CHECK: br i1 [[CMP]], label %if.then, label %if.else -; -; CHECK: if.then:{{[ ]+}}; preds = %entry -; CHECK: [[B_RELOAD:\%.+]] = load i32*, i32** [[B_REGMEM]] -; CHECK: [[TMP1:\%.+]] = load i32, i32* [[B_RELOAD]], align 4 -; CHECK: [[I_RELOAD:\%.+]] = load i32, i32* [[I_REGMEM]] -; CHECK: [[ADD:\%.+]] = add nsw i32 [[TMP1]], [[I_RELOAD]] -; CHECK: [[B_RELOAD:\%.+]] = load i32*, i32** [[B_REGMEM]] -; CHECK: store i32 [[ADD]], i32* [[B_RELOAD]], align 4 -; CHECK: br label %if.end -; -; CHECK: if.else:{{[ ]+}}; preds = %entry -; CHECK: [[A_RELOAD:\%.+]] = load i32*, i32** [[A_REGMEM]] -; CHECK: [[TMP2:\%.+]] = load i32, i32* [[A_RELOAD]], align 8 -; CHECK: [[ADD2:\%.+]] = add nsw i32 [[TMP2]], [[TMP]] -; CHECK: [[A_RELOAD:\%.+]] = load i32*, i32** [[A_REGMEM]] -; CHECK: store i32 [[ADD2]], i32* [[A_RELOAD]], align 8 -; CHECK: br label %if.end -; -; CHECK: if.end:{{[ ]+}}; preds = %if.else, %if.then -; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %[[SPLIT_RECOVER_BB]]) -; CHECK: } - -; Function Attrs: nounwind -declare void @llvm.lifetime.start(i64, i8* nocapture) #1 - -declare void @"\01?may_throw@@YAXXZ"() #2 - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #3 - -declare void @llvm.eh.begincatch(i8*, i8*) - -declare void @llvm.eh.endcatch() - -declare void @"\01?does_not_throw@@YAXH@Z"(i32) #2 - -declare void @"\01?dump@@YAXPEAHHAEAUSomeData@@@Z"(i32*, i32, %struct.SomeData* dereferenceable(8)) #2 - -; Function Attrs: nounwind -declare void @llvm.lifetime.end(i64, i8* nocapture) #1 - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind } -attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #3 = { nounwind readnone } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 (trunk 228868)"} -!2 = !{!3, !4, i64 0} -!3 = !{!"?AUSomeData@@", !4, i64 0, !4, i64 4} -!4 = !{!"int", !5, i64 0} -!5 = !{!"omnipotent char", !6, i64 0} -!6 = !{!"Simple C/C++ TBAA"} -!7 = !{!4, !4, i64 0} -!8 = !{!3, !4, i64 4} diff --git a/llvm/test/CodeGen/WinEH/cppeh-shared-empty-catch.ll b/llvm/test/CodeGen/WinEH/cppeh-shared-empty-catch.ll deleted file mode 100644 index 87ccc9d9ded..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-shared-empty-catch.ll +++ /dev/null @@ -1,110 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test is based on the following source, built with -O2 -; -; void f() { -; try { -; g(); -; try { -; throw; -; } catch (int) { -; } -; } catch (...) { -; } -; } -; - -; ModuleID = '<stdin>' -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } -%eh.CatchHandlerType = type { i32, i8* } -%eh.ThrowInfo = type { i32, i32, i32, i32 } - -$"\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" - -; CHECK-LABEL: define void @"\01?f@@YAXXZ"() -; CHECK: entry: -; CHECK: call void (...) @llvm.localescape() -; CHECK: invoke void @"\01?g@@YAXXZ"() - -; Function Attrs: nounwind -define void @"\01?f@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - invoke void @"\01?g@@YAXXZ"() - to label %invoke.cont unwind label %lpad - -; CHECK-LABEL: invoke.cont: -; CHECK: invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) -; CHECK: to label %unreachable unwind label %[[LPAD1_LABEL:lpad[0-9]+]] - -invoke.cont: ; preds = %entry - invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #4 - to label %unreachable unwind label %lpad1 - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* null - %1 = extractvalue { i8*, i32 } %0, 0 - br label %catch2 - -; Note: Even though this landing pad has two catch clauses, it only has one action because both -; handlers do the same thing. -; CHECK: [[LPAD1_LABEL]]: -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0 -; CHECK-NEXT: catch i8* null -; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @"\01?f@@YAXXZ.catch") -; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont4] - -lpad1: ; preds = %invoke.cont - %2 = landingpad { i8*, i32 } - catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0 - catch i8* null - %3 = extractvalue { i8*, i32 } %2, 0 - br label %catch2 - -catch2: ; preds = %lpad1, %lpad - %exn.slot.0 = phi i8* [ %3, %lpad1 ], [ %1, %lpad ] - tail call void @llvm.eh.begincatch(i8* %exn.slot.0, i8* null) #3 - tail call void @llvm.eh.endcatch() #3 - br label %try.cont4 - -try.cont4: ; preds = %catch, %catch2 - ret void - -unreachable: ; preds = %invoke.cont - unreachable - -; CHECK: } -} - -declare void @"\01?g@@YAXXZ"() #1 - -declare i32 @__CxxFrameHandler3(...) - -declare void @_CxxThrowException(i8*, %eh.ThrowInfo*) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #2 - -; Function Attrs: nounwind -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #3 - -; Function Attrs: nounwind -declare void @llvm.eh.endcatch() #3 - -attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nounwind readnone } -attributes #3 = { nounwind } -attributes #4 = { noreturn } - -!llvm.ident = !{!0} - -!0 = !{!"clang version 3.7.0 (trunk 235112) (llvm/trunk 235121)"} diff --git a/llvm/test/CodeGen/WinEH/cppeh-similar-catch-blocks.ll b/llvm/test/CodeGen/WinEH/cppeh-similar-catch-blocks.ll deleted file mode 100644 index 09213536815..00000000000 --- a/llvm/test/CodeGen/WinEH/cppeh-similar-catch-blocks.ll +++ /dev/null @@ -1,394 +0,0 @@ -; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s - -; This test is based on the following code: -; -; int main(void) { -; try { -; try { -; throw 'a'; -; } catch (char c) { -; printf("%c\n", c); -; } -; throw 1; -; } catch(int x) { -; printf("%d\n", x); -; } catch(...) { -; printf("...\n"); -; } -; try { -; try { -; throw 'b'; -; } catch (char c) { -; printf("%c\n", c); -; } -; throw 2; -; } catch(int x) { -; printf("%d\n", x); -; } catch (char c) { -; printf("%c\n", c); -; } catch(...) { -; printf("...\n"); -; } -; return 0; -; } - -; This test is just checking for failures in processing the IR. -; Extensive handler matching is not required. - -; ModuleID = 'cppeh-similar-catch-blocks.cpp' -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } -%eh.CatchHandlerType = type { i32, i8* } -%eh.CatchableType = type { i32, i32, i32, i32, i32, i32, i32 } -%eh.CatchableTypeArray.1 = type { i32, [1 x i32] } -%eh.ThrowInfo = type { i32, i32, i32, i32 } - -$"\01??_R0H@8" = comdat any - -$"\01??_R0D@8" = comdat any - -$"_CT??_R0D@81" = comdat any - -$_CTA1D = comdat any - -$_TI1D = comdat any - -$"\01??_C@_03PJCJOCBM@?$CFc?6?$AA@" = comdat any - -$"_CT??_R0H@84" = comdat any - -$_CTA1H = comdat any - -$_TI1H = comdat any - -$"\01??_C@_04MPPNMCOK@?4?4?4?6?$AA@" = comdat any - -$"\01??_C@_03PMGGPEJJ@?$CFd?6?$AA@" = 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" -@"\01??_R0D@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".D\00" }, comdat -@llvm.eh.handlertype.D.0 = private unnamed_addr constant %eh.CatchHandlerType { i32 0, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0D@8" to i8*) }, section "llvm.metadata" -@__ImageBase = external constant i8 -@"_CT??_R0D@81" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor2* @"\01??_R0D@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 -1, i32 0, i32 1, i32 0 }, section ".xdata", comdat -@_CTA1D = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableType* @"_CT??_R0D@81" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32)] }, section ".xdata", comdat -@_TI1D = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableTypeArray.1* @_CTA1D to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, section ".xdata", comdat -@"\01??_C@_03PJCJOCBM@?$CFc?6?$AA@" = linkonce_odr unnamed_addr constant [4 x i8] c"%c\0A\00", comdat, align 1 -@"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 -1, i32 0, i32 4, i32 0 }, section ".xdata", comdat -@_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableType* @"_CT??_R0H@84" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32)] }, section ".xdata", comdat -@_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableTypeArray.1* @_CTA1H to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, section ".xdata", comdat -@"\01??_C@_04MPPNMCOK@?4?4?4?6?$AA@" = linkonce_odr unnamed_addr constant [5 x i8] c"...\0A\00", comdat, align 1 -@"\01??_C@_03PMGGPEJJ@?$CFd?6?$AA@" = linkonce_odr unnamed_addr constant [4 x i8] c"%d\0A\00", comdat, align 1 - -; This is just a minimal check to verify that main was handled by WinEHPrepare. -; CHECK: define i32 @main() -; CHECK: entry: -; CHECK: call void (...) @llvm.localescape(i32* [[X_PTR:\%.+]], i32* [[X2_PTR:\%.+]], i8* [[C2_PTR:\%.+]], i8* [[C3_PTR:\%.+]], i8* [[C_PTR:\%.+]]) -; CHECK: invoke void @_CxxThrowException -; CHECK: } - -; Function Attrs: uwtable -define i32 @main() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %retval = alloca i32, align 4 - %tmp = alloca i8, align 1 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - %c = alloca i8, align 1 - %tmp3 = alloca i32, align 4 - %x = alloca i32, align 4 - %tmp20 = alloca i8, align 1 - %c28 = alloca i8, align 1 - %tmp34 = alloca i32, align 4 - %c48 = alloca i8, align 1 - %x56 = alloca i32, align 4 - store i32 0, i32* %retval - store i8 97, i8* %tmp - invoke void @_CxxThrowException(i8* %tmp, %eh.ThrowInfo* @_TI1D) #4 - to label %unreachable unwind label %lpad - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch %eh.CatchHandlerType* @llvm.eh.handlertype.D.0 - catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0 - catch i8* null - %1 = extractvalue { i8*, i32 } %0, 0 - store i8* %1, i8** %exn.slot - %2 = extractvalue { i8*, i32 } %0, 1 - store i32 %2, i32* %ehselector.slot - br label %catch.dispatch - -catch.dispatch: ; preds = %lpad - %sel = load i32, i32* %ehselector.slot - %3 = call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.D.0 to i8*)) #2 - %matches = icmp eq i32 %sel, %3 - br i1 %matches, label %catch, label %catch.dispatch5 - -catch: ; preds = %catch.dispatch - %exn = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn, i8* %c) #2 - %4 = load i8, i8* %c, align 1 - %conv = sext i8 %4 to i32 - %call = invoke i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01??_C@_03PJCJOCBM@?$CFc?6?$AA@", i32 0, i32 0), i32 %conv) - to label %invoke.cont unwind label %lpad2 - -invoke.cont: ; preds = %catch - call void @llvm.eh.endcatch() #2 - br label %try.cont - -try.cont: ; preds = %invoke.cont - store i32 1, i32* %tmp3 - %5 = bitcast i32* %tmp3 to i8* - invoke void @_CxxThrowException(i8* %5, %eh.ThrowInfo* @_TI1H) #4 - to label %unreachable unwind label %lpad4 - -lpad2: ; preds = %catch - %6 = landingpad { i8*, i32 } - catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0 - catch i8* null - %7 = extractvalue { i8*, i32 } %6, 0 - store i8* %7, i8** %exn.slot - %8 = extractvalue { i8*, i32 } %6, 1 - store i32 %8, i32* %ehselector.slot - call void @llvm.eh.endcatch() #2 - br label %catch.dispatch5 - -lpad4: ; preds = %try.cont - %9 = landingpad { i8*, i32 } - catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0 - catch i8* null - %10 = extractvalue { i8*, i32 } %9, 0 - store i8* %10, i8** %exn.slot - %11 = extractvalue { i8*, i32 } %9, 1 - store i32 %11, i32* %ehselector.slot - br label %catch.dispatch5 - -catch.dispatch5: ; preds = %lpad4, %lpad2, %catch.dispatch - %sel6 = load i32, i32* %ehselector.slot - %12 = call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*)) #2 - %matches7 = icmp eq i32 %sel6, %12 - br i1 %matches7, label %catch13, label %catch8 - -catch13: ; preds = %catch.dispatch5 - %exn14 = load i8*, i8** %exn.slot - %13 = bitcast i32* %x to i8* - call void @llvm.eh.begincatch(i8* %exn14, i8* %13) #2 - %14 = load i32, i32* %x, align 4 - %call18 = invoke i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01??_C@_03PMGGPEJJ@?$CFd?6?$AA@", i32 0, i32 0), i32 %14) - to label %invoke.cont17 unwind label %lpad16 - -invoke.cont17: ; preds = %catch13 - call void @llvm.eh.endcatch() #2 - br label %try.cont19 - -try.cont19: ; preds = %invoke.cont17, %invoke.cont11 - store i8 98, i8* %tmp20 - invoke void @_CxxThrowException(i8* %tmp20, %eh.ThrowInfo* @_TI1D) #4 - to label %unreachable unwind label %lpad21 - -catch8: ; preds = %catch.dispatch5 - %exn9 = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn9, i8* null) #2 - %call12 = invoke i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @"\01??_C@_04MPPNMCOK@?4?4?4?6?$AA@", i32 0, i32 0)) - to label %invoke.cont11 unwind label %lpad10 - -invoke.cont11: ; preds = %catch8 - call void @llvm.eh.endcatch() #2 - br label %try.cont19 - -lpad10: ; preds = %catch8 - %15 = landingpad { i8*, i32 } - cleanup - %16 = extractvalue { i8*, i32 } %15, 0 - store i8* %16, i8** %exn.slot - %17 = extractvalue { i8*, i32 } %15, 1 - store i32 %17, i32* %ehselector.slot - call void @llvm.eh.endcatch() #2 - br label %eh.resume - -lpad16: ; preds = %catch13 - %18 = landingpad { i8*, i32 } - cleanup - %19 = extractvalue { i8*, i32 } %18, 0 - store i8* %19, i8** %exn.slot - %20 = extractvalue { i8*, i32 } %18, 1 - store i32 %20, i32* %ehselector.slot - call void @llvm.eh.endcatch() #2 - br label %eh.resume - -lpad21: ; preds = %try.cont19 - %21 = landingpad { i8*, i32 } - catch i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.D.0 to i8*) - catch i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*) - catch i8* null - %22 = extractvalue { i8*, i32 } %21, 0 - store i8* %22, i8** %exn.slot - %23 = extractvalue { i8*, i32 } %21, 1 - store i32 %23, i32* %ehselector.slot - br label %catch.dispatch22 - -catch.dispatch22: ; preds = %lpad21 - %sel23 = load i32, i32* %ehselector.slot - %24 = call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.D.0 to i8*)) #2 - %matches24 = icmp eq i32 %sel23, %24 - br i1 %matches24, label %catch25, label %catch.dispatch36 - -catch25: ; preds = %catch.dispatch22 - %exn26 = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn26, i8* %c28) #2 - %25 = load i8, i8* %c28, align 1 - %conv29 = sext i8 %25 to i32 - %call32 = invoke i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01??_C@_03PJCJOCBM@?$CFc?6?$AA@", i32 0, i32 0), i32 %conv29) - to label %invoke.cont31 unwind label %lpad30 - -invoke.cont31: ; preds = %catch25 - call void @llvm.eh.endcatch() #2 - br label %try.cont33 - -try.cont33: ; preds = %invoke.cont31 - store i32 2, i32* %tmp34 - %26 = bitcast i32* %tmp34 to i8* - invoke void @_CxxThrowException(i8* %26, %eh.ThrowInfo* @_TI1H) #4 - to label %unreachable unwind label %lpad35 - -lpad30: ; preds = %catch25 - %27 = landingpad { i8*, i32 } - catch i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*) - catch i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.D.0 to i8*) - catch i8* null - %28 = extractvalue { i8*, i32 } %27, 0 - store i8* %28, i8** %exn.slot - %29 = extractvalue { i8*, i32 } %27, 1 - store i32 %29, i32* %ehselector.slot - call void @llvm.eh.endcatch() #2 - br label %catch.dispatch36 - -lpad35: ; preds = %try.cont33 - %30 = landingpad { i8*, i32 } - catch i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*) - catch i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.D.0 to i8*) - catch i8* null - %31 = extractvalue { i8*, i32 } %30, 0 - store i8* %31, i8** %exn.slot - %32 = extractvalue { i8*, i32 } %30, 1 - store i32 %32, i32* %ehselector.slot - br label %catch.dispatch36 - -catch.dispatch36: ; preds = %lpad35, %lpad30, %catch.dispatch22 - %sel37 = load i32, i32* %ehselector.slot - %33 = call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*)) #2 - %matches38 = icmp eq i32 %sel37, %33 - br i1 %matches38, label %catch53, label %catch.fallthrough - -catch53: ; preds = %catch.dispatch36 - %exn54 = load i8*, i8** %exn.slot - %34 = bitcast i32* %x56 to i8* - call void @llvm.eh.begincatch(i8* %exn54, i8* %34) #2 - %35 = load i32, i32* %x56, align 4 - %call59 = invoke i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01??_C@_03PMGGPEJJ@?$CFd?6?$AA@", i32 0, i32 0), i32 %35) - to label %invoke.cont58 unwind label %lpad57 - -invoke.cont58: ; preds = %catch53 - call void @llvm.eh.endcatch() #2 - br label %try.cont60 - -try.cont60: ; preds = %invoke.cont58, %invoke.cont51, %invoke.cont43 - ret i32 0 - -catch.fallthrough: ; preds = %catch.dispatch36 - %36 = call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.D.0 to i8*)) #2 - %matches39 = icmp eq i32 %sel37, %36 - br i1 %matches39, label %catch45, label %catch40 - -catch45: ; preds = %catch.fallthrough - %exn46 = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn46, i8* %c48) #2 - %37 = load i8, i8* %c48, align 1 - %conv49 = sext i8 %37 to i32 - %call52 = invoke i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"\01??_C@_03PJCJOCBM@?$CFc?6?$AA@", i32 0, i32 0), i32 %conv49) - to label %invoke.cont51 unwind label %lpad50 - -invoke.cont51: ; preds = %catch45 - call void @llvm.eh.endcatch() #2 - br label %try.cont60 - -catch40: ; preds = %catch.fallthrough - %exn41 = load i8*, i8** %exn.slot - call void @llvm.eh.begincatch(i8* %exn41, i8* null) #2 - %call44 = invoke i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @"\01??_C@_04MPPNMCOK@?4?4?4?6?$AA@", i32 0, i32 0)) - to label %invoke.cont43 unwind label %lpad42 - -invoke.cont43: ; preds = %catch40 - call void @llvm.eh.endcatch() #2 - br label %try.cont60 - -lpad42: ; preds = %catch40 - %38 = landingpad { i8*, i32 } - cleanup - %39 = extractvalue { i8*, i32 } %38, 0 - store i8* %39, i8** %exn.slot - %40 = extractvalue { i8*, i32 } %38, 1 - store i32 %40, i32* %ehselector.slot - call void @llvm.eh.endcatch() #2 - br label %eh.resume - -lpad50: ; preds = %catch45 - %41 = landingpad { i8*, i32 } - cleanup - %42 = extractvalue { i8*, i32 } %41, 0 - store i8* %42, i8** %exn.slot - %43 = extractvalue { i8*, i32 } %41, 1 - store i32 %43, i32* %ehselector.slot - call void @llvm.eh.endcatch() #2 - br label %eh.resume - -lpad57: ; preds = %catch53 - %44 = landingpad { i8*, i32 } - cleanup - %45 = extractvalue { i8*, i32 } %44, 0 - store i8* %45, i8** %exn.slot - %46 = extractvalue { i8*, i32 } %44, 1 - store i32 %46, i32* %ehselector.slot - call void @llvm.eh.endcatch() #2 - br label %eh.resume - -eh.resume: ; preds = %lpad57, %lpad50, %lpad42, %lpad16, %lpad10 - %exn61 = load i8*, i8** %exn.slot - %sel62 = load i32, i32* %ehselector.slot - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn61, 0 - %lpad.val63 = insertvalue { i8*, i32 } %lpad.val, i32 %sel62, 1 - resume { i8*, i32 } %lpad.val63 - -unreachable: ; preds = %try.cont33, %try.cont19, %try.cont, %entry - unreachable -} - -declare void @_CxxThrowException(i8*, %eh.ThrowInfo*) - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #1 - -; Function Attrs: nounwind -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #2 - -declare i32 @printf(i8*, ...) #3 - -; Function Attrs: nounwind -declare void @llvm.eh.endcatch() #2 - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { nounwind readnone } -attributes #2 = { nounwind } -attributes #3 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #4 = { noreturn } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 (trunk 235214) (llvm/trunk 235213)"} diff --git a/llvm/test/CodeGen/WinEH/seh-catch-all.ll b/llvm/test/CodeGen/WinEH/seh-catch-all.ll deleted file mode 100644 index 1255496f78f..00000000000 --- a/llvm/test/CodeGen/WinEH/seh-catch-all.ll +++ /dev/null @@ -1,59 +0,0 @@ -; RUN: opt -S -winehprepare -mtriple=x86_64-pc-windows-msvc < %s | FileCheck %s -; RUN: opt -S -winehprepare -mtriple=x86_64-pc-windows-coreclr < %s | FileCheck %s - -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" - -@str.__except = internal unnamed_addr constant [9 x i8] c"__except\00", align 1 - -; Function Attrs: uwtable - -declare i32 @puts(i8*) - -define void @may_crash() { -entry: - store volatile i32 42, i32* null, align 4 - ret void -} - -declare i32 @__C_specific_handler(...) - -; Function Attrs: nounwind readnone -declare i8* @llvm.frameaddress(i32) - -; Function Attrs: uwtable -define void @seh_catch_all() personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) { -entry: - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - invoke void @may_crash() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - br label %__try.cont - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* null - %1 = extractvalue { i8*, i32 } %0, 0 - store i8* %1, i8** %exn.slot - %2 = extractvalue { i8*, i32 } %0, 1 - store i32 %2, i32* %ehselector.slot - br label %__except - -__except: ; preds = %lpad - %call = call i32 @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @str.__except, i32 0, i32 0)) - br label %__try.cont - -__try.cont: ; preds = %__except, %invoke.cont - ret void -} - -; CHECK-LABEL: define void @seh_catch_all() -; CHECK: landingpad -; CHECK-NEXT: catch i8* null -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@seh_catch_all, %lpad.split)) -; CHECK-NEXT: indirectbr -; -; CHECK: lpad.split: -; CHECK-NOT: extractvalue -; CHECK: call i32 @puts diff --git a/llvm/test/CodeGen/WinEH/seh-exception-code.ll b/llvm/test/CodeGen/WinEH/seh-exception-code.ll deleted file mode 100644 index acb3d5c5e47..00000000000 --- a/llvm/test/CodeGen/WinEH/seh-exception-code.ll +++ /dev/null @@ -1,66 +0,0 @@ -; RUN: opt -winehprepare -S < %s | FileCheck %s - -; WinEHPrepare was crashing during phi demotion. - -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc18.0.0" - -declare i32 @__C_specific_handler(...) - -@str = linkonce_odr unnamed_addr constant [16 x i8] c"caught it! %lx\0A\00", align 1 - -; Function Attrs: nounwind uwtable -declare void @maycrash() - -; Function Attrs: nounwind -declare i32 @printf(i8* nocapture readonly, ...) - -; Function Attrs: nounwind uwtable -define void @doit() personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) { -entry: - invoke void @maycrash() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - invoke void @maycrash() - to label %__try.cont unwind label %lpad.1 - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* null - %1 = extractvalue { i8*, i32 } %0, 0 - br label %__except - -lpad.1: ; preds = %invoke.cont, %lpad - %2 = landingpad { i8*, i32 } - catch i8* null - %3 = extractvalue { i8*, i32 } %2, 0 - br label %__except - -__except: ; preds = %lpad, %lpad.1 - %exn.slot.0 = phi i8* [ %3, %lpad.1 ], [ %1, %lpad ] - %4 = ptrtoint i8* %exn.slot.0 to i64 - %5 = trunc i64 %4 to i32 - %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @str, i64 0, i64 0), i32 %5) - br label %__try.cont - -__try.cont: ; preds = %invoke.cont, %__except - ret void -} - -; CHECK-LABEL: define void @doit() -; CHECK: landingpad -; CHECK: indirectbr i8* %{{[^,]*}}, [label %[[except_split1:.*]]] -; CHECK: [[except_split1]]: -; CHECK: call i32 @llvm.eh.exceptioncode.old() -; CHECK: br label %__except -; -; CHECK: landingpad -; CHECK: indirectbr i8* %{{[^,]*}}, [label %[[except_split2:.*]]] -; CHECK: [[except_split2]]: -; CHECK: call i32 @llvm.eh.exceptioncode.old() -; CHECK: br label %__except -; -; CHECK: __except: -; CHECK: phi -; CHECK: call i32 (i8*, ...) @printf diff --git a/llvm/test/CodeGen/WinEH/seh-exception-code2.ll b/llvm/test/CodeGen/WinEH/seh-exception-code2.ll deleted file mode 100644 index 6b64a7923f6..00000000000 --- a/llvm/test/CodeGen/WinEH/seh-exception-code2.ll +++ /dev/null @@ -1,91 +0,0 @@ -; RUN: opt -winehprepare -S < %s | FileCheck %s - -; WinEHPrepare was crashing during phi demotion. - -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc18.0.0" - -declare i32 @__C_specific_handler(...) - -@str = linkonce_odr unnamed_addr constant [16 x i8] c"caught it! %lx\0A\00", align 1 - -declare void @maycrash() -declare void @finally(i1 %abnormal) -declare i32 @printf(i8* nocapture readonly, ...) -declare i32 @llvm.eh.typeid.for(i8*) - -; Function Attrs: nounwind uwtable -define void @doit() personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) { -entry: - invoke void @maycrash() - to label %invoke.cont unwind label %lpad.1 - -invoke.cont: ; preds = %entry - invoke void @maycrash() - to label %__try.cont unwind label %lpad - -lpad: ; preds = %entry - %lp0 = landingpad { i8*, i32 } - cleanup - catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@doit@@" to i8*) - %ehptr.0 = extractvalue { i8*, i32 } %lp0, 0 - %ehsel.0 = extractvalue { i8*, i32 } %lp0, 1 - call void @finally(i1 true) - br label %ehdispatch - -lpad.1: ; preds = %invoke.cont, %lpad - %lp1 = landingpad { i8*, i32 } - catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@doit@@" to i8*) - %ehptr.1 = extractvalue { i8*, i32 } %lp1, 0 - %ehsel.1 = extractvalue { i8*, i32 } %lp1, 1 - br label %ehdispatch - -ehdispatch: - %ehptr.2 = phi i8* [ %ehptr.0, %lpad ], [ %ehptr.1, %lpad.1 ] - %ehsel.2 = phi i32 [ %ehsel.0, %lpad ], [ %ehsel.1, %lpad.1 ] - %mysel = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@doit@@" to i8*)) - %matches = icmp eq i32 %ehsel.2, %mysel - br i1 %matches, label %__except, label %eh.resume - -__except: ; preds = %lpad, %lpad.1 - %t4 = ptrtoint i8* %ehptr.2 to i64 - %t5 = trunc i64 %t4 to i32 - %call = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([16 x i8], [16 x i8]* @str, i64 0, i64 0), i32 %t5) - br label %__try.cont - -__try.cont: ; preds = %invoke.cont, %__except - call void @finally(i1 false) - ret void - -eh.resume: - %ehvals0 = insertvalue { i8*, i32 } undef, i8* %ehptr.2, 0 - %ehvals = insertvalue { i8*, i32 } %ehvals0, i32 %ehsel.2, 1 - resume { i8*, i32 } %ehvals -} - -define internal i32 @"\01?filt$0@0@doit@@"(i8* %exception_pointers, i8* %frame_pointer) #1 { -entry: - %0 = bitcast i8* %exception_pointers to { i32*, i8* }* - %1 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %0, i32 0, i32 0 - %2 = load i32*, i32** %1 - %3 = load i32, i32* %2 - %cmp = icmp eq i32 %3, -1073741819 - %4 = zext i1 %cmp to i32 - ret i32 %4 -} - -; CHECK-LABEL: define void @doit() -; CHECK: %lp0 = landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: catch i8* -; CHECK-NEXT: call i8* (...) @llvm.eh.actions({{.*}}) -; CHECK-NEXT: indirectbr i8* %{{[^,]*}}, [label %__except] -; -; CHECK: %lp1 = landingpad { i8*, i32 } -; CHECK-NEXT: catch i8* -; CHECK-NEXT: call i8* (...) @llvm.eh.actions({{.*}}) -; CHECK-NEXT: indirectbr i8* %{{[^,]*}}, [label %__except] -; -; CHECK: __except: -; CHECK: call i32 @llvm.eh.exceptioncode.old() -; CHECK: call i32 (i8*, ...) @printf diff --git a/llvm/test/CodeGen/WinEH/seh-inlined-finally.ll b/llvm/test/CodeGen/WinEH/seh-inlined-finally.ll deleted file mode 100644 index 07fe6000867..00000000000 --- a/llvm/test/CodeGen/WinEH/seh-inlined-finally.ll +++ /dev/null @@ -1,83 +0,0 @@ -; RUN: opt -S -winehprepare -mtriple=x86_64-pc-windows-msvc < %s | FileCheck %s -; RUN: opt -S -winehprepare -mtriple=x86_64-pc-windows-coreclr < %s | FileCheck %s - -; Check that things work when the mid-level optimizer inlines the finally -; block. - -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" - -%struct._RTL_CRITICAL_SECTION = type { %struct._RTL_CRITICAL_SECTION_DEBUG*, i32, i32, i8*, i8*, i64 } -%struct._RTL_CRITICAL_SECTION_DEBUG = type { i16, i16, %struct._RTL_CRITICAL_SECTION*, %struct._LIST_ENTRY, i32, i32, i32, i16, i16 } -%struct._LIST_ENTRY = type { %struct._LIST_ENTRY*, %struct._LIST_ENTRY* } - -declare i32 @puts(i8*) -declare void @may_crash() -declare i32 @__C_specific_handler(...) -declare i8* @llvm.localrecover(i8*, i8*, i32) #1 -declare i8* @llvm.localaddress() -declare void @llvm.localescape(...) -declare dllimport void @EnterCriticalSection(%struct._RTL_CRITICAL_SECTION*) -declare dllimport void @LeaveCriticalSection(%struct._RTL_CRITICAL_SECTION*) - -define void @use_finally() personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) { -entry: - invoke void @may_crash() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - %call.i = tail call i32 @puts(i8* null) - ret void - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - cleanup - %call.i2 = tail call i32 @puts(i8* null) - resume { i8*, i32 } %0 -} - -; CHECK-LABEL: define void @use_finally() -; CHECK: invoke void @may_crash() -; -; CHECK: landingpad -; CHECK-NEXT: cleanup -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @use_finally.cleanup) -; CHECK-NEXT: indirectbr i8* %recover, [] - -; Function Attrs: nounwind uwtable -define i32 @call_may_crash_locked() personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) { -entry: - %p = alloca %struct._RTL_CRITICAL_SECTION, align 8 - call void (...) @llvm.localescape(%struct._RTL_CRITICAL_SECTION* %p) - call void @EnterCriticalSection(%struct._RTL_CRITICAL_SECTION* %p) - invoke void @may_crash() - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - %tmp2 = call i8* @llvm.localaddress() - %tmp3 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @call_may_crash_locked to i8*), i8* %tmp2, i32 0) #2 - %tmp6 = bitcast i8* %tmp3 to %struct._RTL_CRITICAL_SECTION* - call void @LeaveCriticalSection(%struct._RTL_CRITICAL_SECTION* %tmp6) - ret i32 42 - -lpad: ; preds = %entry - %tmp7 = landingpad { i8*, i32 } - cleanup - %tmp8 = call i8* @llvm.localaddress() - %tmp9 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @call_may_crash_locked to i8*), i8* %tmp8, i32 0) - %tmp12 = bitcast i8* %tmp9 to %struct._RTL_CRITICAL_SECTION* - call void @LeaveCriticalSection(%struct._RTL_CRITICAL_SECTION* %tmp12) - resume { i8*, i32 } %tmp7 -} - -; CHECK-LABEL: define i32 @call_may_crash_locked() -; CHECK: invoke void @may_crash() -; -; CHECK: landingpad -; CHECK-NEXT: cleanup -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @call_may_crash_locked.cleanup) -; CHECK-NEXT: indirectbr i8* %recover, [] - -; CHECK-LABEL: define internal void @call_may_crash_locked.cleanup(i8*, i8*) -; CHECK: %tmp9 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @call_may_crash_locked to i8*), i8* %1, i32 0) -; CHECK: %tmp12 = bitcast i8* %tmp9 to %struct._RTL_CRITICAL_SECTION* -; CHECK: call void @LeaveCriticalSection(%struct._RTL_CRITICAL_SECTION* %tmp12) diff --git a/llvm/test/CodeGen/WinEH/seh-outlined-finally-win32.ll b/llvm/test/CodeGen/WinEH/seh-outlined-finally-win32.ll deleted file mode 100644 index 3649433c4b6..00000000000 --- a/llvm/test/CodeGen/WinEH/seh-outlined-finally-win32.ll +++ /dev/null @@ -1,172 +0,0 @@ -; RUN: opt -S -winehprepare < %s | FileCheck %s - -; Test case based on this code: -; -; extern "C" int _abnormal_termination(); -; #pragma intrinsic(_abnormal_termination) -; extern "C" int printf(const char *, ...); -; extern "C" void may_crash() { -; *(volatile int *)0 = 42; -; } -; int main() { -; int myres = 0; -; __try { -; __try { -; may_crash(); -; } __finally { -; printf("inner finally %d\n", _abnormal_termination()); -; may_crash(); -; } -; } __finally { -; printf("outer finally %d\n", _abnormal_termination()); -; } -; } -; -; Note that if the inner finally crashes, the outer finally still runs. There -; is nothing like a std::terminate call in this situation. - -target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" -target triple = "i686-pc-windows-msvc" - -$"\01??_C@_0BC@LHHILCPN@outer?5finally?5?$CFd?6?$AA@" = comdat any - -$"\01??_C@_0BC@JELAHKN@inner?5finally?5?$CFd?6?$AA@" = comdat any - -@"\01??_C@_0BC@LHHILCPN@outer?5finally?5?$CFd?6?$AA@" = linkonce_odr unnamed_addr constant [18 x i8] c"outer finally %d\0A\00", comdat, align 1 -@"\01??_C@_0BC@JELAHKN@inner?5finally?5?$CFd?6?$AA@" = linkonce_odr unnamed_addr constant [18 x i8] c"inner finally %d\0A\00", comdat, align 1 - -; Function Attrs: nounwind -define void @may_crash() #0 { -entry: - store volatile i32 42, i32* null, align 4 - ret void -} - -; Function Attrs: nounwind -define i32 @main() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) { -entry: - %myres = alloca i32, align 4 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - store i32 0, i32* %myres, align 4 - invoke void @may_crash() #4 - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - %0 = call i8* @llvm.frameaddress(i32 0) - invoke void @"\01?fin$1@0@main@@"(i8 zeroext 0, i8* %0) #4 - to label %invoke.cont.2 unwind label %lpad.1 - -invoke.cont.2: ; preds = %invoke.cont - %1 = call i8* @llvm.frameaddress(i32 0) - call void @"\01?fin$0@0@main@@"(i8 zeroext 0, i8* %1) - ret i32 0 - -lpad: ; preds = %entry - %2 = landingpad { i8*, i32 } - cleanup - %3 = extractvalue { i8*, i32 } %2, 0 - store i8* %3, i8** %exn.slot - %4 = extractvalue { i8*, i32 } %2, 1 - store i32 %4, i32* %ehselector.slot - %5 = call i8* @llvm.frameaddress(i32 0) - invoke void @"\01?fin$1@0@main@@"(i8 zeroext 1, i8* %5) #4 - to label %invoke.cont.3 unwind label %lpad.1 - -lpad.1: ; preds = %lpad, %invoke.cont - %6 = landingpad { i8*, i32 } - cleanup - %7 = extractvalue { i8*, i32 } %6, 0 - store i8* %7, i8** %exn.slot - %8 = extractvalue { i8*, i32 } %6, 1 - store i32 %8, i32* %ehselector.slot - br label %ehcleanup - -invoke.cont.3: ; preds = %lpad - br label %ehcleanup - -ehcleanup: ; preds = %invoke.cont.3, %lpad.1 - %9 = call i8* @llvm.frameaddress(i32 0) - call void @"\01?fin$0@0@main@@"(i8 zeroext 1, i8* %9) - br label %eh.resume - -eh.resume: ; preds = %ehcleanup - %exn = load i8*, i8** %exn.slot - %sel = load i32, i32* %ehselector.slot - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn, 0 - %lpad.val.4 = insertvalue { i8*, i32 } %lpad.val, i32 %sel, 1 - resume { i8*, i32 } %lpad.val.4 -} - -; CHECK-LABEL: define i32 @main() -; CHECK: invoke void @may_crash() -; -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void ()* @main.cleanup) -; CHECK-NEXT: indirectbr -; -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void ()* @main.cleanup.1) -; CHECK-NEXT: indirectbr - -; CHECK-LABEL: define internal void @main.cleanup() -; CHECK: call i8* @llvm.frameaddress(i32 1) -; CHECK: call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @main to i8*), i8* %{{.*}}) -; CHECK: call void @"\01?fin$1@0@main@@"(i8 zeroext 1, i8* %{{.*}}) -; CHECK: call void @"\01?fin$0@0@main@@"(i8 zeroext 1, i8* %{{.*}}) - -; CHECK-LABEL: define internal void @main.cleanup.1() -; CHECK: call i8* @llvm.frameaddress(i32 1) -; CHECK: call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @main to i8*), i8* %{{.*}}) -; CHECK: call void @"\01?fin$0@0@main@@"(i8 zeroext 1, i8* %{{.*}}) - -; Function Attrs: noinline nounwind -define internal void @"\01?fin$0@0@main@@"(i8 zeroext %abnormal_termination, i8* %frame_pointer) #1 { -entry: - %frame_pointer.addr = alloca i8*, align 4 - %abnormal_termination.addr = alloca i8, align 1 - %0 = call i8* @llvm.frameaddress(i32 1) - %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @main to i8*), i8* %0) - store i8* %frame_pointer, i8** %frame_pointer.addr, align 4 - store i8 %abnormal_termination, i8* %abnormal_termination.addr, align 1 - %2 = zext i8 %abnormal_termination to i32 - %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @"\01??_C@_0BC@LHHILCPN@outer?5finally?5?$CFd?6?$AA@", i32 0, i32 0), i32 %2) - ret void -} - -; Function Attrs: nounwind readnone -declare i8* @llvm.frameaddress(i32) #2 - -; Function Attrs: nounwind readnone -declare i8* @llvm.x86.seh.recoverfp(i8*, i8*) #2 - -declare i32 @printf(i8*, ...) #3 - -; Function Attrs: noinline nounwind -define internal void @"\01?fin$1@0@main@@"(i8 zeroext %abnormal_termination, i8* %frame_pointer) #1 { -entry: - %frame_pointer.addr = alloca i8*, align 4 - %abnormal_termination.addr = alloca i8, align 1 - %0 = call i8* @llvm.frameaddress(i32 1) - %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @main to i8*), i8* %0) - store i8* %frame_pointer, i8** %frame_pointer.addr, align 4 - store i8 %abnormal_termination, i8* %abnormal_termination.addr, align 1 - %2 = zext i8 %abnormal_termination to i32 - %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @"\01??_C@_0BC@JELAHKN@inner?5finally?5?$CFd?6?$AA@", i32 0, i32 0), i32 %2) - call void @may_crash() - ret void -} - -declare i32 @_except_handler3(...) - -attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { noinline nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nounwind readnone } -attributes #3 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #4 = { noinline } - -!llvm.ident = !{!0} - -!0 = !{!"clang version 3.7.0 "} diff --git a/llvm/test/CodeGen/WinEH/seh-outlined-finally.ll b/llvm/test/CodeGen/WinEH/seh-outlined-finally.ll deleted file mode 100644 index b46b4e97672..00000000000 --- a/llvm/test/CodeGen/WinEH/seh-outlined-finally.ll +++ /dev/null @@ -1,155 +0,0 @@ -; RUN: opt -S -winehprepare -mtriple=x86_64-windows-msvc < %s | FileCheck %s -; RUN: opt -S -winehprepare -mtriple=x86_64-windows-coreclr < %s | FileCheck %s - -; Test case based on this code: -; -; extern "C" int _abnormal_termination(); -; #pragma intrinsic(_abnormal_termination) -; extern "C" int printf(const char *, ...); -; extern "C" void may_crash() { -; *(volatile int *)0 = 42; -; } -; int main() { -; int myres = 0; -; __try { -; __try { -; may_crash(); -; } __finally { -; printf("inner finally %d\n", _abnormal_termination()); -; may_crash(); -; } -; } __finally { -; printf("outer finally %d\n", _abnormal_termination()); -; } -; } -; -; Note that if the inner finally crashes, the outer finally still runs. There -; is nothing like a std::terminate call in this situation. - -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" - -@str_outer_finally = linkonce_odr unnamed_addr constant [18 x i8] c"outer finally %d\0A\00", align 1 -@str_inner_finally = linkonce_odr unnamed_addr constant [18 x i8] c"inner finally %d\0A\00", align 1 - -; Function Attrs: nounwind uwtable -define void @may_crash() #0 { -entry: - store volatile i32 42, i32* null, align 4 - ret void -} - -; Function Attrs: uwtable -define i32 @main() #1 personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) { -entry: - %myres = alloca i32, align 4 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - store i32 0, i32* %myres, align 4 - invoke void @may_crash() #4 - to label %invoke.cont unwind label %lpad - -invoke.cont: ; preds = %entry - %0 = call i8* @llvm.localaddress() - invoke void @"\01?fin$1@0@main@@"(i1 zeroext false, i8* %0) #4 - to label %invoke.cont2 unwind label %lpad1 - -invoke.cont2: ; preds = %invoke.cont - %1 = call i8* @llvm.localaddress() - call void @"\01?fin$0@0@main@@"(i1 zeroext false, i8* %1) - ret i32 0 - -lpad: ; preds = %entry - %2 = landingpad { i8*, i32 } - cleanup - %3 = extractvalue { i8*, i32 } %2, 0 - store i8* %3, i8** %exn.slot - %4 = extractvalue { i8*, i32 } %2, 1 - store i32 %4, i32* %ehselector.slot - %5 = call i8* @llvm.localaddress() - invoke void @"\01?fin$1@0@main@@"(i1 zeroext true, i8* %5) #4 - to label %invoke.cont3 unwind label %lpad1 - -lpad1: ; preds = %lpad, %invoke.cont - %6 = landingpad { i8*, i32 } - cleanup - %7 = extractvalue { i8*, i32 } %6, 0 - store i8* %7, i8** %exn.slot - %8 = extractvalue { i8*, i32 } %6, 1 - store i32 %8, i32* %ehselector.slot - br label %ehcleanup - -invoke.cont3: ; preds = %lpad - br label %ehcleanup - -ehcleanup: ; preds = %invoke.cont3, %lpad1 - %9 = call i8* @llvm.localaddress() - call void @"\01?fin$0@0@main@@"(i1 zeroext true, i8* %9) - br label %eh.resume - -eh.resume: ; preds = %ehcleanup - %exn = load i8*, i8** %exn.slot - %sel = load i32, i32* %ehselector.slot - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn, 0 - %lpad.val4 = insertvalue { i8*, i32 } %lpad.val, i32 %sel, 1 - resume { i8*, i32 } %lpad.val4 -} - -; CHECK-NOT: define internal void @ - -; CHECK-LABEL: define i32 @main() -; CHECK: invoke void @may_crash() -; -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void (i1, i8*)* @"\01?fin$1@0@main@@", i32 0, void (i1, i8*)* @"\01?fin$0@0@main@@") -; CHECK-NEXT: indirectbr -; -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void (i1, i8*)* @"\01?fin$0@0@main@@") -; CHECK-NEXT: indirectbr - -; There should not be any *new* cleanup helpers, just the existing ones. -; CHECK-NOT: define internal void @ -; CHECK: define internal void @"\01?fin$0@0@main@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -; CHECK-NOT: define internal void @ -; CHECK: define internal void @"\01?fin$1@0@main@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) -; CHECK-NOT: define internal void @ - -define internal void @"\01?fin$0@0@main@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) #2 { -entry: - %frame_pointer.addr = alloca i8*, align 8 - %abnormal_termination.addr = alloca i8, align 1 - store i8* %frame_pointer, i8** %frame_pointer.addr, align 8 - %frombool = zext i1 %abnormal_termination to i8 - store i8 %frombool, i8* %abnormal_termination.addr, align 1 - %0 = zext i1 %abnormal_termination to i32 - %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @str_outer_finally, i32 0, i32 0), i32 %0) - ret void -} - -declare i32 @printf(i8*, ...) #2 - -define internal void @"\01?fin$1@0@main@@"(i1 zeroext %abnormal_termination, i8* %frame_pointer) #2 { -entry: - %frame_pointer.addr = alloca i8*, align 8 - %abnormal_termination.addr = alloca i8, align 1 - store i8* %frame_pointer, i8** %frame_pointer.addr, align 8 - %frombool = zext i1 %abnormal_termination to i8 - store i8 %frombool, i8* %abnormal_termination.addr, align 1 - %0 = zext i1 %abnormal_termination to i32 - %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @str_inner_finally, i32 0, i32 0), i32 %0) - call void @may_crash() - ret void -} - -declare i32 @__C_specific_handler(...) - -; Function Attrs: nounwind readnone -declare i8* @llvm.localaddress() #3 - -attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #3 = { nounwind readnone } -attributes #4 = { noinline } diff --git a/llvm/test/CodeGen/WinEH/seh-prepared-basic.ll b/llvm/test/CodeGen/WinEH/seh-prepared-basic.ll deleted file mode 100644 index 51ffe7bb3bd..00000000000 --- a/llvm/test/CodeGen/WinEH/seh-prepared-basic.ll +++ /dev/null @@ -1,86 +0,0 @@ -; RUN: llc -mtriple=x86_64-pc-windows-msvc < %s | FileCheck %s -; RUN: llc -mtriple=x86_64-pc-windows-coreclr < %s | FileCheck %s - -; Test case based on this code: -; extern "C" unsigned long _exception_code(); -; extern "C" int filt(unsigned long); -; extern "C" void g(); -; extern "C" void do_except() { -; __try { -; g(); -; } __except(filt(_exception_code())) { -; } -; } - -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" - -; Function Attrs: uwtable -define void @do_except() #0 personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*) { -entry: - call void (...) @llvm.localescape() - invoke void @g() #5 - to label %__try.cont unwind label %lpad1 - -lpad1: ; preds = %entry - %ehvals = landingpad { i8*, i32 } - catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@do_except@@" to i8*) - %recover = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@do_except@@" to i8*), i32 -1, i8* blockaddress(@do_except, %__try.cont)) - indirectbr i8* %recover, [label %__try.cont] - -__try.cont: ; preds = %lpad1, %entry - ret void -} - -; CHECK-LABEL: do_except: -; CHECK: .seh_handler __C_specific_handler -; CHECK-NOT: jmpq * -; CHECK: .seh_handlerdata -; CHECK-NEXT: .text -; CHECK: .seh_endproc -; CHECK: .section .xdata,"dr" -; CHECK-NEXT: .long 1 -; CHECK-NEXT: .long .Ltmp{{.*}} -; CHECK-NEXT: .long .Ltmp{{.*}} -; CHECK-NEXT: .long "?filt$0@0@do_except@@"@IMGREL -; CHECK-NEXT: .long .Ltmp{{.*}}@IMGREL - -; Function Attrs: noinline nounwind -define internal i32 @"\01?filt$0@0@do_except@@"(i8* nocapture readonly %exception_pointers, i8* nocapture readnone %frame_pointer) #1 { -entry: - %0 = bitcast i8* %exception_pointers to i32** - %1 = load i32*, i32** %0, align 8 - %2 = load i32, i32* %1, align 4 - %call = tail call i32 @filt(i32 %2) #4 - ret i32 %call -} - -declare i32 @filt(i32) #2 - -declare void @g() #2 - -declare i32 @__C_specific_handler(...) - -; Function Attrs: nounwind readnone -declare i32 @llvm.eh.typeid.for(i8*) #3 - -; Function Attrs: nounwind -declare i8* @llvm.eh.actions(...) #4 - -; Function Attrs: nounwind -declare void @llvm.localescape(...) #4 - -; Function Attrs: nounwind readnone -declare i8* @llvm.localrecover(i8*, i8*, i32) #3 - -attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" "wineh-parent"="do_except" } -attributes #1 = { noinline nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #3 = { nounwind readnone } -attributes #4 = { nounwind } -attributes #5 = { noinline } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 "} diff --git a/llvm/test/CodeGen/WinEH/seh-resume-phi.ll b/llvm/test/CodeGen/WinEH/seh-resume-phi.ll deleted file mode 100644 index f629a4dd50c..00000000000 --- a/llvm/test/CodeGen/WinEH/seh-resume-phi.ll +++ /dev/null @@ -1,66 +0,0 @@ -; RUN: opt -S -winehprepare -mtriple=x86_64-pc-windows-msvc < %s | FileCheck %s -; RUN: opt -S -winehprepare -mtriple=x86_64-pc-windows-coreclr < %s | FileCheck %s - -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" - -declare void @might_crash(i8* %ehptr) -declare i32 @filt() -declare void @cleanup() -declare i32 @__C_specific_handler(...) -declare i32 @llvm.eh.typeid.for(i8*) - -define void @resume_phi() personality i32 (...)* @__C_specific_handler { -entry: - invoke void @might_crash(i8* null) - to label %return unwind label %lpad1 - -lpad1: - %ehvals1 = landingpad { i8*, i32 } - catch i32 ()* @filt - %ehptr1 = extractvalue { i8*, i32 } %ehvals1, 0 - %ehsel1 = extractvalue { i8*, i32 } %ehvals1, 1 - %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*)) - %matches = icmp eq i32 %ehsel1, %filt_sel - br i1 %matches, label %__except, label %eh.resume - -__except: - invoke void @might_crash(i8* %ehptr1) - to label %return unwind label %lpad2 - -lpad2: - %ehvals2 = landingpad { i8*, i32 } - cleanup - %ehptr2 = extractvalue { i8*, i32 } %ehvals2, 0 - %ehsel2 = extractvalue { i8*, i32 } %ehvals2, 1 - call void @cleanup() - br label %eh.resume - -return: - ret void - -eh.resume: - %ehptr.phi = phi i8* [ %ehptr1, %lpad1 ], [ %ehptr2, %lpad2 ] - %ehsel.phi = phi i32 [ %ehsel1, %lpad1 ], [ %ehsel2, %lpad2 ] - %ehval.phi1 = insertvalue { i8*, i32 } undef, i8* %ehptr.phi, 0 - %ehval.phi2 = insertvalue { i8*, i32 } %ehval.phi1, i32 %ehsel.phi, 1 - resume { i8*, i32 } %ehval.phi2 -} - -; CHECK-LABEL: define void @resume_phi() -; CHECK: invoke void @might_crash(i8* null) -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: catch i32 ()* @filt -; CHECK-NEXT: call i8* (...) @llvm.eh.actions( -; CHECK-SAME: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@resume_phi, %__except)) -; CHECK-NEXT: indirectbr {{.*}} [label %__except] -; -; CHECK: __except: -; CHECK: call i32 @llvm.eh.exceptioncode.old() -; CHECK: invoke void @might_crash(i8* %{{.*}}) -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @resume_phi.cleanup) -; CHECK-NEXT: indirectbr {{.*}} [] - -; CHECK-LABEL: define internal void @resume_phi.cleanup(i8*, i8*) -; CHECK: call void @cleanup() diff --git a/llvm/test/CodeGen/WinEH/seh-simple.ll b/llvm/test/CodeGen/WinEH/seh-simple.ll deleted file mode 100644 index 9974548ba33..00000000000 --- a/llvm/test/CodeGen/WinEH/seh-simple.ll +++ /dev/null @@ -1,235 +0,0 @@ -; RUN: opt -S -winehprepare -mtriple=x86_64-windows-msvc < %s \ -; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X64 -; RUN: opt -S -winehprepare -mtriple=x86_64-windows-coreclr < %s \ -; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X64 - -; This test should also pass in 32-bit using _except_handler3. -; RUN: sed -e 's/__C_specific_handler/_except_handler3/' %s \ -; RUN: | opt -S -winehprepare -mtriple=i686-windows-msvc \ -; RUN: | FileCheck %s --check-prefix=CHECK --check-prefix=X86 - -declare void @cleanup() -declare i32 @filt() -declare void @might_crash() -declare i32 @__C_specific_handler(...) -declare i32 @llvm.eh.typeid.for(i8*) - -define i32 @simple_except_store() personality i32 (...)* @__C_specific_handler { -entry: - %retval = alloca i32 - store i32 0, i32* %retval - invoke void @might_crash() - to label %return unwind label %lpad - -lpad: - %ehvals = landingpad { i8*, i32 } - catch i32 ()* @filt - %sel = extractvalue { i8*, i32 } %ehvals, 1 - %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*)) - %matches = icmp eq i32 %sel, %filt_sel - br i1 %matches, label %__except, label %eh.resume - -__except: - store i32 1, i32* %retval - br label %return - -return: - %r = load i32, i32* %retval - ret i32 %r - -eh.resume: - resume { i8*, i32 } %ehvals -} - -; CHECK-LABEL: define i32 @simple_except_store() -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: catch i32 ()* @filt -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@simple_except_store, %__except)) -; CHECK-NEXT: indirectbr {{.*}} [label %__except] - -define i32 @catch_all() personality i32 (...)* @__C_specific_handler { -entry: - %retval = alloca i32 - store i32 0, i32* %retval - invoke void @might_crash() - to label %return unwind label %lpad - -lpad: - %ehvals = landingpad { i8*, i32 } - catch i8* null - store i32 1, i32* %retval - br label %return - -return: - %r = load i32, i32* %retval - ret i32 %r -} - -; CHECK-LABEL: define i32 @catch_all() -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: catch i8* null -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@catch_all, %lpad.split)) -; CHECK-NEXT: indirectbr {{.*}} [label %lpad.split] -; -; CHECK: lpad.split: -; CHECK: store i32 1, i32* %retval - - -define i32 @except_phi() personality i32 (...)* @__C_specific_handler { -entry: - invoke void @might_crash() - to label %return unwind label %lpad - -lpad: - %ehvals = landingpad { i8*, i32 } - catch i32 ()* @filt - %sel = extractvalue { i8*, i32 } %ehvals, 1 - %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*)) - %matches = icmp eq i32 %sel, %filt_sel - br i1 %matches, label %return, label %eh.resume - -return: - %r = phi i32 [0, %entry], [1, %lpad] - ret i32 %r - -eh.resume: - resume { i8*, i32 } %ehvals -} - -; CHECK-LABEL: define i32 @except_phi() -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: catch i32 ()* @filt -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_phi, %lpad.return_crit_edge)) -; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge] -; -; CHECK: lpad.return_crit_edge: -; CHECK: br label %return -; -; CHECK: return: -; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ] -; CHECK-NEXT: ret i32 %r - -define i32 @except_join() personality i32 (...)* @__C_specific_handler { -entry: - invoke void @might_crash() - to label %return unwind label %lpad - -lpad: - %ehvals = landingpad { i8*, i32 } - catch i32 ()* @filt - %sel = extractvalue { i8*, i32 } %ehvals, 1 - %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*)) - %matches = icmp eq i32 %sel, %filt_sel - br i1 %matches, label %return, label %eh.resume - -return: - ret i32 0 - -eh.resume: - resume { i8*, i32 } %ehvals -} - -; CHECK-LABEL: define i32 @except_join() -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: catch i32 ()* @filt -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@except_join, %lpad.return_crit_edge)) -; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge] -; -; CHECK: lpad.return_crit_edge: -; CHECK: br label %return -; -; CHECK: return: -; CHECK-NEXT: ret i32 0 - -define i32 @lpad_phi() personality i32 (...)* @__C_specific_handler { -entry: - invoke void @might_crash() - to label %cont unwind label %lpad - -cont: - invoke void @might_crash() - to label %return unwind label %lpad - -lpad: - %ncalls.1 = phi i32 [ 0, %entry ], [ 1, %cont ] - %ehvals = landingpad { i8*, i32 } - catch i32 ()* @filt - %sel = extractvalue { i8*, i32 } %ehvals, 1 - %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*)) - %matches = icmp eq i32 %sel, %filt_sel - br i1 %matches, label %return, label %eh.resume - -return: - %r = phi i32 [2, %cont], [%ncalls.1, %lpad] - ret i32 %r - -eh.resume: - resume { i8*, i32 } %ehvals -} - -; CHECK-LABEL: define i32 @lpad_phi() -; CHECK: alloca i32 -; CHECK: store i32 0, i32* -; CHECK: invoke void @might_crash() -; CHECK: store i32 1, i32* -; CHECK: invoke void @might_crash() -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: catch i32 ()* @filt -; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void ({{.*}})* @lpad_phi.cleanup, i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@lpad_phi, %lpad.return_crit_edge)) -; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge] -; -; CHECK: lpad.return_crit_edge: -; CHECK: load i32, i32* -; CHECK: br label %return -; -; CHECK: return: -; CHECK-NEXT: %r = phi i32 [ 2, %cont ], [ %{{.*}}, %lpad.return_crit_edge ] -; CHECK-NEXT: ret i32 %r - -define i32 @cleanup_and_except() personality i32 (...)* @__C_specific_handler { -entry: - invoke void @might_crash() - to label %return unwind label %lpad - -lpad: - %ehvals = landingpad { i8*, i32 } - cleanup - catch i32 ()* @filt - call void @cleanup() - %sel = extractvalue { i8*, i32 } %ehvals, 1 - %filt_sel = tail call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ()* @filt to i8*)) - %matches = icmp eq i32 %sel, %filt_sel - br i1 %matches, label %return, label %eh.resume - -return: - %r = phi i32 [0, %entry], [1, %lpad] - ret i32 %r - -eh.resume: - resume { i8*, i32 } %ehvals -} - -; CHECK-LABEL: define i32 @cleanup_and_except() -; CHECK: landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: catch i32 ()* @filt -; CHECK-NEXT: call i8* (...) @llvm.eh.actions( -; CHECK: i32 0, void ({{.*}})* @cleanup_and_except.cleanup, -; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %lpad.return_crit_edge)) -; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge] -; -; CHECK: lpad.return_crit_edge: -; CHECK: br label %return -; -; CHECK: return: -; CHECK-NEXT: %r = phi i32 [ 0, %entry ], [ 1, %lpad.return_crit_edge ] -; CHECK-NEXT: ret i32 %r - -; FIXME: This cleanup is an artifact of bad demotion. -; X64-LABEL: define internal void @lpad_phi.cleanup(i8*, i8*) -; X86-LABEL: define internal void @lpad_phi.cleanup() -; X86: call i8* @llvm.frameaddress(i32 1) -; CHECK: call i8* @llvm.localrecover({{.*}}) -; CHECK: load i32 -; CHECK: store i32 %{{.*}}, i32* |