[llvm] r247192 - [SEH] Emit 32-bit SEH tables for the new EH IR

Reid Kleckner via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 9 14:10:03 PDT 2015


Author: rnk
Date: Wed Sep  9 16:10:03 2015
New Revision: 247192

URL: http://llvm.org/viewvc/llvm-project?rev=247192&view=rev
Log:
[SEH] Emit 32-bit SEH tables for the new EH IR

The 32-bit tables don't actually contain PC range data, so emitting them
is incredibly simple.

The 64-bit tables, on the other hand, use the same table for state
numbering as well as label ranges. This makes things more difficult, so
it will be implemented later.

Added:
    llvm/trunk/test/CodeGen/X86/win32-seh-catchpad.ll
Modified:
    llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h
    llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp
    llvm/trunk/lib/CodeGen/AsmPrinter/WinException.h
    llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
    llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
    llvm/trunk/lib/Target/X86/X86WinEHState.cpp

Modified: llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h?rev=247192&r1=247191&r2=247192&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h (original)
+++ llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h Wed Sep  9 16:10:03 2015
@@ -14,9 +14,10 @@
 #ifndef LLVM_CODEGEN_WINEHFUNCINFO_H
 #define LLVM_CODEGEN_WINEHFUNCINFO_H
 
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/TinyPtrVector.h"
-#include "llvm/ADT/DenseMap.h"
 
 namespace llvm {
 class AllocaInst;
@@ -120,17 +121,32 @@ struct WinEHUnwindMapEntry {
   const Value *Cleanup;
 };
 
+typedef PointerUnion<const BasicBlock *, MachineBasicBlock *> MBBOrBasicBlock;
+typedef PointerUnion<const Value *, MachineBasicBlock *> ValueOrMBB;
+
+/// Similar to WinEHUnwindMapEntry, but supports SEH filters.
+struct SEHUnwindMapEntry {
+  /// If unwinding continues through this handler, transition to the handler at
+  /// this state. This indexes into SEHUnwindMap.
+  int ToState = -1;
+
+  /// Holds the filter expression function.
+  const Function *Filter = nullptr;
+
+  /// Holds the __except or __finally basic block.
+  MBBOrBasicBlock Handler;
+};
+
 struct WinEHHandlerType {
   int Adjectives;
   GlobalVariable *TypeDescriptor;
   int CatchObjRecoverIdx;
-  const Value *Handler;
-  MachineBasicBlock *HandlerMBB;
+  ValueOrMBB Handler;
 };
 
 struct WinEHTryBlockMapEntry {
-  int TryLow;
-  int TryHigh;
+  int TryLow = -1;
+  int TryHigh = -1;
   int CatchHigh = -1;
   SmallVector<WinEHHandlerType, 1> HandlerArray;
 };
@@ -147,6 +163,7 @@ struct WinEHFuncInfo {
   DenseMap<const Function *, int> HandlerBaseState;
   SmallVector<WinEHUnwindMapEntry, 4> UnwindMap;
   SmallVector<WinEHTryBlockMapEntry, 4> TryBlockMap;
+  SmallVector<SEHUnwindMapEntry, 4> SEHUnwindMap;
   SmallVector<std::pair<MCSymbol *, int>, 4> IPToStateList;
   int UnwindHelpFrameIdx = INT_MAX;
   int UnwindHelpFrameOffset = -1;
@@ -169,5 +186,7 @@ struct WinEHFuncInfo {
 void calculateWinCXXEHStateNumbers(const Function *ParentFn,
                                    WinEHFuncInfo &FuncInfo);
 
+void calculateSEHStateNumbers(const Function *ParentFn,
+                              WinEHFuncInfo &FuncInfo);
 }
 #endif // LLVM_CODEGEN_WINEHFUNCINFO_H

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp?rev=247192&r1=247191&r2=247192&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/WinException.cpp Wed Sep  9 16:10:03 2015
@@ -161,7 +161,7 @@ void WinException::endFunction(const Mac
     // Emit the tables appropriate to the personality function in use. If we
     // don't recognize the personality, assume it uses an Itanium-style LSDA.
     if (Per == EHPersonality::MSVC_Win64SEH)
-      emitCSpecificHandlerTable();
+      emitCSpecificHandlerTable(MF);
     else if (Per == EHPersonality::MSVC_X86SEH)
       emitExceptHandlerTable(MF);
     else if (Per == EHPersonality::MSVC_CXX)
@@ -222,9 +222,13 @@ const MCExpr *WinException::create32bitR
 ///       imagerel32 LabelLPad;        // Zero means __finally.
 ///     } Entries[NumEntries];
 ///   };
-void WinException::emitCSpecificHandlerTable() {
+void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) {
   const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
 
+  WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(MF->getFunction());
+  if (!FuncInfo.SEHUnwindMap.empty())
+    report_fatal_error("x64 SEH tables not yet implemented");
+
   // Simplifying assumptions for first implementation:
   // - Cleanups are not implemented.
   // - Filters are not implemented.
@@ -309,6 +313,15 @@ void WinException::emitCSpecificHandlerT
   }
 }
 
+/// Retreive the MCSymbol for a GlobalValue or MachineBasicBlock. GlobalValues
+/// are used in the old WinEH scheme, and they will be removed eventually.
+static MCSymbol *getMCSymbolForMBBOrGV(AsmPrinter *Asm, ValueOrMBB Handler) {
+  if (Handler.is<MachineBasicBlock *>())
+    return Handler.get<MachineBasicBlock *>()->getSymbol();
+  else
+    return Asm->getSymbol(cast<GlobalValue>(Handler.get<const Value *>()));
+}
+
 void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
   const Function *F = MF->getFunction();
   const Function *ParentF = MMI->getWinEHParent(F);
@@ -422,9 +435,9 @@ void WinException::emitCXXFrameHandler3T
       int CatchHigh = TBME.CatchHigh;
       if (CatchHigh == -1) {
         for (WinEHHandlerType &HT : TBME.HandlerArray)
-          CatchHigh = std::max(
-              CatchHigh,
-              FuncInfo.CatchHandlerMaxState[cast<Function>(HT.Handler)]);
+          CatchHigh =
+              std::max(CatchHigh, FuncInfo.CatchHandlerMaxState[cast<Function>(
+                                      HT.Handler.get<const Value *>())]);
       }
 
       assert(TBME.TryLow <= TBME.TryHigh);
@@ -464,13 +477,12 @@ void WinException::emitCXXFrameHandler3T
           FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext);
         }
 
-        OS.EmitIntValue(HT.Adjectives, 4);                    // Adjectives
-        OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4);   // Type
-        OS.EmitValue(FrameAllocOffsetRef, 4);                 // CatchObjOffset
-        if (HT.HandlerMBB)                                    // Handler
-          OS.EmitValue(create32bitRef(HT.HandlerMBB->getSymbol()), 4);
-        else
-          OS.EmitValue(create32bitRef(HT.Handler), 4);
+        MCSymbol *HandlerSym = getMCSymbolForMBBOrGV(Asm, HT.Handler);
+
+        OS.EmitIntValue(HT.Adjectives, 4);                  // Adjectives
+        OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); // Type
+        OS.EmitValue(FrameAllocOffsetRef, 4);               // CatchObjOffset
+        OS.EmitValue(create32bitRef(HandlerSym), 4);        // Handler
 
         if (shouldEmitPersonality) {
           if (FuncInfo.CatchHandlerParentFrameObjOffset.empty()) {
@@ -482,7 +494,8 @@ void WinException::emitCXXFrameHandler3T
           } else {
             MCSymbol *ParentFrameOffset =
                 Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
-                    GlobalValue::getRealLinkageName(HT.Handler->getName()));
+                    GlobalValue::getRealLinkageName(
+                        HT.Handler.get<const Value *>()->getName()));
             const MCSymbolRefExpr *ParentFrameOffsetRef =
                 MCSymbolRefExpr::create(ParentFrameOffset, Asm->OutContext);
             OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
@@ -642,6 +655,19 @@ void WinException::emitExceptHandlerTabl
     BaseState = -2;
   }
 
+  if (!FuncInfo.SEHUnwindMap.empty()) {
+    for (SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) {
+      MCSymbol *ExceptOrFinally =
+          UME.Handler.get<MachineBasicBlock *>()->getSymbol();
+      OS.EmitIntValue(UME.ToState, 4);                  // ToState
+      OS.EmitValue(create32bitRef(UME.Filter), 4);      // Filter
+      OS.EmitValue(create32bitRef(ExceptOrFinally), 4); // Except/Finally
+    }
+    return;
+  }
+  // FIXME: The following code is for the old landingpad-based SEH
+  // implementation. Remove it when possible.
+
   // Build a list of pointers to LandingPadInfos and then sort by WinEHState.
   const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
   SmallVector<const LandingPadInfo *, 4> LPads;

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/WinException.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/WinException.h?rev=247192&r1=247191&r2=247192&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/WinException.h (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/WinException.h Wed Sep  9 16:10:03 2015
@@ -36,7 +36,7 @@ class LLVM_LIBRARY_VISIBILITY WinExcepti
   /// True if this is a 64-bit target and we should use image relative offsets.
   bool useImageRel32 = false;
 
-  void emitCSpecificHandlerTable();
+  void emitCSpecificHandlerTable(const MachineFunction *MF);
 
   /// Emit the EH table data for 32-bit and 64-bit functions using
   /// the __CxxFrameHandler3 personality.

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp?rev=247192&r1=247191&r2=247192&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp Wed Sep  9 16:10:03 2015
@@ -287,21 +287,31 @@ void FunctionLoweringInfo::set(const Fun
     addSEHHandlersForLPads(LPads);
   }
 
+  // Calculate state numbers if we haven't already.
   WinEHFuncInfo &EHInfo = MMI.getWinEHFuncInfo(&fn);
   if (Personality == EHPersonality::MSVC_CXX) {
-    // Calculate state numbers and then map from funclet BBs to MBBs.
     const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
     calculateWinCXXEHStateNumbers(WinEHParentFn, EHInfo);
+  } else {
+    const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
+    calculateSEHStateNumbers(WinEHParentFn, EHInfo);
+  }
+
+    // Map all BB references in the EH data to MBBs.
     for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap)
       for (WinEHHandlerType &H : TBME.HandlerArray)
-        if (const auto *BB = dyn_cast<BasicBlock>(H.Handler))
-          H.HandlerMBB = MBBMap[BB];
-    // If there's an explicit EH registration node on the stack, record its
-    // frame index.
-    if (EHInfo.EHRegNode && EHInfo.EHRegNode->getParent()->getParent() == Fn) {
-      assert(StaticAllocaMap.count(EHInfo.EHRegNode));
-      EHInfo.EHRegNodeFrameIndex = StaticAllocaMap[EHInfo.EHRegNode];
+        if (const auto *BB =
+                dyn_cast<BasicBlock>(H.Handler.get<const Value *>()))
+          H.Handler = MBBMap[BB];
+    for (SEHUnwindMapEntry &UME : EHInfo.SEHUnwindMap) {
+      const BasicBlock *BB = UME.Handler.get<const BasicBlock *>();
+      UME.Handler = MBBMap[BB];
     }
+  // If there's an explicit EH registration node on the stack, record its
+  // frame index.
+  if (EHInfo.EHRegNode && EHInfo.EHRegNode->getParent()->getParent() == Fn) {
+    assert(StaticAllocaMap.count(EHInfo.EHRegNode));
+    EHInfo.EHRegNodeFrameIndex = StaticAllocaMap[EHInfo.EHRegNode];
   }
 
   // Copy the state numbers to LandingPadInfo for the current function, which

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=247192&r1=247191&r2=247192&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Wed Sep  9 16:10:03 2015
@@ -1989,7 +1989,6 @@ void SelectionDAGBuilder::visitInvoke(co
   // and catchendpads for successors.
   MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)];
   const BasicBlock *EHPadBB = I.getSuccessor(1);
-  bool IsLandingPad = EHPadBB->isLandingPad();
 
   const Value *Callee(I.getCalledValue());
   const Function *Fn = dyn_cast<Function>(Callee);
@@ -2025,16 +2024,26 @@ void SelectionDAGBuilder::visitInvoke(co
   // Catchpads are conditional branches that add real MBB destinations and
   // continue the loop. EH "end" pads are not real BBs and simply continue.
   SmallVector<MachineBasicBlock *, 1> UnwindDests;
+  bool IsMSVCCXX = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn()) ==
+                   EHPersonality::MSVC_CXX;
   while (EHPadBB) {
     const Instruction *Pad = EHPadBB->getFirstNonPHI();
-    if (isa<CleanupPadInst>(Pad) || isa<LandingPadInst>(Pad)) {
-      assert(FuncInfo.MBBMap[EHPadBB]);
-      // Stop on cleanup pads and landingpads.
+    if (isa<LandingPadInst>(Pad)) {
+      // Stop on landingpads. They are not funclets.
       UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
       break;
+    } else if (isa<CleanupPadInst>(Pad) || isa<LandingPadInst>(Pad)) {
+      // Stop on cleanup pads. Cleanups are always funclet entries for all known
+      // personalities.
+      UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]);
+      UnwindDests.back()->setIsEHFuncletEntry();
+      break;
     } else if (const auto *CPI = dyn_cast<CatchPadInst>(Pad)) {
       // Add the catchpad handler to the possible destinations.
       UnwindDests.push_back(FuncInfo.MBBMap[CPI->getNormalDest()]);
+      // In MSVC C++, catchblocks are funclets and need prologues.
+      if (IsMSVCCXX)
+        UnwindDests.back()->setIsEHFuncletEntry();
       EHPadBB = CPI->getUnwindDest();
     } else if (const auto *CEPI = dyn_cast<CatchEndPadInst>(Pad)) {
       EHPadBB = CEPI->getUnwindDest();
@@ -2043,13 +2052,11 @@ void SelectionDAGBuilder::visitInvoke(co
     }
   }
 
-  // Update successor info
+  // Update successor info.
   // FIXME: The weights for catchpads will be wrong.
   addSuccessorWithWeight(InvokeMBB, Return);
-  for (auto *UnwindDest : UnwindDests) {
+  for (MachineBasicBlock *UnwindDest : UnwindDests) {
     UnwindDest->setIsEHPad();
-    if (!IsLandingPad)
-      UnwindDest->setIsEHFuncletEntry();
     addSuccessorWithWeight(InvokeMBB, UnwindDest);
   }
 

Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=247192&r1=247191&r2=247192&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Wed Sep  9 16:10:03 2015
@@ -2616,7 +2616,6 @@ static void addTryBlockMapEntry(WinEHFun
           cast<GlobalVariable>(CS->getAggregateElement(1)->stripPointerCasts());
     }
     HT.Handler = CPI->getNormalDest();
-    HT.HandlerMBB = nullptr;
     // FIXME: Pass CPI->getArgOperand(1).
     HT.CatchObjRecoverIdx = -1;
     TBME.HandlerArray.push_back(HT);
@@ -2645,7 +2644,8 @@ void WinEHNumbering::createTryBlockMapEn
       continue;
     int N;
     for (N = 0; N < NumHandlers; ++N) {
-      if (Entry.HandlerArray[N].Handler != Handlers[N]->getHandlerBlockOrFunc())
+      if (Entry.HandlerArray[N].Handler.get<const Value *>() !=
+          Handlers[N]->getHandlerBlockOrFunc())
         break; // breaks out of inner loop
     }
     // If all the handlers match, this is what we were looking for.
@@ -2692,7 +2692,6 @@ void WinEHNumbering::createTryBlockMapEn
           cast<GlobalVariable>(CS->getAggregateElement(1)->stripPointerCasts());
     }
     HT.Handler = cast<Function>(CH->getHandlerBlockOrFunc());
-    HT.HandlerMBB = nullptr;
     HT.CatchObjRecoverIdx = CH->getExceptionVarIndex();
     TBME.HandlerArray.push_back(HT);
   }
@@ -2949,13 +2948,45 @@ void WinEHNumbering::findActionRootLPads
   }
 }
 
-static const BasicBlock *getSingleCatchPadPredecessor(const BasicBlock &BB) {
-  for (const BasicBlock *PredBlock : predecessors(&BB))
-    if (isa<CatchPadInst>(PredBlock->getFirstNonPHI()))
-      return PredBlock;
+static const CatchPadInst *getSingleCatchPadPredecessor(const BasicBlock *BB) {
+  for (const BasicBlock *PredBlock : predecessors(BB))
+    if (auto *CPI = dyn_cast<CatchPadInst>(PredBlock->getFirstNonPHI()))
+      return CPI;
   return nullptr;
 }
 
+/// Find all the catchpads that feed directly into the catchendpad. Frontends
+/// using this personality should ensure that each catchendpad and catchpad has
+/// one or zero catchpad predecessors.
+///
+/// The following C++ generates the IR after it:
+///   try {
+///   } catch (A) {
+///   } catch (B) {
+///   }
+///
+/// IR:
+///   %catchpad.A
+///     catchpad [i8* A typeinfo]
+///         to label %catch.A unwind label %catchpad.B
+///   %catchpad.B
+///     catchpad [i8* B typeinfo]
+///         to label %catch.B unwind label %endcatches
+///   %endcatches
+///     catchendblock unwind to caller
+void findCatchPadsForCatchEndPad(
+    const BasicBlock *CatchEndBB,
+    SmallVectorImpl<const CatchPadInst *> &Handlers) {
+  const CatchPadInst *CPI = getSingleCatchPadPredecessor(CatchEndBB);
+  while (CPI) {
+    Handlers.push_back(CPI);
+    CPI = getSingleCatchPadPredecessor(CPI->getParent());
+  }
+  // We've pushed these back into reverse source order.  Reverse them to get
+  // the list back into source order.
+  std::reverse(Handlers.begin(), Handlers.end());
+}
+
 // Given BB which ends in an unwind edge, return the EHPad that this BB belongs
 // to. If the unwind edge came from an invoke, return null.
 static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB) {
@@ -2970,9 +3001,9 @@ static const BasicBlock *getEHPadFromPre
   return cast<CleanupReturnInst>(TI)->getCleanupPad()->getParent();
 }
 
-static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo,
-                                          const BasicBlock &BB,
-                                          int ParentState) {
+static void calculateExplicitCXXStateNumbers(WinEHFuncInfo &FuncInfo,
+                                             const BasicBlock &BB,
+                                             int ParentState) {
   assert(BB.isEHPad());
   const Instruction *FirstNonPHI = BB.getFirstNonPHI();
   // All catchpad instructions will be handled when we process their
@@ -2981,36 +3012,30 @@ static void calculateExplicitStateNumber
     return;
 
   if (isa<CatchEndPadInst>(FirstNonPHI)) {
-    const BasicBlock *TryPad = &BB;
-    const BasicBlock *LastTryPad = nullptr;
     SmallVector<const CatchPadInst *, 2> Handlers;
-    do {
-      LastTryPad = TryPad;
-      TryPad = getSingleCatchPadPredecessor(*TryPad);
-      if (TryPad)
-        Handlers.push_back(cast<CatchPadInst>(TryPad->getFirstNonPHI()));
-    } while (TryPad);
-    // We've pushed these back into reverse source order.  Reverse them to get
-    // the list back into source order.
-    std::reverse(Handlers.begin(), Handlers.end());
+    findCatchPadsForCatchEndPad(&BB, Handlers);
+    const BasicBlock *FirstTryPad = Handlers.front()->getParent();
     int TryLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
     FuncInfo.EHPadStateMap[Handlers.front()] = TryLow;
-    for (const BasicBlock *PredBlock : predecessors(LastTryPad))
+    for (const BasicBlock *PredBlock : predecessors(FirstTryPad))
       if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
-        calculateExplicitStateNumbers(FuncInfo, *PredBlock, TryLow);
+        calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, TryLow);
     int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr);
+
+    // catchpads are separate funclets in C++ EH due to the way rethrow works.
+    // In SEH, they aren't, so no invokes will unwind to the catchendpad.
     FuncInfo.EHPadStateMap[FirstNonPHI] = CatchLow;
     int TryHigh = CatchLow - 1;
     for (const BasicBlock *PredBlock : predecessors(&BB))
       if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
-        calculateExplicitStateNumbers(FuncInfo, *PredBlock, CatchLow);
+        calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CatchLow);
     int CatchHigh = FuncInfo.getLastStateNumber();
     addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers);
-    DEBUG(dbgs() << "TryLow[" << LastTryPad->getName() << "]: " << TryLow
+    DEBUG(dbgs() << "TryLow[" << FirstTryPad->getName() << "]: " << TryLow
                  << '\n');
-    DEBUG(dbgs() << "TryHigh[" << LastTryPad->getName() << "]: " << TryHigh
+    DEBUG(dbgs() << "TryHigh[" << FirstTryPad->getName() << "]: " << TryHigh
                  << '\n');
-    DEBUG(dbgs() << "CatchHigh[" << LastTryPad->getName() << "]: " << CatchHigh
+    DEBUG(dbgs() << "CatchHigh[" << FirstTryPad->getName() << "]: " << CatchHigh
                  << '\n');
   } else if (isa<CleanupPadInst>(FirstNonPHI)) {
     int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, &BB);
@@ -3019,7 +3044,7 @@ static void calculateExplicitStateNumber
                  << BB.getName() << '\n');
     for (const BasicBlock *PredBlock : predecessors(&BB))
       if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
-        calculateExplicitStateNumbers(FuncInfo, *PredBlock, CleanupState);
+        calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CleanupState);
   } else if (isa<TerminatePadInst>(FirstNonPHI)) {
     report_fatal_error("Not yet implemented!");
   } else {
@@ -3027,6 +3052,103 @@ static void calculateExplicitStateNumber
   }
 }
 
+static int addSEHHandler(WinEHFuncInfo &FuncInfo, int ParentState,
+                          const Function *Filter, const BasicBlock *Handler) {
+  SEHUnwindMapEntry Entry;
+  Entry.ToState = ParentState;
+  Entry.Filter = Filter;
+  Entry.Handler = Handler;
+  FuncInfo.SEHUnwindMap.push_back(Entry);
+  return FuncInfo.SEHUnwindMap.size() - 1;
+}
+
+static void calculateExplicitSEHStateNumbers(WinEHFuncInfo &FuncInfo,
+                                             const BasicBlock &BB,
+                                             int ParentState) {
+  assert(BB.isEHPad());
+  const Instruction *FirstNonPHI = BB.getFirstNonPHI();
+  // All catchpad instructions will be handled when we process their
+  // respective catchendpad instruction.
+  if (isa<CatchPadInst>(FirstNonPHI))
+    return;
+
+  if (isa<CatchEndPadInst>(FirstNonPHI)) {
+    // Extract the filter function and the __except basic block and create a
+    // state for them.
+    SmallVector<const CatchPadInst *, 1> Handlers;
+    findCatchPadsForCatchEndPad(&BB, Handlers);
+    assert(Handlers.size() == 1 &&
+           "SEH doesn't have multiple handlers per __try");
+    const CatchPadInst *CPI = Handlers.front();
+    const BasicBlock *CatchPadBB = CPI->getParent();
+    const Function *Filter =
+        cast<Function>(CPI->getArgOperand(0)->stripPointerCasts());
+    int TryState =
+        addSEHHandler(FuncInfo, ParentState, Filter, CPI->getNormalDest());
+
+    // Everything in the __try block uses TryState as its parent state.
+    FuncInfo.EHPadStateMap[CPI] = TryState;
+    DEBUG(dbgs() << "Assigning state #" << TryState << " to BB "
+                 << CatchPadBB->getName() << '\n');
+    for (const BasicBlock *PredBlock : predecessors(CatchPadBB))
+      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
+        calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, TryState);
+
+    // Everything in the __except block unwinds to ParentState, just like code
+    // outside the __try.
+    FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState;
+    DEBUG(dbgs() << "Assigning state #" << ParentState << " to BB "
+                 << BB.getName() << '\n');
+    for (const BasicBlock *PredBlock : predecessors(&BB))
+      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
+        calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, ParentState);
+  } else if (isa<CleanupPadInst>(FirstNonPHI)) {
+    int CleanupState =
+        addSEHHandler(FuncInfo, ParentState, /*Filter=*/nullptr, &BB);
+    FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState;
+    DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB "
+                 << BB.getName() << '\n');
+    for (const BasicBlock *PredBlock : predecessors(&BB))
+      if ((PredBlock = getEHPadFromPredecessor(PredBlock)))
+        calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, CleanupState);
+  } else if (isa<TerminatePadInst>(FirstNonPHI)) {
+    report_fatal_error("Not yet implemented!");
+  } else {
+    llvm_unreachable("unexpected EH Pad!");
+  }
+}
+
+/// Check if the EH Pad unwinds to caller.  Cleanups are a little bit of a
+/// special case because we have to look at the cleanupret instruction that uses
+/// the cleanuppad.
+static bool doesEHPadUnwindToCaller(const Instruction *EHPad) {
+  auto *CPI = dyn_cast<CleanupPadInst>(EHPad);
+  if (!CPI)
+    return EHPad->mayThrow();
+
+  // This cleanup does not return or unwind, so we say it unwinds to caller.
+  if (CPI->use_empty())
+    return true;
+
+  const Instruction *User = CPI->user_back();
+  if (auto *CRI = dyn_cast<CleanupReturnInst>(User))
+    return CRI->unwindsToCaller();
+  return cast<CleanupEndPadInst>(User)->unwindsToCaller();
+}
+
+void llvm::calculateSEHStateNumbers(const Function *ParentFn,
+                                    WinEHFuncInfo &FuncInfo) {
+  // Don't compute state numbers twice.
+  if (!FuncInfo.SEHUnwindMap.empty())
+    return;
+
+  for (const BasicBlock &BB : *ParentFn) {
+    if (!BB.isEHPad() || !doesEHPadUnwindToCaller(BB.getFirstNonPHI()))
+      continue;
+    calculateExplicitSEHStateNumbers(FuncInfo, BB, -1);
+  }
+}
+
 void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn,
                                          WinEHFuncInfo &FuncInfo) {
   // Return if it's already been done.
@@ -3041,28 +3163,9 @@ void llvm::calculateWinCXXEHStateNumbers
     // Skip cleanupendpads; they are exits, not entries.
     if (isa<CleanupEndPadInst>(FirstNonPHI))
       continue;
-    // Check if the EH Pad has no exceptional successors (i.e. it unwinds to
-    // caller).  Cleanups are a little bit of a special case because their
-    // control flow cannot be determined by looking at the pad but instead by
-    // the pad's users.
-    bool HasNoSuccessors = false;
-    if (FirstNonPHI->mayThrow()) {
-      HasNoSuccessors = true;
-    } else if (auto *CPI = dyn_cast<CleanupPadInst>(FirstNonPHI)) {
-      if (CPI->use_empty()) {
-        HasNoSuccessors = true;
-      } else {
-        const Instruction *User = CPI->user_back();
-        if (auto *CRI = dyn_cast<CleanupReturnInst>(User))
-          HasNoSuccessors = CRI->unwindsToCaller();
-        else
-          HasNoSuccessors = cast<CleanupEndPadInst>(User)->unwindsToCaller();
-      }
-    }
-
-    if (!HasNoSuccessors)
+    if (!doesEHPadUnwindToCaller(FirstNonPHI))
       continue;
-    calculateExplicitStateNumbers(FuncInfo, BB, -1);
+    calculateExplicitCXXStateNumbers(FuncInfo, BB, -1);
     IsExplicit = true;
   }
 

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=247192&r1=247191&r2=247192&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Wed Sep  9 16:10:03 2015
@@ -16880,6 +16880,16 @@ SDValue X86TargetLowering::LowerCATCHRET
   SDLoc DL(Op);
 
   MVT PtrVT = getPointerTy(DAG.getDataLayout());
+
+  MachineFunction &MF = DAG.getMachineFunction();
+  if (isAsynchronousEHPersonality(
+          classifyEHPersonality(MF.getFunction()->getPersonalityFn()))) {
+    // For SEH, codegen catchret as a branch for now.
+    // FIXME: Insert something to restore the frame.
+    return DAG.getNode(ISD::BR, DL, MVT::Other, Chain, Dest);
+  }
+
+
   unsigned ReturnReg = (PtrVT == MVT::i64 ? X86::RAX : X86::EAX);
 
   // Load the address of the destination block.

Modified: llvm/trunk/lib/Target/X86/X86WinEHState.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86WinEHState.cpp?rev=247192&r1=247191&r2=247192&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86WinEHState.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86WinEHState.cpp Wed Sep  9 16:10:03 2015
@@ -68,9 +68,10 @@ private:
   void unlinkExceptionRegistration(IRBuilder<> &Builder);
   void addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo);
   void addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo);
-  void addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo,
-                                  Function &F, int BaseState);
+  void addStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo,
+                               Function &F, int BaseState);
   void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State);
+  void insertRestoreFrame(BasicBlock *BB);
 
   Value *emitEHLSDA(IRBuilder<> &Builder, Function *F);
 
@@ -91,6 +92,7 @@ private:
   Function *FrameRecover = nullptr;
   Function *FrameAddress = nullptr;
   Function *FrameEscape = nullptr;
+  Function *RestoreFrame = nullptr;
 
   // Per-function state
   EHPersonality Personality = EHPersonality::Unknown;
@@ -123,6 +125,8 @@ bool WinEHStatePass::doInitialization(Mo
   FrameEscape = Intrinsic::getDeclaration(TheModule, Intrinsic::localescape);
   FrameRecover = Intrinsic::getDeclaration(TheModule, Intrinsic::localrecover);
   FrameAddress = Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress);
+  RestoreFrame =
+      Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe);
   return false;
 }
 
@@ -414,7 +418,7 @@ void WinEHStatePass::addCXXStateStores(F
   calculateWinCXXEHStateNumbers(&F, FuncInfo);
 
   // The base state for the parent is -1.
-  addCXXStateStoresToFunclet(RegNode, FuncInfo, F, -1);
+  addStateStoresToFunclet(RegNode, FuncInfo, F, -1);
 
   // Set up RegNodeEscapeIndex
   int RegNodeEscapeIndex = escapeRegNode(F);
@@ -434,7 +438,7 @@ void WinEHStatePass::addCXXStateStores(F
         FrameRecover, {FI8, ParentFP, Builder.getInt32(RegNodeEscapeIndex)});
     RecoveredRegNode =
         Builder.CreateBitCast(RecoveredRegNode, RegNodeTy->getPointerTo(0));
-    addCXXStateStoresToFunclet(RecoveredRegNode, FuncInfo, *Handler, BaseState);
+    addStateStoresToFunclet(RecoveredRegNode, FuncInfo, *Handler, BaseState);
   }
 }
 
@@ -470,11 +474,17 @@ int WinEHStatePass::escapeRegNode(Functi
   return Args.size() - 1;
 }
 
-void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode,
-                                                WinEHFuncInfo &FuncInfo,
-                                                Function &F, int BaseState) {
-  Function *RestoreFrame =
-      Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe);
+void WinEHStatePass::insertRestoreFrame(BasicBlock *BB) {
+  Instruction *Start = BB->getFirstInsertionPt();
+  if (match(Start, m_Intrinsic<Intrinsic::x86_seh_restoreframe>()))
+    return;
+  IRBuilder<> Builder(Start);
+  Builder.CreateCall(RestoreFrame, {});
+}
+
+void WinEHStatePass::addStateStoresToFunclet(Value *ParentRegNode,
+                                             WinEHFuncInfo &FuncInfo,
+                                             Function &F, int BaseState) {
   // Iterate all the instructions and emit state number stores.
   for (BasicBlock &BB : F) {
     for (Instruction &I : BB) {
@@ -494,16 +504,14 @@ void WinEHStatePass::addCXXStateStoresTo
       }
     }
 
-    // Insert calls to llvm.x86.seh.restoreframe at catchret destinations.
-    if (auto *CR = dyn_cast<CatchReturnInst>(BB.getTerminator())) {
-      Instruction *Start = CR->getSuccessor()->begin();
-      assert(!isa<PHINode>(Start) &&
-             "winehprepare failed to demote phi after catchret");
-      if (match(Start, m_Intrinsic<Intrinsic::x86_seh_restoreframe>()))
-        continue;
-      IRBuilder<> Builder(Start);
-      Builder.CreateCall(RestoreFrame, {});
-    }
+    // Insert calls to llvm.x86.seh.restoreframe at catchret destinations.  In
+    // SEH, insert them before the catchret.
+    // FIXME: We should probably do this as part of catchret lowering in the
+    // DAG.
+    if (auto *CR = dyn_cast<CatchReturnInst>(BB.getTerminator()))
+      insertRestoreFrame(Personality == EHPersonality::MSVC_X86SEH
+                             ? CR->getParent()
+                             : CR->getSuccessor());
   }
 }
 
@@ -519,6 +527,23 @@ void WinEHStatePass::addSEHStateStores(F
   int RegNodeEscapeIndex = escapeRegNode(F);
   FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex;
 
+  // If this funciton uses the new EH IR, use the explicit state numbering
+  // algorithm and return early.
+  bool UsesLPads = false;
+  for (BasicBlock &BB : F) {
+    if (BB.isLandingPad()) {
+      UsesLPads = true;
+      break;
+    }
+  }
+  if (!UsesLPads) {
+    calculateSEHStateNumbers(&F, FuncInfo);
+    addStateStoresToFunclet(RegNode, FuncInfo, F, -1);
+    return;
+  }
+  // FIXME: Delete the rest of this code and clean things up when new EH is
+  // done.
+
   // Iterate all the instructions and emit state number stores.
   int CurState = 0;
   SmallPtrSet<BasicBlock *, 4> ExceptBlocks;

Added: llvm/trunk/test/CodeGen/X86/win32-seh-catchpad.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win32-seh-catchpad.ll?rev=247192&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/win32-seh-catchpad.ll (added)
+++ llvm/trunk/test/CodeGen/X86/win32-seh-catchpad.ll Wed Sep  9 16:10:03 2015
@@ -0,0 +1,219 @@
+; RUN: llc < %s | FileCheck %s
+
+target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
+target triple = "i686-pc-windows-msvc"
+
+define void @try_except() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
+entry:
+  %__exception_code = alloca i32, align 4
+  call void (...) @llvm.localescape(i32* %__exception_code)
+  invoke void @f(i32 1) #3
+          to label %invoke.cont unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %entry
+  %0 = catchpad [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
+
+__except.ret:                                     ; preds = %catch.dispatch
+  catchret %0 to label %__except
+
+__except:                                         ; preds = %__except.ret
+  call void @f(i32 2)
+  br label %__try.cont
+
+__try.cont:                                       ; preds = %__except, %invoke.cont
+  call void @f(i32 3)
+  ret void
+
+catchendblock:                                    ; preds = %catch.dispatch
+  catchendpad unwind to caller
+
+invoke.cont:                                      ; preds = %entry
+  br label %__try.cont
+}
+
+; CHECK-LABEL: _try_except:
+;     Store state #0
+; CHECK: movl $0, -[[state:[0-9]+]](%ebp)
+; CHECK: movl $1, (%esp)
+; CHECK: calll _f
+; CHECK: movl $-1, -[[state]](%ebp)
+; CHECK: movl $3, (%esp)
+; CHECK: calll _f
+; CHECK: retl
+
+;   __except
+; CHECK: movl $-1, -[[state]](%ebp)
+; CHECK: movl $2, (%esp)
+; CHECK: calll _f
+
+; CHECK: .section        .xdata,"dr"
+; CHECK: L__ehtable$try_except:
+; CHECK:         .long   -1
+; CHECK:         .long   _try_except_filter_catchall
+; CHECK:         .long   LBB0_1
+
+define internal i32 @try_except_filter_catchall() #0 {
+entry:
+  %0 = call i8* @llvm.frameaddress(i32 1)
+  %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @try_except to i8*), i8* %0)
+  %2 = call i8* @llvm.localrecover(i8* bitcast (void ()* @try_except to i8*), i8* %1, i32 0)
+  %__exception_code = bitcast i8* %2 to i32*
+  %3 = getelementptr inbounds i8, i8* %0, i32 -20
+  %4 = bitcast i8* %3 to i8**
+  %5 = load i8*, i8** %4, align 4
+  %6 = bitcast i8* %5 to { i32*, i8* }*
+  %7 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %6, i32 0, i32 0
+  %8 = load i32*, i32** %7, align 4
+  %9 = load i32, i32* %8, align 4
+  store i32 %9, i32* %__exception_code, align 4
+  ret i32 1
+}
+
+define void @nested_exceptions() #0 personality i8* bitcast (i32 (...)* @_except_handler3 to i8*) {
+entry:
+  %__exception_code = alloca i32, align 4
+  call void (...) @llvm.localescape(i32* %__exception_code)
+  invoke void @crash() #3
+          to label %__try.cont unwind label %catch.dispatch
+
+catch.dispatch:                                   ; preds = %entry
+  %0 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret unwind label %catchendblock
+
+__except.ret:                                     ; preds = %catch.dispatch
+  catchret %0 to label %__try.cont
+
+__try.cont:                                       ; preds = %entry, %__except.ret
+  invoke void @crash() #3
+          to label %__try.cont.9 unwind label %catch.dispatch.5
+
+catch.dispatch.5:                                 ; preds = %__try.cont
+  %1 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.7 unwind label %catchendblock.6
+
+__except.ret.7:                                   ; preds = %catch.dispatch.5
+  catchret %1 to label %__try.cont.9
+
+__try.cont.9:                                     ; preds = %__try.cont, %__except.ret.7
+  invoke void @crash() #3
+          to label %__try.cont.15 unwind label %catch.dispatch.11
+
+catch.dispatch.11:                                ; preds = %catchendblock, %catchendblock.6, %__try.cont.9
+  %2 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.13 unwind label %catchendblock.12
+
+__except.ret.13:                                  ; preds = %catch.dispatch.11
+  catchret %2 to label %__try.cont.15
+
+__try.cont.15:                                    ; preds = %__try.cont.9, %__except.ret.13
+  invoke void @crash() #3
+          to label %__try.cont.35 unwind label %catch.dispatch.17
+
+catch.dispatch.17:                                ; preds = %catchendblock.12, %__try.cont.15
+  %3 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.19 unwind label %catchendblock.18
+
+__except.ret.19:                                  ; preds = %catch.dispatch.17
+  catchret %3 to label %__except.20
+
+__except.20:                                      ; preds = %__except.ret.19
+  invoke void @crash() #3
+          to label %__try.cont.27 unwind label %catch.dispatch.23
+
+catch.dispatch.23:                                ; preds = %__except.20
+  %4 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.25 unwind label %catchendblock.24
+
+__except.ret.25:                                  ; preds = %catch.dispatch.23
+  catchret %4 to label %__try.cont.27
+
+__try.cont.27:                                    ; preds = %__except.20, %__except.ret.25
+  invoke void @crash() #3
+          to label %__try.cont.35 unwind label %catch.dispatch.30
+
+catch.dispatch.30:                                ; preds = %__try.cont.27
+  %5 = catchpad [i8* bitcast (i32 ()* @nested_exceptions_filter_catchall to i8*)] to label %__except.ret.32 unwind label %catchendblock.31
+
+__except.ret.32:                                  ; preds = %catch.dispatch.30
+  catchret %5 to label %__try.cont.35
+
+__try.cont.35:                                    ; preds = %__try.cont.15, %__try.cont.27, %__except.ret.32
+  ret void
+
+catchendblock.31:                                 ; preds = %catch.dispatch.30
+  catchendpad unwind to caller
+
+catchendblock.24:                                 ; preds = %catch.dispatch.23
+  catchendpad unwind to caller
+
+catchendblock.18:                                 ; preds = %catch.dispatch.17
+  catchendpad unwind to caller
+
+catchendblock.12:                                 ; preds = %catch.dispatch.11
+  catchendpad unwind label %catch.dispatch.17
+
+catchendblock.6:                                  ; preds = %catch.dispatch.5
+  catchendpad unwind label %catch.dispatch.11
+
+catchendblock:                                    ; preds = %catch.dispatch
+  catchendpad unwind label %catch.dispatch.11
+}
+
+; This table is equivalent to the one produced by MSVC, even if it isn't in
+; quite the same order.
+
+; CHECK-LABEL: _nested_exceptions:
+; CHECK: L__ehtable$nested_exceptions:
+; CHECK:         .long   -1
+; CHECK:         .long   _nested_exceptions_filter_catchall
+; CHECK:         .long   LBB
+; CHECK:         .long   -1
+; CHECK:         .long   _nested_exceptions_filter_catchall
+; CHECK:         .long   LBB
+; CHECK:         .long   -1
+; CHECK:         .long   _nested_exceptions_filter_catchall
+; CHECK:         .long   LBB
+; CHECK:         .long   2
+; CHECK:         .long   _nested_exceptions_filter_catchall
+; CHECK:         .long   LBB
+; CHECK:         .long   3
+; CHECK:         .long   _nested_exceptions_filter_catchall
+; CHECK:         .long   LBB
+; CHECK:         .long   3
+; CHECK:         .long   _nested_exceptions_filter_catchall
+; CHECK:         .long   LBB
+
+declare void @crash() #0
+
+define internal i32 @nested_exceptions_filter_catchall() #0 {
+entry:
+  %0 = call i8* @llvm.frameaddress(i32 1)
+  %1 = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (void ()* @nested_exceptions to i8*), i8* %0)
+  %2 = call i8* @llvm.localrecover(i8* bitcast (void ()* @nested_exceptions to i8*), i8* %1, i32 0)
+  %__exception_code3 = bitcast i8* %2 to i32*
+  %3 = getelementptr inbounds i8, i8* %0, i32 -20
+  %4 = bitcast i8* %3 to i8**
+  %5 = load i8*, i8** %4, align 4
+  %6 = bitcast i8* %5 to { i32*, i8* }*
+  %7 = getelementptr inbounds { i32*, i8* }, { i32*, i8* }* %6, i32 0, i32 0
+  %8 = load i32*, i32** %7, align 4
+  %9 = load i32, i32* %8, align 4
+  store i32 %9, i32* %__exception_code3, align 4
+  ret i32 1
+}
+
+; Function Attrs: nounwind readnone
+declare i8* @llvm.frameaddress(i32) #1
+
+; Function Attrs: nounwind readnone
+declare i8* @llvm.x86.seh.recoverfp(i8*, i8*) #1
+
+; Function Attrs: nounwind readnone
+declare i8* @llvm.localrecover(i8*, i8*, i32) #1
+
+declare void @f(i32) #0
+
+declare i32 @_except_handler3(...)
+
+; Function Attrs: nounwind
+declare void @llvm.localescape(...) #2
+
+attributes #0 = { "disable-tail-calls"="false" "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 #1 = { nounwind readnone }
+attributes #2 = { nounwind }
+attributes #3 = { noinline }




More information about the llvm-commits mailing list