[MS ABI] Hook clang up to the new EH instructions

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

llvm-svn: 243767
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 613d29a..3084446 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -855,8 +855,14 @@
 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 @@
   // 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);
 }