[llvm] r233767 - [WinEH] Generate .xdata for catch handlers

David Majnemer david.majnemer at gmail.com
Tue Mar 31 16:38:36 PDT 2015


On Tue, Mar 31, 2015 at 4:08 PM, David Majnemer <david.majnemer at gmail.com>
wrote:

>
>
> On Tue, Mar 31, 2015 at 3:57 PM, Kaylor, Andrew <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.
>

Erm, that should read "A catch *handler* has multiple states".  Sorry if
there was any confusion.


>
>
>>
>> -Andy
>>
>> -----Original Message-----
>> From: llvm-commits-bounces at cs.uiuc.edu [mailto:
>> 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
>> 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
>> 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/67b76264/attachment.html>


More information about the llvm-commits mailing list