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