[llvm] r233767 - [WinEH] Generate .xdata for catch handlers
David Majnemer
david.majnemer at gmail.com
Tue Mar 31 16:08:52 PDT 2015
On Tue, Mar 31, 2015 at 3:57 PM, Kaylor, Andrew <andrew.kaylor at intel.com
<javascript:_e(%7B%7D,'cvml','andrew.kaylor at intel.com');>> wrote:
> So you've successfully executed code that contains a try/catch structure
> and caught an exception?!
>
Yes, we have a program where a translation unit compiled by MSVC 2013
throws an exception and clang-cl catches it.
The clang-cl side is the test case in
'test/CodeGen/WinEH/cppeh-prepared-catch.ll'
>
> Any plans for a "live" test case?
>
> I believe "CatchHigh" is the state the function is in while the catch
> handler is being executed. This will come into play when we try to catch
> an exception inside a catch handler.
>
A catch number has multiple states (it can have multiple cleanups, etc.).
We believe CatchHigh is the largest such state number in any of a try's
catch handlers.
>
> -Andy
>
> -----Original Message-----
> From: llvm-commits-bounces at cs.uiuc.edu
> <javascript:_e(%7B%7D,'cvml','llvm-commits-bounces at cs.uiuc.edu');>
> [mailto:llvm-commits-bounces at cs.uiuc.edu
> <javascript:_e(%7B%7D,'cvml','llvm-commits-bounces at cs.uiuc.edu');>] On
> Behalf Of David Majnemer
> Sent: Tuesday, March 31, 2015 3:36 PM
> To: llvm-commits at cs.uiuc.edu
> <javascript:_e(%7B%7D,'cvml','llvm-commits at cs.uiuc.edu');>
> Subject: [llvm] r233767 - [WinEH] Generate .xdata for catch handlers
>
> Author: majnemer
> Date: Tue Mar 31 17:35:44 2015
> New Revision: 233767
>
> URL: http://llvm.org/viewvc/llvm-project?rev=233767&view=rev
> Log:
> [WinEH] Generate .xdata for catch handlers
>
> This lets us catch exceptions in simple cases.
>
> N.B. Things that do not work include (but are not limited to):
> - Throwing from within a catch handler.
> - Catching an object with a named catch parameter.
> - 'CatchHigh' is fictitious, we aren't sure of its purpose.
> - We aren't entirely efficient with regards to the number of EH states
> that we generate.
> - IP-to-State tables are sensitive to the order of emission.
>
> Added:
> llvm/trunk/test/CodeGen/WinEH/cppeh-prepared-catch.ll
> llvm/trunk/test/CodeGen/WinEH/cppeh-prepared-cleanups.ll
> - copied, changed from r233763,
> llvm/trunk/test/CodeGen/WinEH/cppeh-cleanups.ll
> Removed:
> llvm/trunk/test/CodeGen/WinEH/cppeh-cleanups.ll
> Modified:
> llvm/trunk/docs/ExceptionHandling.rst
> llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h
> llvm/trunk/include/llvm/IR/Intrinsics.td
> llvm/trunk/include/llvm/MC/MCContext.h
> llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp
> llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
> llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
> llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
> llvm/trunk/lib/IR/Verifier.cpp
> llvm/trunk/lib/MC/MCContext.cpp
> llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> llvm/trunk/test/CodeGen/WinEH/cppeh-catch-unwind.ll
>
> Modified: llvm/trunk/docs/ExceptionHandling.rst
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/ExceptionHandling.rst?rev=233767&r1=233766&r2=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/docs/ExceptionHandling.rst (original)
> +++ llvm/trunk/docs/ExceptionHandling.rst Tue Mar 31 17:35:44 2015
> @@ -551,17 +551,6 @@ This object is used by Windows native ex where xdata
> unwind information is used. It is typically an 8 byte chunk of memory
> treated as two 32-bit integers.
>
> -``llvm.eh.parentframe``
> ------------------------
> -
> -.. code-block:: llvm
> -
> - void @llvm.eh.parentframe(i8*)
> -
> -This intrinsic designates the provided static alloca as the object which
> holds -the address of the parent frame.
> -This object is used by Windows native exception handling on non-x86
> platforms -where xdata unwind information is used.
>
> SJLJ Intrinsics
> ---------------
>
> Modified: llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h?rev=233767&r1=233766&r2=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h Tue Mar 31 17:35:44
> +++ 2015
> @@ -103,7 +103,9 @@ struct WinEHUnwindMapEntry {
>
> struct WinEHHandlerType {
> int Adjectives;
> - GlobalValue *TypeDescriptor;
> + GlobalVariable *TypeDescriptor;
> + int CatchObjIdx;
> + int CatchObjOffset;
> Function *Handler;
> };
>
> @@ -111,7 +113,7 @@ struct WinEHTryBlockMapEntry {
> int TryLow;
> int TryHigh;
> int CatchHigh;
> - SmallVector<WinEHHandlerType, 4> HandlerArray;
> + SmallVector<WinEHHandlerType, 1> HandlerArray;
> };
>
> struct WinEHFuncInfo {
>
> Modified: llvm/trunk/include/llvm/IR/Intrinsics.td
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Intrinsics.td?rev=233767&r1=233766&r2=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Intrinsics.td (original)
> +++ llvm/trunk/include/llvm/IR/Intrinsics.td Tue Mar 31 17:35:44 2015
> @@ -425,10 +425,6 @@ def int_eh_actions : Intrinsic<[llvm_ptr // for
> WinEH.
> def int_eh_unwindhelp : Intrinsic<[], [llvm_ptr_ty], []>;
>
> -// Designates the provided static alloca as the object which holds the
> address -// of the parent frame. Required for WinEH.
> -def int_eh_parentframe : Intrinsic<[], [llvm_ptrptr_ty], []>;
> -
> // __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.
>
> Modified: llvm/trunk/include/llvm/MC/MCContext.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCContext.h?rev=233767&r1=233766&r2=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/MC/MCContext.h (original)
> +++ llvm/trunk/include/llvm/MC/MCContext.h Tue Mar 31 17:35:44 2015
> @@ -259,6 +259,7 @@ namespace llvm {
> MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section);
>
> MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned
> Idx);
> + MCSymbol *getOrCreateParentFrameOffsetSymbol(StringRef FuncName);
>
> /// Get the symbol for \p Name, or null.
> MCSymbol *LookupSymbol(const Twine &Name) const;
>
> Modified: llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp?rev=233767&r1=233766&r2=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AsmPrinter/Win64Exception.cpp Tue Mar 31
> +++ 17:35:44 2015
> @@ -68,6 +68,27 @@ void Win64Exception::beginFunction(const
> shouldEmitLSDA = shouldEmitPersonality &&
> LSDAEncoding != dwarf::DW_EH_PE_omit;
>
> +
> + // 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.
> + const Function *F = MF->getFunction(); const Function *ParentF =
> + MMI->getWinEHParent(F); 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 (!shouldEmitPersonality && !shouldEmitMoves)
> return;
>
> @@ -253,6 +274,7 @@ void Win64Exception::emitCXXFrameHandler
> const Function *F = MF->getFunction();
> const Function *ParentF = MMI->getWinEHParent(F);
> auto &OS = Asm->OutStreamer;
> + WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF);
>
> StringRef ParentLinkageName =
> GlobalValue::getRealLinkageName(ParentF->getName());
> @@ -279,8 +301,6 @@ void Win64Exception::emitCXXFrameHandler
> // an ordinary call) between the end of the previous try-range and now.
> bool SawPotentiallyThrowing = false;
>
> - WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF);
> -
> int LastEHState = -2;
>
> // The parent function and the catch handlers contribute to the
> 'ip2state'
> @@ -424,11 +444,17 @@ void Win64Exception::emitCXXFrameHandler
> // };
> OS.EmitLabel(HandlerMapXData);
> for (const WinEHHandlerType &HT : TBME.HandlerArray) {
> + MCSymbol *ParentFrameOffset =
> + Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
> + GlobalValue::getRealLinkageName(HT.Handler->getName()));
> + const MCSymbolRefExpr *ParentFrameOffsetRef =
> MCSymbolRefExpr::Create(
> + ParentFrameOffset, MCSymbolRefExpr::VK_None,
> + Asm->OutContext);
> +
> OS.EmitIntValue(HT.Adjectives, 4); //
> Adjectives
> OS.EmitValue(createImageRel32(HT.TypeDescriptor), 4); // Type
> - OS.EmitIntValue(0, 4); //
> CatchObjOffset
> + OS.EmitIntValue(HT.CatchObjOffset, 4); //
> CatchObjOffset
> OS.EmitValue(createImageRel32(HT.Handler), 4); // Handler
> - OS.EmitIntValue(0, 4); //
> ParentFrameOffset
> + OS.EmitValue(ParentFrameOffsetRef, 4); //
> ParentFrameOffset
> }
> }
> }
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp?rev=233767&r1=233766&r2=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp Tue Mar
> +++ 31 17:35:44 2015
> @@ -88,6 +88,7 @@ struct WinEHNumbering {
> int NextState;
>
> SmallVector<ActionHandler *, 4> HandlerStack;
> + SmallPtrSet<const Function *, 4> VisitedHandlers;
>
> int currentEHNumber() const {
> return HandlerStack.empty() ? -1 : HandlerStack.back()->getEHState();
> @@ -96,7 +97,9 @@ struct WinEHNumbering {
> void parseEHActions(const IntrinsicInst *II,
> SmallVectorImpl<ActionHandler *> &Actions);
> void createUnwindMapEntry(int ToState, ActionHandler *AH);
> - void proccessCallSite(ArrayRef<ActionHandler *> Actions,
> ImmutableCallSite CS);
> + void createTryBlockMapEntry(int TryLow, int TryHigh,
> + ArrayRef<CatchHandler *> Handlers); void
> + processCallSite(ArrayRef<ActionHandler *> Actions, ImmutableCallSite
> + CS);
> void calculateStateNumbers(const Function &F); }; } @@ -276,8 +279,12
> @@ void FunctionLoweringInfo::set(const Fun
> MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad();
>
> // Calculate EH numbers for WinEH.
> - if (fn.getFnAttribute("wineh-parent").getValueAsString() ==
> fn.getName())
> - WinEHNumbering(MMI.getWinEHFuncInfo(&fn)).calculateStateNumbers(fn);
> + if (fn.getFnAttribute("wineh-parent").getValueAsString() ==
> fn.getName()) {
> + WinEHNumbering Num(MMI.getWinEHFuncInfo(&fn));
> + Num.calculateStateNumbers(fn);
> + // Pop everything on the handler stack.
> + Num.processCallSite(None, ImmutableCallSite()); }
> }
>
> void WinEHNumbering::parseEHActions(const IntrinsicInst *II,
> @@ -309,13 +316,42 @@ void WinEHNumbering::parseEHActions(cons
> void WinEHNumbering::createUnwindMapEntry(int ToState, ActionHandler *AH)
> {
> WinEHUnwindMapEntry UME;
> UME.ToState = ToState;
> - if (auto *CH = dyn_cast<CleanupHandler>(AH))
> + if (auto *CH = dyn_cast_or_null<CleanupHandler>(AH))
> UME.Cleanup = cast<Function>(CH->getHandlerBlockOrFunc());
> else
> UME.Cleanup = nullptr;
> FuncInfo.UnwindMap.push_back(UME);
> }
>
> +void WinEHNumbering::createTryBlockMapEntry(int TryLow, int TryHigh,
> + ArrayRef<CatchHandler *>
> Handlers) {
> + WinEHTryBlockMapEntry TBME;
> + TBME.TryLow = TryLow;
> + TBME.TryHigh = TryHigh;
> + // FIXME: This should be revisited when we want to throw inside a catch
> + // handler.
> + TBME.CatchHigh = INT_MAX;
> + assert(TBME.TryLow <= TBME.TryHigh);
> + assert(TBME.CatchHigh > TBME.TryHigh);
> + for (CatchHandler *CH : Handlers) {
> + WinEHHandlerType HT;
> + auto *GV =
> cast<GlobalVariable>(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<ConstantStruct>(GV->getInitializer());
> + HT.Adjectives =
> + cast<ConstantInt>(CS->getAggregateElement(0U))->getZExtValue();
> + HT.TypeDescriptor = cast<GlobalVariable>(
> + CS->getAggregateElement(1)->stripPointerCasts());
> + HT.Handler = cast<Function>(CH->getHandlerBlockOrFunc());
> + // FIXME: We don't support catching objects yet!
> + HT.CatchObjIdx = INT_MAX;
> + HT.CatchObjOffset = 0;
> + TBME.HandlerArray.push_back(HT);
> + }
> + FuncInfo.TryBlockMap.push_back(TBME);
> +}
> +
> static void print_name(const Value *V) {
> #ifndef NDEBUG
> if (!V) {
> @@ -330,10 +366,8 @@ static void print_name(const Value *V) {
> #endif
> }
>
> -void WinEHNumbering::proccessCallSite(ArrayRef<ActionHandler *> Actions,
> - ImmutableCallSite CS) {
> - // float, int
> - // float, double, int
> +void WinEHNumbering::processCallSite(ArrayRef<ActionHandler *> Actions,
> + ImmutableCallSite CS) {
> int FirstMismatch = 0;
> for (int E = std::min(HandlerStack.size(), Actions.size());
> FirstMismatch < E;
> ++FirstMismatch) {
> @@ -343,28 +377,65 @@ void WinEHNumbering::proccessCallSite(Ar
> delete Actions[FirstMismatch];
> }
>
> + bool EnteringScope = (int)Actions.size() > FirstMismatch;
> + bool ExitingScope = (int)HandlerStack.size() > 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<const Function *, 4> UnnumberedHandlers;
> + SmallVector<CatchHandler *, 4> PoppedCatches;
> for (int I = HandlerStack.size() - 1; I >= FirstMismatch; --I) {
> - if (auto *CH = dyn_cast<CatchHandler>(HandlerStack.back()))
> - if (const auto *F = dyn_cast<Function>(CH->getHandlerBlockOrFunc()))
> - UnnumberedHandlers.push_back(F);
> - // Pop the handlers off of the stack.
> - delete HandlerStack.back();
> + if (auto *CH = dyn_cast<CatchHandler>(HandlerStack.back())) {
> + PoppedCatches.push_back(CH);
> + } else {
> + // Delete cleanup handlers
> + delete HandlerStack.back();
> + }
> HandlerStack.pop_back();
> }
>
> - for (const Function *F : UnnumberedHandlers)
> - calculateStateNumbers(*F);
> + // We need to create a new state number if we are exiting a try scope
> and we
> + // will not push any more actions.
> + int TryHigh = NextState - 1;
> + if (ExitingScope && !EnteringScope && !PoppedCatches.empty()) {
> + createUnwindMapEntry(currentEHNumber(), nullptr);
> + ++NextState;
> + }
> +
> + int LastTryLowIdx = 0;
> + for (int I = 0, E = PoppedCatches.size(); I != E; ++I) {
> + CatchHandler *CH = PoppedCatches[I];
> + if (I + 1 == E || CH->getEHState() != PoppedCatches[I +
> 1]->getEHState()) {
> + int TryLow = CH->getEHState();
> + auto Handlers =
> + makeArrayRef(&PoppedCatches[LastTryLowIdx], I - LastTryLowIdx +
> 1);
> + createTryBlockMapEntry(TryLow, TryHigh, Handlers);
> + LastTryLowIdx = I + 1;
> + }
> + }
>
> + for (CatchHandler *CH : PoppedCatches) {
> + if (auto *F = dyn_cast<Function>(CH->getHandlerBlockOrFunc()))
> + calculateStateNumbers(*F);
> + delete CH;
> + }
> +
> + bool LastActionWasCatch = false;
> for (size_t I = FirstMismatch; I != Actions.size(); ++I) {
> - createUnwindMapEntry(currentEHNumber(), Actions[I]);
> - Actions[I]->setEHState(NextState++);
> - DEBUG(dbgs() << "Creating unwind map entry for: (");
> - print_name(Actions[I]->getHandlerBlockOrFunc());
> - DEBUG(dbgs() << ", " << currentEHNumber() << ")\n");
> + // We can reuse eh states when pushing two catches for the same
> invoke.
> + bool CurrActionIsCatch = isa<CatchHandler>(Actions[I]);
> + // FIXME: Reenable this optimization!
> + if (CurrActionIsCatch && LastActionWasCatch && false) {
> + Actions[I]->setEHState(currentEHNumber());
> + } else {
> + createUnwindMapEntry(currentEHNumber(), Actions[I]);
> + Actions[I]->setEHState(NextState);
> + NextState++;
> + DEBUG(dbgs() << "Creating unwind map entry for: (");
> + print_name(Actions[I]->getHandlerBlockOrFunc());
> + DEBUG(dbgs() << ", " << currentEHNumber() << ")\n");
> + }
> HandlerStack.push_back(Actions[I]);
> + LastActionWasCatch = CurrActionIsCatch;
> }
>
> DEBUG(dbgs() << "In EHState " << currentEHNumber() << " for CallSite:
> ");
> @@ -373,6 +444,10 @@ void WinEHNumbering::proccessCallSite(Ar
> }
>
> 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.
> +
> DEBUG(dbgs() << "Calculating state numbers for: " << F.getName() <<
> '\n');
> SmallVector<ActionHandler *, 4> ActionList;
> for (const BasicBlock &BB : F) {
> @@ -380,21 +455,21 @@ void WinEHNumbering::calculateStateNumbe
> const auto *CI = dyn_cast<CallInst>(&I);
> if (!CI || CI->doesNotThrow())
> continue;
> - proccessCallSite(None, CI);
> + processCallSite(None, CI);
> }
> const auto *II = dyn_cast<InvokeInst>(BB.getTerminator());
> if (!II)
> continue;
> const LandingPadInst *LPI = II->getLandingPadInst();
> - if (auto *ActionsCall = dyn_cast<IntrinsicInst>(LPI->getNextNode())) {
> - assert(ActionsCall->getIntrinsicID() == Intrinsic::eh_actions);
> - parseEHActions(ActionsCall, ActionList);
> - proccessCallSite(ActionList, II);
> - ActionList.clear();
> - FuncInfo.LandingPadStateMap[LPI] = currentEHNumber();
> - }
> + auto *ActionsCall = dyn_cast<IntrinsicInst>(LPI->getNextNode());
> + if (!ActionsCall)
> + continue;
> + assert(ActionsCall->getIntrinsicID() == Intrinsic::eh_actions);
> + parseEHActions(ActionsCall, ActionList);
> + processCallSite(ActionList, II);
> + ActionList.clear();
> + FuncInfo.LandingPadStateMap[LPI] = currentEHNumber();
> }
> - proccessCallSite(None, ImmutableCallSite());
> }
>
> /// clear - Clear out all the function-specific state. This returns this
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=233767&r1=233766&r2=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Tue Mar 31
> 17:35:44 2015
> @@ -5450,18 +5450,6 @@ SelectionDAGBuilder::visitIntrinsicCall(
> case Intrinsic::eh_begincatch:
> case Intrinsic::eh_endcatch:
> llvm_unreachable("begin/end catch intrinsics not lowered in codegen");
> - case Intrinsic::eh_parentframe: {
> - AllocaInst *Slot =
> - cast<AllocaInst>(I.getArgOperand(0)->stripPointerCasts());
> - assert(FuncInfo.StaticAllocaMap.count(Slot) &&
> - "can only use static allocas with llvm.eh.parentframe");
> - int FI = FuncInfo.StaticAllocaMap[Slot];
> - MachineFunction &MF = DAG.getMachineFunction();
> - const Function *F = MF.getFunction();
> - MachineModuleInfo &MMI = MF.getMMI();
> - MMI.getWinEHFuncInfo(F).CatchHandlerParentFrameObjIdx[F] = FI;
> - return nullptr;
> - }
> case Intrinsic::eh_unwindhelp: {
> AllocaInst *Slot =
> cast<AllocaInst>(I.getArgOperand(0)->stripPointerCasts());
>
> Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=233767&r1=233766&r2=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
> +++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Tue Mar 31 17:35:44 2015
> @@ -638,16 +638,6 @@ bool WinEHPrepare::outlineHandler(Action
> if (!LPadMap.isInitialized())
> LPadMap.mapLandingPad(LPad);
> if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) {
> - // Insert an alloca for the object which holds the address of the
> parent's
> - // frame pointer. The stack offset of this object needs to be
> encoded in
> - // xdata.
> - AllocaInst *ParentFrame = new AllocaInst(Int8PtrType, "parentframe",
> Entry);
> - Builder.CreateStore(&Handler->getArgumentList().back(), ParentFrame,
> - /*isStore=*/true);
> - Function *ParentFrameFn =
> - Intrinsic::getDeclaration(M, Intrinsic::eh_parentframe);
> - Builder.CreateCall(ParentFrameFn, ParentFrame);
> -
> Constant *Sel = CatchAction->getSelector();
> Director.reset(new WinEHCatchDirector(Handler, Sel, VarInfo,
> LPadMap));
> LPadMap.remapSelector(VMap,
> ConstantInt::get(Type::getInt32Ty(Context), 1));
>
> Modified: llvm/trunk/lib/IR/Verifier.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=233767&r1=233766&r2=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/Verifier.cpp (original)
> +++ llvm/trunk/lib/IR/Verifier.cpp Tue Mar 31 17:35:44 2015
> @@ -3228,13 +3228,6 @@ void Verifier::visitIntrinsicFunctionCal
> break;
> }
>
> - case Intrinsic::eh_parentframe: {
> - auto *AI =
> dyn_cast<AllocaInst>(CI.getArgOperand(0)->stripPointerCasts());
> - Assert(AI && AI->isStaticAlloca(),
> - "llvm.eh.parentframe requires a static alloca", &CI);
> - break;
> - }
> -
> case Intrinsic::eh_unwindhelp: {
> auto *AI =
> dyn_cast<AllocaInst>(CI.getArgOperand(0)->stripPointerCasts());
> Assert(AI && AI->isStaticAlloca(),
>
> Modified: llvm/trunk/lib/MC/MCContext.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCContext.cpp?rev=233767&r1=233766&r2=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/MC/MCContext.cpp (original)
> +++ llvm/trunk/lib/MC/MCContext.cpp Tue Mar 31 17:35:44 2015
> @@ -139,6 +139,11 @@ MCSymbol *MCContext::getOrCreateFrameAll
> "$frame_escape_" + Twine(Idx));
> }
>
> +MCSymbol *MCContext::getOrCreateParentFrameOffsetSymbol(StringRef
> FuncName) {
> + return GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) +
> FuncName +
> + "$parent_frame_offset");
> +}
> +
> MCSymbol *MCContext::CreateSymbol(StringRef Name, bool AlwaysAddSuffix) {
> // Determine whether this is an assembler temporary or normal label, if
> used.
> bool IsTemporary = false;
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=233767&r1=233766&r2=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Mar 31 17:35:44 2015
> @@ -32,6 +32,7 @@
> #include "llvm/CodeGen/MachineJumpTableInfo.h"
> #include "llvm/CodeGen/MachineModuleInfo.h"
> #include "llvm/CodeGen/MachineRegisterInfo.h"
> +#include "llvm/CodeGen/WinEHFuncInfo.h"
> #include "llvm/IR/CallSite.h"
> #include "llvm/IR/CallingConv.h"
> #include "llvm/IR/Constants.h"
> @@ -2266,6 +2267,12 @@ static ArrayRef<MCPhysReg> get64BitArgum
> return makeArrayRef(std::begin(XMMArgRegs64Bit),
> std::end(XMMArgRegs64Bit));
> }
>
> +static bool isOutlinedHandler(const MachineFunction &MF) {
> + const MachineModuleInfo &MMI = MF.getMMI();
> + const Function *F = MF.getFunction();
> + return MMI.getWinEHParent(F) != F;
> +}
> +
> SDValue
> X86TargetLowering::LowerFormalArguments(SDValue Chain,
> CallingConv::ID CallConv,
> @@ -2277,6 +2284,7 @@ X86TargetLowering::LowerFormalArguments(
> const {
> MachineFunction &MF = DAG.getMachineFunction();
> X86MachineFunctionInfo *FuncInfo = MF.getInfo<X86MachineFunctionInfo>();
> + const TargetFrameLowering &TFI = *Subtarget->getFrameLowering();
>
> const Function* Fn = MF.getFunction();
> if (Fn->hasExternalLinkage() &&
> @@ -2452,7 +2460,6 @@ X86TargetLowering::LowerFormalArguments(
> }
>
> if (IsWin64) {
> - const TargetFrameLowering &TFI = *Subtarget->getFrameLowering();
> // Get to the caller-allocated home save location. Add 8 to account
> // for the return address.
> int HomeOffset = TFI.getOffsetOfLocalArea() + 8;
> @@ -2505,6 +2512,28 @@ X86TargetLowering::LowerFormalArguments(
>
> if (!MemOps.empty())
> Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
> + } else if (IsWin64 && isOutlinedHandler(MF)) {
> + // 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));
> +
> + MachineModuleInfo &MMI = MF.getMMI();
> + MMI.getWinEHFuncInfo(Fn)
> + .CatchHandlerParentFrameObjIdx[const_cast<Function *>(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());
> + 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(FuncInfo->getRegSaveFrameIndex()),
> + /*isVolatile=*/true, /*isNonTemporal=*/false, /*Alignment=*/0);
> }
>
> if (isVarArg && MFI->hasMustTailInVarArgFunc()) {
>
> Modified: llvm/trunk/test/CodeGen/WinEH/cppeh-catch-unwind.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/cppeh-catch-unwind.ll?rev=233767&r1=233766&r2=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/WinEH/cppeh-catch-unwind.ll (original)
> +++ llvm/trunk/test/CodeGen/WinEH/cppeh-catch-unwind.ll Tue Mar 31
> 17:35:44 2015
> @@ -180,9 +180,6 @@ eh.resume:
>
> ; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*)
> ; CHECK: entry:
> -; CHECK: [[PARENTFRAME:\%.+]] = alloca i8*
> -; CHECK: store volatile i8* %1, i8** [[PARENTFRAME]]
> -; CHECK: call void @llvm.eh.parentframe(i8** [[PARENTFRAME]])
> ; CHECK: [[RECOVER_TMP1:\%.+]] = call i8* @llvm.framerecover(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"()
> @@ -199,9 +196,6 @@ eh.resume:
>
> ; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch1"(i8*, i8*)
> ; CHECK: entry:
> -; CHECK: [[PARENTFRAME:\%.+]] = alloca i8*
> -; CHECK: store volatile i8* %1, i8** [[PARENTFRAME]]
> -; CHECK: call void @llvm.eh.parentframe(i8** [[PARENTFRAME]])
> ; CHECK: [[RECOVER_TMP0:\%.+]] = call i8* @llvm.framerecover(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"()
>
> Removed: llvm/trunk/test/CodeGen/WinEH/cppeh-cleanups.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/cppeh-cleanups.ll?rev=233766&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/WinEH/cppeh-cleanups.ll (original)
> +++ llvm/trunk/test/CodeGen/WinEH/cppeh-cleanups.ll (removed)
> @@ -1,226 +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 at XZ" = comdat any
> -
> -$"\01??_R0H at 8" = comdat any
> -
> -$"_CT??_R0H at 84" = comdat any
> -
> -$_CTA1H = comdat any
> -
> -$_TI1H = comdat any
> -
> -@"\01??_7type_info@@6B@" = external constant i8*
> -@"\01??_R0H at 8" = linkonce_odr global %rtti.TypeDescriptor2 { i8**
> @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
> - at __ImageBase = external constant i8
> -@"_CT??_R0H at 84" = linkonce_odr unnamed_addr constant %eh.CatchableType {
> i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor2*
> @"\01??_R0H at 8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32),
> i32 0, i32 -1, i32 0, i32 4, i32 0 }, section ".xdata", comdat
> - at _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 at 84" to i64), i64 ptrtoint (i8*
> @__ImageBase to i64)) to i32)] }, section ".xdata", comdat
> - at _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:"$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 1
> -; CHECK-NEXT: .long ("$ip2state$?test1@@YAXXZ")@IMGREL
> -; CHECK-NEXT: .long 64
> -; 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 .Ltmp0 at IMGREL
> -; CHECK-NEXT: .long 0
> -
> -define void @"\01?test1@@YAXXZ"() #0 {
> -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.frameescape()
> - 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 } personality i8* bitcast (i32 (...)*
> @__CxxFrameHandler3 to i8*)
> - 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 at 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 at XZ"(%struct.S* %this1) #4
> - ret void
> -}
> -
> -; CHECK-LABEL: "?test2@@YAX_N at Z":
> -; CHECK: .seh_handlerdata
> -; CHECK-NEXT: .long ("$cppxdata$?test2@@YAX_N at Z")@IMGREL
> -; CHECK-NEXT:"$cppxdata$?test2@@YAX_N at Z":
> -; CHECK-NEXT: .long 429065506
> -; CHECK-NEXT: .long 2
> -; CHECK-NEXT: .long ("$stateUnwindMap$?test2@@YAX_N at Z")@IMGREL
> -; CHECK-NEXT: .long 0
> -; CHECK-NEXT: .long 0
> -; CHECK-NEXT: .long 4
> -; CHECK-NEXT: .long ("$ip2state$?test2@@YAX_N at Z")@IMGREL
> -; CHECK-NEXT: .long 64
> -; CHECK-NEXT: .long 0
> -; CHECK-NEXT: .long 1
> -; CHECK-NEXT:"$stateUnwindMap$?test2@@YAX_N at Z":
> -; CHECK-NEXT: .long -1
> -; CHECK-NEXT: .long "?test2@@YAX_N at Z.cleanup"@IMGREL
> -; CHECK-NEXT: .long 0
> -; CHECK-NEXT: .long "?test2@@YAX_N at Z.cleanup1"@IMGREL
> -; CHECK-NEXT:"$ip2state$?test2@@YAX_N at Z":
> -; CHECK-NEXT: .long .Lfunc_begin1 at IMGREL
> -; CHECK-NEXT: .long -1
> -; CHECK-NEXT: .long .Ltmp7 at IMGREL
> -; CHECK-NEXT: .long 0
> -; CHECK-NEXT: .long .Ltmp9 at IMGREL
> -; CHECK-NEXT: .long 1
> -; CHECK-NEXT: .long .Ltmp12 at IMGREL
> -; CHECK-NEXT: .long 0
> -
> -define void @"\01?test2@@YAX_N at Z"(i1 zeroext %b) #2 {
> -entry:
> - %unwindhelp = alloca i64
> - %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 @"\01?may_throw@@YAXXZ"()
> - call void (...)* @llvm.frameescape(%struct.S* %s, %struct.S* %s1)
> - store volatile i64 -2, i64* %unwindhelp
> - %0 = bitcast i64* %unwindhelp to i8*
> - call void @llvm.eh.unwindhelp(i8* %0)
> - 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 at XZ"(%struct.S* %s1) #4
> - br label %if.end
> -
> -lpad1: ; preds = %entry,
> %if.end
> - %2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)*
> @__CxxFrameHandler3 to i8*)
> - cleanup
> - %recover = call i8* (...)* @llvm.eh.actions(i32 0, void (i8*, i8*)*
> @"\01?test2@@YAX_N at Z.cleanup")
> - indirectbr i8* %recover, []
> -
> -lpad3: ; preds = %if.then
> - %3 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)*
> @__CxxFrameHandler3 to i8*)
> - cleanup
> - %recover4 = call i8* (...)* @llvm.eh.actions(i32 0, void (i8*, i8*)*
> @"\01?test2@@YAX_N at Z.cleanup1", i32 0, void (i8*, i8*)* @"\01?test2@
> @YAX_N at 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 at 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 at 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 at XZ"(%struct.S* %s) #4
> - ret void
> -}
> -
> -; Function Attrs: nounwind
> -declare void @llvm.frameescape(...) #4
> -
> -; Function Attrs: nounwind readnone
> -declare i8* @llvm.framerecover(i8*, i8*, i32) #6
> -
> -; Function Attrs: nounwind
> -declare void @llvm.eh.unwindhelp(i8*) #4
> -
> -define internal void @"\01?test2@@YAX_N at Z.cleanup"(i8*, i8*) #7 {
> -entry:
> - %s.i8 = call i8* @llvm.framerecover(i8* bitcast (void (i1)* @"\01?test2@
> @YAX_N at Z" to i8*), i8* %1, i32 0)
> - %s = bitcast i8* %s.i8 to %struct.S*
> - call void @"\01??_DS@@QEAA at XZ"(%struct.S* %s) #4
> - ret void
> -}
> -
> -define internal void @"\01?test2@@YAX_N at Z.cleanup1"(i8*, i8*) #7 {
> -entry:
> - %s1.i8 = call i8* @llvm.framerecover(i8* bitcast (void (i1)*
> @"\01?test2@@YAX_N at Z" to i8*), i8* %1, i32 1)
> - %s1 = bitcast i8* %s1.i8 to %struct.S*
> - call void @"\01??_DS@@QEAA at XZ"(%struct.S* %s1) #4
> - ret void
> -}
> -
> -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 at 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 at Z" }
> -attributes #8 = { noreturn }
>
> Added: llvm/trunk/test/CodeGen/WinEH/cppeh-prepared-catch.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/cppeh-prepared-catch.ll?rev=233767&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/WinEH/cppeh-prepared-catch.ll (added)
> +++ llvm/trunk/test/CodeGen/WinEH/cppeh-prepared-catch.ll Tue Mar 31
> 17:35:44 2015
> @@ -0,0 +1,206 @@
> +; 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:
> +; 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 at 8" = comdat any
> +
> +$"\01??_R0H at 8" = comdat any
> +
> +@"\01??_7type_info@@6B@" = external constant i8*
> +@"\01??_R0N at 8" = linkonce_odr global %rtti.TypeDescriptor2 { i8**
> @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".N\00" }, comdat
> + at llvm.eh.handlertype.N.0 = private unnamed_addr constant
> %eh.CatchHandlerType { i32 0, i8* bitcast (%rtti.TypeDescriptor2*
> @"\01??_R0N at 8" to i8*) }, section "llvm.metadata"
> +@"\01??_R0H at 8" = linkonce_odr global %rtti.TypeDescriptor2 { i8**
> @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
> + at llvm.eh.handlertype.H.8 = private unnamed_addr constant
> %eh.CatchHandlerType { i32 8, i8* bitcast (%rtti.TypeDescriptor2*
> @"\01??_R0H at 8" to i8*) }, section "llvm.metadata"
> +
> +define internal i8* @"\01?f@@YAXXZ.catch"(i8*, i8*) #4 {
> +entry:
> + %.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?f@@YAXXZ"
> to i8*), i8* %1, i32 0)
> + %2 = bitcast i8* %.i8 to i32**
> + %3 = bitcast i32** %2 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
> + %4 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)*
> @__CxxFrameHandler3 to i8*)
> + 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*), double* null, i8*
> (i8*, i8*)* @"\01?f@@YAXXZ.catch1")
> + indirectbr i8* %recover, [label %invoke.cont2]
> +}
> +
> +; CHECK-LABEL: "?f@@YAXXZ.catch":
> +; CHECK: ".L?f@@YAXXZ.catch$parent_frame_offset" = 56
> +; CHECK: movq %rdx, 56(%rsp)
> +; CHECK: .seh_handlerdata
> +; CHECK: .long ("$cppxdata$?f@@YAXXZ")@IMGREL
> +
> +
> +define internal i8* @"\01?f@@YAXXZ.catch1"(i8*, i8*) #4 {
> +entry:
> + %.i8 = call i8* @llvm.framerecover(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 } personality i8* bitcast (i32 (...)*
> @__CxxFrameHandler3 to i8*)
> + cleanup
> + unreachable
> +}
> +
> +; CHECK-LABEL: "?f@@YAXXZ.catch1":
> +; CHECK: ".L?f@@YAXXZ.catch1$parent_frame_offset" = 16
> +; CHECK: movq %rdx, 16(%rsp)
> +; CHECK: .seh_handlerdata
> +; CHECK: .long ("$cppxdata$?f@@YAXXZ")@IMGREL
> +
> +define void @"\01?f@@YAXXZ"() #0 {
> +entry:
> + %unwindhelp = alloca i64
> + %exn.slot = alloca i8*
> + %ehselector.slot = alloca i32
> + %0 = alloca i32*, align 8
> + %1 = alloca double, align 8
> + call void (...)* @llvm.frameescape(i32** %0, double* %1)
> + store volatile i64 -2, i64* %unwindhelp
> + %2 = bitcast i64* %unwindhelp to i8*
> + call void @llvm.eh.unwindhelp(i8* %2)
> + invoke void @"\01?may_throw@@YAXXZ"()
> + to label %invoke.cont unwind label %lpad2
> +
> +invoke.cont: ; preds = %entry
> + br label %try.cont
> +
> +lpad2: ; preds = %entry
> + %3 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)*
> @__CxxFrameHandler3 to i8*)
> + 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*), double* %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:
> + %4 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)*
> @__CxxFrameHandler3 to i8*)
> + 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*), double* null, 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":
> +; CHECK: .seh_handlerdata
> +; CHECK-NEXT: .long ("$cppxdata$?f@@YAXXZ")@IMGREL
> +; CHECK-NEXT:"$cppxdata$?f@@YAXXZ":
> +; CHECK-NEXT: .long 429065506
> +; CHECK-NEXT: .long 4
> +; CHECK-NEXT: .long ("$stateUnwindMap$?f@@YAXXZ")@IMGREL
> +; CHECK-NEXT: .long 2
> +; CHECK-NEXT: .long ("$tryMap$?f@@YAXXZ")@IMGREL
> +; CHECK-NEXT: .long 3
> +; CHECK-NEXT: .long ("$ip2state$?f@@YAXXZ")@IMGREL
> +; CHECK-NEXT: .long 64
> +; CHECK-NEXT: .long 0
> +; CHECK-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 2147483647
> +; CHECK-NEXT: .long 1
> +; CHECK-NEXT: .long ("$handlerMap$0$?f@@YAXXZ")@IMGREL
> +; CHECK-NEXT: .long 0
> +; CHECK-NEXT: .long 2
> +; CHECK-NEXT: .long 2147483647
> +; CHECK-NEXT: .long 1
> +; CHECK-NEXT: .long ("$handlerMap$1$?f@@YAXXZ")@IMGREL
> +; CHECK-NEXT:"$handlerMap$0$?f@@YAXXZ":
> +; CHECK-NEXT: .long 8
> +; CHECK-NEXT: .long "??_R0H at 8"@IMGREL
> +; CHECK-NEXT: .long 0
> +; CHECK-NEXT: .long "?f@@YAXXZ.catch"@IMGREL
> +; CHECK-NEXT: .long ".L?f@@YAXXZ.catch$parent_frame_offset"
> +; CHECK-NEXT:"$handlerMap$1$?f@@YAXXZ":
> +; CHECK-NEXT: .long 0
> +; CHECK-NEXT: .long "??_R0N at 8"@IMGREL
> +; CHECK-NEXT: .long 0
> +; CHECK-NEXT: .long "?f@@YAXXZ.catch1"@IMGREL
> +; CHECK-NEXT: .long ".L?f@@YAXXZ.catch1$parent_frame_offset"
> +; CHECK-NEXT:"$ip2state$?f@@YAXXZ":
> +; CHECK-NEXT: .long .Ltmp0 at IMGREL
> +; CHECK-NEXT: .long 0
> +; CHECK-NEXT: .long .Ltmp13 at IMGREL
> +; CHECK-NEXT: .long 1
> +; CHECK-NEXT: .long .Ltmp16 at IMGREL
> +; CHECK-NEXT: .long 0
> +
> +
> +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.frameescape(...) #3
> +
> +; Function Attrs: nounwind readnone
> +declare i8* @llvm.framerecover(i8*, i8*, i32) #2
> +
> +; Function Attrs: nounwind
> +declare void @llvm.eh.unwindhelp(i8*) #3
> +
> +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" }
>
> Copied: llvm/trunk/test/CodeGen/WinEH/cppeh-prepared-cleanups.ll (from
> r233763, llvm/trunk/test/CodeGen/WinEH/cppeh-cleanups.ll)
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/cppeh-prepared-cleanups.ll?p2=llvm/trunk/test/CodeGen/WinEH/cppeh-prepared-cleanups.ll&p1=llvm/trunk/test/CodeGen/WinEH/cppeh-cleanups.ll&r1=233763&r2=233767&rev=233767&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/WinEH/cppeh-cleanups.ll (original)
> +++ llvm/trunk/test/CodeGen/WinEH/cppeh-prepared-cleanups.ll Tue Mar 31
> 17:35:44 2015
> @@ -27,7 +27,7 @@ $_TI1H = comdat any
> @_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-LABEL: "?test1@@YAXXZ":
> ; CHECK: .seh_handlerdata
> ; CHECK-NEXT: .long ("$cppxdata$?test1@@YAXXZ")@IMGREL
> ; CHECK-NEXT:"$cppxdata$?test1@@YAXXZ":
> @@ -126,11 +126,11 @@ entry:
> %s1 = alloca %struct.S, align 1
> %frombool = zext i1 %b to i8
> store i8 %frombool, i8* %b.addr, align 1
> - call void @"\01?may_throw@@YAXXZ"()
> - call void (...)* @llvm.frameescape(%struct.S* %s, %struct.S* %s1)
> - store volatile i64 -2, i64* %unwindhelp
> %0 = bitcast i64* %unwindhelp to i8*
> + store volatile i64 -2, i64* %unwindhelp
> + call void (...)* @llvm.frameescape(%struct.S* %s, %struct.S* %s1)
> call void @llvm.eh.unwindhelp(i8* %0)
> + call void @"\01?may_throw@@YAXXZ"()
> invoke void @"\01?may_throw@@YAXXZ"()
> to label %invoke.cont unwind label %lpad1
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> <javascript:_e(%7B%7D,'cvml','llvm-commits at cs.uiuc.edu');>
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150331/99eb5f32/attachment.html>
More information about the llvm-commits
mailing list