From 436444d569938cd75bd05f3abb65fe57bce0f067 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 16 Sep 2015 22:14:46 +0000 Subject: [PATCH] [WinEH] Rip out the landingpad-based C++ EH state numbering code It never really worked, and the new code is working better every day. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@247860 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/WinEHFuncInfo.h | 9 - lib/CodeGen/AsmPrinter/WinException.cpp | 113 ++---- lib/CodeGen/AsmPrinter/WinException.h | 3 +- lib/CodeGen/PrologEpilogInserter.cpp | 6 - lib/CodeGen/WinEHPrepare.cpp | 380 +----------------- lib/Target/X86/X86ISelLowering.cpp | 23 -- lib/Target/X86/X86WinEHState.cpp | 17 - .../CodeGen/WinEH/cppeh-prepared-catch-all.ll | 47 --- .../WinEH/cppeh-prepared-catch-reordered.ll | 165 -------- test/CodeGen/WinEH/cppeh-prepared-catch.ll | 232 ----------- test/CodeGen/WinEH/cppeh-prepared-cleanups.ll | 245 ----------- test/CodeGen/WinEH/cppeh-state-calc-1.ll | 289 ------------- test/CodeGen/X86/pr23900.ll | 29 -- test/CodeGen/X86/win32-eh-states.ll | 72 ++-- test/CodeGen/X86/win32-eh.ll | 15 +- 15 files changed, 73 insertions(+), 1572 deletions(-) delete mode 100644 test/CodeGen/WinEH/cppeh-prepared-catch-all.ll delete mode 100644 test/CodeGen/WinEH/cppeh-prepared-catch-reordered.ll delete mode 100644 test/CodeGen/WinEH/cppeh-prepared-catch.ll delete mode 100644 test/CodeGen/WinEH/cppeh-prepared-cleanups.ll delete mode 100644 test/CodeGen/WinEH/cppeh-state-calc-1.ll delete mode 100644 test/CodeGen/X86/pr23900.ll diff --git a/include/llvm/CodeGen/WinEHFuncInfo.h b/include/llvm/CodeGen/WinEHFuncInfo.h index 1c81c713289..0f947812a01 100644 --- a/include/llvm/CodeGen/WinEHFuncInfo.h +++ b/include/llvm/CodeGen/WinEHFuncInfo.h @@ -159,22 +159,13 @@ struct WinEHTryBlockMapEntry { }; struct WinEHFuncInfo { - DenseMap RootLPad; - DenseMap LastInvoke; - DenseMap HandlerEnclosedState; - DenseMap LastInvokeVisited; DenseMap EHPadStateMap; - DenseMap CatchHandlerParentFrameObjIdx; - DenseMap CatchHandlerParentFrameObjOffset; - DenseMap CatchHandlerMaxState; - DenseMap HandlerBaseState; SmallVector UnwindMap; SmallVector TryBlockMap; SmallVector SEHUnwindMap; SmallVector, 4> IPToStateList; int UnwindHelpFrameIdx = INT_MAX; int UnwindHelpFrameOffset = -1; - unsigned NumIPToStateFuncsVisited = 0; int getLastStateNumber() const { return UnwindMap.size() - 1; } diff --git a/lib/CodeGen/AsmPrinter/WinException.cpp b/lib/CodeGen/AsmPrinter/WinException.cpp index 1b75051dd67..95947cb88c4 100644 --- a/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/lib/CodeGen/AsmPrinter/WinException.cpp @@ -98,24 +98,6 @@ void WinException::beginFunction(const MachineFunction *MF) { return; } - // If this was an outlined handler, we need to define the label corresponding - // to the offset of the parent frame relative to the stack pointer after the - // prologue. - if (F != ParentF) { - WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF); - auto I = FuncInfo.CatchHandlerParentFrameObjOffset.find(F); - if (I != FuncInfo.CatchHandlerParentFrameObjOffset.end()) { - MCSymbol *HandlerTypeParentFrameOffset = - Asm->OutContext.getOrCreateParentFrameOffsetSymbol( - GlobalValue::getRealLinkageName(F->getName())); - - // Emit a symbol assignment. - Asm->OutStreamer->EmitAssignment( - HandlerTypeParentFrameOffset, - MCConstantExpr::create(I->second, Asm->OutContext)); - } - } - if (shouldEmitMoves || shouldEmitPersonality) Asm->OutStreamer->EmitWinCFIStartProc(Asm->CurrentFnSym); @@ -325,35 +307,21 @@ static MCSymbol *getMCSymbolForMBBOrGV(AsmPrinter *Asm, ValueOrMBB Handler) { void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { const Function *F = MF->getFunction(); - const Function *ParentF = MMI->getWinEHParent(F); auto &OS = *Asm->OutStreamer; - WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF); + WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F); - StringRef ParentLinkageName = - GlobalValue::getRealLinkageName(ParentF->getName()); + StringRef FuncLinkageName = GlobalValue::getRealLinkageName(F->getName()); MCSymbol *FuncInfoXData = nullptr; if (shouldEmitPersonality) { - FuncInfoXData = Asm->OutContext.getOrCreateSymbol( - Twine("$cppxdata$", ParentLinkageName)); + FuncInfoXData = + Asm->OutContext.getOrCreateSymbol(Twine("$cppxdata$", FuncLinkageName)); OS.EmitValue(create32bitRef(FuncInfoXData), 4); - extendIP2StateTable(MF, ParentF, FuncInfo); - - if (!MMI->hasEHFunclets()) { - // Defer emission until we've visited the parent function and all the - // catch handlers. Cleanups don't contribute to the ip2state table, so - // don't count them. - if (ParentF != F && !FuncInfo.CatchHandlerMaxState.count(F)) - return; - ++FuncInfo.NumIPToStateFuncsVisited; - if (FuncInfo.NumIPToStateFuncsVisited != - FuncInfo.CatchHandlerMaxState.size()) - return; - } + extendIP2StateTable(MF, FuncInfo); } else { - FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(ParentLinkageName); - emitEHRegistrationOffsetLabel(FuncInfo, ParentLinkageName); + FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(FuncLinkageName); + emitEHRegistrationOffsetLabel(FuncInfo, FuncLinkageName); } MCSymbol *UnwindMapXData = nullptr; @@ -361,13 +329,13 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { MCSymbol *IPToStateXData = nullptr; if (!FuncInfo.UnwindMap.empty()) UnwindMapXData = Asm->OutContext.getOrCreateSymbol( - Twine("$stateUnwindMap$", ParentLinkageName)); + Twine("$stateUnwindMap$", FuncLinkageName)); if (!FuncInfo.TryBlockMap.empty()) - TryBlockMapXData = Asm->OutContext.getOrCreateSymbol( - Twine("$tryMap$", ParentLinkageName)); + TryBlockMapXData = + Asm->OutContext.getOrCreateSymbol(Twine("$tryMap$", FuncLinkageName)); if (!FuncInfo.IPToStateList.empty()) - IPToStateXData = Asm->OutContext.getOrCreateSymbol( - Twine("$ip2state$", ParentLinkageName)); + IPToStateXData = + Asm->OutContext.getOrCreateSymbol(Twine("$ip2state$", FuncLinkageName)); // FuncInfo { // uint32_t MagicNumber @@ -423,29 +391,26 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { SmallVector HandlerMaps; for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) { WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I]; - MCSymbol *HandlerMapXData = nullptr; + MCSymbol *HandlerMapXData = nullptr; if (!TBME.HandlerArray.empty()) HandlerMapXData = Asm->OutContext.getOrCreateSymbol(Twine("$handlerMap$") .concat(Twine(I)) .concat("$") - .concat(ParentLinkageName)); - + .concat(FuncLinkageName)); HandlerMaps.push_back(HandlerMapXData); - int CatchHigh = TBME.CatchHigh; - if (CatchHigh == -1) { - for (WinEHHandlerType &HT : TBME.HandlerArray) - CatchHigh = - std::max(CatchHigh, FuncInfo.CatchHandlerMaxState[cast( - HT.Handler.get())]); - } + // TBMEs should form intervals. + 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()) && + "bad trymap interval"); - assert(TBME.TryLow <= TBME.TryHigh); OS.EmitIntValue(TBME.TryLow, 4); // TryLow OS.EmitIntValue(TBME.TryHigh, 4); // TryHigh - OS.EmitIntValue(CatchHigh, 4); // CatchHigh + OS.EmitIntValue(TBME.CatchHigh, 4); // CatchHigh OS.EmitIntValue(TBME.HandlerArray.size(), 4); // NumCatches OS.EmitValue(create32bitRef(HandlerMapXData), 4); // HandlerArray } @@ -471,8 +436,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { if (HT.CatchObjRecoverIdx >= 0) { MCSymbol *FrameAllocOffset = Asm->OutContext.getOrCreateFrameAllocSymbol( - GlobalValue::getRealLinkageName(ParentF->getName()), - HT.CatchObjRecoverIdx); + FuncLinkageName, HT.CatchObjRecoverIdx); FrameAllocOffsetRef = MCSymbolRefExpr::create( FrameAllocOffset, MCSymbolRefExpr::VK_None, Asm->OutContext); } else if (HT.CatchObj.FrameOffset != INT_MAX) { @@ -497,21 +461,11 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { OS.EmitValue(create32bitRef(HandlerSym), 4); // Handler if (shouldEmitPersonality) { - if (FuncInfo.CatchHandlerParentFrameObjOffset.empty()) { - // With the new IR, this is always 16 + 8 + getMaxCallFrameSize(). - // Keep this in sync with X86FrameLowering::emitPrologue. - int ParentFrameOffset = - 16 + 8 + MF->getFrameInfo()->getMaxCallFrameSize(); - OS.EmitIntValue(ParentFrameOffset, 4); // ParentFrameOffset - } else { - MCSymbol *ParentFrameOffset = - Asm->OutContext.getOrCreateParentFrameOffsetSymbol( - GlobalValue::getRealLinkageName( - HT.Handler.get()->getName())); - const MCSymbolRefExpr *ParentFrameOffsetRef = - MCSymbolRefExpr::create(ParentFrameOffset, Asm->OutContext); - OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset - } + // With the new IR, this is always 16 + 8 + getMaxCallFrameSize(). + // Keep this in sync with X86FrameLowering::emitPrologue. + int ParentFrameOffset = + 16 + 8 + MF->getFrameInfo()->getMaxCallFrameSize(); + OS.EmitIntValue(ParentFrameOffset, 4); // ParentFrameOffset } } } @@ -531,10 +485,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { } void WinException::extendIP2StateTable(const MachineFunction *MF, - const Function *ParentF, WinEHFuncInfo &FuncInfo) { - const Function *F = MF->getFunction(); - // The Itanium LSDA table sorts similar landing pads together to simplify the // actions table, but we don't need that. SmallVector LandingPads; @@ -560,14 +511,8 @@ void WinException::extendIP2StateTable(const MachineFunction *MF, // Include ip2state entries for the beginning of the main function and // for catch handler functions. - if (F == ParentF) { - FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1)); - LastEHState = -1; - } else if (FuncInfo.HandlerBaseState.count(F)) { - FuncInfo.IPToStateList.push_back( - std::make_pair(LastLabel, FuncInfo.HandlerBaseState[F])); - LastEHState = FuncInfo.HandlerBaseState[F]; - } + FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1)); + LastEHState = -1; for (const auto &MBB : *MF) { for (const auto &MI : MBB) { if (!MI.isEHLabel()) { diff --git a/lib/CodeGen/AsmPrinter/WinException.h b/lib/CodeGen/AsmPrinter/WinException.h index aa159f5cf6e..ac06db2a2fd 100644 --- a/lib/CodeGen/AsmPrinter/WinException.h +++ b/lib/CodeGen/AsmPrinter/WinException.h @@ -47,8 +47,7 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer { /// tables. void emitExceptHandlerTable(const MachineFunction *MF); - void extendIP2StateTable(const MachineFunction *MF, const Function *ParentF, - WinEHFuncInfo &FuncInfo); + void extendIP2StateTable(const MachineFunction *MF, WinEHFuncInfo &FuncInfo); /// Emits the label used with llvm.x86.seh.recoverfp, which is used by /// outlined funclets. diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index 54f5553d3e1..585c7edc0f0 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -829,12 +829,6 @@ void PEI::replaceFrameIndices(MachineFunction &Fn) { TFI.getFrameIndexReference(Fn, H.CatchObj.FrameIndex, UnusedReg); } } - } else if (MMI.hasWinEHFuncInfo(F)) { - WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(Fn.getFunction()); - auto I = FuncInfo.CatchHandlerParentFrameObjIdx.find(F); - if (I != FuncInfo.CatchHandlerParentFrameObjIdx.end()) - FuncInfo.CatchHandlerParentFrameObjOffset[F] = - TFI.getFrameIndexReferenceFromSP(Fn, I->second, FrameReg); } // Store SPAdj at exit of a basic block. diff --git a/lib/CodeGen/WinEHPrepare.cpp b/lib/CodeGen/WinEHPrepare.cpp index 3eed086a40d..06440e457a8 100644 --- a/lib/CodeGen/WinEHPrepare.cpp +++ b/lib/CodeGen/WinEHPrepare.cpp @@ -2576,33 +2576,6 @@ void llvm::parseEHActions( std::reverse(Actions.begin(), Actions.end()); } -namespace { -struct WinEHNumbering { - WinEHNumbering(WinEHFuncInfo &FuncInfo) : FuncInfo(FuncInfo), - CurrentBaseState(-1), NextState(0) {} - - WinEHFuncInfo &FuncInfo; - int CurrentBaseState; - int NextState; - - SmallVector, 4> HandlerStack; - SmallPtrSet VisitedHandlers; - - int currentEHNumber() const { - return HandlerStack.empty() ? CurrentBaseState : HandlerStack.back()->getEHState(); - } - - void createUnwindMapEntry(int ToState, ActionHandler *AH); - void createTryBlockMapEntry(int TryLow, int TryHigh, - ArrayRef Handlers); - void processCallSite(MutableArrayRef> Actions, - ImmutableCallSite CS); - void popUnmatchedActions(int FirstMismatch); - void calculateStateNumbers(const Function &F); - void findActionRootLPads(const Function &F); -}; -} - static int addUnwindMapEntry(WinEHFuncInfo &FuncInfo, int ToState, const Value *V) { WinEHUnwindMapEntry UME; @@ -2639,332 +2612,6 @@ static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow, FuncInfo.TryBlockMap.push_back(TBME); } -void WinEHNumbering::createUnwindMapEntry(int ToState, ActionHandler *AH) { - Value *V = nullptr; - if (auto *CH = dyn_cast_or_null(AH)) - V = cast(CH->getHandlerBlockOrFunc()); - addUnwindMapEntry(FuncInfo, ToState, V); -} - -void WinEHNumbering::createTryBlockMapEntry(int TryLow, int TryHigh, - ArrayRef Handlers) { - // See if we already have an entry for this set of handlers. - // This is using iterators rather than a range-based for loop because - // if we find the entry we're looking for we'll need the iterator to erase it. - int NumHandlers = Handlers.size(); - auto I = FuncInfo.TryBlockMap.begin(); - auto E = FuncInfo.TryBlockMap.end(); - for ( ; I != E; ++I) { - auto &Entry = *I; - if (Entry.HandlerArray.size() != (size_t)NumHandlers) - continue; - int N; - for (N = 0; N < NumHandlers; ++N) { - if (Entry.HandlerArray[N].Handler.get() != - Handlers[N]->getHandlerBlockOrFunc()) - break; // breaks out of inner loop - } - // If all the handlers match, this is what we were looking for. - if (N == NumHandlers) { - break; - } - } - - // If we found an existing entry for this set of handlers, extend the range - // but move the entry to the end of the map vector. The order of entries - // in the map is critical to the way that the runtime finds handlers. - // FIXME: Depending on what has happened with block ordering, this may - // incorrectly combine entries that should remain separate. - if (I != E) { - // Copy the existing entry. - WinEHTryBlockMapEntry Entry = *I; - Entry.TryLow = std::min(TryLow, Entry.TryLow); - Entry.TryHigh = std::max(TryHigh, Entry.TryHigh); - assert(Entry.TryLow <= Entry.TryHigh); - // Erase the old entry and add this one to the back. - FuncInfo.TryBlockMap.erase(I); - FuncInfo.TryBlockMap.push_back(Entry); - return; - } - - // If we didn't find an entry, create a new one. - WinEHTryBlockMapEntry TBME; - TBME.TryLow = TryLow; - TBME.TryHigh = TryHigh; - assert(TBME.TryLow <= TBME.TryHigh); - for (CatchHandler *CH : Handlers) { - WinEHHandlerType HT; - if (CH->getSelector()->isNullValue()) { - HT.Adjectives = 0x40; - HT.TypeDescriptor = nullptr; - } else { - auto *GV = cast(CH->getSelector()->stripPointerCasts()); - // Selectors are always pointers to GlobalVariables with 'struct' type. - // The struct has two fields, adjectives and a type descriptor. - auto *CS = cast(GV->getInitializer()); - HT.Adjectives = - cast(CS->getAggregateElement(0U))->getZExtValue(); - HT.TypeDescriptor = - cast(CS->getAggregateElement(1)->stripPointerCasts()); - } - HT.Handler = cast(CH->getHandlerBlockOrFunc()); - HT.CatchObjRecoverIdx = CH->getExceptionVarIndex(); - HT.CatchObj.Alloca = nullptr; - TBME.HandlerArray.push_back(HT); - } - FuncInfo.TryBlockMap.push_back(TBME); -} - -static void print_name(const Value *V) { -#ifndef NDEBUG - if (!V) { - DEBUG(dbgs() << "null"); - return; - } - - if (const auto *F = dyn_cast(V)) - DEBUG(dbgs() << F->getName()); - else - DEBUG(V->dump()); -#endif -} - -void WinEHNumbering::processCallSite( - MutableArrayRef> Actions, - ImmutableCallSite CS) { - DEBUG(dbgs() << "processCallSite (EH state = " << currentEHNumber() - << ") for: "); - print_name(CS ? CS.getCalledValue() : nullptr); - DEBUG(dbgs() << '\n'); - - DEBUG(dbgs() << "HandlerStack: \n"); - for (int I = 0, E = HandlerStack.size(); I < E; ++I) { - DEBUG(dbgs() << " "); - print_name(HandlerStack[I]->getHandlerBlockOrFunc()); - DEBUG(dbgs() << '\n'); - } - DEBUG(dbgs() << "Actions: \n"); - for (int I = 0, E = Actions.size(); I < E; ++I) { - DEBUG(dbgs() << " "); - print_name(Actions[I]->getHandlerBlockOrFunc()); - DEBUG(dbgs() << '\n'); - } - int FirstMismatch = 0; - for (int E = std::min(HandlerStack.size(), Actions.size()); FirstMismatch < E; - ++FirstMismatch) { - if (HandlerStack[FirstMismatch]->getHandlerBlockOrFunc() != - Actions[FirstMismatch]->getHandlerBlockOrFunc()) - break; - } - - // Remove unmatched actions from the stack and process their EH states. - popUnmatchedActions(FirstMismatch); - - DEBUG(dbgs() << "Pushing actions for CallSite: "); - print_name(CS ? CS.getCalledValue() : nullptr); - DEBUG(dbgs() << '\n'); - - bool LastActionWasCatch = false; - const LandingPadInst *LastRootLPad = nullptr; - for (size_t I = FirstMismatch; I != Actions.size(); ++I) { - // We can reuse eh states when pushing two catches for the same invoke. - bool CurrActionIsCatch = isa(Actions[I].get()); - auto *Handler = cast(Actions[I]->getHandlerBlockOrFunc()); - // Various conditions can lead to a handler being popped from the - // stack and re-pushed later. That shouldn't create a new state. - // FIXME: Can code optimization lead to re-used handlers? - if (FuncInfo.HandlerEnclosedState.count(Handler)) { - // If we already assigned the state enclosed by this handler re-use it. - Actions[I]->setEHState(FuncInfo.HandlerEnclosedState[Handler]); - continue; - } - const LandingPadInst* RootLPad = FuncInfo.RootLPad[Handler]; - if (CurrActionIsCatch && LastActionWasCatch && RootLPad == LastRootLPad) { - DEBUG(dbgs() << "setEHState for handler to " << currentEHNumber() << "\n"); - Actions[I]->setEHState(currentEHNumber()); - } else { - DEBUG(dbgs() << "createUnwindMapEntry(" << currentEHNumber() << ", "); - print_name(Actions[I]->getHandlerBlockOrFunc()); - DEBUG(dbgs() << ") with EH state " << NextState << "\n"); - createUnwindMapEntry(currentEHNumber(), Actions[I].get()); - DEBUG(dbgs() << "setEHState for handler to " << NextState << "\n"); - Actions[I]->setEHState(NextState); - NextState++; - } - HandlerStack.push_back(std::move(Actions[I])); - LastActionWasCatch = CurrActionIsCatch; - LastRootLPad = RootLPad; - } - - // This is used to defer numbering states for a handler until after the - // last time it appears in an invoke action list. - if (CS.isInvoke()) { - for (int I = 0, E = HandlerStack.size(); I < E; ++I) { - auto *Handler = cast(HandlerStack[I]->getHandlerBlockOrFunc()); - if (FuncInfo.LastInvoke[Handler] != cast(CS.getInstruction())) - continue; - FuncInfo.LastInvokeVisited[Handler] = true; - DEBUG(dbgs() << "Last invoke of "); - print_name(Handler); - DEBUG(dbgs() << " has been visited.\n"); - } - } - - DEBUG(dbgs() << "In EHState " << currentEHNumber() << " for CallSite: "); - print_name(CS ? CS.getCalledValue() : nullptr); - DEBUG(dbgs() << '\n'); -} - -void WinEHNumbering::popUnmatchedActions(int FirstMismatch) { - // Don't recurse while we are looping over the handler stack. Instead, defer - // the numbering of the catch handlers until we are done popping. - SmallVector PoppedCatches; - for (int I = HandlerStack.size() - 1; I >= FirstMismatch; --I) { - std::unique_ptr Handler = HandlerStack.pop_back_val(); - if (isa(Handler.get())) - PoppedCatches.push_back(cast(Handler.release())); - } - - int TryHigh = NextState - 1; - int LastTryLowIdx = 0; - for (int I = 0, E = PoppedCatches.size(); I != E; ++I) { - CatchHandler *CH = PoppedCatches[I]; - DEBUG(dbgs() << "Popped handler with state " << CH->getEHState() << "\n"); - if (I + 1 == E || CH->getEHState() != PoppedCatches[I + 1]->getEHState()) { - int TryLow = CH->getEHState(); - auto Handlers = - makeArrayRef(&PoppedCatches[LastTryLowIdx], I - LastTryLowIdx + 1); - DEBUG(dbgs() << "createTryBlockMapEntry(" << TryLow << ", " << TryHigh); - for (size_t J = 0; J < Handlers.size(); ++J) { - DEBUG(dbgs() << ", "); - print_name(Handlers[J]->getHandlerBlockOrFunc()); - } - DEBUG(dbgs() << ")\n"); - createTryBlockMapEntry(TryLow, TryHigh, Handlers); - LastTryLowIdx = I + 1; - } - } - - for (CatchHandler *CH : PoppedCatches) { - if (auto *F = dyn_cast(CH->getHandlerBlockOrFunc())) { - if (FuncInfo.LastInvokeVisited[F]) { - DEBUG(dbgs() << "Assigning base state " << NextState << " to "); - print_name(F); - DEBUG(dbgs() << '\n'); - FuncInfo.HandlerBaseState[F] = NextState; - DEBUG(dbgs() << "createUnwindMapEntry(" << currentEHNumber() - << ", null)\n"); - createUnwindMapEntry(currentEHNumber(), nullptr); - ++NextState; - calculateStateNumbers(*F); - } - else { - DEBUG(dbgs() << "Deferring handling of "); - print_name(F); - DEBUG(dbgs() << " until last invoke visited.\n"); - } - } - delete CH; - } -} - -void WinEHNumbering::calculateStateNumbers(const Function &F) { - auto I = VisitedHandlers.insert(&F); - if (!I.second) - return; // We've already visited this handler, don't renumber it. - - int OldBaseState = CurrentBaseState; - if (FuncInfo.HandlerBaseState.count(&F)) { - CurrentBaseState = FuncInfo.HandlerBaseState[&F]; - } - - size_t SavedHandlerStackSize = HandlerStack.size(); - - DEBUG(dbgs() << "Calculating state numbers for: " << F.getName() << '\n'); - SmallVector, 4> ActionList; - for (const BasicBlock &BB : F) { - for (const Instruction &I : BB) { - const auto *CI = dyn_cast(&I); - if (!CI || CI->doesNotThrow()) - continue; - processCallSite(None, CI); - } - const auto *II = dyn_cast(BB.getTerminator()); - if (!II) - continue; - const LandingPadInst *LPI = II->getLandingPadInst(); - auto *ActionsCall = dyn_cast(LPI->getNextNode()); - if (!ActionsCall) - continue; - parseEHActions(ActionsCall, ActionList); - if (ActionList.empty()) - continue; - processCallSite(ActionList, II); - ActionList.clear(); - FuncInfo.EHPadStateMap[LPI] = currentEHNumber(); - DEBUG(dbgs() << "Assigning state " << currentEHNumber() - << " to landing pad at " << LPI->getParent()->getName() - << '\n'); - } - - // Pop any actions that were pushed on the stack for this function. - popUnmatchedActions(SavedHandlerStackSize); - - DEBUG(dbgs() << "Assigning max state " << NextState - 1 - << " to " << F.getName() << '\n'); - FuncInfo.CatchHandlerMaxState[&F] = NextState - 1; - - CurrentBaseState = OldBaseState; -} - -// This function follows the same basic traversal as calculateStateNumbers -// but it is necessary to identify the root landing pad associated -// with each action before we start assigning state numbers. -void WinEHNumbering::findActionRootLPads(const Function &F) { - auto I = VisitedHandlers.insert(&F); - if (!I.second) - return; // We've already visited this handler, don't revisit it. - - SmallVector, 4> ActionList; - for (const BasicBlock &BB : F) { - const auto *II = dyn_cast(BB.getTerminator()); - if (!II) - continue; - const LandingPadInst *LPI = II->getLandingPadInst(); - auto *ActionsCall = dyn_cast(LPI->getNextNode()); - if (!ActionsCall) - continue; - - assert(ActionsCall->getIntrinsicID() == Intrinsic::eh_actions); - parseEHActions(ActionsCall, ActionList); - if (ActionList.empty()) - continue; - for (int I = 0, E = ActionList.size(); I < E; ++I) { - if (auto *Handler - = dyn_cast(ActionList[I]->getHandlerBlockOrFunc())) { - FuncInfo.LastInvoke[Handler] = II; - // Don't replace the root landing pad if we previously saw this - // handler in a different function. - if (FuncInfo.RootLPad.count(Handler) && - FuncInfo.RootLPad[Handler]->getParent()->getParent() != &F) - continue; - DEBUG(dbgs() << "Setting root lpad for "); - print_name(Handler); - DEBUG(dbgs() << " to " << LPI->getParent()->getName() << '\n'); - FuncInfo.RootLPad[Handler] = LPI; - } - } - // Walk the actions again and look for nested handlers. This has to - // happen after all of the actions have been processed in the current - // function. - for (int I = 0, E = ActionList.size(); I < E; ++I) - if (auto *Handler - = dyn_cast(ActionList[I]->getHandlerBlockOrFunc())) - findActionRootLPads(*Handler); - ActionList.clear(); - } -} - static const CatchPadInst *getSingleCatchPadPredecessor(const BasicBlock *BB) { for (const BasicBlock *PredBlock : predecessors(BB)) if (auto *CPI = dyn_cast(PredBlock->getFirstNonPHI())) @@ -3158,29 +2805,30 @@ static bool doesEHPadUnwindToCaller(const Instruction *EHPad) { return cast(User)->unwindsToCaller(); } -void llvm::calculateSEHStateNumbers(const Function *ParentFn, +void llvm::calculateSEHStateNumbers(const Function *Fn, WinEHFuncInfo &FuncInfo) { // Don't compute state numbers twice. if (!FuncInfo.SEHUnwindMap.empty()) return; - for (const BasicBlock &BB : *ParentFn) { + for (const BasicBlock &BB : *Fn) { if (!BB.isEHPad() || !doesEHPadUnwindToCaller(BB.getFirstNonPHI())) continue; calculateExplicitSEHStateNumbers(FuncInfo, BB, -1); } } -void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn, +void llvm::calculateWinCXXEHStateNumbers(const Function *Fn, WinEHFuncInfo &FuncInfo) { // Return if it's already been done. if (!FuncInfo.EHPadStateMap.empty()) return; - bool IsExplicit = false; - for (const BasicBlock &BB : *ParentFn) { + for (const BasicBlock &BB : *Fn) { if (!BB.isEHPad()) continue; + if (BB.isLandingPad()) + report_fatal_error("MSVC C++ EH cannot use landingpads"); const Instruction *FirstNonPHI = BB.getFirstNonPHI(); // Skip cleanupendpads; they are exits, not entries. if (isa(FirstNonPHI)) @@ -3188,23 +2836,7 @@ void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn, if (!doesEHPadUnwindToCaller(FirstNonPHI)) continue; calculateExplicitCXXStateNumbers(FuncInfo, BB, -1); - IsExplicit = true; } - - if (IsExplicit) - return; - - WinEHNumbering Num(FuncInfo); - Num.findActionRootLPads(*ParentFn); - // The VisitedHandlers list is used by both findActionRootLPads and - // calculateStateNumbers, but both functions need to visit all handlers. - Num.VisitedHandlers.clear(); - Num.calculateStateNumbers(*ParentFn); - // Pop everything on the handler stack. - // It may be necessary to call this more than once because a handler can - // be pushed on the stack as a result of clearing the stack. - while (!Num.HandlerStack.empty()) - Num.processCallSite(None, ImmutableCallSite()); } void WinEHPrepare::replaceTerminatePadWithCleanup(Function &F) { diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 00b88c68d5c..6f337984336 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2656,7 +2656,6 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, const Function *WinEHParent = nullptr; if (MMI.hasWinEHFuncInfo(Fn)) WinEHParent = MMI.getWinEHParent(Fn); - bool IsWinEHOutlined = WinEHParent && WinEHParent != Fn; bool IsWinEHParent = WinEHParent && WinEHParent == Fn; // Figure out if XMM registers are in use. @@ -2748,28 +2747,6 @@ X86TargetLowering::LowerFormalArguments(SDValue Chain, if (!MemOps.empty()) Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps); - } else if (IsWin64 && IsWinEHOutlined) { - // Get to the caller-allocated home save location. Add 8 to account - // for the return address. - int HomeOffset = TFI.getOffsetOfLocalArea() + 8; - FuncInfo->setRegSaveFrameIndex(MFI->CreateFixedObject( - /*Size=*/1, /*SPOffset=*/HomeOffset + 8, /*Immutable=*/false)); - - MMI.getWinEHFuncInfo(Fn) - .CatchHandlerParentFrameObjIdx[const_cast(Fn)] = - FuncInfo->getRegSaveFrameIndex(); - - // Store the second integer parameter (rdx) into rsp+16 relative to the - // stack pointer at the entry of the function. - SDValue RSFIN = DAG.getFrameIndex(FuncInfo->getRegSaveFrameIndex(), - getPointerTy(DAG.getDataLayout())); - unsigned GPR = MF.addLiveIn(X86::RDX, &X86::GR64RegClass); - SDValue Val = DAG.getCopyFromReg(Chain, dl, GPR, MVT::i64); - Chain = DAG.getStore( - Val.getValue(1), dl, Val, RSFIN, - MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), - FuncInfo->getRegSaveFrameIndex()), - /*isVolatile=*/true, /*isNonTemporal=*/false, /*Alignment=*/0); } if (isVarArg && MFI->hasMustTailInVarArgFunc()) { diff --git a/lib/Target/X86/X86WinEHState.cpp b/lib/Target/X86/X86WinEHState.cpp index d1206ec0ee0..d148be618ed 100644 --- a/lib/Target/X86/X86WinEHState.cpp +++ b/lib/Target/X86/X86WinEHState.cpp @@ -437,23 +437,6 @@ void WinEHStatePass::addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo) { // Set up RegNodeEscapeIndex int RegNodeEscapeIndex = escapeRegNode(F); FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex; - - // Only insert stores in catch handlers. - Constant *FI8 = - ConstantExpr::getBitCast(&F, Type::getInt8PtrTy(TheModule->getContext())); - for (auto P : FuncInfo.HandlerBaseState) { - Function *Handler = const_cast(P.first); - int BaseState = P.second; - IRBuilder<> Builder(&Handler->getEntryBlock(), - Handler->getEntryBlock().begin()); - // FIXME: Find and reuse such a call if present. - Value *ParentFP = Builder.CreateCall(FrameAddress, {Builder.getInt32(1)}); - Value *RecoveredRegNode = Builder.CreateCall( - FrameRecover, {FI8, ParentFP, Builder.getInt32(RegNodeEscapeIndex)}); - RecoveredRegNode = - Builder.CreateBitCast(RecoveredRegNode, RegNodeTy->getPointerTo(0)); - addStateStoresToFunclet(RecoveredRegNode, FuncInfo, *Handler, BaseState); - } } /// Escape RegNode so that we can access it from child handlers. Find the call diff --git a/test/CodeGen/WinEH/cppeh-prepared-catch-all.ll b/test/CodeGen/WinEH/cppeh-prepared-catch-all.ll deleted file mode 100644 index 31b5e58562b..00000000000 --- a/test/CodeGen/WinEH/cppeh-prepared-catch-all.ll +++ /dev/null @@ -1,47 +0,0 @@ -; RUN: llc < %s | FileCheck %s - -target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-pc-windows-msvc" - -; This test case is equivalent to: -; extern "C" void may_throw(); -; extern "C" void test_catch_all() { -; try { -; may_throw(); -; } catch (...) { -; } -; } - -declare void @may_throw() #1 -declare i32 @__CxxFrameHandler3(...) -declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #2 -declare void @llvm.eh.endcatch() #2 - -; Function Attrs: nounwind uwtable -define void @test_catch_all() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - invoke void @may_throw() - to label %try.cont unwind label %lpad - -lpad: ; preds = %entry - %0 = landingpad { i8*, i32 } - catch i8* null - %1 = extractvalue { i8*, i32 } %0, 0 - tail call void @llvm.eh.begincatch(i8* %1, i8* null) #2 - tail call void @llvm.eh.endcatch() #2 - br label %try.cont - -try.cont: ; preds = %entry, %lpad - ret void -} - -; CHECK-LABEL: $handlerMap$0$test_catch_all: -; CHECK: .long {{[0-9]+}} -; CHECK: .long 0 -; CHECK: .long 0 -; CHECK: .long test_catch_all.catch@IMGREL -; CHECK: .long .Ltest_catch_all.catch$parent_frame_offset - -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 } diff --git a/test/CodeGen/WinEH/cppeh-prepared-catch-reordered.ll b/test/CodeGen/WinEH/cppeh-prepared-catch-reordered.ll deleted file mode 100644 index 2d31a1d5cf4..00000000000 --- a/test/CodeGen/WinEH/cppeh-prepared-catch-reordered.ll +++ /dev/null @@ -1,165 +0,0 @@ -; RUN: llc < %s | FileCheck %s - -; Verify that we get the right frame escape label when the catch comes after the -; parent function. - -; This test case is equivalent to: -; int main() { -; try { -; throw 42; -; } catch (int e) { -; printf("e: %d\n", e); -; } -; } - -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 } -%eh.CatchHandlerType = type { i32, i8* } - -$"\01??_R0H@8" = comdat any - -$"_CT??_R0H@84" = comdat any - -$_CTA1H = comdat any - -$_TI1H = comdat any - -$"\01??_C@_06PNOAJMHG@e?3?5?$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 -@__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 -@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??_C@_06PNOAJMHG@e?3?5?$CFd?6?$AA@" = linkonce_odr unnamed_addr constant [7 x i8] c"e: %d\0A\00", comdat, align 1 - -declare void @_CxxThrowException(i8*, %eh.ThrowInfo*) - -; Function Attrs: uwtable -define i32 @main() #1 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %tmp.i = alloca i32, align 4 - %e = alloca i32, align 4 - %0 = bitcast i32* %tmp.i to i8* - store i32 42, i32* %tmp.i, align 4, !tbaa !2 - call void (...) @llvm.localescape(i32* %e) - invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* @_TI1H) #6 - to label %.noexc unwind label %lpad1 - -.noexc: ; preds = %entry - unreachable - -lpad1: ; preds = %entry - %1 = landingpad { i8*, i32 } - catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0 - %recover = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*), i32 0, i8* (i8*, i8*)* @main.catch) - indirectbr i8* %recover, [label %try.cont.split] - -try.cont.split: ; preds = %lpad1 - ret i32 0 -} - -; CHECK-LABEL: main: -; CHECK: .seh_handlerdata -; CHECK: .long ($cppxdata$main)@IMGREL - -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 i32 @printf(i8* nocapture readonly, ...) #4 - -; Function Attrs: nounwind -declare void @llvm.eh.endcatch() #3 - -; Function Attrs: nounwind -declare void @llvm.lifetime.start(i64, i8* nocapture) #3 - -; Function Attrs: nounwind -declare i8* @llvm.eh.actions(...) #3 - -define internal i8* @main.catch(i8*, i8*) #5 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %e.i8 = call i8* @llvm.localrecover(i8* bitcast (i32 ()* @main to i8*), i8* %1, i32 0) - %e = bitcast i8* %e.i8 to i32* - %2 = bitcast i32* %e to i8* - %3 = load i32, i32* %e, align 4, !tbaa !2 - %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @"\01??_C@_06PNOAJMHG@e?3?5?$CFd?6?$AA@", i64 0, i64 0), i32 %3) - invoke void @llvm.donothing() - to label %entry.split unwind label %stub - -entry.split: ; preds = %entry - ret i8* blockaddress(@main, %try.cont.split) - -stub: ; preds = %entry - %4 = landingpad { i8*, i32 } - cleanup - %recover = call i8* (...) @llvm.eh.actions() - unreachable -} - -; CHECK-LABEL: main.catch: -; CHECK: .seh_handlerdata -; CHECK: .long ($cppxdata$main)@IMGREL - -; CHECK: .align 4 -; CHECK-NEXT: $cppxdata$main: -; CHECK-NEXT: .long 429065506 -; CHECK-NEXT: .long 2 -; CHECK-NEXT: .long ($stateUnwindMap$main)@IMGREL -; CHECK-NEXT: .long 1 -; CHECK-NEXT: .long ($tryMap$main)@IMGREL -; CHECK-NEXT: .long 3 -; CHECK-NEXT: .long ($ip2state$main)@IMGREL -; CHECK-NEXT: .long 40 -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 1 - -; Make sure we get the right frame escape label. - -; CHECK: $handlerMap$0$main: -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long "??_R0H@8"@IMGREL -; CHECK-NEXT: .long .Lmain$frame_escape_0 -; CHECK-NEXT: .long main.catch@IMGREL -; CHECK-NEXT: .long .Lmain.catch$parent_frame_offset - -; Function Attrs: nounwind readnone -declare void @llvm.donothing() #2 - -; Function Attrs: nounwind -declare void @llvm.localescape(...) #3 - -; Function Attrs: nounwind readnone -declare i8* @llvm.localrecover(i8*, i8*, i32) #2 - -attributes #0 = { noreturn 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" "wineh-parent"="main" } -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" "target-cpu"="x86-64" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #5 = { "wineh-parent"="main" } -attributes #6 = { noreturn } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 "} -!2 = !{!3, !3, i64 0} -!3 = !{!"int", !4, i64 0} -!4 = !{!"omnipotent char", !5, i64 0} -!5 = !{!"Simple C/C++ TBAA"} - diff --git a/test/CodeGen/WinEH/cppeh-prepared-catch.ll b/test/CodeGen/WinEH/cppeh-prepared-catch.ll deleted file mode 100644 index a5d86dceea9..00000000000 --- a/test/CodeGen/WinEH/cppeh-prepared-catch.ll +++ /dev/null @@ -1,232 +0,0 @@ -; RUN: llc -mtriple=x86_64-windows-msvc < %s | FileCheck %s --check-prefix=CHECK --check-prefix=X64 -; RUN: llc -mtriple=i686-windows-msvc < %s | FileCheck %s --check-prefix=CHECK --check-prefix=X86 - -; This test case is equivalent to: -; void f() { -; try { -; try { -; may_throw(); -; } catch (int &) { -; may_throw(); -; } -; may_throw(); -; } catch (double) { -; } -; } - - -%rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] } -%eh.CatchHandlerType = type { i32, i8* } - -$"\01??_R0N@8" = comdat any - -$"\01??_R0H@8" = comdat any - -@"\01??_7type_info@@6B@" = external constant i8* -@"\01??_R0N@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".N\00" }, comdat -@llvm.eh.handlertype.N.0 = private unnamed_addr constant %eh.CatchHandlerType { i32 0, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0N@8" to i8*) }, section "llvm.metadata" -@"\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.8 = private unnamed_addr constant %eh.CatchHandlerType { i32 8, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) }, section "llvm.metadata" - -define internal i8* @"\01?f@@YAXXZ.catch"(i8*, i8*) #4 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %.i8 = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?f@@YAXXZ" to i8*), i8* %1, i32 0) - %bc2 = bitcast i8* %.i8 to i32** - %bc3 = bitcast i32** %bc2 to i8* - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont2 unwind label %lpad1 - -invoke.cont2: ; preds = %entry - ret i8* blockaddress(@"\01?f@@YAXXZ", %try.cont) - -lpad1: ; preds = %entry - %lp4 = landingpad { i8*, i32 } - cleanup - catch %eh.CatchHandlerType* @llvm.eh.handlertype.N.0 - %recover = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.N.0 to i8*), i32 1, i8* (i8*, i8*)* @"\01?f@@YAXXZ.catch1") - indirectbr i8* %recover, [label %invoke.cont2] -} - -; CHECK-LABEL: "?f@@YAXXZ.catch": -; No code should be generated for the indirectbr. -; CHECK-NOT: jmp{{[ql]}} * -; X64: .seh_handlerdata -; X64-NEXT: .long ("$cppxdata$?f@@YAXXZ")@IMGREL - - -define internal i8* @"\01?f@@YAXXZ.catch1"(i8*, i8*) #4 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %.i8 = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?f@@YAXXZ" to i8*), i8* %1, i32 1) - %2 = bitcast i8* %.i8 to double* - %3 = bitcast double* %2 to i8* - invoke void () @llvm.donothing() - to label %done unwind label %lpad - -done: - ret i8* blockaddress(@"\01?f@@YAXXZ", %try.cont8) - -lpad: ; preds = %entry - %4 = landingpad { i8*, i32 } - cleanup - %recover = call i8* (...) @llvm.eh.actions() - unreachable -} - -; CHECK-LABEL: "?f@@YAXXZ.catch1": -; No code should be generated for the indirectbr. -; CHECK-NOT: jmp{{[ql]}} * -; X64: ".L?f@@YAXXZ.catch1$parent_frame_offset" = 16 -; X64: movq %rdx, 16(%rsp) -; X64: .seh_handlerdata -; X64: .long ("$cppxdata$?f@@YAXXZ")@IMGREL - -define void @"\01?f@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - %0 = alloca i32*, align 8 - %1 = alloca double, align 8 - call void (...) @llvm.localescape(i32** %0, double* %1) - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont unwind label %lpad2 - -invoke.cont: ; preds = %entry - br label %try.cont - -lpad2: ; preds = %entry - %2 = landingpad { i8*, i32 } - catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.8 - catch %eh.CatchHandlerType* @llvm.eh.handlertype.N.0 - %recover = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.8 to i8*), i32 0, i8* (i8*, i8*)* @"\01?f@@YAXXZ.catch", i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.N.0 to i8*), i32 1, i8* (i8*, i8*)* @"\01?f@@YAXXZ.catch1") - indirectbr i8* %recover, [label %try.cont, label %try.cont8] - -try.cont: ; preds = %lpad2, %invoke.cont - invoke void @"\01?may_throw@@YAXXZ"() - to label %try.cont8 unwind label %lpad1 - -lpad1: - %3 = landingpad { i8*, i32 } - catch %eh.CatchHandlerType* @llvm.eh.handlertype.N.0 - %recover2 = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.N.0 to i8*), i32 1, i8* (i8*, i8*)* @"\01?f@@YAXXZ.catch1") - indirectbr i8* %recover2, [label %try.cont8] - -try.cont8: ; preds = %lpad2, %try.cont - ret void -} - -; CHECK-LABEL: "?f@@YAXXZ": -; No code should be generated for the indirectbr. -; CHECK-NOT: jmp{{[ql]}} * - -; X64: .seh_handlerdata -; X64-NEXT: .long ("$cppxdata$?f@@YAXXZ")@IMGREL -; X86: .section .xdata,"dr" - -; CHECK: .align 4 - -; X64: "$cppxdata$?f@@YAXXZ": -; X64-NEXT: .long 429065506 -; X64-NEXT: .long 4 -; X64-NEXT: .long ("$stateUnwindMap$?f@@YAXXZ")@IMGREL -; X64-NEXT: .long 2 -; X64-NEXT: .long ("$tryMap$?f@@YAXXZ")@IMGREL -; X64-NEXT: .long 6 -; X64-NEXT: .long ("$ip2state$?f@@YAXXZ")@IMGREL -; X64-NEXT: .long 32 -; X64-NEXT: .long 0 -; X64-NEXT: .long 1 - -; X86: "L__ehtable$?f@@YAXXZ": -; X86-NEXT: .long 429065506 -; X86-NEXT: .long 4 -; X86-NEXT: .long ("$stateUnwindMap$?f@@YAXXZ") -; X86-NEXT: .long 2 -; X86-NEXT: .long ("$tryMap$?f@@YAXXZ") -; X86-NEXT: .long 0 -; X86-NEXT: .long 0 -; X86-NEXT: .long 0 -; X86-NEXT: .long 1 - - -; CHECK-NEXT:"$stateUnwindMap$?f@@YAXXZ": -; CHECK-NEXT: .long -1 -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long -1 -; CHECK-NEXT: .long 0 -; CHECK-NEXT:"$tryMap$?f@@YAXXZ": -; CHECK-NEXT: .long 1 -; CHECK-NEXT: .long 1 -; CHECK-NEXT: .long 2 -; CHECK-NEXT: .long 1 -; CHECK-NEXT: .long ("$handlerMap$0$?f@@YAXXZ") -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 2 -; CHECK-NEXT: .long 3 -; CHECK-NEXT: .long 1 -; CHECK-NEXT: .long ("$handlerMap$1$?f@@YAXXZ") -; CHECK-NEXT:"$handlerMap$0$?f@@YAXXZ": -; CHECK-NEXT: .long 8 -; CHECK-NEXT: .long "??_R0H@8" -; CHECK-NEXT: .long "{{.?}}L?f@@YAXXZ$frame_escape_0" -; CHECK-NEXT: .long "?f@@YAXXZ.catch" -; X64-NEXT: .long ".L?f@@YAXXZ.catch$parent_frame_offset" -; CHECK-NEXT:"$handlerMap$1$?f@@YAXXZ": -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long "??_R0N@8" -; CHECK-NEXT: .long "{{.?}}L?f@@YAXXZ$frame_escape_1" -; CHECK-NEXT: .long "?f@@YAXXZ.catch1" -; X64-NEXT: .long ".L?f@@YAXXZ.catch1$parent_frame_offset" - -; X64-NEXT:"$ip2state$?f@@YAXXZ": -; X64-NEXT: .long .Lfunc_begin0 -; X64-NEXT: .long 2 -; X64-NEXT: .long .Ltmp0 -; X64-NEXT: .long 0 -; X64-NEXT: .long .Lfunc_begin1 -; X64-NEXT: .long 3 -; X64-NEXT: .long .Lfunc_begin2 -; X64-NEXT: .long -1 -; X64-NEXT: .long .Ltmp13 -; X64-NEXT: .long 1 -; X64-NEXT: .long .Ltmp16 -; X64-NEXT: .long 0 - - -; X86: "___ehhandler$?f@@YAXXZ": # @"__ehhandler$?f@@YAXXZ" -; X86: movl $"L__ehtable$?f@@YAXXZ", %eax -; X86: jmp ___CxxFrameHandler3 # TAILCALL - - -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 - -; Function Attrs: nounwind -declare i8* @llvm.eh.actions(...) #3 - -; Function Attrs: nounwind -declare void @llvm.localescape(...) #3 - -; Function Attrs: nounwind readnone -declare i8* @llvm.localrecover(i8*, i8*, i32) #2 - -declare void @llvm.donothing() - -attributes #0 = { "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" "wineh-parent"="?f@@YAXXZ" } -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 = { "wineh-parent"="?f@@YAXXZ" } diff --git a/test/CodeGen/WinEH/cppeh-prepared-cleanups.ll b/test/CodeGen/WinEH/cppeh-prepared-cleanups.ll deleted file mode 100644 index b5cfd65030a..00000000000 --- a/test/CodeGen/WinEH/cppeh-prepared-cleanups.ll +++ /dev/null @@ -1,245 +0,0 @@ -; RUN: llc < %s | FileCheck %s - -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 } -%struct.S = type { i8 } - -$"\01??_DS@@QEAA@XZ" = comdat any - -$"\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: "?test1@@YAXXZ": -; CHECK: .seh_handlerdata -; CHECK-NEXT: .long ("$cppxdata$?test1@@YAXXZ")@IMGREL -; CHECK-NEXT: .align 4 -; CHECK-NEXT:"$cppxdata$?test1@@YAXXZ": -; CHECK-NEXT: .long 429065506 -; CHECK-NEXT: .long 1 -; CHECK-NEXT: .long ("$stateUnwindMap$?test1@@YAXXZ")@IMGREL -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 2 -; CHECK-NEXT: .long ("$ip2state$?test1@@YAXXZ")@IMGREL -; CHECK-NEXT: .long 32 -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 1 -; CHECK-NEXT:"$stateUnwindMap$?test1@@YAXXZ": -; CHECK-NEXT: .long -1 -; CHECK-NEXT: .long "?test1@@YAXXZ.cleanup"@IMGREL -; CHECK-NEXT:"$ip2state$?test1@@YAXXZ": -; CHECK-NEXT: .long .Lfunc_begin0@IMGREL -; CHECK-NEXT: .long -1 -; CHECK-NEXT: .long .Ltmp0@IMGREL -; CHECK-NEXT: .long 0 - -define void @"\01?test1@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %unwindhelp = alloca i64 - %tmp = alloca i32, align 4 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - store i32 0, i32* %tmp - %0 = bitcast i32* %tmp to i8* - call void (...) @llvm.localescape() - store volatile i64 -2, i64* %unwindhelp - %1 = bitcast i64* %unwindhelp to i8* - call void @llvm.eh.unwindhelp(i8* %1) - invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* @_TI1H) #8 - to label %unreachable unwind label %lpad1 - -lpad1: ; preds = %entry - %2 = landingpad { i8*, i32 } - cleanup - %recover = call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @"\01?test1@@YAXXZ.cleanup") - indirectbr i8* %recover, [] - -unreachable: ; preds = %entry - unreachable -} - -declare void @_CxxThrowException(i8*, %eh.ThrowInfo*) - -declare i32 @__CxxFrameHandler3(...) - -; Function Attrs: nounwind -define linkonce_odr void @"\01??_DS@@QEAA@XZ"(%struct.S* %this) unnamed_addr #1 comdat align 2 { -entry: - %this.addr = alloca %struct.S*, align 8 - store %struct.S* %this, %struct.S** %this.addr, align 8 - %this1 = load %struct.S*, %struct.S** %this.addr - call void @"\01??1S@@QEAA@XZ"(%struct.S* %this1) #4 - ret void -} - -; CHECK-LABEL: "?test2@@YAX_N@Z": -; CHECK: .seh_handlerdata -; CHECK-NEXT: .long ("$cppxdata$?test2@@YAX_N@Z")@IMGREL -; CHECK-NEXT: .align 4 -; CHECK-NEXT:"$cppxdata$?test2@@YAX_N@Z": -; CHECK-NEXT: .long 429065506 -; CHECK-NEXT: .long 2 -; CHECK-NEXT: .long ("$stateUnwindMap$?test2@@YAX_N@Z")@IMGREL -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 4 -; CHECK-NEXT: .long ("$ip2state$?test2@@YAX_N@Z")@IMGREL -; CHECK-NEXT: .long 40 -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 1 -; CHECK-NEXT:"$stateUnwindMap$?test2@@YAX_N@Z": -; CHECK-NEXT: .long -1 -; CHECK-NEXT: .long "?test2@@YAX_N@Z.cleanup"@IMGREL -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long "?test2@@YAX_N@Z.cleanup1"@IMGREL -; CHECK-NEXT:"$ip2state$?test2@@YAX_N@Z": -; CHECK-NEXT: .long .Lfunc_begin1@IMGREL -; CHECK-NEXT: .long -1 -; CHECK-NEXT: .long .Ltmp7@IMGREL -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long .Ltmp9@IMGREL -; CHECK-NEXT: .long 1 -; CHECK-NEXT: .long .Ltmp12@IMGREL -; CHECK-NEXT: .long 0 - -define void @"\01?test2@@YAX_N@Z"(i1 zeroext %b) #2 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { - %b.addr = alloca i8, align 1 - %s = alloca %struct.S, align 1 - %exn.slot = alloca i8* - %ehselector.slot = alloca i32 - %s1 = alloca %struct.S, align 1 - %frombool = zext i1 %b to i8 - store i8 %frombool, i8* %b.addr, align 1 - call void (...) @llvm.localescape(%struct.S* %s, %struct.S* %s1) - call void @"\01?may_throw@@YAXXZ"() - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont unwind label %lpad1 - -invoke.cont: ; preds = %entry - %1 = load i8, i8* %b.addr, align 1 - %tobool = trunc i8 %1 to i1 - br i1 %tobool, label %if.then, label %if.else - -if.then: ; preds = %invoke.cont - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont3 unwind label %lpad3 - -invoke.cont3: ; preds = %if.then - call void @"\01??_DS@@QEAA@XZ"(%struct.S* %s1) #4 - br label %if.end - -lpad1: ; preds = %entry, %if.end - %2 = landingpad { i8*, i32 } - cleanup - %recover = call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @"\01?test2@@YAX_N@Z.cleanup") - indirectbr i8* %recover, [] - -lpad3: ; preds = %if.then - %3 = landingpad { i8*, i32 } - cleanup - %recover4 = call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @"\01?test2@@YAX_N@Z.cleanup1", i32 0, void (i8*, i8*)* @"\01?test2@@YAX_N@Z.cleanup") - indirectbr i8* %recover4, [] - -if.else: ; preds = %invoke.cont - call void @"\01?dont_throw@@YAXXZ"() #4 - br label %if.end - -if.end: ; preds = %if.else, %invoke.cont3 - invoke void @"\01?may_throw@@YAXXZ"() - to label %invoke.cont4 unwind label %lpad1 - -invoke.cont4: ; preds = %if.end - call void @"\01??_DS@@QEAA@XZ"(%struct.S* %s) #4 - ret void -} - -declare void @"\01?may_throw@@YAXXZ"() #3 - -; Function Attrs: nounwind -declare void @"\01?dont_throw@@YAXXZ"() #1 - -; Function Attrs: nounwind -declare void @"\01??1S@@QEAA@XZ"(%struct.S*) #1 - -; Function Attrs: nounwind -declare i8* @llvm.eh.actions(...) #4 - -define internal void @"\01?test1@@YAXXZ.cleanup"(i8*, i8*) #5 { -entry: - %s = alloca %struct.S, align 1 - call void @"\01??_DS@@QEAA@XZ"(%struct.S* %s) #4 - ret void -} - -; Function Attrs: nounwind -declare void @llvm.localescape(...) #4 - -; Function Attrs: nounwind readnone -declare i8* @llvm.localrecover(i8*, i8*, i32) #6 - -; Function Attrs: nounwind -declare void @llvm.eh.unwindhelp(i8*) #4 - -define internal void @"\01?test2@@YAX_N@Z.cleanup"(i8*, i8*) #7 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %s.i8 = call i8* @llvm.localrecover(i8* bitcast (void (i1)* @"\01?test2@@YAX_N@Z" to i8*), i8* %1, i32 0) - %s = bitcast i8* %s.i8 to %struct.S* - call void @"\01??_DS@@QEAA@XZ"(%struct.S* %s) #4 - invoke void @llvm.donothing() - to label %entry.split unwind label %stub - -entry.split: ; preds = %entry - ret void - -stub: ; preds = %entry - %2 = landingpad { i8*, i32 } - cleanup - unreachable -} - -define internal void @"\01?test2@@YAX_N@Z.cleanup1"(i8*, i8*) #7 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %s1.i8 = call i8* @llvm.localrecover(i8* bitcast (void (i1)* @"\01?test2@@YAX_N@Z" to i8*), i8* %1, i32 1) - %s1 = bitcast i8* %s1.i8 to %struct.S* - call void @"\01??_DS@@QEAA@XZ"(%struct.S* %s1) #4 - invoke void @llvm.donothing() - to label %entry.split unwind label %stub - -entry.split: ; preds = %entry - ret void - -stub: ; preds = %entry - %2 = landingpad { i8*, i32 } - cleanup - unreachable -} - -declare void @llvm.donothing() - -attributes #0 = { "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" "wineh-parent"="?test1@@YAXXZ" } -attributes #1 = { 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 #2 = { "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" "wineh-parent"="?test2@@YAX_N@Z" } -attributes #3 = { "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 = { nounwind } -attributes #5 = { "wineh-parent"="?test1@@YAXXZ" } -attributes #6 = { nounwind readnone } -attributes #7 = { "wineh-parent"="?test2@@YAX_N@Z" } -attributes #8 = { noreturn } diff --git a/test/CodeGen/WinEH/cppeh-state-calc-1.ll b/test/CodeGen/WinEH/cppeh-state-calc-1.ll deleted file mode 100644 index abc5d5292cf..00000000000 --- a/test/CodeGen/WinEH/cppeh-state-calc-1.ll +++ /dev/null @@ -1,289 +0,0 @@ -; RUN: llc < %s | FileCheck %s - -; This test was generated from the following code. -; -; void test() { -; try { -; try { -; try { -; two(); -; throw 2; -; } catch (int x) { -; catch_two(); -; } -; a(); -; throw 'a'; -; } catch (char c) { -; catch_a(); -; } -; one(); -; throw 1; -; } catch(int x) { -; catch_one(); -; } catch(...) { -; catch_all(); -; } -; } -; -; The function calls before the throws were declared as 'noexcept' and are -; just here to make blocks easier to identify in the IR. - -; ModuleID = '' -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??_R0H@84" = comdat any - -$_CTA1H = comdat any - -$_TI1H = comdat any - -$"_CT??_R0D@81" = comdat any - -$_CTA1D = comdat any - -$_TI1D = 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??_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 -@"_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 - -; Function Attrs: nounwind uwtable -define void @"\01?test@@YAXXZ"() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %tmp = alloca i32, align 4 - %x = alloca i32, align 4 - %tmp2 = alloca i8, align 1 - %c = alloca i8, align 1 - %tmp11 = alloca i32, align 4 - %x21 = alloca i32, align 4 - call void @"\01?two@@YAXXZ"() #3 - store i32 2, i32* %tmp - %0 = bitcast i32* %tmp to i8* - call void (...) @llvm.localescape(i32* %x, i8* %c, i32* %x21) - invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* @_TI1H) #5 - to label %unreachable unwind label %lpad - -lpad: ; preds = %entry - %1 = landingpad { i8*, i32 } - catch i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*) - catch %eh.CatchHandlerType* @llvm.eh.handlertype.D.0 - catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0 - catch i8* null - %recover = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch", i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.D.0 to i8*), i32 1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch1", i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch2", i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch3") - indirectbr i8* %recover, [label %try.cont, label %try.cont10, label %try.cont22] - -try.cont: ; preds = %lpad - call void @"\01?a@@YAXXZ"() #3 - store i8 97, i8* %tmp2 - invoke void @_CxxThrowException(i8* %tmp2, %eh.ThrowInfo* @_TI1D) #5 - to label %unreachable unwind label %lpad3 - -lpad3: ; preds = %try.cont - %2 = landingpad { i8*, i32 } - catch %eh.CatchHandlerType* @llvm.eh.handlertype.D.0 - catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0 - catch i8* null - %recover1 = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.D.0 to i8*), i32 1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch1", i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch2", i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch3") - indirectbr i8* %recover1, [label %try.cont10, label %try.cont22] - -try.cont10: ; preds = %lpad3, %lpad - call void @"\01?one@@YAXXZ"() #3 - store i32 1, i32* %tmp11 - %3 = bitcast i32* %tmp11 to i8* - invoke void @_CxxThrowException(i8* %3, %eh.ThrowInfo* @_TI1H) #5 - to label %unreachable unwind label %lpad12 - -lpad12: ; preds = %try.cont10 - %4 = landingpad { i8*, i32 } - catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0 - catch i8* null - %recover2 = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch2", i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch3") - indirectbr i8* %recover2, [label %try.cont22] - -try.cont22: ; preds = %lpad12, %lpad3, %lpad - ret void - -unreachable: ; preds = %try.cont10, %try.cont, %entry - unreachable -} - -; Function Attrs: nounwind -declare void @"\01?two@@YAXXZ"() #1 - -declare void @_CxxThrowException(i8*, %eh.ThrowInfo*) - -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 @"\01?catch_two@@YAXXZ"() #1 - -; Function Attrs: nounwind -declare void @llvm.eh.endcatch() #3 - -; Function Attrs: nounwind -declare void @"\01?a@@YAXXZ"() #1 - -; Function Attrs: nounwind -declare void @"\01?catch_a@@YAXXZ"() #1 - -; Function Attrs: nounwind -declare void @"\01?one@@YAXXZ"() #1 - -; Function Attrs: nounwind -declare void @"\01?catch_all@@YAXXZ"() #1 - -; Function Attrs: nounwind -declare void @"\01?catch_one@@YAXXZ"() #1 - -; Function Attrs: nounwind -declare i8* @llvm.eh.actions(...) #3 - -define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*) #4 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %x.i8 = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0) - %x = bitcast i8* %x.i8 to i32* - %2 = bitcast i32* %x to i8* - call void @"\01?catch_two@@YAXXZ"() #3 - invoke void @llvm.donothing() - to label %entry.split unwind label %stub - -entry.split: ; preds = %entry - ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont) - -stub: ; preds = %entry - %3 = landingpad { i8*, i32 } - cleanup - %recover = call i8* (...) @llvm.eh.actions() - unreachable -} - -; Function Attrs: nounwind readnone -declare void @llvm.donothing() #2 - -define internal i8* @"\01?test@@YAXXZ.catch1"(i8*, i8*) #4 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - call void @"\01?catch_a@@YAXXZ"() #3 - invoke void @llvm.donothing() - to label %entry.split unwind label %stub - -entry.split: ; preds = %entry - ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont10) - -stub: ; preds = %entry - %2 = landingpad { i8*, i32 } - cleanup - %recover = call i8* (...) @llvm.eh.actions() - unreachable -} - -define internal i8* @"\01?test@@YAXXZ.catch2"(i8*, i8*) #4 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - %x21.i8 = call i8* @llvm.localrecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 2) - %x21 = bitcast i8* %x21.i8 to i32* - %2 = bitcast i32* %x21 to i8* - call void @"\01?catch_one@@YAXXZ"() #3 - invoke void @llvm.donothing() - to label %entry.split unwind label %stub - -entry.split: ; preds = %entry - ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont22) - -stub: ; preds = %entry - %3 = landingpad { i8*, i32 } - cleanup - %recover = call i8* (...) @llvm.eh.actions() - unreachable -} - -define internal i8* @"\01?test@@YAXXZ.catch3"(i8*, i8*) #4 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { -entry: - call void @"\01?catch_all@@YAXXZ"() #3 - invoke void @llvm.donothing() - to label %entry.split unwind label %stub - -entry.split: ; preds = %entry - ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont22) - -stub: ; preds = %entry - %2 = landingpad { i8*, i32 } - cleanup - %recover = call i8* (...) @llvm.eh.actions() - unreachable -} - -; Function Attrs: nounwind -declare void @llvm.localescape(...) #3 - -; Function Attrs: nounwind readnone -declare i8* @llvm.localrecover(i8*, i8*, i32) #2 - -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" "wineh-parent"="?test@@YAXXZ" } -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" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #2 = { nounwind readnone } -attributes #3 = { nounwind } -attributes #4 = { "wineh-parent"="?test@@YAXXZ" } -attributes #5 = { noreturn } - -!llvm.module.flags = !{!0} -!llvm.ident = !{!1} - -!0 = !{i32 1, !"PIC Level", i32 2} -!1 = !{!"clang version 3.7.0 (trunk 236059)"} - -; CHECK-LABEL: "$cppxdata$?test@@YAXXZ": -; CHECK-NEXT: .long 429065506 -; CHECK-NEXT: .long -; CHECK-NEXT: .long ("$stateUnwindMap$?test@@YAXXZ")@IMGREL -; CHECK-NEXT: .long -; CHECK-NEXT: .long ("$tryMap$?test@@YAXXZ")@IMGREL -; CHECK-NEXT: .long -; CHECK-NEXT: .long ("$ip2state$?test@@YAXXZ")@IMGREL -; CHECK-NEXT: .long 40 -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long 1 -; CHECK: "$stateUnwindMap$?test@@YAXXZ": -; CHECK: "$tryMap$?test@@YAXXZ": -; CHECK: "$handlerMap$0$?test@@YAXXZ": -; CHECK: "$ip2state$?test@@YAXXZ": -; CHECK-NEXT: .long .Lfunc_begin0@IMGREL -; CHECK-NEXT: .long -1 -; CHECK-NEXT: .long .Ltmp0@IMGREL -; CHECK-NEXT: .long 2 -; CHECK-NEXT: .long .Ltmp3@IMGREL -; CHECK-NEXT: .long 1 -; CHECK-NEXT: .long .Ltmp6@IMGREL -; CHECK-NEXT: .long 0 -; CHECK-NEXT: .long .Lfunc_begin1@IMGREL -; CHECK-NEXT: .long 3 -; CHECK-NEXT: .long .Lfunc_begin2@IMGREL -; CHECK-NEXT: .long 4 -; CHECK-NEXT: .long .Lfunc_begin3@IMGREL -; CHECK-NEXT: .long 5 -; CHECK-NEXT: .long .Lfunc_begin4@IMGREL -; CHECK-NEXT: .long 6 diff --git a/test/CodeGen/X86/pr23900.ll b/test/CodeGen/X86/pr23900.ll deleted file mode 100644 index cbc77161c04..00000000000 --- a/test/CodeGen/X86/pr23900.ll +++ /dev/null @@ -1,29 +0,0 @@ -; RUN: llc -filetype=obj %s -o %t.o -; RUN: llvm-nm %t.o | FileCheck %s - -; Test that it doesn't crash (and produces an object file). -; This use to pass a symbol with a null name to code that expected a valid -; C string. - -; CHECK: U __CxxFrameHandler3 -; CHECK: T f -; CHECK: t f.cleanup -; CHECK: U g -; CHECK: U h - - -target triple = "x86_64-pc-windows-msvc18.0.0" -define void @f(i32 %x) personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { - invoke void @h() - to label %invoke.cont unwind label %lpad -invoke.cont: - ret void -lpad: - landingpad { i8*, i32 } - cleanup - call void @g(i32 %x) - ret void -} -declare void @h() -declare i32 @__CxxFrameHandler3(...) -declare void @g(i32 %x) diff --git a/test/CodeGen/X86/win32-eh-states.ll b/test/CodeGen/X86/win32-eh-states.ll index 0aae8c4d018..cb7b053e14d 100644 --- a/test/CodeGen/X86/win32-eh-states.ll +++ b/test/CodeGen/X86/win32-eh-states.ll @@ -33,11 +33,11 @@ $"\01??_R0H@8" = comdat any define void @f() #0 personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*) { entry: invoke void @may_throw(i32 1) - to label %invoke.cont unwind label %lpad + to label %invoke.cont unwind label %lpad.1 invoke.cont: ; preds = %entry invoke void @may_throw(i32 2) - to label %try.cont.9 unwind label %lpad.1 + to label %try.cont.9 unwind label %lpad try.cont.9: ; preds = %invoke.cont.3, %invoke.cont, %catch.7 ; FIXME: Something about our CFG breaks TailDuplication. This empy asm blocks @@ -46,47 +46,33 @@ try.cont.9: ; preds = %invoke.cont.3, %inv ret void lpad: ; preds = %catch, %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.4 - -lpad.1: ; preds = %invoke.cont - %3 = landingpad { i8*, i32 } - catch i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*) - %4 = extractvalue { i8*, i32 } %3, 0 - %5 = extractvalue { i8*, i32 } %3, 1 - %6 = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*)) #3 - %matches = icmp eq i32 %5, %6 - br i1 %matches, label %catch, label %catch.dispatch.4 - -catch.dispatch.4: ; preds = %lpad.1, %lpad - %exn.slot.0 = phi i8* [ %4, %lpad.1 ], [ %1, %lpad ] - %ehselector.slot.0 = phi i32 [ %5, %lpad.1 ], [ %2, %lpad ] - %.pre = tail call i32 @llvm.eh.typeid.for(i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*)) #3 - %matches6 = icmp eq i32 %ehselector.slot.0, %.pre - br i1 %matches6, label %catch.7, label %eh.resume - -catch.7: ; preds = %catch.dispatch.4 - tail call void @llvm.eh.begincatch(i8* %exn.slot.0, i8* null) #3 - tail call void @may_throw(i32 4) - tail call void @llvm.eh.endcatch() #3 - br label %try.cont.9 + %p1 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] + to label %catch unwind label %end.inner.catch catch: ; preds = %lpad.1 - tail call void @llvm.eh.begincatch(i8* %4, i8* null) #3 invoke void @may_throw(i32 3) - to label %invoke.cont.3 unwind label %lpad + to label %invoke.cont.3 unwind label %end.inner.catch invoke.cont.3: ; preds = %catch - tail call void @llvm.eh.endcatch() #3 - br label %try.cont.9 + catchret %p1 to label %try.cont.9 + + +end.inner.catch: + catchendpad unwind label %lpad.1 + +lpad.1: ; preds = %invoke.cont + %p2 = catchpad [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null] + to label %catch.7 unwind label %eh.resume + +catch.7: + invoke void @may_throw(i32 4) + to label %invoke.cont.10 unwind label %eh.resume + +invoke.cont.10: + catchret %p2 to label %try.cont.9 eh.resume: ; preds = %catch.dispatch.4 - %lpad.val = insertvalue { i8*, i32 } undef, i8* %exn.slot.0, 0 - %lpad.val.12 = insertvalue { i8*, i32 } %lpad.val, i32 %ehselector.slot.0, 1 - resume { i8*, i32 } %lpad.val.12 + catchendpad unwind to caller } ; CHECK-LABEL: _f: @@ -100,15 +86,13 @@ eh.resume: ; preds = %catch.dispatch.4 ; CHECK: movl $1, [[state]](%ebp) ; CHECK: movl $2, (%esp) ; CHECK: calll _may_throw - -; CHECK-LABEL: _f.catch: -; CHECK: movl $4, Lf$frame_escape_{{[0-9]+.*}} -; CHECK: movl $4, (%esp) -; CHECK: calll _may_throw - -; CHECK-LABEL: _f.catch.1: -; CHECK: movl $3, Lf$frame_escape_{{[0-9]+.*}} +; +; CHECK: movl $2, [[state]](%ebp) ; CHECK: movl $3, (%esp) ; CHECK: calll _may_throw +; +; CHECK: movl $3, [[state]](%ebp) +; CHECK: movl $4, (%esp) +; CHECK: calll _may_throw ; CHECK: .safeseh ___ehhandler$f diff --git a/test/CodeGen/X86/win32-eh.ll b/test/CodeGen/X86/win32-eh.ll index 3ee4723ce5f..f477ed1d4c6 100644 --- a/test/CodeGen/X86/win32-eh.ll +++ b/test/CodeGen/X86/win32-eh.ll @@ -105,13 +105,16 @@ define void @use_CxxFrameHandler3() personality i32 (...)* @__CxxFrameHandler3 { to label %cont unwind label %catchall cont: ret void + catchall: - %ehvals = landingpad { i8*, i32 } - catch i8* null - %ehptr = extractvalue { i8*, i32 } %ehvals, 0 - call void @llvm.eh.begincatch(i8* %ehptr, i8* null) - call void @llvm.eh.endcatch() - br label %cont + %p = catchpad [i8* null, i32 64, i8* null] + to label %catch unwind label %endcatch + +catch: + catchret %p to label %cont + +endcatch: + catchendpad unwind to caller } ; CHECK-LABEL: _use_CxxFrameHandler3: -- 2.34.1