[WinEH] Start EH preparation for 32-bit x86, it uses no arguments
authorReid Kleckner <reid@kleckner.net>
Wed, 29 Apr 2015 22:49:54 +0000 (22:49 +0000)
committerReid Kleckner <reid@kleckner.net>
Wed, 29 Apr 2015 22:49:54 +0000 (22:49 +0000)
32-bit x86 MSVC-style exceptions are functionaly similar to 64-bit, but
they take no arguments. Instead, they implicitly use the value of EBP
passed in by the caller as a pointer to the parent's frame. In LLVM, we
can represent this as llvm.frameaddress(1), and feed that into all of
our calls to llvm.framerecover.

The next steps are:
- Add an alloca to the fs:00 linked list of handlers
- Add something like llvm.sjlj.lsda or generalize it to store in the
  alloca
- Move state number calculation to WinEHPrepare, arrange for
  FunctionLoweringInfo to call it
- Use the state numbers to insert explicit loads and stores in the IR

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236172 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/LibCallSemantics.cpp
lib/CodeGen/WinEHPrepare.cpp
test/CodeGen/WinEH/cppeh-demote-liveout.ll
test/CodeGen/WinEH/cppeh-inalloca.ll
test/CodeGen/WinEH/seh-simple.ll

index 328b186b527a3fe4fc2e13dc43715ff4240b21a6..e98540ba7e90a57e6d05b309f2f2627fca6bd97d 100644 (file)
@@ -73,8 +73,8 @@ EHPersonality llvm::classifyEHPersonality(const Value *Pers) {
     .Case("__gxx_personality_v0",  EHPersonality::GNU_CXX)
     .Case("__gcc_personality_v0",  EHPersonality::GNU_C)
     .Case("__objc_personality_v0", EHPersonality::GNU_ObjC)
     .Case("__gxx_personality_v0",  EHPersonality::GNU_CXX)
     .Case("__gcc_personality_v0",  EHPersonality::GNU_C)
     .Case("__objc_personality_v0", EHPersonality::GNU_ObjC)
-    .Case("__except_handler3",     EHPersonality::MSVC_X86SEH)
-    .Case("__except_handler4",     EHPersonality::MSVC_X86SEH)
+    .Case("_except_handler3",      EHPersonality::MSVC_X86SEH)
+    .Case("_except_handler4",      EHPersonality::MSVC_X86SEH)
     .Case("__C_specific_handler",  EHPersonality::MSVC_Win64SEH)
     .Case("__CxxFrameHandler3",    EHPersonality::MSVC_CXX)
     .Default(EHPersonality::Unknown);
     .Case("__C_specific_handler",  EHPersonality::MSVC_Win64SEH)
     .Case("__CxxFrameHandler3",    EHPersonality::MSVC_CXX)
     .Default(EHPersonality::Unknown);
index 0fa5a12e2da2e32f35cf7e29cf429c85714fbd4b..0461d71507b0b1eea172e3b018a2cc913b1c714c 100644 (file)
@@ -19,6 +19,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/Triple.h"
 #include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Analysis/LibCallSemantics.h"
 #include "llvm/CodeGen/WinEHFuncInfo.h"
 #include "llvm/ADT/TinyPtrVector.h"
 #include "llvm/Analysis/LibCallSemantics.h"
 #include "llvm/CodeGen/WinEHFuncInfo.h"
@@ -71,7 +72,10 @@ class WinEHPrepare : public FunctionPass {
 public:
   static char ID; // Pass identification, replacement for typeid.
   WinEHPrepare(const TargetMachine *TM = nullptr)
 public:
   static char ID; // Pass identification, replacement for typeid.
   WinEHPrepare(const TargetMachine *TM = nullptr)
-      : FunctionPass(ID), DT(nullptr), SEHExceptionCodeSlot(nullptr) {}
+      : FunctionPass(ID), DT(nullptr), SEHExceptionCodeSlot(nullptr) {
+    if (TM)
+      TheTriple = Triple(TM->getTargetTriple());
+  }
 
   bool runOnFunction(Function &Fn) override;
 
 
   bool runOnFunction(Function &Fn) override;
 
@@ -97,6 +101,8 @@ private:
                                 LandingPadInst *OutlinedLPad,
                                 const LandingPadInst *OriginalLPad,
                                 FrameVarInfoMap &VarInfo);
                                 LandingPadInst *OutlinedLPad,
                                 const LandingPadInst *OriginalLPad,
                                 FrameVarInfoMap &VarInfo);
+  Function *createHandlerFunc(Type *RetTy, const Twine &Name, Module *M,
+                              Value *&ParentFP);
   bool outlineHandler(ActionHandler *Action, Function *SrcFn,
                       LandingPadInst *LPad, BasicBlock *StartBB,
                       FrameVarInfoMap &VarInfo);
   bool outlineHandler(ActionHandler *Action, Function *SrcFn,
                       LandingPadInst *LPad, BasicBlock *StartBB,
                       FrameVarInfoMap &VarInfo);
@@ -110,6 +116,8 @@ private:
 
   void processSEHCatchHandler(CatchHandler *Handler, BasicBlock *StartBB);
 
 
   void processSEHCatchHandler(CatchHandler *Handler, BasicBlock *StartBB);
 
+  Triple TheTriple;
+
   // All fields are reset by runOnFunction.
   DominatorTree *DT;
   EHPersonality Personality;
   // All fields are reset by runOnFunction.
   DominatorTree *DT;
   EHPersonality Personality;
@@ -138,12 +146,16 @@ private:
   // outlined but before the outlined code is pruned from the parent function.
   DenseMap<const BasicBlock *, BasicBlock *> LPadTargetBlocks;
 
   // outlined but before the outlined code is pruned from the parent function.
   DenseMap<const BasicBlock *, BasicBlock *> LPadTargetBlocks;
 
+  // Map from outlined handler to call to llvm.frameaddress(1). Only used for
+  // 32-bit EH.
+  DenseMap<Function *, Value *> HandlerToParentFP;
+
   AllocaInst *SEHExceptionCodeSlot;
 };
 
 class WinEHFrameVariableMaterializer : public ValueMaterializer {
 public:
   AllocaInst *SEHExceptionCodeSlot;
 };
 
 class WinEHFrameVariableMaterializer : public ValueMaterializer {
 public:
-  WinEHFrameVariableMaterializer(Function *OutlinedFn,
+  WinEHFrameVariableMaterializer(Function *OutlinedFn, Value *ParentFP,
                                  FrameVarInfoMap &FrameVarInfo);
   ~WinEHFrameVariableMaterializer() override {}
 
                                  FrameVarInfoMap &FrameVarInfo);
   ~WinEHFrameVariableMaterializer() override {}
 
@@ -179,16 +191,12 @@ private:
 
 class WinEHCloningDirectorBase : public CloningDirector {
 public:
 
 class WinEHCloningDirectorBase : public CloningDirector {
 public:
-  WinEHCloningDirectorBase(Function *HandlerFn, FrameVarInfoMap &VarInfo,
-                           LandingPadMap &LPadMap)
-      : Materializer(HandlerFn, VarInfo),
+  WinEHCloningDirectorBase(Function *HandlerFn, Value *ParentFP,
+                           FrameVarInfoMap &VarInfo, LandingPadMap &LPadMap)
+      : Materializer(HandlerFn, ParentFP, VarInfo),
         SelectorIDType(Type::getInt32Ty(HandlerFn->getContext())),
         Int8PtrType(Type::getInt8PtrTy(HandlerFn->getContext())),
         SelectorIDType(Type::getInt32Ty(HandlerFn->getContext())),
         Int8PtrType(Type::getInt8PtrTy(HandlerFn->getContext())),
-        LPadMap(LPadMap) {
-    auto AI = HandlerFn->getArgumentList().begin();
-    ++AI;
-    EstablisherFrame = AI;
-  }
+        LPadMap(LPadMap), ParentFP(ParentFP) {}
 
   CloningAction handleInstruction(ValueToValueMapTy &VMap,
                                   const Instruction *Inst,
 
   CloningAction handleInstruction(ValueToValueMapTy &VMap,
                                   const Instruction *Inst,
@@ -225,16 +233,16 @@ protected:
   LandingPadMap &LPadMap;
 
   /// The value representing the parent frame pointer.
   LandingPadMap &LPadMap;
 
   /// The value representing the parent frame pointer.
-  Value *EstablisherFrame;
+  Value *ParentFP;
 };
 
 class WinEHCatchDirector : public WinEHCloningDirectorBase {
 public:
   WinEHCatchDirector(
 };
 
 class WinEHCatchDirector : public WinEHCloningDirectorBase {
 public:
   WinEHCatchDirector(
-      Function *CatchFn, Value *Selector, FrameVarInfoMap &VarInfo,
-      LandingPadMap &LPadMap,
+      Function *CatchFn, Value *ParentFP, Value *Selector,
+      FrameVarInfoMap &VarInfo, LandingPadMap &LPadMap,
       DenseMap<LandingPadInst *, const LandingPadInst *> &NestedLPads)
       DenseMap<LandingPadInst *, const LandingPadInst *> &NestedLPads)
-      : WinEHCloningDirectorBase(CatchFn, VarInfo, LPadMap),
+      : WinEHCloningDirectorBase(CatchFn, ParentFP, VarInfo, LPadMap),
         CurrentSelector(Selector->stripPointerCasts()),
         ExceptionObjectVar(nullptr), NestedLPtoOriginalLP(NestedLPads) {}
 
         CurrentSelector(Selector->stripPointerCasts()),
         ExceptionObjectVar(nullptr), NestedLPtoOriginalLP(NestedLPads) {}
 
@@ -272,9 +280,10 @@ private:
 
 class WinEHCleanupDirector : public WinEHCloningDirectorBase {
 public:
 
 class WinEHCleanupDirector : public WinEHCloningDirectorBase {
 public:
-  WinEHCleanupDirector(Function *CleanupFn, FrameVarInfoMap &VarInfo,
-                       LandingPadMap &LPadMap)
-      : WinEHCloningDirectorBase(CleanupFn, VarInfo, LPadMap) {}
+  WinEHCleanupDirector(Function *CleanupFn, Value *ParentFP,
+                       FrameVarInfoMap &VarInfo, LandingPadMap &LPadMap)
+      : WinEHCloningDirectorBase(CleanupFn, ParentFP, VarInfo,
+                                 LPadMap) {}
 
   CloningAction handleBeginCatch(ValueToValueMapTy &VMap,
                                  const Instruction *Inst,
 
   CloningAction handleBeginCatch(ValueToValueMapTy &VMap,
                                  const Instruction *Inst,
@@ -880,19 +889,23 @@ bool WinEHPrepare::prepareExceptionHandlers(
       if (TempAlloca == getCatchObjectSentinel())
         continue; // Skip catch parameter sentinels.
       Function *HandlerFn = TempAlloca->getParent()->getParent();
       if (TempAlloca == getCatchObjectSentinel())
         continue; // Skip catch parameter sentinels.
       Function *HandlerFn = TempAlloca->getParent()->getParent();
-      // FIXME: Sink this GEP into the blocks where it is used.
+      llvm::Value *FP = HandlerToParentFP[HandlerFn];
+      assert(FP);
+
+      // FIXME: Sink this framerecover into the blocks where it is used.
       Builder.SetInsertPoint(TempAlloca);
       Builder.SetCurrentDebugLocation(TempAlloca->getDebugLoc());
       Value *RecoverArgs[] = {
       Builder.SetInsertPoint(TempAlloca);
       Builder.SetCurrentDebugLocation(TempAlloca->getDebugLoc());
       Value *RecoverArgs[] = {
-          Builder.CreateBitCast(&F, Int8PtrType, ""),
-          &(HandlerFn->getArgumentList().back()),
+          Builder.CreateBitCast(&F, Int8PtrType, ""), FP,
           llvm::ConstantInt::get(Int32Type, AllocasToEscape.size() - 1)};
           llvm::ConstantInt::get(Int32Type, AllocasToEscape.size() - 1)};
-      Value *RecoveredAlloca = Builder.CreateCall(RecoverFrameFn, RecoverArgs);
+      Instruction *RecoveredAlloca =
+          Builder.CreateCall(RecoverFrameFn, RecoverArgs);
+
       // Add a pointer bitcast if the alloca wasn't an i8.
       if (RecoveredAlloca->getType() != TempAlloca->getType()) {
         RecoveredAlloca->setName(Twine(TempAlloca->getName()) + ".i8");
       // Add a pointer bitcast if the alloca wasn't an i8.
       if (RecoveredAlloca->getType() != TempAlloca->getType()) {
         RecoveredAlloca->setName(Twine(TempAlloca->getName()) + ".i8");
-        RecoveredAlloca =
-            Builder.CreateBitCast(RecoveredAlloca, TempAlloca->getType());
+        RecoveredAlloca = cast<Instruction>(
+            Builder.CreateBitCast(RecoveredAlloca, TempAlloca->getType()));
       }
       TempAlloca->replaceAllUsesWith(RecoveredAlloca);
       TempAlloca->removeFromParent();
       }
       TempAlloca->replaceAllUsesWith(RecoveredAlloca);
       TempAlloca->removeFromParent();
@@ -918,6 +931,8 @@ bool WinEHPrepare::prepareExceptionHandlers(
   CatchHandlerMap.clear();
   DeleteContainerSeconds(CleanupHandlerMap);
   CleanupHandlerMap.clear();
   CatchHandlerMap.clear();
   DeleteContainerSeconds(CleanupHandlerMap);
   CleanupHandlerMap.clear();
+  HandlerToParentFP.clear();
+  DT = nullptr;
 
   return HandlersOutlined;
 }
 
   return HandlersOutlined;
 }
@@ -987,7 +1002,6 @@ void WinEHPrepare::completeNestedLandingPad(Function *ParentFn,
   IntrinsicInst *EHActions = cast<IntrinsicInst>(Recover->clone());
 
   // Remap the exception variables into the outlined function.
   IntrinsicInst *EHActions = cast<IntrinsicInst>(Recover->clone());
 
   // Remap the exception variables into the outlined function.
-  WinEHFrameVariableMaterializer Materializer(OutlinedHandlerFn, FrameVarInfo);
   SmallVector<BlockAddress *, 4> ActionTargets;
   SmallVector<ActionHandler *, 4> ActionList;
   parseEHActions(EHActions, ActionList);
   SmallVector<BlockAddress *, 4> ActionTargets;
   SmallVector<ActionHandler *, 4> ActionList;
   parseEHActions(EHActions, ActionList);
@@ -1148,35 +1162,62 @@ void WinEHPrepare::addStubInvokeToHandlerIfNeeded(Function *Handler,
   InvokeInst::Create(F, NewRetBB, StubLandingPad, None, "", OldRetBB);
 }
 
   InvokeInst::Create(F, NewRetBB, StubLandingPad, None, "", OldRetBB);
 }
 
+// FIXME: Consider sinking this into lib/Target/X86 somehow. TargetLowering
+// usually doesn't build LLVM IR, so that's probably the wrong place.
+Function *WinEHPrepare::createHandlerFunc(Type *RetTy, const Twine &Name,
+                                          Module *M, Value *&ParentFP) {
+  // x64 uses a two-argument prototype where the parent FP is the second
+  // argument. x86 uses no arguments, just the incoming EBP value.
+  LLVMContext &Context = M->getContext();
+  FunctionType *FnType;
+  if (TheTriple.getArch() == Triple::x86_64) {
+    Type *Int8PtrType = Type::getInt8PtrTy(Context);
+    Type *ArgTys[2] = {Int8PtrType, Int8PtrType};
+    FnType = FunctionType::get(RetTy, ArgTys, false);
+  } else {
+    FnType = FunctionType::get(RetTy, None, false);
+  }
+
+  Function *Handler =
+      Function::Create(FnType, GlobalVariable::InternalLinkage, Name, M);
+  BasicBlock *Entry = BasicBlock::Create(Context, "entry");
+  Handler->getBasicBlockList().push_front(Entry);
+  if (TheTriple.getArch() == Triple::x86_64) {
+    ParentFP = &(Handler->getArgumentList().back());
+  } else {
+    assert(M);
+    Function *FrameAddressFn =
+        Intrinsic::getDeclaration(M, Intrinsic::frameaddress);
+    Value *Args[1] = {ConstantInt::get(Type::getInt32Ty(Context), 1)};
+    ParentFP = CallInst::Create(FrameAddressFn, Args, "parent_fp",
+                                &Handler->getEntryBlock());
+  }
+  return Handler;
+}
+
 bool WinEHPrepare::outlineHandler(ActionHandler *Action, Function *SrcFn,
                                   LandingPadInst *LPad, BasicBlock *StartBB,
                                   FrameVarInfoMap &VarInfo) {
   Module *M = SrcFn->getParent();
   LLVMContext &Context = M->getContext();
 bool WinEHPrepare::outlineHandler(ActionHandler *Action, Function *SrcFn,
                                   LandingPadInst *LPad, BasicBlock *StartBB,
                                   FrameVarInfoMap &VarInfo) {
   Module *M = SrcFn->getParent();
   LLVMContext &Context = M->getContext();
+  Type *Int8PtrType = Type::getInt8PtrTy(Context);
 
   // Create a new function to receive the handler contents.
 
   // Create a new function to receive the handler contents.
-  Type *Int8PtrType = Type::getInt8PtrTy(Context);
-  std::vector<Type *> ArgTys;
-  ArgTys.push_back(Int8PtrType);
-  ArgTys.push_back(Int8PtrType);
+  Value *ParentFP;
   Function *Handler;
   if (Action->getType() == Catch) {
   Function *Handler;
   if (Action->getType() == Catch) {
-    FunctionType *FnType = FunctionType::get(Int8PtrType, ArgTys, false);
-    Handler = Function::Create(FnType, GlobalVariable::InternalLinkage,
-                               SrcFn->getName() + ".catch", M);
+    Handler = createHandlerFunc(Int8PtrType, SrcFn->getName() + ".catch", M,
+                                ParentFP);
   } else {
   } else {
-    FunctionType *FnType =
-        FunctionType::get(Type::getVoidTy(Context), ArgTys, false);
-    Handler = Function::Create(FnType, GlobalVariable::InternalLinkage,
-                               SrcFn->getName() + ".cleanup", M);
+    Handler = createHandlerFunc(Type::getVoidTy(Context),
+                                SrcFn->getName() + ".cleanup", M, ParentFP);
   }
   }
-
+  HandlerToParentFP[Handler] = ParentFP;
   Handler->addFnAttr("wineh-parent", SrcFn->getName());
   Handler->addFnAttr("wineh-parent", SrcFn->getName());
+  BasicBlock *Entry = &Handler->getEntryBlock();
 
   // Generate a standard prolog to setup the frame recovery structure.
   IRBuilder<> Builder(Context);
 
   // Generate a standard prolog to setup the frame recovery structure.
   IRBuilder<> Builder(Context);
-  BasicBlock *Entry = BasicBlock::Create(Context, "entry");
-  Handler->getBasicBlockList().push_front(Entry);
   Builder.SetInsertPoint(Entry);
   Builder.SetCurrentDebugLocation(LPad->getDebugLoc());
 
   Builder.SetInsertPoint(Entry);
   Builder.SetCurrentDebugLocation(LPad->getDebugLoc());
 
@@ -1189,12 +1230,14 @@ bool WinEHPrepare::outlineHandler(ActionHandler *Action, Function *SrcFn,
     LPadMap.mapLandingPad(LPad);
   if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) {
     Constant *Sel = CatchAction->getSelector();
     LPadMap.mapLandingPad(LPad);
   if (auto *CatchAction = dyn_cast<CatchHandler>(Action)) {
     Constant *Sel = CatchAction->getSelector();
-    Director.reset(new WinEHCatchDirector(Handler, Sel, VarInfo, LPadMap,
+    Director.reset(new WinEHCatchDirector(Handler, ParentFP, Sel,
+                                          VarInfo, LPadMap,
                                           NestedLPtoOriginalLP));
     LPadMap.remapEHValues(VMap, UndefValue::get(Int8PtrType),
                           ConstantInt::get(Type::getInt32Ty(Context), 1));
   } else {
                                           NestedLPtoOriginalLP));
     LPadMap.remapEHValues(VMap, UndefValue::get(Int8PtrType),
                           ConstantInt::get(Type::getInt32Ty(Context), 1));
   } else {
-    Director.reset(new WinEHCleanupDirector(Handler, VarInfo, LPadMap));
+    Director.reset(
+        new WinEHCleanupDirector(Handler, ParentFP, VarInfo, LPadMap));
     LPadMap.remapEHValues(VMap, UndefValue::get(Int8PtrType),
                           UndefValue::get(Type::getInt32Ty(Context)));
   }
     LPadMap.remapEHValues(VMap, UndefValue::get(Int8PtrType),
                           UndefValue::get(Type::getInt32Ty(Context)));
   }
@@ -1421,7 +1464,7 @@ CloningDirector::CloningAction WinEHCloningDirectorBase::handleInstruction(
   // When outlining llvm.frameaddress(i32 0), remap that to the second argument,
   // which is the FP of the parent.
   if (isFrameAddressCall(Inst)) {
   // When outlining llvm.frameaddress(i32 0), remap that to the second argument,
   // which is the FP of the parent.
   if (isFrameAddressCall(Inst)) {
-    VMap[Inst] = EstablisherFrame;
+    VMap[Inst] = ParentFP;
     return CloningDirector::SkipInstruction;
   }
 
     return CloningDirector::SkipInstruction;
   }
 
@@ -1660,10 +1703,16 @@ WinEHCleanupDirector::handleCompare(ValueToValueMapTy &VMap,
 }
 
 WinEHFrameVariableMaterializer::WinEHFrameVariableMaterializer(
 }
 
 WinEHFrameVariableMaterializer::WinEHFrameVariableMaterializer(
-    Function *OutlinedFn, FrameVarInfoMap &FrameVarInfo)
+    Function *OutlinedFn, Value *ParentFP, FrameVarInfoMap &FrameVarInfo)
     : FrameVarInfo(FrameVarInfo), Builder(OutlinedFn->getContext()) {
   BasicBlock *EntryBB = &OutlinedFn->getEntryBlock();
     : FrameVarInfo(FrameVarInfo), Builder(OutlinedFn->getContext()) {
   BasicBlock *EntryBB = &OutlinedFn->getEntryBlock();
-  Builder.SetInsertPoint(EntryBB, EntryBB->getFirstInsertionPt());
+
+  // New allocas should be inserted in the entry block, but after the parent FP
+  // is established if it is an instruction.
+  Instruction *InsertPoint = EntryBB->getFirstInsertionPt();
+  if (auto *FPInst = dyn_cast<Instruction>(ParentFP))
+    InsertPoint = FPInst->getNextNode();
+  Builder.SetInsertPoint(EntryBB, InsertPoint);
 }
 
 Value *WinEHFrameVariableMaterializer::materializeValueFor(Value *V) {
 }
 
 Value *WinEHFrameVariableMaterializer::materializeValueFor(Value *V) {
index 2de2cc67aaa7b2d0f7ed2a045e236d21dc2fc4e4..48d9b39ca64a763488aa090ee7e817b3ae0ba610 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: opt -winehprepare -S < %s | FileCheck %s
+; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S < %s | FileCheck %s
 
 ; Notionally based on this C++ source:
 ; int liveout_catch(int p) {
 
 ; Notionally based on this C++ source:
 ; int liveout_catch(int p) {
index 927aeed3b6f3773b60c00a4344842ed16693acb7..13471b8661a36f02370f633869c2ac33f792d2a9 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: opt -mtriple=i386-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s
+; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s
 
 ; This test is built from the following code:
 ; struct A {
 
 ; This test is built from the following code:
 ; struct A {
@@ -24,8 +24,6 @@
 ; the inalloca instruction was manually sunk into the landingpad.
 
 ; ModuleID = 'cppeh-inalloca.cpp'
 ; the inalloca instruction was manually sunk into the landingpad.
 
 ; ModuleID = 'cppeh-inalloca.cpp'
-target datalayout = "e-m:w-p:32:32-i64:64-f80:32-n8:16:32-S32"
-target triple = "i386-pc-windows-msvc"
 
 %rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
 %struct.A = type { i32 }
 
 %rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
 %struct.A = type { i32 }
index aa9a6ca03b1ca38fed7c8596c12bc9973d2f29ff..ea453df80a2bc221a032a142968a8fa3347b478f 100644 (file)
@@ -1,7 +1,10 @@
-; RUN: opt -S -winehprepare -mtriple=x86_64-windows-msvc < %s | FileCheck %s
+; RUN: opt -S -winehprepare -mtriple=x86_64-windows-msvc < %s \
+; RUN:                 | FileCheck %s --check-prefix=CHECK --check-prefix=X64
 
 
-target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
-target triple = "x86_64-pc-windows-msvc"
+; This test should also pass in 32-bit using _except_handler3.
+; RUN: sed %s -e 's/__C_specific_handler/_except_handler3/' \
+; RUN:                 | opt -S -winehprepare -mtriple=i686-windows-msvc \
+; RUN:                 | FileCheck %s --check-prefix=CHECK --check-prefix=X86
 
 declare void @cleanup()
 declare i32 @filt()
 
 declare void @cleanup()
 declare i32 @filt()
@@ -139,7 +142,7 @@ eh.resume:
 ; CHECK: landingpad { i8*, i32 }
 ; CHECK-NEXT: cleanup
 ; CHECK-NEXT: catch i32 ()* @filt
 ; CHECK: landingpad { i8*, i32 }
 ; CHECK-NEXT: cleanup
 ; CHECK-NEXT: catch i32 ()* @filt
-; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void (i8*, i8*)* @lpad_phi.cleanup, i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@lpad_phi, %lpad.return_crit_edge))
+; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 0, void ({{.*}})* @lpad_phi.cleanup, i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@lpad_phi, %lpad.return_crit_edge))
 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
 ;
 ; CHECK: lpad.return_crit_edge:
 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
 ;
 ; CHECK: lpad.return_crit_edge:
@@ -178,7 +181,7 @@ eh.resume:
 ; CHECK-NEXT: cleanup
 ; CHECK-NEXT: catch i32 ()* @filt
 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(
 ; CHECK-NEXT: cleanup
 ; CHECK-NEXT: catch i32 ()* @filt
 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(
-; CHECK: i32 0, void (i8*, i8*)* @cleanup_and_except.cleanup,
+; CHECK: i32 0, void ({{.*}})* @cleanup_and_except.cleanup,
 ; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %lpad.return_crit_edge))
 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
 ;
 ; CHECK: i32 1, i8* bitcast (i32 ()* @filt to i8*), i32 -1, i8* blockaddress(@cleanup_and_except, %lpad.return_crit_edge))
 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.return_crit_edge]
 ;
@@ -190,6 +193,9 @@ eh.resume:
 ; CHECK-NEXT: ret i32 %r
 
 ; FIXME: This cleanup is an artifact of bad demotion.
 ; CHECK-NEXT: ret i32 %r
 
 ; FIXME: This cleanup is an artifact of bad demotion.
-; CHECK-LABEL: define internal void @lpad_phi.cleanup(i8*, i8*)
+; X64-LABEL: define internal void @lpad_phi.cleanup(i8*, i8*)
+; X86-LABEL: define internal void @lpad_phi.cleanup()
+; X86: call i8* @llvm.frameaddress(i32 1)
+; CHECK: call i8* @llvm.framerecover({{.*}})
 ; CHECK: load i32
 ; CHECK: store i32 %{{.*}}, i32*
 ; CHECK: load i32
 ; CHECK: store i32 %{{.*}}, i32*