]> granicus.if.org Git - clang/commitdiff
[MS ABI] Hook clang up to the new EH instructions
authorDavid Majnemer <david.majnemer@gmail.com>
Fri, 31 Jul 2015 17:58:45 +0000 (17:58 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Fri, 31 Jul 2015 17:58:45 +0000 (17:58 +0000)
The new EH instructions make it possible for LLVM to generate .xdata
tables that the MSVC personality routines will be happy about.  Because
this is experimental, hide it behind a -cc1 flag (-fnew-ms-eh).

Differential Revision: http://reviews.llvm.org/D11405

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

include/clang/Driver/CC1Options.td
include/clang/Frontend/CodeGenOptions.def
lib/CodeGen/CGCleanup.cpp
lib/CodeGen/CGCleanup.h
lib/CodeGen/CGException.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h
lib/CodeGen/EHScopeStack.h
lib/CodeGen/MicrosoftCXXABI.cpp
lib/Frontend/CompilerInvocation.cpp

index 16b105be370f68e0ea3e9066d25d144357a4d20c..3636f3260cf735f95b5767237723332ecd12224d 100644 (file)
@@ -486,6 +486,8 @@ def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">,
   HelpText<"Weakly link in the blocks runtime">;
 def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">,
   HelpText<"Use SjLj style exceptions">;
+def fnew_ms_eh: Flag<["-"], "fnew-ms-eh">,
+  HelpText<"Use the new IR representation for MS exceptions">;
 def split_dwarf_file : Separate<["-"], "split-dwarf-file">,
   HelpText<"File name to use for split dwarf debug info output">;
 def fno_wchar : Flag<["-"], "fno-wchar">,
index 72f88031f29dd1401cd5bddaa8f5b05a931a5433..ead74ad03dc4b147cd98842e984b88aa95fc03c9 100644 (file)
@@ -33,6 +33,7 @@ CODEGENOPT(CompressDebugSections, 1, 0) ///< -Wa,-compress-debug-sections
 CODEGENOPT(Autolink          , 1, 1) ///< -fno-autolink
 CODEGENOPT(AsmVerbose        , 1, 0) ///< -dA, -fverbose-asm.
 CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe.
+CODEGENOPT(NewMSEH           , 1, 0) ///< Whether we should use the new IR representation for MS exceptions
 CODEGENOPT(CoverageExtraChecksum, 1, 0) ///< Whether we need a second checksum for functions in GCNO files.
 CODEGENOPT(CoverageNoFunctionNamesInData, 1, 0) ///< Do not include function names in GCDA files.
 CODEGENOPT(CoverageExitBlockBeforeBody, 1, 0) ///< Whether to emit the exit block before the body blocks in GCNO files.
index 3d4c4850f60dbdee92a31de1d56c75055f2d85f4..ef5a98ead98723a1fac4af26fad60aaa067469ce 100644 (file)
@@ -247,6 +247,13 @@ void EHScopeStack::pushTerminate() {
   InnermostEHScope = stable_begin();
 }
 
+void EHScopeStack::pushCatchEnd(llvm::BasicBlock *CatchEndBlockBB) {
+  char *Buffer = allocate(EHCatchEndScope::getSize());
+  auto *CES = new (Buffer) EHCatchEndScope(InnermostEHScope);
+  CES->setCachedEHDispatchBlock(CatchEndBlockBB);
+  InnermostEHScope = stable_begin();
+}
+
 /// Remove any 'null' fixups on the stack.  However, we can't pop more
 /// fixups than the fixup depth on the innermost normal cleanup, or
 /// else fixups that we try to add to that cleanup will end up in the
@@ -896,6 +903,14 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
     CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP();
 
     EmitBlock(EHEntry);
+    llvm::BasicBlock *NextAction = getEHDispatchBlock(EHParent);
+    if (CGM.getCodeGenOpts().NewMSEH &&
+        EHPersonality::get(*this).isMSVCPersonality()) {
+      if (NextAction)
+        Builder.CreateCleanupPad(VoidTy, NextAction);
+      else
+        Builder.CreateCleanupPad(VoidTy, {});
+    }
 
     // We only actually emit the cleanup code if the cleanup is either
     // active or was used before it was deactivated.
@@ -905,7 +920,10 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
       EmitCleanup(*this, Fn, cleanupFlags, EHActiveFlag);
     }
 
-    Builder.CreateBr(getEHDispatchBlock(EHParent));
+    if (CGM.getCodeGenOpts().NewMSEH && EHPersonality::get(*this).isMSVCPersonality())
+      Builder.CreateCleanupRet(NextAction);
+    else
+      Builder.CreateBr(NextAction);
 
     Builder.restoreIP(SavedIP);
 
index 8338691ab5d62b245bdd0f6c4376b81d3943ff3c..dcbc40db8732a48d34951d11acb614d50182f292 100644 (file)
@@ -40,9 +40,9 @@ class EHScope {
 
   class CommonBitFields {
     friend class EHScope;
-    unsigned Kind : 2;
+    unsigned Kind : 3;
   };
-  enum { NumCommonBits = 2 };
+  enum { NumCommonBits = 3 };
 
 protected:
   class CatchBitFields {
@@ -81,7 +81,7 @@ protected:
     /// The number of fixups required by enclosing scopes (not including
     /// this one).  If this is the top cleanup scope, all the fixups
     /// from this index onwards belong to this scope.
-    unsigned FixupDepth : 32 - 18 - NumCommonBits; // currently 13
+    unsigned FixupDepth : 32 - 18 - NumCommonBits; // currently 12
   };
 
   class FilterBitFields {
@@ -99,7 +99,7 @@ protected:
   };
 
 public:
-  enum Kind { Cleanup, Catch, Terminate, Filter };
+  enum Kind { Cleanup, Catch, Terminate, Filter, CatchEnd };
 
   EHScope(Kind kind, EHScopeStack::stable_iterator enclosingEHScope)
     : CachedLandingPad(nullptr), CachedEHDispatchBlock(nullptr),
@@ -466,6 +466,17 @@ public:
   }
 };
 
+class EHCatchEndScope : public EHScope {
+public:
+  EHCatchEndScope(EHScopeStack::stable_iterator enclosingEHScope)
+      : EHScope(CatchEnd, enclosingEHScope) {}
+  static size_t getSize() { return sizeof(EHCatchEndScope); }
+
+  static bool classof(const EHScope *scope) {
+    return scope->getKind() == CatchEnd;
+  }
+};
+
 /// A non-stable pointer into the scope stack.
 class EHScopeStack::iterator {
   char *Ptr;
@@ -503,6 +514,10 @@ public:
     case EHScope::Terminate:
       Size = EHTerminateScope::getSize();
       break;
+
+    case EHScope::CatchEnd:
+      Size = EHCatchEndScope::getSize();
+      break;
     }
     Ptr += llvm::RoundUpToAlignment(Size, ScopeStackAlignment);
     return *this;
@@ -551,6 +566,14 @@ inline void EHScopeStack::popTerminate() {
   deallocate(EHTerminateScope::getSize());
 }
 
+inline void EHScopeStack::popCatchEnd() {
+  assert(!empty() && "popping exception stack when not empty");
+
+  EHCatchEndScope &scope = cast<EHCatchEndScope>(*begin());
+  InnermostEHScope = scope.getEnclosingEHScope();
+  deallocate(EHCatchEndScope::getSize());
+}
+
 inline EHScopeStack::iterator EHScopeStack::find(stable_iterator sp) const {
   assert(sp.isValid() && "finding invalid savepoint");
   assert(sp.Size <= stable_begin().Size && "finding savepoint after pop");
@@ -588,6 +611,13 @@ struct EHPersonality {
   static const EHPersonality MSVC_except_handler;
   static const EHPersonality MSVC_C_specific_handler;
   static const EHPersonality MSVC_CxxFrameHandler3;
+
+  bool isMSVCPersonality() const {
+    return this == &MSVC_except_handler || this == &MSVC_C_specific_handler ||
+           this == &MSVC_CxxFrameHandler3;
+  }
+
+  bool isMSVCXXPersonality() const { return this == &MSVC_CxxFrameHandler3; }
 };
 }
 }
index d0e86ae2d9aec61bdff5fb59032d6b3669f5c1b7..16dc7d16dd4220c5a6561032451b7f04e3f0bd23 100644 (file)
@@ -559,6 +559,10 @@ void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
 
 llvm::BasicBlock *
 CodeGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) {
+  if (CGM.getCodeGenOpts().NewMSEH &&
+      EHPersonality::get(*this).isMSVCPersonality())
+    return getMSVCDispatchBlock(si);
+
   // The dispatch block for the end of the scope chain is a block that
   // just resumes unwinding.
   if (si == EHStack.stable_end())
@@ -595,12 +599,58 @@ CodeGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) {
     case EHScope::Terminate:
       dispatchBlock = getTerminateHandler();
       break;
+
+    case EHScope::CatchEnd:
+      llvm_unreachable("CatchEnd unnecessary for Itanium!");
     }
     scope.setCachedEHDispatchBlock(dispatchBlock);
   }
   return dispatchBlock;
 }
 
+llvm::BasicBlock *
+CodeGenFunction::getMSVCDispatchBlock(EHScopeStack::stable_iterator SI) {
+  // Returning nullptr indicates that the previous dispatch block should unwind
+  // to caller.
+  if (SI == EHStack.stable_end())
+    return nullptr;
+
+  // Otherwise, we should look at the actual scope.
+  EHScope &EHS = *EHStack.find(SI);
+
+  llvm::BasicBlock *DispatchBlock = EHS.getCachedEHDispatchBlock();
+  if (DispatchBlock)
+    return DispatchBlock;
+
+  if (EHS.getKind() == EHScope::Terminate)
+    DispatchBlock = getTerminateHandler();
+  else
+    DispatchBlock = createBasicBlock();
+  CGBuilderTy Builder(DispatchBlock);
+
+  switch (EHS.getKind()) {
+  case EHScope::Catch:
+    DispatchBlock->setName("catch.dispatch");
+    break;
+
+  case EHScope::Cleanup:
+    DispatchBlock->setName("ehcleanup");
+    break;
+
+  case EHScope::Filter:
+    llvm_unreachable("exception specifications not handled yet!");
+
+  case EHScope::Terminate:
+    DispatchBlock->setName("terminate");
+    break;
+
+  case EHScope::CatchEnd:
+    llvm_unreachable("CatchEnd dispatch block missing!");
+  }
+  EHS.setCachedEHDispatchBlock(DispatchBlock);
+  return DispatchBlock;
+}
+
 /// Check whether this is a non-EH scope, i.e. a scope which doesn't
 /// affect exception handling.  Currently, the only non-EH scopes are
 /// normal-only cleanup scopes.
@@ -611,6 +661,7 @@ static bool isNonEHScope(const EHScope &S) {
   case EHScope::Filter:
   case EHScope::Catch:
   case EHScope::Terminate:
+  case EHScope::CatchEnd:
     return false;
   }
 
@@ -636,8 +687,19 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() {
   llvm::BasicBlock *LP = EHStack.begin()->getCachedLandingPad();
   if (LP) return LP;
 
-  // Build the landing pad for this scope.
-  LP = EmitLandingPad();
+  const EHPersonality &Personality = EHPersonality::get(*this);
+
+  if (!CurFn->hasPersonalityFn())
+    CurFn->setPersonalityFn(getOpaquePersonalityFn(CGM, Personality));
+
+  if (CGM.getCodeGenOpts().NewMSEH && Personality.isMSVCPersonality()) {
+    // We don't need separate landing pads in the MSVC model.
+    LP = getEHDispatchBlock(EHStack.getInnermostEHScope());
+  } else {
+    // Build the landing pad for this scope.
+    LP = EmitLandingPad();
+  }
+
   assert(LP);
 
   // Cache the landing pad on the innermost scope.  If this is a
@@ -658,6 +720,9 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
   case EHScope::Terminate:
     return getTerminateLandingPad();
 
+  case EHScope::CatchEnd:
+    llvm_unreachable("CatchEnd unnecessary for Itanium!");
+
   case EHScope::Catch:
   case EHScope::Cleanup:
   case EHScope::Filter:
@@ -669,11 +734,6 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
   CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP();
   auto DL = ApplyDebugLocation::CreateDefaultArtificial(*this, CurEHLocation);
 
-  const EHPersonality &personality = EHPersonality::get(*this);
-
-  if (!CurFn->hasPersonalityFn())
-    CurFn->setPersonalityFn(getOpaquePersonalityFn(CGM, personality));
-
   // Create and configure the landing pad.
   llvm::BasicBlock *lpad = createBasicBlock("lpad");
   EmitBlock(lpad);
@@ -728,6 +788,9 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
 
     case EHScope::Catch:
       break;
+
+    case EHScope::CatchEnd:
+      llvm_unreachable("CatchEnd unnecessary for Itanium!");
     }
 
     EHCatchScope &catchScope = cast<EHCatchScope>(*I);
@@ -792,10 +855,63 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {
   return lpad;
 }
 
+static llvm::BasicBlock *emitMSVCCatchDispatchBlock(CodeGenFunction &CGF,
+                                                    EHCatchScope &CatchScope) {
+  llvm::BasicBlock *DispatchBlock = CatchScope.getCachedEHDispatchBlock();
+  assert(DispatchBlock);
+
+  CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveIP();
+  CGF.EmitBlockAfterUses(DispatchBlock);
+
+  // Figure out the next block.
+  llvm::BasicBlock *NextBlock = nullptr;
+
+  // Test against each of the exception types we claim to catch.
+  for (unsigned I = 0, E = CatchScope.getNumHandlers(); I < E; ++I) {
+    const EHCatchScope::Handler &Handler = CatchScope.getHandler(I);
+
+    llvm::Value *TypeValue = Handler.Type;
+    assert(TypeValue != nullptr || Handler.isCatchAll());
+    if (!TypeValue)
+      TypeValue = llvm::Constant::getNullValue(CGF.VoidPtrTy);
+
+    // If this is the last handler, we're at the end, and the next
+    // block is the block for the enclosing EH scope.
+    if (I + 1 == E) {
+      NextBlock = CGF.createBasicBlock("catchendblock");
+      CGBuilderTy(NextBlock).CreateCatchEndPad(
+          CGF.getEHDispatchBlock(CatchScope.getEnclosingEHScope()));
+    } else {
+      NextBlock = CGF.createBasicBlock("catch.dispatch");
+    }
+
+    if (EHPersonality::get(CGF).isMSVCXXPersonality()) {
+      CGF.Builder.CreateCatchPad(
+          CGF.VoidTy, Handler.Block, NextBlock,
+          {TypeValue, llvm::Constant::getNullValue(CGF.VoidPtrTy)});
+    } else {
+      CGF.Builder.CreateCatchPad(CGF.VoidTy, Handler.Block, NextBlock,
+                                 {TypeValue});
+    }
+
+    // Otherwise we need to emit and continue at that block.
+    CGF.EmitBlock(NextBlock);
+  }
+  CGF.Builder.restoreIP(SavedIP);
+
+  return NextBlock;
+}
+
 /// Emit the structure of the dispatch block for the given catch scope.
 /// It is an invariant that the dispatch block already exists.
-static void emitCatchDispatchBlock(CodeGenFunction &CGF,
-                                   EHCatchScope &catchScope) {
+/// If the catchblock instructions are used for EH dispatch, then the basic
+/// block holding the final catchendblock instruction is returned.
+static llvm::BasicBlock *emitCatchDispatchBlock(CodeGenFunction &CGF,
+                                                EHCatchScope &catchScope) {
+  if (CGF.CGM.getCodeGenOpts().NewMSEH &&
+      EHPersonality::get(CGF).isMSVCPersonality())
+    return emitMSVCCatchDispatchBlock(CGF, catchScope);
+
   llvm::BasicBlock *dispatchBlock = catchScope.getCachedEHDispatchBlock();
   assert(dispatchBlock);
 
@@ -804,7 +920,7 @@ static void emitCatchDispatchBlock(CodeGenFunction &CGF,
   if (catchScope.getNumHandlers() == 1 &&
       catchScope.getHandler(0).isCatchAll()) {
     assert(dispatchBlock == catchScope.getHandler(0).Block);
-    return;
+    return nullptr;
   }
 
   CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP();
@@ -860,11 +976,12 @@ static void emitCatchDispatchBlock(CodeGenFunction &CGF,
     // If the next handler is a catch-all, we're completely done.
     if (nextIsEnd) {
       CGF.Builder.restoreIP(savedIP);
-      return;
+      return nullptr;
     }
     // Otherwise we need to emit and continue at that block.
     CGF.EmitBlock(nextBlock);
   }
+  return nullptr;
 }
 
 void CodeGenFunction::popCatchScope() {
@@ -887,7 +1004,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
   }
 
   // Emit the structure of the EH dispatch for this catch.
-  emitCatchDispatchBlock(*this, CatchScope);
+  llvm::BasicBlock *CatchEndBlockBB = emitCatchDispatchBlock(*this, CatchScope);
 
   // Copy the handler blocks off before we pop the EH stack.  Emitting
   // the handlers might scribble on this memory.
@@ -911,6 +1028,9 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
     doImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) ||
                         isa<CXXConstructorDecl>(CurCodeDecl);
 
+  if (CatchEndBlockBB)
+    EHStack.pushCatchEnd(CatchEndBlockBB);
+
   // Perversely, we emit the handlers backwards precisely because we
   // want them to appear in source order.  In all of these cases, the
   // catch block will have exactly one predecessor, which will be a
@@ -963,6 +1083,8 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {
 
   EmitBlock(ContBB);
   incrementProfileCounter(&S);
+  if (CatchEndBlockBB)
+    EHStack.popCatchEnd();
 }
 
 namespace {
@@ -1200,13 +1322,18 @@ llvm::BasicBlock *CodeGenFunction::getTerminateHandler() {
   // end of the function by FinishFunction.
   TerminateHandler = createBasicBlock("terminate.handler");
   Builder.SetInsertPoint(TerminateHandler);
-  llvm::Value *Exn = 0;
-  if (getLangOpts().CPlusPlus)
-    Exn = getExceptionFromSlot();
-  llvm::CallInst *terminateCall =
-      CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);
-  terminateCall->setDoesNotReturn();
-  Builder.CreateUnreachable();
+  if (CGM.getCodeGenOpts().NewMSEH &&
+      EHPersonality::get(*this).isMSVCPersonality()) {
+    Builder.CreateTerminatePad(/*UnwindBB=*/nullptr, CGM.getTerminateFn());
+  } else {
+    llvm::Value *Exn = 0;
+    if (getLangOpts().CPlusPlus)
+      Exn = getExceptionFromSlot();
+    llvm::CallInst *terminateCall =
+        CGM.getCXXABI().emitTerminateForUnexpectedException(*this, Exn);
+    terminateCall->setDoesNotReturn();
+    Builder.CreateUnreachable();
+  }
 
   // Restore the saved insertion state.
   Builder.restoreIP(SavedIP);
index ec3c75ccd257a18938748d368249991d338434dc..9bf4161e945c12fb317102a2081744f72645dabc 100644 (file)
@@ -826,15 +826,11 @@ static void TryMarkNoThrow(llvm::Function *F) {
   // can't do this on functions that can be overwritten.
   if (F->mayBeOverridden()) return;
 
-  for (llvm::Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI)
-    for (llvm::BasicBlock::iterator
-           BI = FI->begin(), BE = FI->end(); BI != BE; ++BI)
-      if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(&*BI)) {
-        if (!Call->doesNotThrow())
-          return;
-      } else if (isa<llvm::ResumeInst>(&*BI)) {
+  for (llvm::BasicBlock &BB : *F)
+    for (llvm::Instruction &I : BB)
+      if (I.mayThrow())
         return;
-      }
+
   F->setDoesNotThrow();
 }
 
index b7d6bbd93d2aa8d58e920bdfd33ea36408bce50a..c4633501eb7695a495f50a81447c6359ae4fd5dc 100644 (file)
@@ -665,6 +665,7 @@ public:
 
   llvm::BasicBlock *getEHResumeBlock(bool isCleanup);
   llvm::BasicBlock *getEHDispatchBlock(EHScopeStack::stable_iterator scope);
+  llvm::BasicBlock *getMSVCDispatchBlock(EHScopeStack::stable_iterator scope);
 
   /// An object to manage conditionally-evaluated expressions.
   class ConditionalEvaluation {
index dc7a6c60856262f006ffd09ef917d30d6b2c70b6..8cad5b61eaf9368961595138e895233174365d2e 100644 (file)
@@ -329,6 +329,10 @@ public:
   /// Pops a terminate handler off the stack.
   void popTerminate();
 
+  void pushCatchEnd(llvm::BasicBlock *CatchEndBlockBB);
+
+  void popCatchEnd();
+
   // Returns true iff the current scope is either empty or contains only
   // lifetime markers, i.e. no real cleanup code
   bool containsOnlyLifetimeMarkers(stable_iterator Old) const;
index 613d29a63cd3b21692590b9e99f64f786efaedd1..3084446795e80847d10f47f2b66e9e6eab8dc99b 100644 (file)
@@ -855,8 +855,14 @@ namespace {
 struct CallEndCatchMSVC : EHScopeStack::Cleanup {
   CallEndCatchMSVC() {}
   void Emit(CodeGenFunction &CGF, Flags flags) override {
-    CGF.EmitNounwindRuntimeCall(
-        CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_endcatch));
+    if (CGF.CGM.getCodeGenOpts().NewMSEH) {
+      llvm::BasicBlock *BB = CGF.createBasicBlock("catchret.dest");
+      CGF.Builder.CreateCatchRet(BB);
+      CGF.EmitBlock(BB);
+    } else {
+      CGF.EmitNounwindRuntimeCall(
+          CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_endcatch));
+    }
   }
 };
 }
@@ -866,24 +872,36 @@ void MicrosoftCXXABI::emitBeginCatch(CodeGenFunction &CGF,
   // In the MS ABI, the runtime handles the copy, and the catch handler is
   // responsible for destruction.
   VarDecl *CatchParam = S->getExceptionDecl();
-  llvm::Value *Exn = CGF.getExceptionFromSlot();
-  llvm::Function *BeginCatch =
-      CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_begincatch);
-
+  llvm::Value *Exn = nullptr;
+  llvm::Function *BeginCatch = nullptr;
+  bool NewEH = CGF.CGM.getCodeGenOpts().NewMSEH;
+  if (!NewEH) {
+    Exn = CGF.getExceptionFromSlot();
+    BeginCatch = CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_begincatch);
+  }
   // If this is a catch-all or the catch parameter is unnamed, we don't need to
   // emit an alloca to the object.
   if (!CatchParam || !CatchParam->getDeclName()) {
-    llvm::Value *Args[2] = {Exn, llvm::Constant::getNullValue(CGF.Int8PtrTy)};
-    CGF.EmitNounwindRuntimeCall(BeginCatch, Args);
+    if (!NewEH) {
+      llvm::Value *Args[2] = {Exn, llvm::Constant::getNullValue(CGF.Int8PtrTy)};
+      CGF.EmitNounwindRuntimeCall(BeginCatch, Args);
+    }
     CGF.EHStack.pushCleanup<CallEndCatchMSVC>(NormalCleanup);
     return;
   }
 
   CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);
-  llvm::Value *ParamAddr =
-      CGF.Builder.CreateBitCast(var.getObjectAddress(CGF), CGF.Int8PtrTy);
-  llvm::Value *Args[2] = {Exn, ParamAddr};
-  CGF.EmitNounwindRuntimeCall(BeginCatch, Args);
+  if (!NewEH) {
+    llvm::Value *ParamAddr =
+        CGF.Builder.CreateBitCast(var.getObjectAddress(CGF), CGF.Int8PtrTy);
+    llvm::Value *Args[2] = {Exn, ParamAddr};
+    CGF.EmitNounwindRuntimeCall(BeginCatch, Args);
+  } else {
+    llvm::BasicBlock *CatchPadBB =
+        CGF.Builder.GetInsertBlock()->getSinglePredecessor();
+    auto *CPI = cast<llvm::CatchPadInst>(CatchPadBB->getFirstNonPHI());
+    CPI->setArgOperand(1, var.getObjectAddress(CGF));
+  }
   CGF.EHStack.pushCleanup<CallEndCatchMSVC>(NormalCleanup);
   CGF.EmitAutoVarCleanups(var);
 }
index b496c7c01a9e78a10017cac3e234255084e8ac9d..9307711c82fe2586ac8b10fc0141941a2eb388ff 100644 (file)
@@ -456,6 +456,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
   Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping);
   Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
   Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions);
+  Opts.NewMSEH = Args.hasArg(OPT_fnew_ms_eh);
   Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
   Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
   Opts.CodeModel = getCodeModel(Args, Diags);