[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