MS ABI: Turn throw into std::terminate for now, make try/catch "work"
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 25 Feb 2015 23:01:21 +0000 (23:01 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 25 Feb 2015 23:01:21 +0000 (23:01 +0000)
This lets us compile programs which make use of exceptional constructs
statically without executing any of them dynamically.

llvm-svn: 230568

clang/lib/CodeGen/CGException.cpp
clang/test/CodeGenCXX/microsoft-abi-try-throw.cpp

index b7953bc..f1ffa58 100644 (file)
@@ -64,6 +64,9 @@ static llvm::Constant *getGetExceptionPtrFn(CodeGenModule &CGM) {
 }
 
 static llvm::Constant *getBeginCatchFn(CodeGenModule &CGM) {
+  if (CGM.getTarget().getCXXABI().isMicrosoft())
+    return CGM.getIntrinsic(llvm::Intrinsic::eh_begincatch);
+
   // void *__cxa_begin_catch(void*);
 
   llvm::FunctionType *FTy =
@@ -73,6 +76,9 @@ static llvm::Constant *getBeginCatchFn(CodeGenModule &CGM) {
 }
 
 static llvm::Constant *getEndCatchFn(CodeGenModule &CGM) {
+  if (CGM.getTarget().getCXXABI().isMicrosoft())
+    return CGM.getIntrinsic(llvm::Intrinsic::eh_endcatch);
+
   // void __cxa_end_catch();
 
   llvm::FunctionType *FTy =
@@ -102,8 +108,11 @@ static llvm::Constant *getTerminateFn(CodeGenModule &CGM) {
   if (CGM.getLangOpts().CPlusPlus &&
       CGM.getTarget().getCXXABI().isItaniumFamily()) {
     name = "_ZSt9terminatev";
+  } else if (CGM.getLangOpts().CPlusPlus &&
+             CGM.getTarget().getCXXABI().isMicrosoft()) {
+    name = "\01?terminate@@YAXXZ";
   } else if (CGM.getLangOpts().ObjC1 &&
-           CGM.getLangOpts().ObjCRuntime.hasTerminate())
+             CGM.getLangOpts().ObjCRuntime.hasTerminate())
     name = "objc_terminate";
   else
     name = "abort";
@@ -472,7 +481,15 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E,
   }
 
   if (CGM.getTarget().getTriple().isKnownWindowsMSVCEnvironment()) {
-    ErrorUnsupported(E, "throw expression");
+    // Call std::terminate().
+    llvm::CallInst *TermCall = EmitNounwindRuntimeCall(getTerminateFn(CGM));
+    TermCall->setDoesNotReturn();
+
+    // throw is an expression, and the expression emitters expect us
+    // to leave ourselves at a valid insertion point.
+    if (KeepInsertionPoint)
+      EmitBlock(createBasicBlock("throw.cont"));
+
     return;
   }
 
@@ -633,11 +650,6 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) {
 }
 
 void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
-  if (CGM.getTarget().getTriple().isKnownWindowsMSVCEnvironment()) {
-    ErrorUnsupported(&S, "try statement");
-    return;
-  }
-
   EnterCXXTryStmt(S);
   EmitStmt(S.getTryBlock());
   ExitCXXTryStmt(S);
index 95c2cbd..6b83307 100644 (file)
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm-only %s -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -verify -DTRY
-// RUN: %clang_cc1 -emit-llvm-only %s -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -verify -DTHROW
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTRY   | FileCheck %s -check-prefix=TRY
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fcxx-exceptions -fexceptions -fno-rtti -DTHROW | FileCheck %s -check-prefix=THROW
 
 void external();
 
@@ -10,14 +10,17 @@ inline void not_emitted() {
 int main() {
   int rv = 0;
 #ifdef TRY
-  try { // expected-error {{cannot compile this try statement yet}}
-    external();
+  try {
+    external(); // TRY: invoke void @"\01?external@@YAXXZ"
   } catch (int) {
     rv = 1;
+    // TRY: call i8* @llvm.eh.begincatch
+    // TRY: call void @llvm.eh.endcatch
   }
 #endif
 #ifdef THROW
-  throw int(42); // expected-error {{cannot compile this throw expression yet}}
+  // THROW: call void @"\01?terminate@@YAXXZ"
+  throw int(42);
 #endif
   return rv;
 }