r241244 - Revert 241171, 241187, 241199 (32-bit SEH).

Nico Weber nicolasweber at gmx.de
Wed Jul 1 23:10:54 PDT 2015


Author: nico
Date: Thu Jul  2 01:10:53 2015
New Revision: 241244

URL: http://llvm.org/viewvc/llvm-project?rev=241244&view=rev
Log:
Revert 241171, 241187, 241199 (32-bit SEH).

It still doesn't produce quite the right code, test binaries built with this
enabled fail some tests.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/TargetInfo.h
    cfe/trunk/lib/CodeGen/CGException.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/test/CodeGen/exceptions-seh-finally.c
    cfe/trunk/test/CodeGen/exceptions-seh-leave.c
    cfe/trunk/test/CodeGen/exceptions-seh.c

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=241244&r1=241243&r2=241244&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Jul  2 01:10:53 2015
@@ -5576,8 +5576,6 @@ def err_seh_try_outside_functions : Erro
   "cannot use SEH '__try' in blocks, captured regions, or Obj-C method decls">;
 def err_mixing_cxx_try_seh_try : Error<
   "cannot use C++ 'try' in the same function as SEH '__try'">;
-def err_seh_try_unsupported : Error<
-  "SEH '__try' is not supported on this target">;
 def note_conflicting_try_here : Note<
   "conflicting %0 here">;
 def warn_jump_out_of_seh_finally : Warning<

Modified: cfe/trunk/include/clang/Basic/TargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=241244&r1=241243&r2=241244&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TargetInfo.h (original)
+++ cfe/trunk/include/clang/Basic/TargetInfo.h Thu Jul  2 01:10:53 2015
@@ -809,11 +809,6 @@ public:
     return TLSSupported;
   }
 
-  /// \brief Whether the target supports SEH __try.
-  bool isSEHTrySupported() const {
-    return getTriple().isOSWindows();
-  }
-
   /// \brief Return true if {|} are normal characters in the asm string.
   ///
   /// If this returns false (the default), then {abc|xyz} is syntax

Modified: cfe/trunk/lib/CodeGen/CGException.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGException.cpp?rev=241244&r1=241243&r2=241244&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGException.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGException.cpp Thu Jul  2 01:10:53 2015
@@ -20,7 +20,6 @@
 #include "clang/AST/StmtCXX.h"
 #include "clang/AST/StmtObjC.h"
 #include "clang/AST/StmtVisitor.h"
-#include "clang/Basic/TargetBuiltins.h"
 #include "llvm/IR/CallSite.h"
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/IntrinsicInst.h"
@@ -1280,6 +1279,14 @@ llvm::BasicBlock *CodeGenFunction::getEH
 }
 
 void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) {
+  // FIXME: Implement SEH on other architectures.
+  const llvm::Triple &T = CGM.getTarget().getTriple();
+  if (T.getArch() != llvm::Triple::x86_64 ||
+      !T.isKnownWindowsMSVCEnvironment()) {
+    ErrorUnsupported(&S, "__try statement");
+    return;
+  }
+
   EnterSEHTryStmt(S);
   {
     JumpDest TryExit = getJumpDestInCurrentScope("__try.__leave");
@@ -1304,28 +1311,24 @@ struct PerformSEHFinally : EHScopeStack:
 
   void Emit(CodeGenFunction &CGF, Flags F) override {
     ASTContext &Context = CGF.getContext();
-    CodeGenModule &CGM = CGF.CGM;
+    QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy};
+    FunctionProtoType::ExtProtoInfo EPI;
+    const auto *FTP = cast<FunctionType>(
+        Context.getFunctionType(Context.VoidTy, ArgTys, EPI));
 
     CallArgList Args;
-
-    // Compute the two argument values.
-    QualType ArgTys[2] = {Context.UnsignedCharTy, Context.VoidPtrTy};
-    llvm::Value *FrameAddr = CGM.getIntrinsic(llvm::Intrinsic::frameaddress);
-    llvm::Value *FP =
-        CGF.Builder.CreateCall(FrameAddr, {CGF.Builder.getInt32(0)});
     llvm::Value *IsForEH =
         llvm::ConstantInt::get(CGF.ConvertType(ArgTys[0]), F.isForEHCleanup());
     Args.add(RValue::get(IsForEH), ArgTys[0]);
+
+    CodeGenModule &CGM = CGF.CGM;
+    llvm::Value *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0);
+    llvm::Value *FrameAddr = CGM.getIntrinsic(llvm::Intrinsic::frameaddress);
+    llvm::Value *FP = CGF.Builder.CreateCall(FrameAddr, Zero);
     Args.add(RValue::get(FP), ArgTys[1]);
 
-    // Arrange a two-arg function info and type.
-    FunctionProtoType::ExtProtoInfo EPI;
-    const auto *FPT = cast<FunctionProtoType>(
-        Context.getFunctionType(Context.VoidTy, ArgTys, EPI));
     const CGFunctionInfo &FnInfo =
-        CGM.getTypes().arrangeFreeFunctionCall(Args, FPT,
-                                               /*chainCall=*/false);
-
+        CGM.getTypes().arrangeFreeFunctionCall(Args, FTP, /*chainCall=*/false);
     CGF.EmitCall(FnInfo, OutlinedFinally, ReturnValueSlot(), Args);
   }
 };
@@ -1337,15 +1340,9 @@ struct CaptureFinder : ConstStmtVisitor<
   CodeGenFunction &ParentCGF;
   const VarDecl *ParentThis;
   SmallVector<const VarDecl *, 4> Captures;
-  llvm::Value *SEHCodeSlot = nullptr;
   CaptureFinder(CodeGenFunction &ParentCGF, const VarDecl *ParentThis)
       : ParentCGF(ParentCGF), ParentThis(ParentThis) {}
 
-  // Return true if we need to do any capturing work.
-  bool foundCaptures() {
-    return !Captures.empty() || SEHCodeSlot;
-  }
-
   void Visit(const Stmt *S) {
     // See if this is a capture, then recurse.
     ConstStmtVisitor<CaptureFinder>::Visit(S);
@@ -1369,104 +1366,25 @@ struct CaptureFinder : ConstStmtVisitor<
   void VisitCXXThisExpr(const CXXThisExpr *E) {
     Captures.push_back(ParentThis);
   }
-
-  void VisitCallExpr(const CallExpr *E) {
-    // We only need to add parent frame allocations for these builtins in x86.
-    if (ParentCGF.getTarget().getTriple().getArch() != llvm::Triple::x86)
-      return;
-
-    unsigned ID = E->getBuiltinCallee();
-    switch (ID) {
-    case Builtin::BI__exception_code:
-    case Builtin::BI_exception_code:
-      // This is the simple case where we are the outermost finally. All we
-      // have to do here is make sure we escape this and recover it in the
-      // outlined handler.
-      if (!SEHCodeSlot)
-        SEHCodeSlot = ParentCGF.SEHCodeSlotStack.back();
-      break;
-    }
-  }
 };
 }
 
-llvm::Value *CodeGenFunction::recoverAddrOfEscapedLocal(
-    CodeGenFunction &ParentCGF, llvm::Value *ParentVar, llvm::Value *ParentFP) {
-  llvm::CallInst *RecoverCall = nullptr;
-  CGBuilderTy Builder(AllocaInsertPt);
-  if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) {
-    // Mark the variable escaped if nobody else referenced it and compute the
-    // frameescape index.
-    auto InsertPair = ParentCGF.EscapedLocals.insert(
-        std::make_pair(ParentAlloca, ParentCGF.EscapedLocals.size()));
-    int FrameEscapeIdx = InsertPair.first->second;
-    // call i8* @llvm.framerecover(i8* bitcast(@parentFn), i8* %fp, i32 N)
-    llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
-        &CGM.getModule(), llvm::Intrinsic::framerecover);
-    llvm::Constant *ParentI8Fn =
-        llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
-    RecoverCall = Builder.CreateCall(
-        FrameRecoverFn, {ParentI8Fn, ParentFP,
-                         llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)});
-
-  } else {
-    // If the parent didn't have an alloca, we're doing some nested outlining.
-    // Just clone the existing framerecover call, but tweak the FP argument to
-    // use our FP value. All other arguments are constants.
-    auto *ParentRecover =
-        cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts());
-    assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::framerecover &&
-           "expected alloca or framerecover in parent LocalDeclMap");
-    RecoverCall = cast<llvm::CallInst>(ParentRecover->clone());
-    RecoverCall->setArgOperand(1, ParentFP);
-    RecoverCall->insertBefore(AllocaInsertPt);
-  }
-
-  // Bitcast the variable, rename it, and insert it in the local decl map.
-  llvm::Value *ChildVar =
-      Builder.CreateBitCast(RecoverCall, ParentVar->getType());
-  ChildVar->setName(ParentVar->getName());
-  return ChildVar;
-}
-
 void CodeGenFunction::EmitCapturedLocals(CodeGenFunction &ParentCGF,
                                          const Stmt *OutlinedStmt,
-                                         bool IsFilter) {
+                                         llvm::Value *ParentFP) {
   // Find all captures in the Stmt.
   CaptureFinder Finder(ParentCGF, ParentCGF.CXXABIThisDecl);
   Finder.Visit(OutlinedStmt);
 
-  // We can exit early on x86_64 when there are no captures. We just have to
-  // save the exception code in filters so that __exception_code() works.
-  if (!Finder.foundCaptures() &&
-      CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) {
-    if (IsFilter)
-      EmitSEHExceptionCodeSave(ParentCGF, nullptr, nullptr);
+  // Typically there are no captures and we can exit early.
+  if (Finder.Captures.empty())
     return;
-  }
 
-  llvm::Value *EntryEBP = nullptr;
-  llvm::Value *ParentFP;
-  if (IsFilter && CGM.getTarget().getTriple().getArch() == llvm::Triple::x86) {
-    // 32-bit SEH filters need to be careful about FP recovery.  The end of the
-    // EH registration is passed in as the EBP physical register.  We can
-    // recover that with llvm.frameaddress(1), and adjust that to recover the
-    // parent's true frame pointer.
-    CGBuilderTy Builder(AllocaInsertPt);
-    EntryEBP = Builder.CreateCall(
-        CGM.getIntrinsic(llvm::Intrinsic::frameaddress), {Builder.getInt32(1)});
-    llvm::Function *RecoverFPIntrin =
-        CGM.getIntrinsic(llvm::Intrinsic::x86_seh_recoverfp);
-    llvm::Constant *ParentI8Fn =
-        llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
-    ParentFP = Builder.CreateCall(RecoverFPIntrin, {ParentI8Fn, EntryEBP});
-  } else {
-    // Otherwise, for x64 and 32-bit finally functions, the parent FP is the
-    // second parameter.
-    auto AI = CurFn->arg_begin();
-    ++AI;
-    ParentFP = AI;
-  }
+  // Prepare the first two arguments to llvm.framerecover.
+  llvm::Function *FrameRecoverFn = llvm::Intrinsic::getDeclaration(
+      &CGM.getModule(), llvm::Intrinsic::framerecover);
+  llvm::Constant *ParentI8Fn =
+      llvm::ConstantExpr::getBitCast(ParentCGF.CurFn, Int8PtrTy);
 
   // Create llvm.framerecover calls for all captures.
   for (const VarDecl *VD : Finder.Captures) {
@@ -1489,63 +1407,49 @@ void CodeGenFunction::EmitCapturedLocals
       continue;
     llvm::Value *ParentVar = I->second;
 
-    LocalDeclMap[VD] =
-        recoverAddrOfEscapedLocal(ParentCGF, ParentVar, ParentFP);
-  }
+    llvm::CallInst *RecoverCall = nullptr;
+    CGBuilderTy Builder(AllocaInsertPt);
+    if (auto *ParentAlloca = dyn_cast<llvm::AllocaInst>(ParentVar)) {
+      // Mark the variable escaped if nobody else referenced it and compute the
+      // frameescape index.
+      auto InsertPair =
+          ParentCGF.EscapedLocals.insert(std::make_pair(ParentAlloca, -1));
+      if (InsertPair.second)
+        InsertPair.first->second = ParentCGF.EscapedLocals.size() - 1;
+      int FrameEscapeIdx = InsertPair.first->second;
+      // call i8* @llvm.framerecover(i8* bitcast(@parentFn), i8* %fp, i32 N)
+      RecoverCall = Builder.CreateCall(
+          FrameRecoverFn, {ParentI8Fn, ParentFP,
+                           llvm::ConstantInt::get(Int32Ty, FrameEscapeIdx)});
 
-  if (Finder.SEHCodeSlot) {
-    SEHCodeSlotStack.push_back(
-        recoverAddrOfEscapedLocal(ParentCGF, Finder.SEHCodeSlot, ParentFP));
+    } else {
+      // If the parent didn't have an alloca, we're doing some nested outlining.
+      // Just clone the existing framerecover call, but tweak the FP argument to
+      // use our FP value. All other arguments are constants.
+      auto *ParentRecover =
+          cast<llvm::IntrinsicInst>(ParentVar->stripPointerCasts());
+      assert(ParentRecover->getIntrinsicID() == llvm::Intrinsic::framerecover &&
+             "expected alloca or framerecover in parent LocalDeclMap");
+      RecoverCall = cast<llvm::CallInst>(ParentRecover->clone());
+      RecoverCall->setArgOperand(1, ParentFP);
+      RecoverCall->insertBefore(AllocaInsertPt);
+    }
+
+    // Bitcast the variable, rename it, and insert it in the local decl map.
+    llvm::Value *ChildVar =
+        Builder.CreateBitCast(RecoverCall, ParentVar->getType());
+    ChildVar->setName(ParentVar->getName());
+    LocalDeclMap[VD] = ChildVar;
   }
-
-  if (IsFilter)
-    EmitSEHExceptionCodeSave(ParentCGF, ParentFP, EntryEBP);
 }
 
 /// Arrange a function prototype that can be called by Windows exception
 /// handling personalities. On Win64, the prototype looks like:
 /// RetTy func(void *EHPtrs, void *ParentFP);
 void CodeGenFunction::startOutlinedSEHHelper(CodeGenFunction &ParentCGF,
-                                             bool IsFilter,
+                                             StringRef Name, QualType RetTy,
+                                             FunctionArgList &Args,
                                              const Stmt *OutlinedStmt) {
-  SourceLocation StartLoc = OutlinedStmt->getLocStart();
-
-  // Get the mangled function name.
-  SmallString<128> Name;
-  {
-    llvm::raw_svector_ostream OS(Name);
-    const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
-    const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
-    assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
-    MangleContext &Mangler = CGM.getCXXABI().getMangleContext();
-    if (IsFilter)
-      Mangler.mangleSEHFilterExpression(Parent, OS);
-    else
-      Mangler.mangleSEHFinallyBlock(Parent, OS);
-  }
-
-  FunctionArgList Args;
-  if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 || !IsFilter) {
-    // All SEH finally functions take two parameters. Win64 filters take two
-    // parameters. Win32 filters take no parameters.
-    if (IsFilter) {
-      Args.push_back(ImplicitParamDecl::Create(
-          getContext(), nullptr, StartLoc,
-          &getContext().Idents.get("exception_pointers"),
-          getContext().VoidPtrTy));
-    } else {
-      Args.push_back(ImplicitParamDecl::Create(
-          getContext(), nullptr, StartLoc,
-          &getContext().Idents.get("abnormal_termination"),
-          getContext().UnsignedCharTy));
-    }
-    Args.push_back(ImplicitParamDecl::Create(
-        getContext(), nullptr, StartLoc,
-        &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
-  }
-
-  QualType RetTy = IsFilter ? getContext().LongTy : getContext().VoidTy;
-
   llvm::Function *ParentFn = ParentCGF.CurFn;
   const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeFreeFunctionDeclaration(
       RetTy, Args, FunctionType::ExtInfo(), /*isVariadic=*/false);
@@ -1570,7 +1474,10 @@ void CodeGenFunction::startOutlinedSEHHe
                 OutlinedStmt->getLocStart(), OutlinedStmt->getLocStart());
 
   CGM.SetLLVMFunctionAttributes(nullptr, FnInfo, CurFn);
-  EmitCapturedLocals(ParentCGF, OutlinedStmt, IsFilter);
+
+  auto AI = Fn->arg_begin();
+  ++AI;
+  EmitCapturedLocals(ParentCGF, OutlinedStmt, &*AI);
 }
 
 /// Create a stub filter function that will ultimately hold the code of the
@@ -1580,7 +1487,37 @@ llvm::Function *
 CodeGenFunction::GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
                                            const SEHExceptStmt &Except) {
   const Expr *FilterExpr = Except.getFilterExpr();
-  startOutlinedSEHHelper(ParentCGF, true, FilterExpr);
+  SourceLocation StartLoc = FilterExpr->getLocStart();
+
+  SEHPointersDecl = ImplicitParamDecl::Create(
+      getContext(), nullptr, StartLoc,
+      &getContext().Idents.get("exception_pointers"), getContext().VoidPtrTy);
+  FunctionArgList Args;
+  Args.push_back(SEHPointersDecl);
+  Args.push_back(ImplicitParamDecl::Create(
+      getContext(), nullptr, StartLoc,
+      &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
+
+  // Get the mangled function name.
+  SmallString<128> Name;
+  {
+    llvm::raw_svector_ostream OS(Name);
+    const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
+    const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
+    assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
+    CGM.getCXXABI().getMangleContext().mangleSEHFilterExpression(Parent, OS);
+  }
+
+  startOutlinedSEHHelper(ParentCGF, Name, getContext().LongTy, Args,
+                         FilterExpr);
+
+  // Mark finally block calls as nounwind and noinline to make LLVM's job a
+  // little easier.
+  // FIXME: Remove these restrictions in the future.
+  CurFn->addFnAttr(llvm::Attribute::NoUnwind);
+  CurFn->addFnAttr(llvm::Attribute::NoInline);
+
+  EmitSEHExceptionCodeSave();
 
   // Emit the original filter expression, convert to i32, and return.
   llvm::Value *R = EmitScalarExpr(FilterExpr);
@@ -1597,13 +1534,29 @@ llvm::Function *
 CodeGenFunction::GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
                                             const SEHFinallyStmt &Finally) {
   const Stmt *FinallyBlock = Finally.getBlock();
-  startOutlinedSEHHelper(ParentCGF, false, FinallyBlock);
+  SourceLocation StartLoc = FinallyBlock->getLocStart();
 
-  // Mark finally block calls as nounwind and noinline to make LLVM's job a
-  // little easier.
-  // FIXME: Remove these restrictions in the future.
-  CurFn->addFnAttr(llvm::Attribute::NoUnwind);
-  CurFn->addFnAttr(llvm::Attribute::NoInline);
+  FunctionArgList Args;
+  Args.push_back(ImplicitParamDecl::Create(
+      getContext(), nullptr, StartLoc,
+      &getContext().Idents.get("abnormal_termination"),
+      getContext().UnsignedCharTy));
+  Args.push_back(ImplicitParamDecl::Create(
+      getContext(), nullptr, StartLoc,
+      &getContext().Idents.get("frame_pointer"), getContext().VoidPtrTy));
+
+  // Get the mangled function name.
+  SmallString<128> Name;
+  {
+    llvm::raw_svector_ostream OS(Name);
+    const Decl *ParentCodeDecl = ParentCGF.CurCodeDecl;
+    const NamedDecl *Parent = dyn_cast_or_null<NamedDecl>(ParentCodeDecl);
+    assert(Parent && "FIXME: handle unnamed decls (lambdas, blocks) with SEH");
+    CGM.getCXXABI().getMangleContext().mangleSEHFinallyBlock(Parent, OS);
+  }
+
+  startOutlinedSEHHelper(ParentCGF, Name, getContext().VoidTy, Args,
+                         FinallyBlock);
 
   // Emit the original filter expression, convert to i32, and return.
   EmitStmt(FinallyBlock);
@@ -1613,58 +1566,44 @@ CodeGenFunction::GenerateSEHFinallyFunct
   return CurFn;
 }
 
-void CodeGenFunction::EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF,
-                                               llvm::Value *ParentFP,
-                                               llvm::Value *EntryEBP) {
-  // Get the pointer to the EXCEPTION_POINTERS struct. This is returned by the
-  // __exception_info intrinsic.
-  if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) {
-    // On Win64, the info is passed as the first parameter to the filter.
-    auto AI = CurFn->arg_begin();
-    SEHInfo = AI;
-    SEHCodeSlotStack.push_back(
-        CreateMemTemp(getContext().IntTy, "__exception_code"));
-  } else {
-    // On Win32, the EBP on entry to the filter points to the end of an
-    // exception registration object. It contains 6 32-bit fields, and the info
-    // pointer is stored in the second field. So, GEP 20 bytes backwards and
-    // load the pointer.
-    SEHInfo = Builder.CreateConstInBoundsGEP1_32(Int8Ty, EntryEBP, -20);
-    SEHInfo = Builder.CreateBitCast(SEHInfo, Int8PtrTy->getPointerTo());
-    SEHInfo = Builder.CreateLoad(Int8PtrTy, SEHInfo);
-    SEHCodeSlotStack.push_back(recoverAddrOfEscapedLocal(
-        ParentCGF, ParentCGF.SEHCodeSlotStack.back(), ParentFP));
-  }
-
+void CodeGenFunction::EmitSEHExceptionCodeSave() {
   // Save the exception code in the exception slot to unify exception access in
   // the filter function and the landing pad.
   // struct EXCEPTION_POINTERS {
   //   EXCEPTION_RECORD *ExceptionRecord;
   //   CONTEXT *ContextRecord;
   // };
-  // int exceptioncode = exception_pointers->ExceptionRecord->ExceptionCode;
+  // void *exn.slot =
+  //     (void *)(uintptr_t)exception_pointers->ExceptionRecord->ExceptionCode;
+  llvm::Value *Ptrs = Builder.CreateLoad(GetAddrOfLocalVar(SEHPointersDecl));
   llvm::Type *RecordTy = CGM.Int32Ty->getPointerTo();
   llvm::Type *PtrsTy = llvm::StructType::get(RecordTy, CGM.VoidPtrTy, nullptr);
-  llvm::Value *Ptrs = Builder.CreateBitCast(SEHInfo, PtrsTy->getPointerTo());
+  Ptrs = Builder.CreateBitCast(Ptrs, PtrsTy->getPointerTo());
   llvm::Value *Rec = Builder.CreateStructGEP(PtrsTy, Ptrs, 0);
   Rec = Builder.CreateLoad(Rec);
   llvm::Value *Code = Builder.CreateLoad(Rec);
-  assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except");
-  Builder.CreateStore(Code, SEHCodeSlotStack.back());
+  Code = Builder.CreateZExt(Code, CGM.IntPtrTy);
+  // FIXME: Change landing pads to produce {i32, i32} and make the exception
+  // slot an i32.
+  Code = Builder.CreateIntToPtr(Code, CGM.VoidPtrTy);
+  Builder.CreateStore(Code, getExceptionSlot());
 }
 
 llvm::Value *CodeGenFunction::EmitSEHExceptionInfo() {
   // Sema should diagnose calling this builtin outside of a filter context, but
   // don't crash if we screw up.
-  if (!SEHInfo)
+  if (!SEHPointersDecl)
     return llvm::UndefValue::get(Int8PtrTy);
-  assert(SEHInfo->getType() == Int8PtrTy);
-  return SEHInfo;
+  return Builder.CreateLoad(GetAddrOfLocalVar(SEHPointersDecl));
 }
 
 llvm::Value *CodeGenFunction::EmitSEHExceptionCode() {
-  assert(!SEHCodeSlotStack.empty() && "emitting EH code outside of __except");
-  return Builder.CreateLoad(Int32Ty, SEHCodeSlotStack.back());
+  // If we're in a landing pad or filter function, the exception slot contains
+  // the code.
+  assert(ExceptionSlot);
+  llvm::Value *Code =
+      Builder.CreatePtrToInt(getExceptionFromSlot(), CGM.IntPtrTy);
+  return Builder.CreateTrunc(Code, CGM.Int32Ty);
 }
 
 llvm::Value *CodeGenFunction::EmitSEHAbnormalTermination() {
@@ -1677,11 +1616,9 @@ llvm::Value *CodeGenFunction::EmitSEHAbn
 void CodeGenFunction::EnterSEHTryStmt(const SEHTryStmt &S) {
   CodeGenFunction HelperCGF(CGM, /*suppressNewContext=*/true);
   if (const SEHFinallyStmt *Finally = S.getFinallyHandler()) {
-    // Outline the finally block.
+    // Push a cleanup for __finally blocks.
     llvm::Function *FinallyFunc =
         HelperCGF.GenerateSEHFinallyFunction(*this, *Finally);
-
-    // Push a cleanup for __finally blocks.
     EHStack.pushCleanup<PerformSEHFinally>(NormalAndEHCleanup, FinallyFunc);
     return;
   }
@@ -1690,16 +1627,12 @@ void CodeGenFunction::EnterSEHTryStmt(co
   const SEHExceptStmt *Except = S.getExceptHandler();
   assert(Except);
   EHCatchScope *CatchScope = EHStack.pushCatch(1);
-  SEHCodeSlotStack.push_back(
-      CreateMemTemp(getContext().IntTy, "__exception_code"));
 
-  // If the filter is known to evaluate to 1, then we can use the clause
-  // "catch i8* null". We can't do this on x86 because the filter has to save
-  // the exception code.
+  // If the filter is known to evaluate to 1, then we can use the clause "catch
+  // i8* null".
   llvm::Constant *C =
       CGM.EmitConstantExpr(Except->getFilterExpr(), getContext().IntTy, this);
-  if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86 && C &&
-      C->isOneValue()) {
+  if (C && C->isOneValue()) {
     CatchScope->setCatchAllHandler(0, createBasicBlock("__except"));
     return;
   }
@@ -1731,7 +1664,6 @@ void CodeGenFunction::ExitSEHTryStmt(con
   if (!CatchScope.hasEHBranches()) {
     CatchScope.clearHandlerBlocks();
     EHStack.popCatch();
-    SEHCodeSlotStack.pop_back();
     return;
   }
 
@@ -1751,20 +1683,9 @@ void CodeGenFunction::ExitSEHTryStmt(con
 
   EmitBlockAfterUses(ExceptBB);
 
-  // On Win64, the exception pointer is the exception code. Copy it to the slot.
-  if (CGM.getTarget().getTriple().getArch() != llvm::Triple::x86) {
-    llvm::Value *Code =
-        Builder.CreatePtrToInt(getExceptionFromSlot(), IntPtrTy);
-    Code = Builder.CreateTrunc(Code, Int32Ty);
-    Builder.CreateStore(Code, SEHCodeSlotStack.back());
-  }
-
   // Emit the __except body.
   EmitStmt(Except->getBlock());
 
-  // End the lifetime of the exception code.
-  SEHCodeSlotStack.pop_back();
-
   if (HaveInsertPoint())
     Builder.CreateBr(ContBB);
 

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=241244&r1=241243&r2=241244&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Thu Jul  2 01:10:53 2015
@@ -45,12 +45,12 @@ CodeGenFunction::CodeGenFunction(CodeGen
       LambdaThisCaptureField(nullptr), NormalCleanupDest(nullptr),
       NextCleanupDestIndex(1), FirstBlockInfo(nullptr), EHResumeBlock(nullptr),
       ExceptionSlot(nullptr), EHSelectorSlot(nullptr),
-      DebugInfo(CGM.getModuleDebugInfo()),
-      DisableDebugInfo(false), DidCallStackSave(false), IndirectBranch(nullptr),
-      PGO(cgm), SwitchInsn(nullptr), SwitchWeights(nullptr),
-      CaseRangeBlock(nullptr), UnreachableBlock(nullptr), NumReturnExprs(0),
-      NumSimpleReturnExprs(0), CXXABIThisDecl(nullptr),
-      CXXABIThisValue(nullptr), CXXThisValue(nullptr),
+      AbnormalTerminationSlot(nullptr), SEHPointersDecl(nullptr),
+      DebugInfo(CGM.getModuleDebugInfo()), DisableDebugInfo(false),
+      DidCallStackSave(false), IndirectBranch(nullptr), PGO(cgm),
+      SwitchInsn(nullptr), SwitchWeights(nullptr), CaseRangeBlock(nullptr),
+      UnreachableBlock(nullptr), NumReturnExprs(0), NumSimpleReturnExprs(0),
+      CXXABIThisDecl(nullptr), CXXABIThisValue(nullptr), CXXThisValue(nullptr),
       CXXDefaultInitExprThis(nullptr), CXXStructorImplicitParamDecl(nullptr),
       CXXStructorImplicitParamValue(nullptr), OutermostConditional(nullptr),
       CurLexicalScope(nullptr), TerminateLandingPad(nullptr),

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=241244&r1=241243&r2=241244&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Jul  2 01:10:53 2015
@@ -324,13 +324,11 @@ public:
   /// write the current selector value into this alloca.
   llvm::AllocaInst *EHSelectorSlot;
 
-  /// A stack of exception code slots. Entering an __except block pushes a slot
-  /// on the stack and leaving pops one. The __exception_code() intrinsic loads
-  /// a value from the top of the stack.
-  SmallVector<llvm::Value *, 1> SEHCodeSlotStack;
+  llvm::AllocaInst *AbnormalTerminationSlot;
 
-  /// Value returned by __exception_info intrinsic.
-  llvm::Value *SEHInfo = nullptr;
+  /// The implicit parameter to SEH filter functions of type
+  /// 'EXCEPTION_POINTERS*'.
+  ImplicitParamDecl *SEHPointersDecl;
 
   /// Emits a landing pad for the current EH stack.
   llvm::BasicBlock *EmitLandingPad();
@@ -2050,7 +2048,8 @@ public:
   void EnterSEHTryStmt(const SEHTryStmt &S);
   void ExitSEHTryStmt(const SEHTryStmt &S);
 
-  void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter,
+  void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, StringRef Name,
+                              QualType RetTy, FunctionArgList &Args,
                               const Stmt *OutlinedStmt);
 
   llvm::Function *GenerateSEHFilterFunction(CodeGenFunction &ParentCGF,
@@ -2059,9 +2058,7 @@ public:
   llvm::Function *GenerateSEHFinallyFunction(CodeGenFunction &ParentCGF,
                                              const SEHFinallyStmt &Finally);
 
-  void EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF,
-                                llvm::Value *ParentFP,
-                                llvm::Value *EntryEBP);
+  void EmitSEHExceptionCodeSave();
   llvm::Value *EmitSEHExceptionCode();
   llvm::Value *EmitSEHExceptionInfo();
   llvm::Value *EmitSEHAbnormalTermination();
@@ -2070,16 +2067,7 @@ public:
   /// each capture, mark the capture as escaped and emit a call to
   /// llvm.framerecover. Insert the framerecover result into the LocalDeclMap.
   void EmitCapturedLocals(CodeGenFunction &ParentCGF, const Stmt *OutlinedStmt,
-                          bool IsFilter);
-
-  /// Recovers the address of a local in a parent function. ParentVar is the
-  /// address of the variable used in the immediate parent function. It can
-  /// either be an alloca or a call to llvm.framerecover if there are nested
-  /// outlined functions. ParentFP is the frame pointer of the outermost parent
-  /// frame.
-  llvm::Value *recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF,
-                                         llvm::Value *ParentVar,
-                                         llvm::Value *ParentFP);
+                          llvm::Value *ParentFP);
 
   void EmitCXXForRangeStmt(const CXXForRangeStmt &S,
                            ArrayRef<const Attr *> Attrs = None);

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=241244&r1=241243&r2=241244&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Thu Jul  2 01:10:53 2015
@@ -25,7 +25,6 @@
 #include "clang/AST/StmtObjC.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/AST/TypeOrdering.h"
-#include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
@@ -3650,10 +3649,6 @@ StmtResult Sema::ActOnSEHTryBlock(bool I
   else
     Diag(TryLoc, diag::err_seh_try_outside_functions);
 
-  // Reject __try on unsupported targets.
-  if (!Context.getTargetInfo().isSEHTrySupported())
-    Diag(TryLoc, diag::err_seh_try_unsupported);
-
   return SEHTryStmt::Create(Context, IsCXXTry, TryLoc, TryBlock, Handler);
 }
 

Modified: cfe/trunk/test/CodeGen/exceptions-seh-finally.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/exceptions-seh-finally.c?rev=241244&r1=241243&r2=241244&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/exceptions-seh-finally.c (original)
+++ cfe/trunk/test/CodeGen/exceptions-seh-finally.c Thu Jul  2 01:10:53 2015
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
-// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
 
 void abort(void) __attribute__((noreturn));
 void might_crash(void);
@@ -19,17 +18,17 @@ void basic_finally(void) {
 //
 // CHECK: [[invoke_cont]]
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
+// CHECK: call void @"\01?fin$0 at 0@basic_finally@@"(i8 0, i8* %[[fp]])
 // CHECK-NEXT: ret void
 //
 // CHECK: [[lpad]]
 // CHECK-NEXT: landingpad
 // CHECK-NEXT: cleanup
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK: call void @"\01?fin$0 at 0@basic_finally@@"(i8 1, i8* %[[fp]])
 // CHECK: resume { i8*, i32 }
 
-// CHECK: define internal void @"\01?fin$0 at 0@basic_finally@@"({{.*}})
+// CHECK: define internal void @"\01?fin$0 at 0@basic_finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
 // CHECK: call void @cleanup()
 
 // Mostly check that we don't double emit 'r' which would crash.
@@ -59,10 +58,10 @@ l:
 //
 // CHECK: [[invoke_cont]]
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@label_in_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
+// CHECK: call void @"\01?fin$0 at 0@label_in_finally@@"(i8 0, i8* %[[fp]])
 // CHECK: ret void
 
-// CHECK: define internal void @"\01?fin$0 at 0@label_in_finally@@"({{.*}})
+// CHECK: define internal void @"\01?fin$0 at 0@label_in_finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
 // CHECK: br label %[[l:[^ ]*]]
 //
 // CHECK: [[l]]
@@ -86,18 +85,18 @@ void use_abnormal_termination(void) {
 //
 // CHECK: [[invoke_cont]]
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@use_abnormal_termination@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
+// CHECK: call void @"\01?fin$0 at 0@use_abnormal_termination@@"(i8 0, i8* %[[fp]])
 // CHECK: ret void
 //
 // CHECK: [[lpad]]
 // CHECK-NEXT: landingpad
 // CHECK-NEXT: cleanup
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@use_abnormal_termination@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK: call void @"\01?fin$0 at 0@use_abnormal_termination@@"(i8 1, i8* %[[fp]])
 // CHECK: resume { i8*, i32 }
 
-// CHECK: define internal void @"\01?fin$0 at 0@use_abnormal_termination@@"({{i8( zeroext)?}} %[[abnormal:abnormal_termination]], i8* %frame_pointer)
-// CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %[[abnormal]] to i32
+// CHECK: define internal void @"\01?fin$0 at 0@use_abnormal_termination@@"(i8 %abnormal_termination, i8* %frame_pointer)
+// CHECK: %[[abnormal_zext:[^ ]*]] = zext i8 %abnormal_termination to i32
 // CHECK: store i32 %[[abnormal_zext]], i32* @crashed
 // CHECK-NEXT: ret void
 
@@ -110,10 +109,11 @@ void noreturn_noop_finally() {
 }
 
 // CHECK-LABEL: define void @noreturn_noop_finally()
-// CHECK: call void @"\01?fin$0 at 0@noreturn_noop_finally@@"({{.*}})
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK: call void @"\01?fin$0 at 0@noreturn_noop_finally@@"(i8 0, i8* %[[fp]])
 // CHECK: ret void
 
-// CHECK: define internal void @"\01?fin$0 at 0@noreturn_noop_finally@@"({{.*}})
+// CHECK: define internal void @"\01?fin$0 at 0@noreturn_noop_finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
 // CHECK: call void @abort()
 // CHECK: unreachable
 
@@ -130,16 +130,18 @@ void noreturn_finally() {
 // CHECK:     to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
 //
 // CHECK: [[cont]]
-// CHECK: call void @"\01?fin$0 at 0@noreturn_finally@@"({{.*}})
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK: call void @"\01?fin$0 at 0@noreturn_finally@@"(i8 0, i8* %[[fp]])
 // CHECK: ret void
 //
 // CHECK: [[lpad]]
 // CHECK: landingpad
 // CHECK-NEXT: cleanup
-// CHECK: call void @"\01?fin$0 at 0@noreturn_finally@@"({{.*}})
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK: call void @"\01?fin$0 at 0@noreturn_finally@@"(i8 1, i8* %[[fp]])
 // CHECK: resume { i8*, i32 }
 
-// CHECK: define internal void @"\01?fin$0 at 0@noreturn_finally@@"({{.*}})
+// CHECK: define internal void @"\01?fin$0 at 0@noreturn_finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
 // CHECK: call void @abort()
 // CHECK: unreachable
 
@@ -150,10 +152,11 @@ int finally_with_return() {
   }
 }
 // CHECK-LABEL: define i32 @finally_with_return()
-// CHECK: call void @"\01?fin$0 at 0@finally_with_return@@"({{.*}})
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK-NEXT: call void @"\01?fin$0 at 0@finally_with_return@@"(i8 0, i8* %[[fp]])
 // CHECK-NEXT: ret i32 42
 
-// CHECK: define internal void @"\01?fin$0 at 0@finally_with_return@@"({{.*}})
+// CHECK: define internal void @"\01?fin$0 at 0@finally_with_return@@"(i8 %abnormal_termination, i8* %frame_pointer)
 // CHECK-NOT: br i1
 // CHECK-NOT: br label
 // CHECK: ret void
@@ -171,22 +174,25 @@ int nested___finally___finally() {
 }
 
 // CHECK-LABEL: define i32 @nested___finally___finally
-// CHECK: invoke void @"\01?fin$1 at 0@nested___finally___finally@@"({{.*}})
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK: invoke void @"\01?fin$1 at 0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
 // CHECK:          to label %[[outercont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
 //
 // CHECK: [[outercont]]
-// CHECK: call void @"\01?fin$0 at 0@nested___finally___finally@@"({{.*}})
+// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK-NEXT: call void @"\01?fin$0 at 0@nested___finally___finally@@"(i8 0, i8* %[[fp]])
 // CHECK-NEXT: ret i32 0
 //
 // CHECK: [[lpad]]
 // CHECK-NEXT: landingpad
 // CHECK-NEXT: cleanup
-// CHECK: call void @"\01?fin$0 at 0@nested___finally___finally@@"({{.*}})
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK-NEXT: call void @"\01?fin$0 at 0@nested___finally___finally@@"(i8 1, i8* %[[fp]])
 
-// CHECK-LABEL: define internal void @"\01?fin$0 at 0@nested___finally___finally@@"({{.*}})
+// CHECK-LABEL: define internal void @"\01?fin$0 at 0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
 // CHECK: ret void
 
-// CHECK-LABEL: define internal void @"\01?fin$1 at 0@nested___finally___finally@@"({{.*}})
+// CHECK-LABEL: define internal void @"\01?fin$1 at 0@nested___finally___finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
 // CHECK: unreachable
 
 int nested___finally___finally_with_eh_edge() {
@@ -206,27 +212,31 @@ int nested___finally___finally_with_eh_e
 // CHECK-NEXT: to label %[[invokecont:[^ ]*]] unwind label %[[lpad1:[^ ]*]]
 //
 // [[invokecont]]
-// CHECK: invoke void @"\01?fin$1 at 0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK: invoke void @"\01?fin$1 at 0@nested___finally___finally_with_eh_edge@@"(i8 0, i8* %[[fp]])
 // CHECK:          to label %[[outercont:[^ ]*]] unwind label %[[lpad2:[^ ]*]]
 //
 // CHECK: [[outercont]]
-// CHECK: call void @"\01?fin$0 at 0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK-NEXT: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK-NEXT: call void @"\01?fin$0 at 0@nested___finally___finally_with_eh_edge@@"(i8 0, i8* %[[fp]])
 // CHECK-NEXT: ret i32 912
 //
 // CHECK: [[lpad1]]
 // CHECK-NEXT: landingpad
 // CHECK-NEXT: cleanup
-// CHECK: invoke void @"\01?fin$1 at 0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK: invoke void @"\01?fin$1 at 0@nested___finally___finally_with_eh_edge@@"(i8 1, i8* %[[fp]])
 // CHECK:          to label %[[outercont:[^ ]*]] unwind label %[[lpad2]]
 //
 // CHECK: [[lpad2]]
 // CHECK-NEXT: landingpad
 // CHECK-NEXT: cleanup
-// CHECK: call void @"\01?fin$0 at 0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
+// CHECK: call void @"\01?fin$0 at 0@nested___finally___finally_with_eh_edge@@"(i8 1, i8* %[[fp]])
 // CHECK: resume
 
-// CHECK-LABEL: define internal void @"\01?fin$0 at 0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK-LABEL: define internal void @"\01?fin$0 at 0@nested___finally___finally_with_eh_edge@@"(i8 %abnormal_termination, i8* %frame_pointer)
 // CHECK: ret void
 
-// CHECK-LABEL: define internal void @"\01?fin$1 at 0@nested___finally___finally_with_eh_edge@@"({{.*}})
+// CHECK-LABEL: define internal void @"\01?fin$1 at 0@nested___finally___finally_with_eh_edge@@"(i8 %abnormal_termination, i8* %frame_pointer)
 // CHECK: unreachable

Modified: cfe/trunk/test/CodeGen/exceptions-seh-leave.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/exceptions-seh-leave.c?rev=241244&r1=241243&r2=241244&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/exceptions-seh-leave.c (original)
+++ cfe/trunk/test/CodeGen/exceptions-seh-leave.c Thu Jul  2 01:10:53 2015
@@ -205,7 +205,7 @@ int nested___except___except() {
 // CHECK:  br label %[[except:[^ ]*]]
 
 // CHECK: [[except]]
-// CHECK: invoke void @g()
+// CHECK-NEXT: invoke void @g()
 // CHECK-NEXT:       to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
 
 // CHECK: [[g2_cont]]
@@ -216,7 +216,7 @@ int nested___except___except() {
 // CHECK: br label %[[outerexcept:[^ ]*]]
 
 // CHECK: [[outerexcept]]
-// CHECK: br label %[[trycont4:[^ ]*]]
+// CHECK-NEXT: br label %[[trycont4:[^ ]*]]
 
 // CHECK: [[trycont4]]
 // CHECK-NEXT: ret i32 1
@@ -258,11 +258,11 @@ int nested___finally___except() {
 // CHECK:  br label %[[except:[^ ]*]]
 
 // CHECK: [[except]]
-// CHECK: invoke void @g()
+// CHECK-NEXT: invoke void @g()
 // CHECK-NEXT:       to label %[[g2_cont:.*]] unwind label %[[g2_lpad:.*]]
 
 // CHECK: [[g2_cont]]
-// CHECK: br label %[[tryleave:[^ ]*]]
+// CHECK-NEXT: br label %[[tryleave:[^ ]*]]
 // CHECK-NOT: 23
 
 // CHECK: [[g2_lpad]]

Modified: cfe/trunk/test/CodeGen/exceptions-seh.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/exceptions-seh.c?rev=241244&r1=241243&r2=241244&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/exceptions-seh.c (original)
+++ cfe/trunk/test/CodeGen/exceptions-seh.c Thu Jul  2 01:10:53 2015
@@ -1,7 +1,4 @@
-// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - \
-// RUN:         | FileCheck %s --check-prefix=CHECK --check-prefix=X64
-// RUN: %clang_cc1 %s -triple i686-pc-win32 -fms-extensions -emit-llvm -o - \
-// RUN:         | FileCheck %s --check-prefix=CHECK --check-prefix=X86
+// RUN: %clang_cc1 %s -triple x86_64-pc-win32 -fms-extensions -emit-llvm -o - | FileCheck %s
 
 void try_body(int numerator, int denominator, int *myres) {
   *myres = numerator / denominator;
@@ -22,46 +19,20 @@ int safe_div(int numerator, int denomina
   *res = myres;
   return success;
 }
-
-// X64-LABEL: define i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res) {{.*}} personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
-// X64: invoke void @try_body(i32 %{{.*}}, i32 %{{.*}}, i32* %{{.*}}) #[[NOINLINE:[0-9]+]]
-// X64:       to label %{{.*}} unwind label %[[lpad:[^ ]*]]
-//
-// X64: [[lpad]]
-// X64: landingpad { i8*, i32 }
-// X64-NEXT: catch i8* null
-// X64-NOT: br i1
-// X64: br label %[[except:[^ ]*]]
-// X64: [[except]]
-// X64: store i32 -42, i32* %[[success:[^ ]*]]
-//
-// X64: %[[res:[^ ]*]] = load i32, i32* %[[success]]
-// X64: ret i32 %[[res]]
-
-// X86-LABEL: define i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res) {{.*}} personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
-// X86: invoke void @try_body(i32 %{{.*}}, i32 %{{.*}}, i32* %{{.*}}) #[[NOINLINE:[0-9]+]]
-// X86:       to label %{{.*}} unwind label %[[lpad:[^ ]*]]
-//
-// X86: [[lpad]]
-// X86: landingpad { i8*, i32 }
-// X86-NEXT: catch i8* bitcast (i32 ()* @"\01?filt$0 at 0@safe_div@@" to i8*)
-// X86-NOT: br i1
-// X86: br label %[[except:[^ ]*]]
-// X86: [[except]]
-// X86: store i32 -42, i32* %[[success:[^ ]*]]
-//
-// X86: %[[res:[^ ]*]] = load i32, i32* %[[success]]
-// X86: ret i32 %[[res]]
-
-// X86-LABEL: define internal i32 @"\01?filt$0 at 0@safe_div@@"()
-// X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
-// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[ebp]])
-// X86: call i8* @llvm.framerecover(i8* bitcast (i32 (i32, i32, i32*)* @safe_div to i8*), i8* %[[fp]], i32 0)
-// X86: load i8*, i8**
-// X86: load i32*, i32**
-// X86: load i32, i32*
-// X86: store i32 %{{.*}}, i32*
-// X86: ret i32 1
+// CHECK-LABEL: define i32 @safe_div(i32 %numerator, i32 %denominator, i32* %res) {{.*}} personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// CHECK: invoke void @try_body(i32 %{{.*}}, i32 %{{.*}}, i32* %{{.*}}) #[[NOINLINE:[0-9]+]]
+// CHECK:       to label %{{.*}} unwind label %[[lpad:[^ ]*]]
+//
+// CHECK: [[lpad]]
+// CHECK: landingpad { i8*, i32 }
+// CHECK-NEXT: catch i8* null
+// CHECK-NOT: br i1
+// CHECK: br label %[[except:[^ ]*]]
+// CHECK: [[except]]
+// CHECK-NEXT: store i32 -42, i32* %[[success:[^ ]*]]
+//
+// CHECK: %[[res:[^ ]*]] = load i32, i32* %[[success]]
+// CHECK: ret i32 %[[res]]
 
 void j(void);
 
@@ -75,29 +46,20 @@ int filter_expr_capture(void) {
   return r;
 }
 
-// CHECK-LABEL: define i32 @filter_expr_capture()
-// X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
-// X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
-// X64: call void (...) @llvm.frameescape(i32* %[[r:[^ ,]*]])
-// X86: call void (...) @llvm.frameescape(i32* %[[r:[^ ,]*]], i32* %[[code:[^ ,]*]])
+// CHECK-LABEL: define i32 @filter_expr_capture() {{.*}} personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// CHECK: call void (...) @llvm.frameescape(i32* %[[r:[^ ,]*]])
 // CHECK: store i32 42, i32* %[[r]]
 // CHECK: invoke void @j() #[[NOINLINE]]
 //
 // CHECK: landingpad
-// CHECK-NEXT: catch i8* bitcast (i32 ({{.*}})* @"\01?filt$0 at 0@filter_expr_capture@@" to i8*)
+// CHECK-NEXT: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0 at 0@filter_expr_capture@@" to i8*)
 // CHECK: store i32 13, i32* %[[r]]
 //
 // CHECK: %[[rv:[^ ]*]] = load i32, i32* %[[r]]
 // CHECK: ret i32 %[[rv]]
 
-// X64-LABEL: define internal i32 @"\01?filt$0 at 0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer)
-// X64: call i8* @llvm.framerecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer, i32 0)
-//
-// X86-LABEL: define internal i32 @"\01?filt$0 at 0@filter_expr_capture@@"()
-// X86: %[[ebp:[^ ]*]] = call i8* @llvm.frameaddress(i32 1)
-// X86: %[[fp:[^ ]*]] = call i8* @llvm.x86.seh.recoverfp(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[ebp]])
-// X86: call i8* @llvm.framerecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %[[fp]], i32 0)
-//
+// CHECK-LABEL: define internal i32 @"\01?filt$0 at 0@filter_expr_capture@@"(i8* %exception_pointers, i8* %frame_pointer)
+// CHECK: call i8* @llvm.framerecover(i8* bitcast (i32 ()* @filter_expr_capture to i8*), i8* %frame_pointer, i32 0)
 // CHECK: store i32 -1, i32* %{{.*}}
 // CHECK: ret i32 -1
 
@@ -115,9 +77,7 @@ int nested_try(void) {
   }
   return r;
 }
-// CHECK-LABEL: define i32 @nested_try()
-// X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
-// X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
+// CHECK-LABEL: define i32 @nested_try() {{.*}} personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
 // CHECK: store i32 42, i32* %[[r:[^ ,]*]]
 // CHECK: invoke void @j() #[[NOINLINE]]
 // CHECK:       to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
@@ -128,18 +88,18 @@ int nested_try(void) {
 //
 // CHECK: [[lpad]]
 // CHECK: landingpad { i8*, i32 }
-// CHECK: catch i8* bitcast (i32 ({{.*}})* @"\01?filt$1 at 0@nested_try@@" to i8*)
-// CHECK: catch i8* bitcast (i32 ({{.*}})* @"\01?filt$0 at 0@nested_try@@" to i8*)
+// CHECK: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$1 at 0@nested_try@@" to i8*)
+// CHECK: catch i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0 at 0@nested_try@@" to i8*)
 // CHECK: store i8* %{{.*}}, i8** %[[ehptr_slot:[^ ]*]]
 // CHECK: store i32 %{{.*}}, i32* %[[sel_slot:[^ ]*]]
 //
 // CHECK: load i32, i32* %[[sel_slot]]
-// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ({{.*}})* @"\01?filt$1 at 0@nested_try@@" to i8*))
+// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @"\01?filt$1 at 0@nested_try@@" to i8*))
 // CHECK: icmp eq i32
 // CHECK: br i1
 //
 // CHECK: load i32, i32* %[[sel_slot]]
-// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 ({{.*}})* @"\01?filt$0 at 0@nested_try@@" to i8*))
+// CHECK: call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0 at 0@nested_try@@" to i8*))
 // CHECK: icmp eq i32
 // CHECK: br i1
 //
@@ -155,55 +115,40 @@ int nested_try(void) {
 //
 // CHECK: [[inner_try_cont]]
 // CHECK: br label %[[outer_try_cont]]
-//
-// CHECK-LABEL: define internal i32 @"\01?filt$0 at 0@nested_try@@"({{.*}})
-// X86: call i8* @llvm.x86.seh.recoverfp({{.*}})
-// CHECK: load i32*, i32**
-// CHECK: load i32, i32*
-// CHECK: icmp eq i32 %{{.*}}, 456
-//
-// CHECK-LABEL: define internal i32 @"\01?filt$1 at 0@nested_try@@"({{.*}})
-// X86: call i8* @llvm.x86.seh.recoverfp({{.*}})
-// CHECK: load i32*, i32**
-// CHECK: load i32, i32*
-// CHECK: icmp eq i32 %{{.*}}, 123
 
-int basic_finally(int g) {
+static unsigned g = 0;
+void basic_finally(void) {
+  ++g;
   __try {
     j();
   } __finally {
-    ++g;
+    --g;
   }
-  return g;
 }
-// CHECK-LABEL: define i32 @basic_finally(i32 %g)
-// X64-SAME: personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
-// X86-SAME: personality i8* bitcast (i32 (...)* @_except_handler3 to i8*)
-// CHECK: %[[g_addr:[^ ]*]] = alloca i32, align 4
-// CHECK: call void (...) @llvm.frameescape(i32* %[[g_addr]])
-// CHECK: store i32 %g, i32* %[[g_addr]]
+// CHECK-LABEL: define void @basic_finally() {{.*}} personality i8* bitcast (i32 (...)* @__C_specific_handler to i8*)
+// CHECK: load i32, i32* @g
+// CHECK: add i32 %{{.*}}, 1
+// CHECK: store i32 %{{.*}}, i32* @g
 //
 // CHECK: invoke void @j()
 // CHECK:       to label %[[cont:[^ ]*]] unwind label %[[lpad:[^ ]*]]
 //
 // CHECK: [[cont]]
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@basic_finally@@"({{i8( zeroext)?}} 0, i8* %[[fp]])
-// CHECK: load i32, i32* %[[g_addr]], align 4
-// CHECK: ret i32
+// CHECK: call void @"\01?fin$0 at 0@basic_finally@@"(i8 0, i8* %[[fp]])
+// CHECK: ret void
 //
 // CHECK: [[lpad]]
 // CHECK: landingpad { i8*, i32 }
 // CHECK-NEXT: cleanup
 // CHECK: %[[fp:[^ ]*]] = call i8* @llvm.frameaddress(i32 0)
-// CHECK: call void @"\01?fin$0 at 0@basic_finally@@"({{i8( zeroext)?}} 1, i8* %[[fp]])
+// CHECK: call void @"\01?fin$0 at 0@basic_finally@@"(i8 1, i8* %[[fp]])
 // CHECK: resume
 
-// CHECK: define internal void @"\01?fin$0 at 0@basic_finally@@"({{i8( zeroext)?}} %abnormal_termination, i8* %frame_pointer)
-// CHECK:   call i8* @llvm.framerecover(i8* bitcast (i32 (i32)* @basic_finally to i8*), i8* %frame_pointer, i32 0)
-// CHECK:   load i32, i32* %{{.*}}, align 4
-// CHECK:   add nsw i32 %{{.*}}, 1
-// CHECK:   store i32 %{{.*}}, i32* %{{.*}}, align 4
+// CHECK: define internal void @"\01?fin$0 at 0@basic_finally@@"(i8 %abnormal_termination, i8* %frame_pointer)
+// CHECK:   load i32, i32* @g, align 4
+// CHECK:   add i32 %{{.*}}, -1
+// CHECK:   store i32 %{{.*}}, i32* @g, align 4
 // CHECK:   ret void
 
 int returns_int(void);





More information about the cfe-commits mailing list