| Anders Carlsson | 756b5c4 | 2009-10-30 01:42:31 +0000 | [diff] [blame] | 1 | //===--- CGException.cpp - Emit LLVM Code for C++ exceptions --------------===// | 
 | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
 | 5 | // This file is distributed under the University of Illinois Open Source | 
 | 6 | // License. See LICENSE.TXT for details. | 
 | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
 | 10 | // This contains code dealing with C++ exception related code generation. | 
 | 11 | // | 
 | 12 | //===----------------------------------------------------------------------===// | 
 | 13 |  | 
 | 14 | #include "CodeGenFunction.h" | 
| John McCall | 36f893c | 2011-01-28 11:13:47 +0000 | [diff] [blame] | 15 | #include "CGCleanup.h" | 
| Benjamin Kramer | af2771b | 2012-02-08 12:41:24 +0000 | [diff] [blame] | 16 | #include "CGObjCRuntime.h" | 
| John McCall | 204b075 | 2010-07-20 22:17:55 +0000 | [diff] [blame] | 17 | #include "TargetInfo.h" | 
| Benjamin Kramer | af2771b | 2012-02-08 12:41:24 +0000 | [diff] [blame] | 18 | #include "clang/AST/StmtCXX.h" | 
 | 19 | #include "llvm/Intrinsics.h" | 
 | 20 | #include "llvm/Support/CallSite.h" | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 21 |  | 
| Anders Carlsson | 756b5c4 | 2009-10-30 01:42:31 +0000 | [diff] [blame] | 22 | using namespace clang; | 
 | 23 | using namespace CodeGen; | 
 | 24 |  | 
| Anders Carlsson | d337929 | 2009-10-30 02:27:02 +0000 | [diff] [blame] | 25 | static llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) { | 
 | 26 |   // void *__cxa_allocate_exception(size_t thrown_size); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 27 |  | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 28 |   llvm::FunctionType *FTy = | 
| Jay Foad | da549e8 | 2011-07-29 13:56:53 +0000 | [diff] [blame] | 29 |     llvm::FunctionType::get(CGF.Int8PtrTy, CGF.SizeTy, /*IsVarArgs=*/false); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 30 |  | 
| Anders Carlsson | d337929 | 2009-10-30 02:27:02 +0000 | [diff] [blame] | 31 |   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception"); | 
 | 32 | } | 
 | 33 |  | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 34 | static llvm::Constant *getFreeExceptionFn(CodeGenFunction &CGF) { | 
 | 35 |   // void __cxa_free_exception(void *thrown_exception); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 36 |  | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 37 |   llvm::FunctionType *FTy = | 
| Jay Foad | da549e8 | 2011-07-29 13:56:53 +0000 | [diff] [blame] | 38 |     llvm::FunctionType::get(CGF.VoidTy, CGF.Int8PtrTy, /*IsVarArgs=*/false); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 39 |  | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 40 |   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception"); | 
 | 41 | } | 
 | 42 |  | 
| Anders Carlsson | d337929 | 2009-10-30 02:27:02 +0000 | [diff] [blame] | 43 | static llvm::Constant *getThrowFn(CodeGenFunction &CGF) { | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 44 |   // void __cxa_throw(void *thrown_exception, std::type_info *tinfo, | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 45 |   //                  void (*dest) (void *)); | 
| Anders Carlsson | d337929 | 2009-10-30 02:27:02 +0000 | [diff] [blame] | 46 |  | 
| John McCall | 61c1601 | 2011-07-10 20:11:30 +0000 | [diff] [blame] | 47 |   llvm::Type *Args[3] = { CGF.Int8PtrTy, CGF.Int8PtrTy, CGF.Int8PtrTy }; | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 48 |   llvm::FunctionType *FTy = | 
| John McCall | 61c1601 | 2011-07-10 20:11:30 +0000 | [diff] [blame] | 49 |     llvm::FunctionType::get(CGF.VoidTy, Args, /*IsVarArgs=*/false); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 50 |  | 
| Anders Carlsson | d337929 | 2009-10-30 02:27:02 +0000 | [diff] [blame] | 51 |   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_throw"); | 
 | 52 | } | 
 | 53 |  | 
| Mike Stump | b4eea69 | 2009-11-20 00:56:31 +0000 | [diff] [blame] | 54 | static llvm::Constant *getReThrowFn(CodeGenFunction &CGF) { | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 55 |   // void __cxa_rethrow(); | 
| Mike Stump | b4eea69 | 2009-11-20 00:56:31 +0000 | [diff] [blame] | 56 |  | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 57 |   llvm::FunctionType *FTy = | 
| John McCall | 61c1601 | 2011-07-10 20:11:30 +0000 | [diff] [blame] | 58 |     llvm::FunctionType::get(CGF.VoidTy, /*IsVarArgs=*/false); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 59 |  | 
| Mike Stump | b4eea69 | 2009-11-20 00:56:31 +0000 | [diff] [blame] | 60 |   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow"); | 
 | 61 | } | 
 | 62 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 63 | static llvm::Constant *getGetExceptionPtrFn(CodeGenFunction &CGF) { | 
 | 64 |   // void *__cxa_get_exception_ptr(void*); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 65 |  | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 66 |   llvm::FunctionType *FTy = | 
| Jay Foad | da549e8 | 2011-07-29 13:56:53 +0000 | [diff] [blame] | 67 |     llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrTy, /*IsVarArgs=*/false); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 68 |  | 
 | 69 |   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr"); | 
 | 70 | } | 
 | 71 |  | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 72 | static llvm::Constant *getBeginCatchFn(CodeGenFunction &CGF) { | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 73 |   // void *__cxa_begin_catch(void*); | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 74 |  | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 75 |   llvm::FunctionType *FTy = | 
| Jay Foad | da549e8 | 2011-07-29 13:56:53 +0000 | [diff] [blame] | 76 |     llvm::FunctionType::get(CGF.Int8PtrTy, CGF.Int8PtrTy, /*IsVarArgs=*/false); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 77 |  | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 78 |   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); | 
 | 79 | } | 
 | 80 |  | 
 | 81 | static llvm::Constant *getEndCatchFn(CodeGenFunction &CGF) { | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 82 |   // void __cxa_end_catch(); | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 83 |  | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 84 |   llvm::FunctionType *FTy = | 
| John McCall | 61c1601 | 2011-07-10 20:11:30 +0000 | [diff] [blame] | 85 |     llvm::FunctionType::get(CGF.VoidTy, /*IsVarArgs=*/false); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 86 |  | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 87 |   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); | 
 | 88 | } | 
 | 89 |  | 
| Mike Stump | cce3d4f | 2009-12-07 23:38:24 +0000 | [diff] [blame] | 90 | static llvm::Constant *getUnexpectedFn(CodeGenFunction &CGF) { | 
 | 91 |   // void __cxa_call_unexepcted(void *thrown_exception); | 
 | 92 |  | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 93 |   llvm::FunctionType *FTy = | 
| Jay Foad | da549e8 | 2011-07-29 13:56:53 +0000 | [diff] [blame] | 94 |     llvm::FunctionType::get(CGF.VoidTy, CGF.Int8PtrTy, /*IsVarArgs=*/false); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 95 |  | 
| Mike Stump | cce3d4f | 2009-12-07 23:38:24 +0000 | [diff] [blame] | 96 |   return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected"); | 
 | 97 | } | 
 | 98 |  | 
| John McCall | 93c332a | 2011-05-28 21:13:02 +0000 | [diff] [blame] | 99 | llvm::Constant *CodeGenFunction::getUnwindResumeFn() { | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 100 |   llvm::FunctionType *FTy = | 
| Jay Foad | da549e8 | 2011-07-29 13:56:53 +0000 | [diff] [blame] | 101 |     llvm::FunctionType::get(VoidTy, Int8PtrTy, /*IsVarArgs=*/false); | 
| John McCall | 93c332a | 2011-05-28 21:13:02 +0000 | [diff] [blame] | 102 |  | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 103 |   if (CGM.getLangOpts().SjLjExceptions) | 
| John McCall | 93c332a | 2011-05-28 21:13:02 +0000 | [diff] [blame] | 104 |     return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume"); | 
 | 105 |   return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume"); | 
 | 106 | } | 
 | 107 |  | 
 | 108 | llvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() { | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 109 |   llvm::FunctionType *FTy = | 
| Jay Foad | da549e8 | 2011-07-29 13:56:53 +0000 | [diff] [blame] | 110 |     llvm::FunctionType::get(VoidTy, Int8PtrTy, /*IsVarArgs=*/false); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 111 |  | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 112 |   if (CGM.getLangOpts().SjLjExceptions) | 
| John McCall | a5f2de2 | 2010-08-11 20:59:53 +0000 | [diff] [blame] | 113 |     return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume_or_Rethrow"); | 
| Douglas Gregor | 86a3a03 | 2010-05-16 01:24:12 +0000 | [diff] [blame] | 114 |   return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow"); | 
| Mike Stump | 0f590be | 2009-12-01 03:41:18 +0000 | [diff] [blame] | 115 | } | 
 | 116 |  | 
| Mike Stump | 9953383 | 2009-12-02 07:41:41 +0000 | [diff] [blame] | 117 | static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) { | 
 | 118 |   // void __terminate(); | 
 | 119 |  | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 120 |   llvm::FunctionType *FTy = | 
| John McCall | 61c1601 | 2011-07-10 20:11:30 +0000 | [diff] [blame] | 121 |     llvm::FunctionType::get(CGF.VoidTy, /*IsVarArgs=*/false); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 122 |  | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 123 |   StringRef name; | 
| John McCall | 256a76e | 2011-07-06 01:22:26 +0000 | [diff] [blame] | 124 |  | 
 | 125 |   // In C++, use std::terminate(). | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 126 |   if (CGF.getLangOpts().CPlusPlus) | 
| John McCall | 256a76e | 2011-07-06 01:22:26 +0000 | [diff] [blame] | 127 |     name = "_ZSt9terminatev"; // FIXME: mangling! | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 128 |   else if (CGF.getLangOpts().ObjC1 && | 
| John McCall | 256a76e | 2011-07-06 01:22:26 +0000 | [diff] [blame] | 129 |            CGF.CGM.getCodeGenOpts().ObjCRuntimeHasTerminate) | 
 | 130 |     name = "objc_terminate"; | 
 | 131 |   else | 
 | 132 |     name = "abort"; | 
 | 133 |   return CGF.CGM.CreateRuntimeFunction(FTy, name); | 
| David Chisnall | 79a9ad8 | 2010-05-17 13:49:20 +0000 | [diff] [blame] | 134 | } | 
 | 135 |  | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 136 | static llvm::Constant *getCatchallRethrowFn(CodeGenFunction &CGF, | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 137 |                                             StringRef Name) { | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 138 |   llvm::FunctionType *FTy = | 
| Jay Foad | da549e8 | 2011-07-29 13:56:53 +0000 | [diff] [blame] | 139 |     llvm::FunctionType::get(CGF.VoidTy, CGF.Int8PtrTy, /*IsVarArgs=*/false); | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 140 |  | 
 | 141 |   return CGF.CGM.CreateRuntimeFunction(FTy, Name); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 142 | } | 
 | 143 |  | 
| Benjamin Kramer | af2771b | 2012-02-08 12:41:24 +0000 | [diff] [blame] | 144 | namespace { | 
 | 145 |   /// The exceptions personality for a function. | 
 | 146 |   struct EHPersonality { | 
 | 147 |     const char *PersonalityFn; | 
 | 148 |  | 
 | 149 |     // If this is non-null, this personality requires a non-standard | 
 | 150 |     // function for rethrowing an exception after a catchall cleanup. | 
 | 151 |     // This function must have prototype void(void*). | 
 | 152 |     const char *CatchallRethrowFn; | 
 | 153 |  | 
 | 154 |     static const EHPersonality &get(const LangOptions &Lang); | 
 | 155 |     static const EHPersonality GNU_C; | 
 | 156 |     static const EHPersonality GNU_C_SJLJ; | 
 | 157 |     static const EHPersonality GNU_ObjC; | 
 | 158 |     static const EHPersonality GNU_ObjCXX; | 
 | 159 |     static const EHPersonality NeXT_ObjC; | 
 | 160 |     static const EHPersonality GNU_CPlusPlus; | 
 | 161 |     static const EHPersonality GNU_CPlusPlus_SJLJ; | 
 | 162 |   }; | 
 | 163 | } | 
 | 164 |  | 
 | 165 | const EHPersonality EHPersonality::GNU_C = { "__gcc_personality_v0", 0 }; | 
 | 166 | const EHPersonality EHPersonality::GNU_C_SJLJ = { "__gcc_personality_sj0", 0 }; | 
 | 167 | const EHPersonality EHPersonality::NeXT_ObjC = { "__objc_personality_v0", 0 }; | 
 | 168 | const EHPersonality EHPersonality::GNU_CPlusPlus = { "__gxx_personality_v0", 0}; | 
 | 169 | const EHPersonality | 
 | 170 | EHPersonality::GNU_CPlusPlus_SJLJ = { "__gxx_personality_sj0", 0 }; | 
 | 171 | const EHPersonality | 
 | 172 | EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0", "objc_exception_throw"}; | 
 | 173 | const EHPersonality | 
 | 174 | EHPersonality::GNU_ObjCXX = { "__gnustep_objcxx_personality_v0", 0 }; | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 175 |  | 
 | 176 | static const EHPersonality &getCPersonality(const LangOptions &L) { | 
| John McCall | 4468078 | 2010-11-07 02:35:25 +0000 | [diff] [blame] | 177 |   if (L.SjLjExceptions) | 
 | 178 |     return EHPersonality::GNU_C_SJLJ; | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 179 |   return EHPersonality::GNU_C; | 
 | 180 | } | 
 | 181 |  | 
 | 182 | static const EHPersonality &getObjCPersonality(const LangOptions &L) { | 
 | 183 |   if (L.NeXTRuntime) { | 
 | 184 |     if (L.ObjCNonFragileABI) return EHPersonality::NeXT_ObjC; | 
 | 185 |     else return getCPersonality(L); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 186 |   } else { | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 187 |     return EHPersonality::GNU_ObjC; | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 188 |   } | 
 | 189 | } | 
 | 190 |  | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 191 | static const EHPersonality &getCXXPersonality(const LangOptions &L) { | 
 | 192 |   if (L.SjLjExceptions) | 
 | 193 |     return EHPersonality::GNU_CPlusPlus_SJLJ; | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 194 |   else | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 195 |     return EHPersonality::GNU_CPlusPlus; | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 196 | } | 
 | 197 |  | 
 | 198 | /// Determines the personality function to use when both C++ | 
 | 199 | /// and Objective-C exceptions are being caught. | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 200 | static const EHPersonality &getObjCXXPersonality(const LangOptions &L) { | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 201 |   // The ObjC personality defers to the C++ personality for non-ObjC | 
 | 202 |   // handlers.  Unlike the C++ case, we use the same personality | 
 | 203 |   // function on targets using (backend-driven) SJLJ EH. | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 204 |   if (L.NeXTRuntime) { | 
 | 205 |     if (L.ObjCNonFragileABI) | 
 | 206 |       return EHPersonality::NeXT_ObjC; | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 207 |  | 
 | 208 |     // In the fragile ABI, just use C++ exception handling and hope | 
 | 209 |     // they're not doing crazy exception mixing. | 
 | 210 |     else | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 211 |       return getCXXPersonality(L); | 
| Chandler Carruth | dcf22ad | 2010-05-17 20:58:49 +0000 | [diff] [blame] | 212 |   } | 
| David Chisnall | 79a9ad8 | 2010-05-17 13:49:20 +0000 | [diff] [blame] | 213 |  | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 214 |   // The GNU runtime's personality function inherently doesn't support | 
 | 215 |   // mixed EH.  Use the C++ personality just to avoid returning null. | 
| David Chisnall | 80558d2 | 2011-03-20 21:35:39 +0000 | [diff] [blame] | 216 |   return EHPersonality::GNU_ObjCXX; | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 217 | } | 
 | 218 |  | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 219 | const EHPersonality &EHPersonality::get(const LangOptions &L) { | 
 | 220 |   if (L.CPlusPlus && L.ObjC1) | 
 | 221 |     return getObjCXXPersonality(L); | 
 | 222 |   else if (L.CPlusPlus) | 
 | 223 |     return getCXXPersonality(L); | 
 | 224 |   else if (L.ObjC1) | 
 | 225 |     return getObjCPersonality(L); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 226 |   else | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 227 |     return getCPersonality(L); | 
 | 228 | } | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 229 |  | 
| John McCall | b259383 | 2010-09-16 06:16:50 +0000 | [diff] [blame] | 230 | static llvm::Constant *getPersonalityFn(CodeGenModule &CGM, | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 231 |                                         const EHPersonality &Personality) { | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 232 |   llvm::Constant *Fn = | 
| Chris Lattner | 8b41868 | 2012-02-07 00:39:47 +0000 | [diff] [blame] | 233 |     CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty, true), | 
| Benjamin Kramer | af2771b | 2012-02-08 12:41:24 +0000 | [diff] [blame] | 234 |                               Personality.PersonalityFn); | 
| John McCall | b259383 | 2010-09-16 06:16:50 +0000 | [diff] [blame] | 235 |   return Fn; | 
 | 236 | } | 
 | 237 |  | 
 | 238 | static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM, | 
 | 239 |                                         const EHPersonality &Personality) { | 
 | 240 |   llvm::Constant *Fn = getPersonalityFn(CGM, Personality); | 
| John McCall | d16c2cf | 2011-02-08 08:22:06 +0000 | [diff] [blame] | 241 |   return llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); | 
| John McCall | b259383 | 2010-09-16 06:16:50 +0000 | [diff] [blame] | 242 | } | 
 | 243 |  | 
 | 244 | /// Check whether a personality function could reasonably be swapped | 
 | 245 | /// for a C++ personality function. | 
 | 246 | static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) { | 
 | 247 |   for (llvm::Constant::use_iterator | 
 | 248 |          I = Fn->use_begin(), E = Fn->use_end(); I != E; ++I) { | 
 | 249 |     llvm::User *User = *I; | 
 | 250 |  | 
 | 251 |     // Conditionally white-list bitcasts. | 
 | 252 |     if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(User)) { | 
 | 253 |       if (CE->getOpcode() != llvm::Instruction::BitCast) return false; | 
 | 254 |       if (!PersonalityHasOnlyCXXUses(CE)) | 
 | 255 |         return false; | 
 | 256 |       continue; | 
 | 257 |     } | 
 | 258 |  | 
| Bill Wendling | 40ccacc | 2011-09-19 22:08:36 +0000 | [diff] [blame] | 259 |     // Otherwise, it has to be a landingpad instruction. | 
 | 260 |     llvm::LandingPadInst *LPI = dyn_cast<llvm::LandingPadInst>(User); | 
 | 261 |     if (!LPI) return false; | 
| John McCall | b259383 | 2010-09-16 06:16:50 +0000 | [diff] [blame] | 262 |  | 
| Bill Wendling | 40ccacc | 2011-09-19 22:08:36 +0000 | [diff] [blame] | 263 |     for (unsigned I = 0, E = LPI->getNumClauses(); I != E; ++I) { | 
| John McCall | b259383 | 2010-09-16 06:16:50 +0000 | [diff] [blame] | 264 |       // Look for something that would've been returned by the ObjC | 
 | 265 |       // runtime's GetEHType() method. | 
| Bill Wendling | 40ccacc | 2011-09-19 22:08:36 +0000 | [diff] [blame] | 266 |       llvm::Value *Val = LPI->getClause(I)->stripPointerCasts(); | 
 | 267 |       if (LPI->isCatch(I)) { | 
 | 268 |         // Check if the catch value has the ObjC prefix. | 
| Bill Wendling | eecb6a1 | 2011-09-20 00:40:19 +0000 | [diff] [blame] | 269 |         if (llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Val)) | 
 | 270 |           // ObjC EH selector entries are always global variables with | 
 | 271 |           // names starting like this. | 
 | 272 |           if (GV->getName().startswith("OBJC_EHTYPE")) | 
 | 273 |             return false; | 
| Bill Wendling | 40ccacc | 2011-09-19 22:08:36 +0000 | [diff] [blame] | 274 |       } else { | 
 | 275 |         // Check if any of the filter values have the ObjC prefix. | 
 | 276 |         llvm::Constant *CVal = cast<llvm::Constant>(Val); | 
 | 277 |         for (llvm::User::op_iterator | 
 | 278 |                II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) { | 
| Bill Wendling | eecb6a1 | 2011-09-20 00:40:19 +0000 | [diff] [blame] | 279 |           if (llvm::GlobalVariable *GV = | 
 | 280 |               cast<llvm::GlobalVariable>((*II)->stripPointerCasts())) | 
 | 281 |             // ObjC EH selector entries are always global variables with | 
 | 282 |             // names starting like this. | 
 | 283 |             if (GV->getName().startswith("OBJC_EHTYPE")) | 
 | 284 |               return false; | 
| Bill Wendling | 40ccacc | 2011-09-19 22:08:36 +0000 | [diff] [blame] | 285 |         } | 
 | 286 |       } | 
| John McCall | b259383 | 2010-09-16 06:16:50 +0000 | [diff] [blame] | 287 |     } | 
 | 288 |   } | 
 | 289 |  | 
 | 290 |   return true; | 
 | 291 | } | 
 | 292 |  | 
 | 293 | /// Try to use the C++ personality function in ObjC++.  Not doing this | 
 | 294 | /// can cause some incompatibilities with gcc, which is more | 
 | 295 | /// aggressive about only using the ObjC++ personality in a function | 
 | 296 | /// when it really needs it. | 
 | 297 | void CodeGenModule::SimplifyPersonality() { | 
 | 298 |   // For now, this is really a Darwin-specific operation. | 
| Douglas Gregor | bcfd1f5 | 2011-09-02 00:18:52 +0000 | [diff] [blame] | 299 |   if (!Context.getTargetInfo().getTriple().isOSDarwin()) | 
| John McCall | b259383 | 2010-09-16 06:16:50 +0000 | [diff] [blame] | 300 |     return; | 
 | 301 |  | 
 | 302 |   // If we're not in ObjC++ -fexceptions, there's nothing to do. | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 303 |   if (!LangOpts.CPlusPlus || !LangOpts.ObjC1 || !LangOpts.Exceptions) | 
| John McCall | b259383 | 2010-09-16 06:16:50 +0000 | [diff] [blame] | 304 |     return; | 
 | 305 |  | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 306 |   const EHPersonality &ObjCXX = EHPersonality::get(LangOpts); | 
 | 307 |   const EHPersonality &CXX = getCXXPersonality(LangOpts); | 
| Benjamin Kramer | af2771b | 2012-02-08 12:41:24 +0000 | [diff] [blame] | 308 |   if (&ObjCXX == &CXX) | 
| John McCall | b259383 | 2010-09-16 06:16:50 +0000 | [diff] [blame] | 309 |     return; | 
 | 310 |  | 
| Benjamin Kramer | af2771b | 2012-02-08 12:41:24 +0000 | [diff] [blame] | 311 |   assert(std::strcmp(ObjCXX.PersonalityFn, CXX.PersonalityFn) != 0 && | 
 | 312 |          "Different EHPersonalities using the same personality function."); | 
 | 313 |  | 
 | 314 |   llvm::Function *Fn = getModule().getFunction(ObjCXX.PersonalityFn); | 
| John McCall | b259383 | 2010-09-16 06:16:50 +0000 | [diff] [blame] | 315 |  | 
 | 316 |   // Nothing to do if it's unused. | 
 | 317 |   if (!Fn || Fn->use_empty()) return; | 
 | 318 |    | 
 | 319 |   // Can't do the optimization if it has non-C++ uses. | 
 | 320 |   if (!PersonalityHasOnlyCXXUses(Fn)) return; | 
 | 321 |  | 
 | 322 |   // Create the C++ personality function and kill off the old | 
 | 323 |   // function. | 
 | 324 |   llvm::Constant *CXXFn = getPersonalityFn(*this, CXX); | 
 | 325 |  | 
 | 326 |   // This can happen if the user is screwing with us. | 
 | 327 |   if (Fn->getType() != CXXFn->getType()) return; | 
 | 328 |  | 
 | 329 |   Fn->replaceAllUsesWith(CXXFn); | 
 | 330 |   Fn->eraseFromParent(); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 331 | } | 
 | 332 |  | 
 | 333 | /// Returns the value to inject into a selector to indicate the | 
 | 334 | /// presence of a catch-all. | 
 | 335 | static llvm::Constant *getCatchAllValue(CodeGenFunction &CGF) { | 
 | 336 |   // Possibly we should use @llvm.eh.catch.all.value here. | 
| John McCall | d16c2cf | 2011-02-08 08:22:06 +0000 | [diff] [blame] | 337 |   return llvm::ConstantPointerNull::get(CGF.Int8PtrTy); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 338 | } | 
 | 339 |  | 
| John McCall | 09faeab | 2010-07-13 21:17:51 +0000 | [diff] [blame] | 340 | namespace { | 
 | 341 |   /// A cleanup to free the exception object if its initialization | 
 | 342 |   /// throws. | 
| John McCall | c4a1a84 | 2011-07-12 00:15:30 +0000 | [diff] [blame] | 343 |   struct FreeException : EHScopeStack::Cleanup { | 
 | 344 |     llvm::Value *exn; | 
 | 345 |     FreeException(llvm::Value *exn) : exn(exn) {} | 
| John McCall | ad346f4 | 2011-07-12 20:27:29 +0000 | [diff] [blame] | 346 |     void Emit(CodeGenFunction &CGF, Flags flags) { | 
| John McCall | 3ad32c8 | 2011-01-28 08:37:24 +0000 | [diff] [blame] | 347 |       CGF.Builder.CreateCall(getFreeExceptionFn(CGF), exn) | 
| John McCall | 09faeab | 2010-07-13 21:17:51 +0000 | [diff] [blame] | 348 |         ->setDoesNotThrow(); | 
| John McCall | 09faeab | 2010-07-13 21:17:51 +0000 | [diff] [blame] | 349 |     } | 
 | 350 |   }; | 
 | 351 | } | 
 | 352 |  | 
| John McCall | ac41816 | 2010-04-22 01:10:34 +0000 | [diff] [blame] | 353 | // Emits an exception expression into the given location.  This | 
 | 354 | // differs from EmitAnyExprToMem only in that, if a final copy-ctor | 
 | 355 | // call is required, an exception within that copy ctor causes | 
 | 356 | // std::terminate to be invoked. | 
| John McCall | 3ad32c8 | 2011-01-28 08:37:24 +0000 | [diff] [blame] | 357 | static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *e, | 
 | 358 |                              llvm::Value *addr) { | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 359 |   // Make sure the exception object is cleaned up if there's an | 
 | 360 |   // exception during initialization. | 
| John McCall | 3ad32c8 | 2011-01-28 08:37:24 +0000 | [diff] [blame] | 361 |   CGF.pushFullExprCleanup<FreeException>(EHCleanup, addr); | 
 | 362 |   EHScopeStack::stable_iterator cleanup = CGF.EHStack.stable_begin(); | 
| John McCall | ac41816 | 2010-04-22 01:10:34 +0000 | [diff] [blame] | 363 |  | 
 | 364 |   // __cxa_allocate_exception returns a void*;  we need to cast this | 
 | 365 |   // to the appropriate type for the object. | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 366 |   llvm::Type *ty = CGF.ConvertTypeForMem(e->getType())->getPointerTo(); | 
| John McCall | 3ad32c8 | 2011-01-28 08:37:24 +0000 | [diff] [blame] | 367 |   llvm::Value *typedAddr = CGF.Builder.CreateBitCast(addr, ty); | 
| John McCall | ac41816 | 2010-04-22 01:10:34 +0000 | [diff] [blame] | 368 |  | 
 | 369 |   // FIXME: this isn't quite right!  If there's a final unelided call | 
 | 370 |   // to a copy constructor, then according to [except.terminate]p1 we | 
 | 371 |   // must call std::terminate() if that constructor throws, because | 
 | 372 |   // technically that copy occurs after the exception expression is | 
 | 373 |   // evaluated but before the exception is caught.  But the best way | 
 | 374 |   // to handle that is to teach EmitAggExpr to do the final copy | 
 | 375 |   // differently if it can't be elided. | 
| John McCall | f85e193 | 2011-06-15 23:02:42 +0000 | [diff] [blame] | 376 |   CGF.EmitAnyExprToMem(e, typedAddr, e->getType().getQualifiers(),  | 
 | 377 |                        /*IsInit*/ true); | 
| John McCall | ac41816 | 2010-04-22 01:10:34 +0000 | [diff] [blame] | 378 |  | 
| John McCall | 3ad32c8 | 2011-01-28 08:37:24 +0000 | [diff] [blame] | 379 |   // Deactivate the cleanup block. | 
| John McCall | 6f103ba | 2011-11-10 10:43:54 +0000 | [diff] [blame] | 380 |   CGF.DeactivateCleanupBlock(cleanup, cast<llvm::Instruction>(typedAddr)); | 
| Mike Stump | 0f590be | 2009-12-01 03:41:18 +0000 | [diff] [blame] | 381 | } | 
 | 382 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 383 | llvm::Value *CodeGenFunction::getExceptionSlot() { | 
| John McCall | 93c332a | 2011-05-28 21:13:02 +0000 | [diff] [blame] | 384 |   if (!ExceptionSlot) | 
 | 385 |     ExceptionSlot = CreateTempAlloca(Int8PtrTy, "exn.slot"); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 386 |   return ExceptionSlot; | 
| Mike Stump | 0f590be | 2009-12-01 03:41:18 +0000 | [diff] [blame] | 387 | } | 
 | 388 |  | 
| John McCall | 93c332a | 2011-05-28 21:13:02 +0000 | [diff] [blame] | 389 | llvm::Value *CodeGenFunction::getEHSelectorSlot() { | 
 | 390 |   if (!EHSelectorSlot) | 
 | 391 |     EHSelectorSlot = CreateTempAlloca(Int32Ty, "ehselector.slot"); | 
 | 392 |   return EHSelectorSlot; | 
 | 393 | } | 
 | 394 |  | 
| Bill Wendling | ae27059 | 2011-09-15 18:57:19 +0000 | [diff] [blame] | 395 | llvm::Value *CodeGenFunction::getExceptionFromSlot() { | 
 | 396 |   return Builder.CreateLoad(getExceptionSlot(), "exn"); | 
 | 397 | } | 
 | 398 |  | 
 | 399 | llvm::Value *CodeGenFunction::getSelectorFromSlot() { | 
 | 400 |   return Builder.CreateLoad(getEHSelectorSlot(), "sel"); | 
 | 401 | } | 
 | 402 |  | 
| Anders Carlsson | 756b5c4 | 2009-10-30 01:42:31 +0000 | [diff] [blame] | 403 | void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { | 
| Anders Carlsson | d337929 | 2009-10-30 02:27:02 +0000 | [diff] [blame] | 404 |   if (!E->getSubExpr()) { | 
| Douglas Gregor | 1eb2e59 | 2010-05-16 00:44:00 +0000 | [diff] [blame] | 405 |     if (getInvokeDest()) { | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 406 |       Builder.CreateInvoke(getReThrowFn(*this), | 
 | 407 |                            getUnreachableBlock(), | 
 | 408 |                            getInvokeDest()) | 
| Douglas Gregor | 1eb2e59 | 2010-05-16 00:44:00 +0000 | [diff] [blame] | 409 |         ->setDoesNotReturn(); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 410 |     } else { | 
| Douglas Gregor | 1eb2e59 | 2010-05-16 00:44:00 +0000 | [diff] [blame] | 411 |       Builder.CreateCall(getReThrowFn(*this))->setDoesNotReturn(); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 412 |       Builder.CreateUnreachable(); | 
 | 413 |     } | 
| Douglas Gregor | 1eb2e59 | 2010-05-16 00:44:00 +0000 | [diff] [blame] | 414 |  | 
| John McCall | cd5b22e | 2011-01-12 03:41:02 +0000 | [diff] [blame] | 415 |     // throw is an expression, and the expression emitters expect us | 
 | 416 |     // to leave ourselves at a valid insertion point. | 
 | 417 |     EmitBlock(createBasicBlock("throw.cont")); | 
 | 418 |  | 
| Anders Carlsson | d337929 | 2009-10-30 02:27:02 +0000 | [diff] [blame] | 419 |     return; | 
 | 420 |   } | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 421 |  | 
| Anders Carlsson | d337929 | 2009-10-30 02:27:02 +0000 | [diff] [blame] | 422 |   QualType ThrowType = E->getSubExpr()->getType(); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 423 |  | 
| Anders Carlsson | d337929 | 2009-10-30 02:27:02 +0000 | [diff] [blame] | 424 |   // Now allocate the exception object. | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 425 |   llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); | 
| John McCall | 3d3ec1c | 2010-04-21 10:05:39 +0000 | [diff] [blame] | 426 |   uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity(); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 427 |  | 
| Anders Carlsson | d337929 | 2009-10-30 02:27:02 +0000 | [diff] [blame] | 428 |   llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(*this); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 429 |   llvm::CallInst *ExceptionPtr = | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 430 |     Builder.CreateCall(AllocExceptionFn, | 
| Anders Carlsson | d337929 | 2009-10-30 02:27:02 +0000 | [diff] [blame] | 431 |                        llvm::ConstantInt::get(SizeTy, TypeSize), | 
 | 432 |                        "exception"); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 433 |   ExceptionPtr->setDoesNotThrow(); | 
| Anders Carlsson | 8370c58 | 2009-12-11 00:32:37 +0000 | [diff] [blame] | 434 |    | 
| John McCall | ac41816 | 2010-04-22 01:10:34 +0000 | [diff] [blame] | 435 |   EmitAnyExprToExn(*this, E->getSubExpr(), ExceptionPtr); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 436 |  | 
| Anders Carlsson | d337929 | 2009-10-30 02:27:02 +0000 | [diff] [blame] | 437 |   // Now throw the exception. | 
| Anders Carlsson | 82a113a | 2011-01-24 01:59:49 +0000 | [diff] [blame] | 438 |   llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,  | 
 | 439 |                                                          /*ForEH=*/true); | 
| John McCall | ac41816 | 2010-04-22 01:10:34 +0000 | [diff] [blame] | 440 |  | 
 | 441 |   // The address of the destructor.  If the exception type has a | 
 | 442 |   // trivial destructor (or isn't a record), we just pass null. | 
 | 443 |   llvm::Constant *Dtor = 0; | 
 | 444 |   if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) { | 
 | 445 |     CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); | 
 | 446 |     if (!Record->hasTrivialDestructor()) { | 
| Douglas Gregor | 1d110e0 | 2010-07-01 14:13:13 +0000 | [diff] [blame] | 447 |       CXXDestructorDecl *DtorD = Record->getDestructor(); | 
| John McCall | ac41816 | 2010-04-22 01:10:34 +0000 | [diff] [blame] | 448 |       Dtor = CGM.GetAddrOfCXXDestructor(DtorD, Dtor_Complete); | 
 | 449 |       Dtor = llvm::ConstantExpr::getBitCast(Dtor, Int8PtrTy); | 
 | 450 |     } | 
 | 451 |   } | 
 | 452 |   if (!Dtor) Dtor = llvm::Constant::getNullValue(Int8PtrTy); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 453 |  | 
| Mike Stump | 0a3816e | 2009-12-04 01:51:45 +0000 | [diff] [blame] | 454 |   if (getInvokeDest()) { | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 455 |     llvm::InvokeInst *ThrowCall = | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 456 |       Builder.CreateInvoke3(getThrowFn(*this), | 
 | 457 |                             getUnreachableBlock(), getInvokeDest(), | 
| Mike Stump | 0a3816e | 2009-12-04 01:51:45 +0000 | [diff] [blame] | 458 |                             ExceptionPtr, TypeInfo, Dtor); | 
 | 459 |     ThrowCall->setDoesNotReturn(); | 
| Mike Stump | 0a3816e | 2009-12-04 01:51:45 +0000 | [diff] [blame] | 460 |   } else { | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 461 |     llvm::CallInst *ThrowCall = | 
| Mike Stump | 0a3816e | 2009-12-04 01:51:45 +0000 | [diff] [blame] | 462 |       Builder.CreateCall3(getThrowFn(*this), ExceptionPtr, TypeInfo, Dtor); | 
 | 463 |     ThrowCall->setDoesNotReturn(); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 464 |     Builder.CreateUnreachable(); | 
| Mike Stump | 0a3816e | 2009-12-04 01:51:45 +0000 | [diff] [blame] | 465 |   } | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 466 |  | 
| John McCall | cd5b22e | 2011-01-12 03:41:02 +0000 | [diff] [blame] | 467 |   // throw is an expression, and the expression emitters expect us | 
 | 468 |   // to leave ourselves at a valid insertion point. | 
 | 469 |   EmitBlock(createBasicBlock("throw.cont")); | 
| Anders Carlsson | 756b5c4 | 2009-10-30 01:42:31 +0000 | [diff] [blame] | 470 | } | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 471 |  | 
| Mike Stump | cce3d4f | 2009-12-07 23:38:24 +0000 | [diff] [blame] | 472 | void CodeGenFunction::EmitStartEHSpec(const Decl *D) { | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 473 |   if (!CGM.getLangOpts().CXXExceptions) | 
| Anders Carlsson | a994ee4 | 2010-02-06 23:59:05 +0000 | [diff] [blame] | 474 |     return; | 
 | 475 |    | 
| Mike Stump | cce3d4f | 2009-12-07 23:38:24 +0000 | [diff] [blame] | 476 |   const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); | 
 | 477 |   if (FD == 0) | 
 | 478 |     return; | 
 | 479 |   const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); | 
 | 480 |   if (Proto == 0) | 
 | 481 |     return; | 
 | 482 |  | 
| Sebastian Redl | a968e97 | 2011-03-15 18:42:48 +0000 | [diff] [blame] | 483 |   ExceptionSpecificationType EST = Proto->getExceptionSpecType(); | 
 | 484 |   if (isNoexceptExceptionSpec(EST)) { | 
 | 485 |     if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) { | 
 | 486 |       // noexcept functions are simple terminate scopes. | 
 | 487 |       EHStack.pushTerminate(); | 
 | 488 |     } | 
 | 489 |   } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { | 
 | 490 |     unsigned NumExceptions = Proto->getNumExceptions(); | 
 | 491 |     EHFilterScope *Filter = EHStack.pushFilter(NumExceptions); | 
| Mike Stump | cce3d4f | 2009-12-07 23:38:24 +0000 | [diff] [blame] | 492 |  | 
| Sebastian Redl | a968e97 | 2011-03-15 18:42:48 +0000 | [diff] [blame] | 493 |     for (unsigned I = 0; I != NumExceptions; ++I) { | 
 | 494 |       QualType Ty = Proto->getExceptionType(I); | 
 | 495 |       QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType(); | 
 | 496 |       llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType, | 
 | 497 |                                                         /*ForEH=*/true); | 
 | 498 |       Filter->setFilter(I, EHType); | 
 | 499 |     } | 
| Mike Stump | cce3d4f | 2009-12-07 23:38:24 +0000 | [diff] [blame] | 500 |   } | 
| Mike Stump | cce3d4f | 2009-12-07 23:38:24 +0000 | [diff] [blame] | 501 | } | 
 | 502 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 503 | /// Emit the dispatch block for a filter scope if necessary. | 
 | 504 | static void emitFilterDispatchBlock(CodeGenFunction &CGF, | 
 | 505 |                                     EHFilterScope &filterScope) { | 
 | 506 |   llvm::BasicBlock *dispatchBlock = filterScope.getCachedEHDispatchBlock(); | 
 | 507 |   if (!dispatchBlock) return; | 
 | 508 |   if (dispatchBlock->use_empty()) { | 
 | 509 |     delete dispatchBlock; | 
 | 510 |     return; | 
 | 511 |   } | 
 | 512 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 513 |   CGF.EmitBlockAfterUses(dispatchBlock); | 
 | 514 |  | 
 | 515 |   // If this isn't a catch-all filter, we need to check whether we got | 
 | 516 |   // here because the filter triggered. | 
 | 517 |   if (filterScope.getNumFilters()) { | 
 | 518 |     // Load the selector value. | 
| Bill Wendling | ae27059 | 2011-09-15 18:57:19 +0000 | [diff] [blame] | 519 |     llvm::Value *selector = CGF.getSelectorFromSlot(); | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 520 |     llvm::BasicBlock *unexpectedBB = CGF.createBasicBlock("ehspec.unexpected"); | 
 | 521 |  | 
 | 522 |     llvm::Value *zero = CGF.Builder.getInt32(0); | 
 | 523 |     llvm::Value *failsFilter = | 
 | 524 |       CGF.Builder.CreateICmpSLT(selector, zero, "ehspec.fails"); | 
 | 525 |     CGF.Builder.CreateCondBr(failsFilter, unexpectedBB, CGF.getEHResumeBlock()); | 
 | 526 |  | 
 | 527 |     CGF.EmitBlock(unexpectedBB); | 
 | 528 |   } | 
 | 529 |  | 
 | 530 |   // Call __cxa_call_unexpected.  This doesn't need to be an invoke | 
 | 531 |   // because __cxa_call_unexpected magically filters exceptions | 
 | 532 |   // according to the last landing pad the exception was thrown | 
 | 533 |   // into.  Seriously. | 
| Bill Wendling | ae27059 | 2011-09-15 18:57:19 +0000 | [diff] [blame] | 534 |   llvm::Value *exn = CGF.getExceptionFromSlot(); | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 535 |   CGF.Builder.CreateCall(getUnexpectedFn(CGF), exn) | 
 | 536 |     ->setDoesNotReturn(); | 
 | 537 |   CGF.Builder.CreateUnreachable(); | 
 | 538 | } | 
 | 539 |  | 
| Mike Stump | cce3d4f | 2009-12-07 23:38:24 +0000 | [diff] [blame] | 540 | void CodeGenFunction::EmitEndEHSpec(const Decl *D) { | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 541 |   if (!CGM.getLangOpts().CXXExceptions) | 
| Anders Carlsson | a994ee4 | 2010-02-06 23:59:05 +0000 | [diff] [blame] | 542 |     return; | 
 | 543 |    | 
| Mike Stump | cce3d4f | 2009-12-07 23:38:24 +0000 | [diff] [blame] | 544 |   const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); | 
 | 545 |   if (FD == 0) | 
 | 546 |     return; | 
 | 547 |   const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); | 
 | 548 |   if (Proto == 0) | 
 | 549 |     return; | 
 | 550 |  | 
| Sebastian Redl | a968e97 | 2011-03-15 18:42:48 +0000 | [diff] [blame] | 551 |   ExceptionSpecificationType EST = Proto->getExceptionSpecType(); | 
 | 552 |   if (isNoexceptExceptionSpec(EST)) { | 
 | 553 |     if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) { | 
 | 554 |       EHStack.popTerminate(); | 
 | 555 |     } | 
 | 556 |   } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 557 |     EHFilterScope &filterScope = cast<EHFilterScope>(*EHStack.begin()); | 
 | 558 |     emitFilterDispatchBlock(*this, filterScope); | 
| Sebastian Redl | a968e97 | 2011-03-15 18:42:48 +0000 | [diff] [blame] | 559 |     EHStack.popFilter(); | 
 | 560 |   } | 
| Mike Stump | cce3d4f | 2009-12-07 23:38:24 +0000 | [diff] [blame] | 561 | } | 
 | 562 |  | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 563 | void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { | 
| John McCall | 59a7000 | 2010-07-07 06:56:46 +0000 | [diff] [blame] | 564 |   EnterCXXTryStmt(S); | 
| John McCall | 9fc6a77 | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 565 |   EmitStmt(S.getTryBlock()); | 
| John McCall | 59a7000 | 2010-07-07 06:56:46 +0000 | [diff] [blame] | 566 |   ExitCXXTryStmt(S); | 
| John McCall | 9fc6a77 | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 567 | } | 
 | 568 |  | 
| John McCall | 59a7000 | 2010-07-07 06:56:46 +0000 | [diff] [blame] | 569 | void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 570 |   unsigned NumHandlers = S.getNumHandlers(); | 
 | 571 |   EHCatchScope *CatchScope = EHStack.pushCatch(NumHandlers); | 
| John McCall | 9fc6a77 | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 572 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 573 |   for (unsigned I = 0; I != NumHandlers; ++I) { | 
 | 574 |     const CXXCatchStmt *C = S.getHandler(I); | 
| John McCall | 9fc6a77 | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 575 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 576 |     llvm::BasicBlock *Handler = createBasicBlock("catch"); | 
 | 577 |     if (C->getExceptionDecl()) { | 
 | 578 |       // FIXME: Dropping the reference type on the type into makes it | 
 | 579 |       // impossible to correctly implement catch-by-reference | 
 | 580 |       // semantics for pointers.  Unfortunately, this is what all | 
 | 581 |       // existing compilers do, and it's not clear that the standard | 
 | 582 |       // personality routine is capable of doing this right.  See C++ DR 388: | 
 | 583 |       //   http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388 | 
 | 584 |       QualType CaughtType = C->getCaughtType(); | 
 | 585 |       CaughtType = CaughtType.getNonReferenceType().getUnqualifiedType(); | 
| John McCall | 5a18039 | 2010-07-24 00:37:23 +0000 | [diff] [blame] | 586 |  | 
 | 587 |       llvm::Value *TypeInfo = 0; | 
 | 588 |       if (CaughtType->isObjCObjectPointerType()) | 
| Fariborz Jahanian | cf5abc7 | 2011-06-23 19:00:08 +0000 | [diff] [blame] | 589 |         TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType); | 
| John McCall | 5a18039 | 2010-07-24 00:37:23 +0000 | [diff] [blame] | 590 |       else | 
| Anders Carlsson | 82a113a | 2011-01-24 01:59:49 +0000 | [diff] [blame] | 591 |         TypeInfo = CGM.GetAddrOfRTTIDescriptor(CaughtType, /*ForEH=*/true); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 592 |       CatchScope->setHandler(I, TypeInfo, Handler); | 
 | 593 |     } else { | 
 | 594 |       // No exception decl indicates '...', a catch-all. | 
 | 595 |       CatchScope->setCatchAllHandler(I, Handler); | 
 | 596 |     } | 
 | 597 |   } | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 598 | } | 
 | 599 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 600 | llvm::BasicBlock * | 
 | 601 | CodeGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) { | 
 | 602 |   // The dispatch block for the end of the scope chain is a block that | 
 | 603 |   // just resumes unwinding. | 
 | 604 |   if (si == EHStack.stable_end()) | 
 | 605 |     return getEHResumeBlock(); | 
 | 606 |  | 
 | 607 |   // Otherwise, we should look at the actual scope. | 
 | 608 |   EHScope &scope = *EHStack.find(si); | 
 | 609 |  | 
 | 610 |   llvm::BasicBlock *dispatchBlock = scope.getCachedEHDispatchBlock(); | 
 | 611 |   if (!dispatchBlock) { | 
 | 612 |     switch (scope.getKind()) { | 
 | 613 |     case EHScope::Catch: { | 
 | 614 |       // Apply a special case to a single catch-all. | 
 | 615 |       EHCatchScope &catchScope = cast<EHCatchScope>(scope); | 
 | 616 |       if (catchScope.getNumHandlers() == 1 && | 
 | 617 |           catchScope.getHandler(0).isCatchAll()) { | 
 | 618 |         dispatchBlock = catchScope.getHandler(0).Block; | 
 | 619 |  | 
 | 620 |       // Otherwise, make a dispatch block. | 
 | 621 |       } else { | 
 | 622 |         dispatchBlock = createBasicBlock("catch.dispatch"); | 
 | 623 |       } | 
 | 624 |       break; | 
 | 625 |     } | 
 | 626 |  | 
 | 627 |     case EHScope::Cleanup: | 
 | 628 |       dispatchBlock = createBasicBlock("ehcleanup"); | 
 | 629 |       break; | 
 | 630 |  | 
 | 631 |     case EHScope::Filter: | 
 | 632 |       dispatchBlock = createBasicBlock("filter.dispatch"); | 
 | 633 |       break; | 
 | 634 |  | 
 | 635 |     case EHScope::Terminate: | 
 | 636 |       dispatchBlock = getTerminateHandler(); | 
 | 637 |       break; | 
 | 638 |     } | 
 | 639 |     scope.setCachedEHDispatchBlock(dispatchBlock); | 
 | 640 |   } | 
 | 641 |   return dispatchBlock; | 
 | 642 | } | 
 | 643 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 644 | /// Check whether this is a non-EH scope, i.e. a scope which doesn't | 
 | 645 | /// affect exception handling.  Currently, the only non-EH scopes are | 
 | 646 | /// normal-only cleanup scopes. | 
 | 647 | static bool isNonEHScope(const EHScope &S) { | 
| John McCall | da65ea8 | 2010-07-13 20:32:21 +0000 | [diff] [blame] | 648 |   switch (S.getKind()) { | 
| John McCall | 1f0fca5 | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 649 |   case EHScope::Cleanup: | 
 | 650 |     return !cast<EHCleanupScope>(S).isEHCleanup(); | 
| John McCall | da65ea8 | 2010-07-13 20:32:21 +0000 | [diff] [blame] | 651 |   case EHScope::Filter: | 
 | 652 |   case EHScope::Catch: | 
 | 653 |   case EHScope::Terminate: | 
 | 654 |     return false; | 
 | 655 |   } | 
 | 656 |  | 
| David Blaikie | 3026348 | 2012-01-20 21:50:17 +0000 | [diff] [blame] | 657 |   llvm_unreachable("Invalid EHScope Kind!"); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 658 | } | 
 | 659 |  | 
 | 660 | llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() { | 
 | 661 |   assert(EHStack.requiresLandingPad()); | 
 | 662 |   assert(!EHStack.empty()); | 
 | 663 |  | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 664 |   if (!CGM.getLangOpts().Exceptions) | 
| John McCall | da65ea8 | 2010-07-13 20:32:21 +0000 | [diff] [blame] | 665 |     return 0; | 
 | 666 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 667 |   // Check the innermost scope for a cached landing pad.  If this is | 
 | 668 |   // a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad. | 
 | 669 |   llvm::BasicBlock *LP = EHStack.begin()->getCachedLandingPad(); | 
 | 670 |   if (LP) return LP; | 
 | 671 |  | 
 | 672 |   // Build the landing pad for this scope. | 
 | 673 |   LP = EmitLandingPad(); | 
 | 674 |   assert(LP); | 
 | 675 |  | 
 | 676 |   // Cache the landing pad on the innermost scope.  If this is a | 
 | 677 |   // non-EH scope, cache the landing pad on the enclosing scope, too. | 
 | 678 |   for (EHScopeStack::iterator ir = EHStack.begin(); true; ++ir) { | 
 | 679 |     ir->setCachedLandingPad(LP); | 
 | 680 |     if (!isNonEHScope(*ir)) break; | 
 | 681 |   } | 
 | 682 |  | 
 | 683 |   return LP; | 
 | 684 | } | 
 | 685 |  | 
| John McCall | 93c332a | 2011-05-28 21:13:02 +0000 | [diff] [blame] | 686 | // This code contains a hack to work around a design flaw in | 
 | 687 | // LLVM's EH IR which breaks semantics after inlining.  This same | 
 | 688 | // hack is implemented in llvm-gcc. | 
 | 689 | // | 
 | 690 | // The LLVM EH abstraction is basically a thin veneer over the | 
 | 691 | // traditional GCC zero-cost design: for each range of instructions | 
 | 692 | // in the function, there is (at most) one "landing pad" with an | 
 | 693 | // associated chain of EH actions.  A language-specific personality | 
 | 694 | // function interprets this chain of actions and (1) decides whether | 
 | 695 | // or not to resume execution at the landing pad and (2) if so, | 
 | 696 | // provides an integer indicating why it's stopping.  In LLVM IR, | 
 | 697 | // the association of a landing pad with a range of instructions is | 
 | 698 | // achieved via an invoke instruction, the chain of actions becomes | 
 | 699 | // the arguments to the @llvm.eh.selector call, and the selector | 
 | 700 | // call returns the integer indicator.  Other than the required | 
 | 701 | // presence of two intrinsic function calls in the landing pad, | 
 | 702 | // the IR exactly describes the layout of the output code. | 
 | 703 | // | 
 | 704 | // A principal advantage of this design is that it is completely | 
 | 705 | // language-agnostic; in theory, the LLVM optimizers can treat | 
 | 706 | // landing pads neutrally, and targets need only know how to lower | 
 | 707 | // the intrinsics to have a functioning exceptions system (assuming | 
 | 708 | // that platform exceptions follow something approximately like the | 
 | 709 | // GCC design).  Unfortunately, landing pads cannot be combined in a | 
 | 710 | // language-agnostic way: given selectors A and B, there is no way | 
 | 711 | // to make a single landing pad which faithfully represents the | 
 | 712 | // semantics of propagating an exception first through A, then | 
 | 713 | // through B, without knowing how the personality will interpret the | 
 | 714 | // (lowered form of the) selectors.  This means that inlining has no | 
 | 715 | // choice but to crudely chain invokes (i.e., to ignore invokes in | 
 | 716 | // the inlined function, but to turn all unwindable calls into | 
 | 717 | // invokes), which is only semantically valid if every unwind stops | 
 | 718 | // at every landing pad. | 
 | 719 | // | 
 | 720 | // Therefore, the invoke-inline hack is to guarantee that every | 
 | 721 | // landing pad has a catch-all. | 
 | 722 | enum CleanupHackLevel_t { | 
 | 723 |   /// A level of hack that requires that all landing pads have | 
 | 724 |   /// catch-alls. | 
 | 725 |   CHL_MandatoryCatchall, | 
 | 726 |  | 
 | 727 |   /// A level of hack that requires that all landing pads handle | 
 | 728 |   /// cleanups. | 
 | 729 |   CHL_MandatoryCleanup, | 
 | 730 |  | 
 | 731 |   /// No hacks at all;  ideal IR generation. | 
 | 732 |   CHL_Ideal | 
 | 733 | }; | 
 | 734 | const CleanupHackLevel_t CleanupHackLevel = CHL_MandatoryCleanup; | 
 | 735 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 736 | llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { | 
 | 737 |   assert(EHStack.requiresLandingPad()); | 
 | 738 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 739 |   EHScope &innermostEHScope = *EHStack.find(EHStack.getInnermostEHScope()); | 
 | 740 |   switch (innermostEHScope.getKind()) { | 
 | 741 |   case EHScope::Terminate: | 
 | 742 |     return getTerminateLandingPad(); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 743 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 744 |   case EHScope::Catch: | 
 | 745 |   case EHScope::Cleanup: | 
 | 746 |   case EHScope::Filter: | 
 | 747 |     if (llvm::BasicBlock *lpad = innermostEHScope.getCachedLandingPad()) | 
 | 748 |       return lpad; | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 749 |   } | 
 | 750 |  | 
 | 751 |   // Save the current IR generation state. | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 752 |   CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP(); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 753 |  | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 754 |   const EHPersonality &personality = EHPersonality::get(getLangOpts()); | 
| John McCall | 8262b6a | 2010-07-17 00:43:08 +0000 | [diff] [blame] | 755 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 756 |   // Create and configure the landing pad. | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 757 |   llvm::BasicBlock *lpad = createBasicBlock("lpad"); | 
 | 758 |   EmitBlock(lpad); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 759 |  | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 760 |   llvm::LandingPadInst *LPadInst = | 
 | 761 |     Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty, NULL), | 
 | 762 |                              getOpaquePersonalityFn(CGM, personality), 0); | 
 | 763 |  | 
 | 764 |   llvm::Value *LPadExn = Builder.CreateExtractValue(LPadInst, 0); | 
 | 765 |   Builder.CreateStore(LPadExn, getExceptionSlot()); | 
 | 766 |   llvm::Value *LPadSel = Builder.CreateExtractValue(LPadInst, 1); | 
 | 767 |   Builder.CreateStore(LPadSel, getEHSelectorSlot()); | 
 | 768 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 769 |   // Save the exception pointer.  It's safe to use a single exception | 
 | 770 |   // pointer per function because EH cleanups can never have nested | 
 | 771 |   // try/catches. | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 772 |   // Build the landingpad instruction. | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 773 |  | 
 | 774 |   // Accumulate all the handlers in scope. | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 775 |   bool hasCatchAll = false; | 
 | 776 |   bool hasCleanup = false; | 
 | 777 |   bool hasFilter = false; | 
 | 778 |   SmallVector<llvm::Value*, 4> filterTypes; | 
 | 779 |   llvm::SmallPtrSet<llvm::Value*, 4> catchTypes; | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 780 |   for (EHScopeStack::iterator I = EHStack.begin(), E = EHStack.end(); | 
 | 781 |          I != E; ++I) { | 
 | 782 |  | 
 | 783 |     switch (I->getKind()) { | 
| John McCall | 1f0fca5 | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 784 |     case EHScope::Cleanup: | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 785 |       // If we have a cleanup, remember that. | 
 | 786 |       hasCleanup = (hasCleanup || cast<EHCleanupScope>(*I).isEHCleanup()); | 
| John McCall | da65ea8 | 2010-07-13 20:32:21 +0000 | [diff] [blame] | 787 |       continue; | 
 | 788 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 789 |     case EHScope::Filter: { | 
 | 790 |       assert(I.next() == EHStack.end() && "EH filter is not end of EH stack"); | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 791 |       assert(!hasCatchAll && "EH filter reached after catch-all"); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 792 |  | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 793 |       // Filter scopes get added to the landingpad in weird ways. | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 794 |       EHFilterScope &filter = cast<EHFilterScope>(*I); | 
 | 795 |       hasFilter = true; | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 796 |  | 
| Bill Wendling | 8990daf | 2011-09-22 20:32:54 +0000 | [diff] [blame] | 797 |       // Add all the filter values. | 
 | 798 |       for (unsigned i = 0, e = filter.getNumFilters(); i != e; ++i) | 
 | 799 |         filterTypes.push_back(filter.getFilter(i)); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 800 |       goto done; | 
 | 801 |     } | 
 | 802 |  | 
 | 803 |     case EHScope::Terminate: | 
 | 804 |       // Terminate scopes are basically catch-alls. | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 805 |       assert(!hasCatchAll); | 
 | 806 |       hasCatchAll = true; | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 807 |       goto done; | 
 | 808 |  | 
 | 809 |     case EHScope::Catch: | 
 | 810 |       break; | 
 | 811 |     } | 
 | 812 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 813 |     EHCatchScope &catchScope = cast<EHCatchScope>(*I); | 
 | 814 |     for (unsigned hi = 0, he = catchScope.getNumHandlers(); hi != he; ++hi) { | 
 | 815 |       EHCatchScope::Handler handler = catchScope.getHandler(hi); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 816 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 817 |       // If this is a catch-all, register that and abort. | 
 | 818 |       if (!handler.Type) { | 
 | 819 |         assert(!hasCatchAll); | 
 | 820 |         hasCatchAll = true; | 
 | 821 |         goto done; | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 822 |       } | 
 | 823 |  | 
 | 824 |       // Check whether we already have a handler for this type. | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 825 |       if (catchTypes.insert(handler.Type)) | 
 | 826 |         // If not, add it directly to the landingpad. | 
 | 827 |         LPadInst->addClause(handler.Type); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 828 |     } | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 829 |   } | 
 | 830 |  | 
 | 831 |  done: | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 832 |   // If we have a catch-all, add null to the landingpad. | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 833 |   assert(!(hasCatchAll && hasFilter)); | 
 | 834 |   if (hasCatchAll) { | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 835 |     LPadInst->addClause(getCatchAllValue(*this)); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 836 |  | 
 | 837 |   // If we have an EH filter, we need to add those handlers in the | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 838 |   // right place in the landingpad, which is to say, at the end. | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 839 |   } else if (hasFilter) { | 
| Bill Wendling | 40ccacc | 2011-09-19 22:08:36 +0000 | [diff] [blame] | 840 |     // Create a filter expression: a constant array indicating which filter | 
 | 841 |     // types there are. The personality routine only lands here if the filter | 
 | 842 |     // doesn't match. | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 843 |     llvm::SmallVector<llvm::Constant*, 8> Filters; | 
 | 844 |     llvm::ArrayType *AType = | 
 | 845 |       llvm::ArrayType::get(!filterTypes.empty() ? | 
 | 846 |                              filterTypes[0]->getType() : Int8PtrTy, | 
 | 847 |                            filterTypes.size()); | 
 | 848 |  | 
 | 849 |     for (unsigned i = 0, e = filterTypes.size(); i != e; ++i) | 
 | 850 |       Filters.push_back(cast<llvm::Constant>(filterTypes[i])); | 
 | 851 |     llvm::Constant *FilterArray = llvm::ConstantArray::get(AType, Filters); | 
 | 852 |     LPadInst->addClause(FilterArray); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 853 |  | 
 | 854 |     // Also check whether we need a cleanup. | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 855 |     if (hasCleanup) | 
 | 856 |       LPadInst->setCleanup(true); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 857 |  | 
 | 858 |   // Otherwise, signal that we at least have cleanups. | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 859 |   } else if (CleanupHackLevel == CHL_MandatoryCatchall || hasCleanup) { | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 860 |     if (CleanupHackLevel == CHL_MandatoryCatchall) | 
 | 861 |       LPadInst->addClause(getCatchAllValue(*this)); | 
 | 862 |     else | 
 | 863 |       LPadInst->setCleanup(true); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 864 |   } | 
 | 865 |  | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 866 |   assert((LPadInst->getNumClauses() > 0 || LPadInst->isCleanup()) && | 
 | 867 |          "landingpad instruction has no clauses!"); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 868 |  | 
 | 869 |   // Tell the backend how to generate the landing pad. | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 870 |   Builder.CreateBr(getEHDispatchBlock(EHStack.getInnermostEHScope())); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 871 |  | 
 | 872 |   // Restore the old IR generation state. | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 873 |   Builder.restoreIP(savedIP); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 874 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 875 |   return lpad; | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 876 | } | 
 | 877 |  | 
| John McCall | 8e3f861 | 2010-07-13 22:12:14 +0000 | [diff] [blame] | 878 | namespace { | 
 | 879 |   /// A cleanup to call __cxa_end_catch.  In many cases, the caught | 
 | 880 |   /// exception type lets us state definitively that the thrown exception | 
 | 881 |   /// type does not have a destructor.  In particular: | 
 | 882 |   ///   - Catch-alls tell us nothing, so we have to conservatively | 
 | 883 |   ///     assume that the thrown exception might have a destructor. | 
 | 884 |   ///   - Catches by reference behave according to their base types. | 
 | 885 |   ///   - Catches of non-record types will only trigger for exceptions | 
 | 886 |   ///     of non-record types, which never have destructors. | 
 | 887 |   ///   - Catches of record types can trigger for arbitrary subclasses | 
 | 888 |   ///     of the caught type, so we have to assume the actual thrown | 
 | 889 |   ///     exception type might have a throwing destructor, even if the | 
 | 890 |   ///     caught type's destructor is trivial or nothrow. | 
| John McCall | 1f0fca5 | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 891 |   struct CallEndCatch : EHScopeStack::Cleanup { | 
| John McCall | 8e3f861 | 2010-07-13 22:12:14 +0000 | [diff] [blame] | 892 |     CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {} | 
 | 893 |     bool MightThrow; | 
 | 894 |  | 
| John McCall | ad346f4 | 2011-07-12 20:27:29 +0000 | [diff] [blame] | 895 |     void Emit(CodeGenFunction &CGF, Flags flags) { | 
| John McCall | 8e3f861 | 2010-07-13 22:12:14 +0000 | [diff] [blame] | 896 |       if (!MightThrow) { | 
 | 897 |         CGF.Builder.CreateCall(getEndCatchFn(CGF))->setDoesNotThrow(); | 
 | 898 |         return; | 
 | 899 |       } | 
 | 900 |  | 
| Jay Foad | 4c7d9f1 | 2011-07-15 08:37:34 +0000 | [diff] [blame] | 901 |       CGF.EmitCallOrInvoke(getEndCatchFn(CGF)); | 
| John McCall | 8e3f861 | 2010-07-13 22:12:14 +0000 | [diff] [blame] | 902 |     } | 
 | 903 |   }; | 
 | 904 | } | 
 | 905 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 906 | /// Emits a call to __cxa_begin_catch and enters a cleanup to call | 
 | 907 | /// __cxa_end_catch. | 
| John McCall | 8e3f861 | 2010-07-13 22:12:14 +0000 | [diff] [blame] | 908 | /// | 
 | 909 | /// \param EndMightThrow - true if __cxa_end_catch might throw | 
 | 910 | static llvm::Value *CallBeginCatch(CodeGenFunction &CGF, | 
 | 911 |                                    llvm::Value *Exn, | 
 | 912 |                                    bool EndMightThrow) { | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 913 |   llvm::CallInst *Call = CGF.Builder.CreateCall(getBeginCatchFn(CGF), Exn); | 
 | 914 |   Call->setDoesNotThrow(); | 
 | 915 |  | 
| John McCall | 1f0fca5 | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 916 |   CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 917 |  | 
 | 918 |   return Call; | 
 | 919 | } | 
 | 920 |  | 
 | 921 | /// A "special initializer" callback for initializing a catch | 
 | 922 | /// parameter during catch initialization. | 
 | 923 | static void InitCatchParam(CodeGenFunction &CGF, | 
 | 924 |                            const VarDecl &CatchParam, | 
 | 925 |                            llvm::Value *ParamAddr) { | 
 | 926 |   // Load the exception from where the landing pad saved it. | 
| Bill Wendling | ae27059 | 2011-09-15 18:57:19 +0000 | [diff] [blame] | 927 |   llvm::Value *Exn = CGF.getExceptionFromSlot(); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 928 |  | 
 | 929 |   CanQualType CatchType = | 
 | 930 |     CGF.CGM.getContext().getCanonicalType(CatchParam.getType()); | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 931 |   llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 932 |  | 
 | 933 |   // If we're catching by reference, we can just cast the object | 
 | 934 |   // pointer to the appropriate pointer. | 
 | 935 |   if (isa<ReferenceType>(CatchType)) { | 
| John McCall | 204b075 | 2010-07-20 22:17:55 +0000 | [diff] [blame] | 936 |     QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType(); | 
 | 937 |     bool EndCatchMightThrow = CaughtType->isRecordType(); | 
| John McCall | 8e3f861 | 2010-07-13 22:12:14 +0000 | [diff] [blame] | 938 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 939 |     // __cxa_begin_catch returns the adjusted object pointer. | 
| John McCall | 8e3f861 | 2010-07-13 22:12:14 +0000 | [diff] [blame] | 940 |     llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow); | 
| John McCall | 204b075 | 2010-07-20 22:17:55 +0000 | [diff] [blame] | 941 |  | 
 | 942 |     // We have no way to tell the personality function that we're | 
 | 943 |     // catching by reference, so if we're catching a pointer, | 
 | 944 |     // __cxa_begin_catch will actually return that pointer by value. | 
 | 945 |     if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) { | 
 | 946 |       QualType PointeeType = PT->getPointeeType(); | 
 | 947 |  | 
 | 948 |       // When catching by reference, generally we should just ignore | 
 | 949 |       // this by-value pointer and use the exception object instead. | 
 | 950 |       if (!PointeeType->isRecordType()) { | 
 | 951 |  | 
 | 952 |         // Exn points to the struct _Unwind_Exception header, which | 
 | 953 |         // we have to skip past in order to reach the exception data. | 
 | 954 |         unsigned HeaderSize = | 
 | 955 |           CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException(); | 
 | 956 |         AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize); | 
 | 957 |  | 
 | 958 |       // However, if we're catching a pointer-to-record type that won't | 
 | 959 |       // work, because the personality function might have adjusted | 
 | 960 |       // the pointer.  There's actually no way for us to fully satisfy | 
 | 961 |       // the language/ABI contract here:  we can't use Exn because it | 
 | 962 |       // might have the wrong adjustment, but we can't use the by-value | 
 | 963 |       // pointer because it's off by a level of abstraction. | 
 | 964 |       // | 
 | 965 |       // The current solution is to dump the adjusted pointer into an | 
 | 966 |       // alloca, which breaks language semantics (because changing the | 
 | 967 |       // pointer doesn't change the exception) but at least works. | 
 | 968 |       // The better solution would be to filter out non-exact matches | 
 | 969 |       // and rethrow them, but this is tricky because the rethrow | 
 | 970 |       // really needs to be catchable by other sites at this landing | 
 | 971 |       // pad.  The best solution is to fix the personality function. | 
 | 972 |       } else { | 
 | 973 |         // Pull the pointer for the reference type off. | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 974 |         llvm::Type *PtrTy = | 
| John McCall | 204b075 | 2010-07-20 22:17:55 +0000 | [diff] [blame] | 975 |           cast<llvm::PointerType>(LLVMCatchTy)->getElementType(); | 
 | 976 |  | 
 | 977 |         // Create the temporary and write the adjusted pointer into it. | 
 | 978 |         llvm::Value *ExnPtrTmp = CGF.CreateTempAlloca(PtrTy, "exn.byref.tmp"); | 
 | 979 |         llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); | 
 | 980 |         CGF.Builder.CreateStore(Casted, ExnPtrTmp); | 
 | 981 |  | 
 | 982 |         // Bind the reference to the temporary. | 
 | 983 |         AdjustedExn = ExnPtrTmp; | 
 | 984 |       } | 
 | 985 |     } | 
 | 986 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 987 |     llvm::Value *ExnCast = | 
 | 988 |       CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref"); | 
 | 989 |     CGF.Builder.CreateStore(ExnCast, ParamAddr); | 
 | 990 |     return; | 
 | 991 |   } | 
 | 992 |  | 
 | 993 |   // Non-aggregates (plus complexes). | 
 | 994 |   bool IsComplex = false; | 
 | 995 |   if (!CGF.hasAggregateLLVMType(CatchType) || | 
 | 996 |       (IsComplex = CatchType->isAnyComplexType())) { | 
| John McCall | 8e3f861 | 2010-07-13 22:12:14 +0000 | [diff] [blame] | 997 |     llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 998 |      | 
 | 999 |     // If the catch type is a pointer type, __cxa_begin_catch returns | 
 | 1000 |     // the pointer by value. | 
 | 1001 |     if (CatchType->hasPointerRepresentation()) { | 
 | 1002 |       llvm::Value *CastExn = | 
 | 1003 |         CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted"); | 
| John McCall | b29b12d | 2012-01-17 20:16:56 +0000 | [diff] [blame] | 1004 |  | 
 | 1005 |       switch (CatchType.getQualifiers().getObjCLifetime()) { | 
 | 1006 |       case Qualifiers::OCL_Strong: | 
 | 1007 |         CastExn = CGF.EmitARCRetainNonBlock(CastExn); | 
 | 1008 |         // fallthrough | 
 | 1009 |  | 
 | 1010 |       case Qualifiers::OCL_None: | 
 | 1011 |       case Qualifiers::OCL_ExplicitNone: | 
 | 1012 |       case Qualifiers::OCL_Autoreleasing: | 
 | 1013 |         CGF.Builder.CreateStore(CastExn, ParamAddr); | 
 | 1014 |         return; | 
 | 1015 |  | 
 | 1016 |       case Qualifiers::OCL_Weak: | 
 | 1017 |         CGF.EmitARCInitWeak(ParamAddr, CastExn); | 
 | 1018 |         return; | 
 | 1019 |       } | 
 | 1020 |       llvm_unreachable("bad ownership qualifier!"); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1021 |     } | 
 | 1022 |  | 
 | 1023 |     // Otherwise, it returns a pointer into the exception object. | 
 | 1024 |  | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 1025 |     llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1026 |     llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); | 
 | 1027 |  | 
 | 1028 |     if (IsComplex) { | 
 | 1029 |       CGF.StoreComplexToAddr(CGF.LoadComplexFromAddr(Cast, /*volatile*/ false), | 
 | 1030 |                              ParamAddr, /*volatile*/ false); | 
 | 1031 |     } else { | 
| Daniel Dunbar | 91a16fa | 2010-08-21 02:24:36 +0000 | [diff] [blame] | 1032 |       unsigned Alignment = | 
 | 1033 |         CGF.getContext().getDeclAlign(&CatchParam).getQuantity(); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1034 |       llvm::Value *ExnLoad = CGF.Builder.CreateLoad(Cast, "exn.scalar"); | 
| Daniel Dunbar | 91a16fa | 2010-08-21 02:24:36 +0000 | [diff] [blame] | 1035 |       CGF.EmitStoreOfScalar(ExnLoad, ParamAddr, /*volatile*/ false, Alignment, | 
 | 1036 |                             CatchType); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1037 |     } | 
 | 1038 |     return; | 
 | 1039 |   } | 
 | 1040 |  | 
| John McCall | acff696 | 2011-02-16 08:39:19 +0000 | [diff] [blame] | 1041 |   assert(isa<RecordType>(CatchType) && "unexpected catch type!"); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1042 |  | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 1043 |   llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1044 |  | 
| John McCall | acff696 | 2011-02-16 08:39:19 +0000 | [diff] [blame] | 1045 |   // Check for a copy expression.  If we don't have a copy expression, | 
 | 1046 |   // that means a trivial copy is okay. | 
| John McCall | e996ffd | 2011-02-16 08:02:54 +0000 | [diff] [blame] | 1047 |   const Expr *copyExpr = CatchParam.getInit(); | 
 | 1048 |   if (!copyExpr) { | 
| John McCall | acff696 | 2011-02-16 08:39:19 +0000 | [diff] [blame] | 1049 |     llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true); | 
 | 1050 |     llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy); | 
 | 1051 |     CGF.EmitAggregateCopy(ParamAddr, adjustedExn, CatchType); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1052 |     return; | 
 | 1053 |   } | 
 | 1054 |  | 
 | 1055 |   // We have to call __cxa_get_exception_ptr to get the adjusted | 
 | 1056 |   // pointer before copying. | 
| John McCall | e996ffd | 2011-02-16 08:02:54 +0000 | [diff] [blame] | 1057 |   llvm::CallInst *rawAdjustedExn = | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1058 |     CGF.Builder.CreateCall(getGetExceptionPtrFn(CGF), Exn); | 
| John McCall | e996ffd | 2011-02-16 08:02:54 +0000 | [diff] [blame] | 1059 |   rawAdjustedExn->setDoesNotThrow(); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1060 |  | 
| John McCall | e996ffd | 2011-02-16 08:02:54 +0000 | [diff] [blame] | 1061 |   // Cast that to the appropriate type. | 
 | 1062 |   llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1063 |  | 
| John McCall | e996ffd | 2011-02-16 08:02:54 +0000 | [diff] [blame] | 1064 |   // The copy expression is defined in terms of an OpaqueValueExpr. | 
 | 1065 |   // Find it and map it to the adjusted expression. | 
 | 1066 |   CodeGenFunction::OpaqueValueMapping | 
| John McCall | 56ca35d | 2011-02-17 10:25:35 +0000 | [diff] [blame] | 1067 |     opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr), | 
 | 1068 |            CGF.MakeAddrLValue(adjustedExn, CatchParam.getType())); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1069 |  | 
 | 1070 |   // Call the copy ctor in a terminate scope. | 
 | 1071 |   CGF.EHStack.pushTerminate(); | 
| John McCall | e996ffd | 2011-02-16 08:02:54 +0000 | [diff] [blame] | 1072 |  | 
 | 1073 |   // Perform the copy construction. | 
| Eli Friedman | d7722d9 | 2011-12-03 02:13:40 +0000 | [diff] [blame] | 1074 |   CharUnits Alignment = CGF.getContext().getDeclAlign(&CatchParam); | 
| Eli Friedman | f394078 | 2011-12-03 00:54:26 +0000 | [diff] [blame] | 1075 |   CGF.EmitAggExpr(copyExpr, | 
 | 1076 |                   AggValueSlot::forAddr(ParamAddr, Alignment, Qualifiers(), | 
 | 1077 |                                         AggValueSlot::IsNotDestructed, | 
 | 1078 |                                         AggValueSlot::DoesNotNeedGCBarriers, | 
 | 1079 |                                         AggValueSlot::IsNotAliased)); | 
| John McCall | e996ffd | 2011-02-16 08:02:54 +0000 | [diff] [blame] | 1080 |  | 
 | 1081 |   // Leave the terminate scope. | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1082 |   CGF.EHStack.popTerminate(); | 
 | 1083 |  | 
| John McCall | e996ffd | 2011-02-16 08:02:54 +0000 | [diff] [blame] | 1084 |   // Undo the opaque value mapping. | 
 | 1085 |   opaque.pop(); | 
 | 1086 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1087 |   // Finally we can call __cxa_begin_catch. | 
| John McCall | 8e3f861 | 2010-07-13 22:12:14 +0000 | [diff] [blame] | 1088 |   CallBeginCatch(CGF, Exn, true); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1089 | } | 
 | 1090 |  | 
 | 1091 | /// Begins a catch statement by initializing the catch variable and | 
 | 1092 | /// calling __cxa_begin_catch. | 
| John McCall | e996ffd | 2011-02-16 08:02:54 +0000 | [diff] [blame] | 1093 | static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) { | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1094 |   // We have to be very careful with the ordering of cleanups here: | 
 | 1095 |   //   C++ [except.throw]p4: | 
 | 1096 |   //     The destruction [of the exception temporary] occurs | 
 | 1097 |   //     immediately after the destruction of the object declared in | 
 | 1098 |   //     the exception-declaration in the handler. | 
 | 1099 |   // | 
 | 1100 |   // So the precise ordering is: | 
 | 1101 |   //   1.  Construct catch variable. | 
 | 1102 |   //   2.  __cxa_begin_catch | 
 | 1103 |   //   3.  Enter __cxa_end_catch cleanup | 
 | 1104 |   //   4.  Enter dtor cleanup | 
 | 1105 |   // | 
| John McCall | 3469585 | 2011-02-22 06:44:22 +0000 | [diff] [blame] | 1106 |   // We do this by using a slightly abnormal initialization process. | 
 | 1107 |   // Delegation sequence: | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1108 |   //   - ExitCXXTryStmt opens a RunCleanupsScope | 
| John McCall | 3469585 | 2011-02-22 06:44:22 +0000 | [diff] [blame] | 1109 |   //     - EmitAutoVarAlloca creates the variable and debug info | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1110 |   //       - InitCatchParam initializes the variable from the exception | 
| John McCall | 3469585 | 2011-02-22 06:44:22 +0000 | [diff] [blame] | 1111 |   //       - CallBeginCatch calls __cxa_begin_catch | 
 | 1112 |   //       - CallBeginCatch enters the __cxa_end_catch cleanup | 
 | 1113 |   //     - EmitAutoVarCleanups enters the variable destructor cleanup | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1114 |   //   - EmitCXXTryStmt emits the code for the catch body | 
 | 1115 |   //   - EmitCXXTryStmt close the RunCleanupsScope | 
 | 1116 |  | 
 | 1117 |   VarDecl *CatchParam = S->getExceptionDecl(); | 
 | 1118 |   if (!CatchParam) { | 
| Bill Wendling | ae27059 | 2011-09-15 18:57:19 +0000 | [diff] [blame] | 1119 |     llvm::Value *Exn = CGF.getExceptionFromSlot(); | 
| John McCall | 8e3f861 | 2010-07-13 22:12:14 +0000 | [diff] [blame] | 1120 |     CallBeginCatch(CGF, Exn, true); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1121 |     return; | 
 | 1122 |   } | 
 | 1123 |  | 
 | 1124 |   // Emit the local. | 
| John McCall | 3469585 | 2011-02-22 06:44:22 +0000 | [diff] [blame] | 1125 |   CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); | 
 | 1126 |   InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF)); | 
 | 1127 |   CGF.EmitAutoVarCleanups(var); | 
| John McCall | 9fc6a77 | 2010-02-19 09:25:03 +0000 | [diff] [blame] | 1128 | } | 
 | 1129 |  | 
| John McCall | fcd5c0c | 2010-07-13 22:24:23 +0000 | [diff] [blame] | 1130 | namespace { | 
| John McCall | 1f0fca5 | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 1131 |   struct CallRethrow : EHScopeStack::Cleanup { | 
| John McCall | ad346f4 | 2011-07-12 20:27:29 +0000 | [diff] [blame] | 1132 |     void Emit(CodeGenFunction &CGF, Flags flags) { | 
| Jay Foad | 4c7d9f1 | 2011-07-15 08:37:34 +0000 | [diff] [blame] | 1133 |       CGF.EmitCallOrInvoke(getReThrowFn(CGF)); | 
| John McCall | fcd5c0c | 2010-07-13 22:24:23 +0000 | [diff] [blame] | 1134 |     } | 
 | 1135 |   }; | 
 | 1136 | } | 
 | 1137 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1138 | /// Emit the structure of the dispatch block for the given catch scope. | 
 | 1139 | /// It is an invariant that the dispatch block already exists. | 
 | 1140 | static void emitCatchDispatchBlock(CodeGenFunction &CGF, | 
 | 1141 |                                    EHCatchScope &catchScope) { | 
 | 1142 |   llvm::BasicBlock *dispatchBlock = catchScope.getCachedEHDispatchBlock(); | 
 | 1143 |   assert(dispatchBlock); | 
 | 1144 |  | 
 | 1145 |   // If there's only a single catch-all, getEHDispatchBlock returned | 
 | 1146 |   // that catch-all as the dispatch block. | 
 | 1147 |   if (catchScope.getNumHandlers() == 1 && | 
 | 1148 |       catchScope.getHandler(0).isCatchAll()) { | 
 | 1149 |     assert(dispatchBlock == catchScope.getHandler(0).Block); | 
 | 1150 |     return; | 
 | 1151 |   } | 
 | 1152 |  | 
 | 1153 |   CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP(); | 
 | 1154 |   CGF.EmitBlockAfterUses(dispatchBlock); | 
 | 1155 |  | 
 | 1156 |   // Select the right handler. | 
 | 1157 |   llvm::Value *llvm_eh_typeid_for = | 
 | 1158 |     CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); | 
 | 1159 |  | 
 | 1160 |   // Load the selector value. | 
| Bill Wendling | ae27059 | 2011-09-15 18:57:19 +0000 | [diff] [blame] | 1161 |   llvm::Value *selector = CGF.getSelectorFromSlot(); | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1162 |  | 
 | 1163 |   // Test against each of the exception types we claim to catch. | 
 | 1164 |   for (unsigned i = 0, e = catchScope.getNumHandlers(); ; ++i) { | 
 | 1165 |     assert(i < e && "ran off end of handlers!"); | 
 | 1166 |     const EHCatchScope::Handler &handler = catchScope.getHandler(i); | 
 | 1167 |  | 
 | 1168 |     llvm::Value *typeValue = handler.Type; | 
 | 1169 |     assert(typeValue && "fell into catch-all case!"); | 
 | 1170 |     typeValue = CGF.Builder.CreateBitCast(typeValue, CGF.Int8PtrTy); | 
 | 1171 |  | 
 | 1172 |     // Figure out the next block. | 
 | 1173 |     bool nextIsEnd; | 
 | 1174 |     llvm::BasicBlock *nextBlock; | 
 | 1175 |  | 
 | 1176 |     // If this is the last handler, we're at the end, and the next | 
 | 1177 |     // block is the block for the enclosing EH scope. | 
 | 1178 |     if (i + 1 == e) { | 
 | 1179 |       nextBlock = CGF.getEHDispatchBlock(catchScope.getEnclosingEHScope()); | 
 | 1180 |       nextIsEnd = true; | 
 | 1181 |  | 
 | 1182 |     // If the next handler is a catch-all, we're at the end, and the | 
 | 1183 |     // next block is that handler. | 
 | 1184 |     } else if (catchScope.getHandler(i+1).isCatchAll()) { | 
 | 1185 |       nextBlock = catchScope.getHandler(i+1).Block; | 
 | 1186 |       nextIsEnd = true; | 
 | 1187 |  | 
 | 1188 |     // Otherwise, we're not at the end and we need a new block. | 
 | 1189 |     } else { | 
 | 1190 |       nextBlock = CGF.createBasicBlock("catch.fallthrough"); | 
 | 1191 |       nextIsEnd = false; | 
 | 1192 |     } | 
 | 1193 |  | 
 | 1194 |     // Figure out the catch type's index in the LSDA's type table. | 
 | 1195 |     llvm::CallInst *typeIndex = | 
 | 1196 |       CGF.Builder.CreateCall(llvm_eh_typeid_for, typeValue); | 
 | 1197 |     typeIndex->setDoesNotThrow(); | 
 | 1198 |  | 
 | 1199 |     llvm::Value *matchesTypeIndex = | 
 | 1200 |       CGF.Builder.CreateICmpEQ(selector, typeIndex, "matches"); | 
 | 1201 |     CGF.Builder.CreateCondBr(matchesTypeIndex, handler.Block, nextBlock); | 
 | 1202 |  | 
 | 1203 |     // If the next handler is a catch-all, we're completely done. | 
 | 1204 |     if (nextIsEnd) { | 
 | 1205 |       CGF.Builder.restoreIP(savedIP); | 
 | 1206 |       return; | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1207 |     } | 
| Ahmed Charles | e8e92b9 | 2012-02-19 11:57:29 +0000 | [diff] [blame] | 1208 |     // Otherwise we need to emit and continue at that block. | 
 | 1209 |     CGF.EmitBlock(nextBlock); | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1210 |   } | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1211 | } | 
 | 1212 |  | 
 | 1213 | void CodeGenFunction::popCatchScope() { | 
 | 1214 |   EHCatchScope &catchScope = cast<EHCatchScope>(*EHStack.begin()); | 
 | 1215 |   if (catchScope.hasEHBranches()) | 
 | 1216 |     emitCatchDispatchBlock(*this, catchScope); | 
 | 1217 |   EHStack.popCatch(); | 
 | 1218 | } | 
 | 1219 |  | 
| John McCall | 59a7000 | 2010-07-07 06:56:46 +0000 | [diff] [blame] | 1220 | void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1221 |   unsigned NumHandlers = S.getNumHandlers(); | 
 | 1222 |   EHCatchScope &CatchScope = cast<EHCatchScope>(*EHStack.begin()); | 
 | 1223 |   assert(CatchScope.getNumHandlers() == NumHandlers); | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 1224 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1225 |   // If the catch was not required, bail out now. | 
 | 1226 |   if (!CatchScope.hasEHBranches()) { | 
 | 1227 |     EHStack.popCatch(); | 
 | 1228 |     return; | 
 | 1229 |   } | 
 | 1230 |  | 
 | 1231 |   // Emit the structure of the EH dispatch for this catch. | 
 | 1232 |   emitCatchDispatchBlock(*this, CatchScope); | 
 | 1233 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1234 |   // Copy the handler blocks off before we pop the EH stack.  Emitting | 
 | 1235 |   // the handlers might scribble on this memory. | 
| Chris Lattner | 5f9e272 | 2011-07-23 10:55:15 +0000 | [diff] [blame] | 1236 |   SmallVector<EHCatchScope::Handler, 8> Handlers(NumHandlers); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1237 |   memcpy(Handlers.data(), CatchScope.begin(), | 
 | 1238 |          NumHandlers * sizeof(EHCatchScope::Handler)); | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1239 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1240 |   EHStack.popCatch(); | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 1241 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1242 |   // The fall-through block. | 
 | 1243 |   llvm::BasicBlock *ContBB = createBasicBlock("try.cont"); | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 1244 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1245 |   // We just emitted the body of the try; jump to the continue block. | 
 | 1246 |   if (HaveInsertPoint()) | 
 | 1247 |     Builder.CreateBr(ContBB); | 
| Mike Stump | 639787c | 2009-12-02 19:53:57 +0000 | [diff] [blame] | 1248 |  | 
| John McCall | 59a7000 | 2010-07-07 06:56:46 +0000 | [diff] [blame] | 1249 |   // Determine if we need an implicit rethrow for all these catch handlers. | 
 | 1250 |   bool ImplicitRethrow = false; | 
 | 1251 |   if (IsFnTryBlock) | 
 | 1252 |     ImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) || | 
 | 1253 |                       isa<CXXConstructorDecl>(CurCodeDecl); | 
 | 1254 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1255 |   // Perversely, we emit the handlers backwards precisely because we | 
 | 1256 |   // want them to appear in source order.  In all of these cases, the | 
 | 1257 |   // catch block will have exactly one predecessor, which will be a | 
 | 1258 |   // particular block in the catch dispatch.  However, in the case of | 
 | 1259 |   // a catch-all, one of the dispatch blocks will branch to two | 
 | 1260 |   // different handlers, and EmitBlockAfterUses will cause the second | 
 | 1261 |   // handler to be moved before the first. | 
 | 1262 |   for (unsigned I = NumHandlers; I != 0; --I) { | 
 | 1263 |     llvm::BasicBlock *CatchBlock = Handlers[I-1].Block; | 
 | 1264 |     EmitBlockAfterUses(CatchBlock); | 
| Mike Stump | 8755ec3 | 2009-12-10 00:06:18 +0000 | [diff] [blame] | 1265 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1266 |     // Catch the exception if this isn't a catch-all. | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1267 |     const CXXCatchStmt *C = S.getHandler(I-1); | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 1268 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1269 |     // Enter a cleanup scope, including the catch variable and the | 
 | 1270 |     // end-catch. | 
 | 1271 |     RunCleanupsScope CatchScope(*this); | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 1272 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1273 |     // Initialize the catch variable and set up the cleanups. | 
 | 1274 |     BeginCatch(*this, C); | 
 | 1275 |  | 
| John McCall | 59a7000 | 2010-07-07 06:56:46 +0000 | [diff] [blame] | 1276 |     // If there's an implicit rethrow, push a normal "cleanup" to call | 
| John McCall | fcd5c0c | 2010-07-13 22:24:23 +0000 | [diff] [blame] | 1277 |     // _cxa_rethrow.  This needs to happen before __cxa_end_catch is | 
 | 1278 |     // called, and so it is pushed after BeginCatch. | 
 | 1279 |     if (ImplicitRethrow) | 
| John McCall | 1f0fca5 | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 1280 |       EHStack.pushCleanup<CallRethrow>(NormalCleanup); | 
| John McCall | 59a7000 | 2010-07-07 06:56:46 +0000 | [diff] [blame] | 1281 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1282 |     // Perform the body of the catch. | 
 | 1283 |     EmitStmt(C->getHandlerBlock()); | 
 | 1284 |  | 
 | 1285 |     // Fall out through the catch cleanups. | 
 | 1286 |     CatchScope.ForceCleanup(); | 
 | 1287 |  | 
 | 1288 |     // Branch out of the try. | 
 | 1289 |     if (HaveInsertPoint()) | 
 | 1290 |       Builder.CreateBr(ContBB); | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 1291 |   } | 
 | 1292 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1293 |   EmitBlock(ContBB); | 
| Mike Stump | 2bf701e | 2009-11-20 23:44:51 +0000 | [diff] [blame] | 1294 | } | 
| Mike Stump | d88ea56 | 2009-12-09 03:35:49 +0000 | [diff] [blame] | 1295 |  | 
| John McCall | 55b20fc | 2010-07-21 00:52:03 +0000 | [diff] [blame] | 1296 | namespace { | 
| John McCall | 1f0fca5 | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 1297 |   struct CallEndCatchForFinally : EHScopeStack::Cleanup { | 
| John McCall | 55b20fc | 2010-07-21 00:52:03 +0000 | [diff] [blame] | 1298 |     llvm::Value *ForEHVar; | 
 | 1299 |     llvm::Value *EndCatchFn; | 
 | 1300 |     CallEndCatchForFinally(llvm::Value *ForEHVar, llvm::Value *EndCatchFn) | 
 | 1301 |       : ForEHVar(ForEHVar), EndCatchFn(EndCatchFn) {} | 
 | 1302 |  | 
| John McCall | ad346f4 | 2011-07-12 20:27:29 +0000 | [diff] [blame] | 1303 |     void Emit(CodeGenFunction &CGF, Flags flags) { | 
| John McCall | 55b20fc | 2010-07-21 00:52:03 +0000 | [diff] [blame] | 1304 |       llvm::BasicBlock *EndCatchBB = CGF.createBasicBlock("finally.endcatch"); | 
 | 1305 |       llvm::BasicBlock *CleanupContBB = | 
 | 1306 |         CGF.createBasicBlock("finally.cleanup.cont"); | 
 | 1307 |  | 
 | 1308 |       llvm::Value *ShouldEndCatch = | 
 | 1309 |         CGF.Builder.CreateLoad(ForEHVar, "finally.endcatch"); | 
 | 1310 |       CGF.Builder.CreateCondBr(ShouldEndCatch, EndCatchBB, CleanupContBB); | 
 | 1311 |       CGF.EmitBlock(EndCatchBB); | 
| Jay Foad | 4c7d9f1 | 2011-07-15 08:37:34 +0000 | [diff] [blame] | 1312 |       CGF.EmitCallOrInvoke(EndCatchFn); // catch-all, so might throw | 
| John McCall | 55b20fc | 2010-07-21 00:52:03 +0000 | [diff] [blame] | 1313 |       CGF.EmitBlock(CleanupContBB); | 
 | 1314 |     } | 
 | 1315 |   }; | 
| John McCall | 7719971 | 2010-07-21 05:47:49 +0000 | [diff] [blame] | 1316 |  | 
| John McCall | 1f0fca5 | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 1317 |   struct PerformFinally : EHScopeStack::Cleanup { | 
| John McCall | 7719971 | 2010-07-21 05:47:49 +0000 | [diff] [blame] | 1318 |     const Stmt *Body; | 
 | 1319 |     llvm::Value *ForEHVar; | 
 | 1320 |     llvm::Value *EndCatchFn; | 
 | 1321 |     llvm::Value *RethrowFn; | 
 | 1322 |     llvm::Value *SavedExnVar; | 
 | 1323 |  | 
 | 1324 |     PerformFinally(const Stmt *Body, llvm::Value *ForEHVar, | 
 | 1325 |                    llvm::Value *EndCatchFn, | 
 | 1326 |                    llvm::Value *RethrowFn, llvm::Value *SavedExnVar) | 
 | 1327 |       : Body(Body), ForEHVar(ForEHVar), EndCatchFn(EndCatchFn), | 
 | 1328 |         RethrowFn(RethrowFn), SavedExnVar(SavedExnVar) {} | 
 | 1329 |  | 
| John McCall | ad346f4 | 2011-07-12 20:27:29 +0000 | [diff] [blame] | 1330 |     void Emit(CodeGenFunction &CGF, Flags flags) { | 
| John McCall | 7719971 | 2010-07-21 05:47:49 +0000 | [diff] [blame] | 1331 |       // Enter a cleanup to call the end-catch function if one was provided. | 
 | 1332 |       if (EndCatchFn) | 
| John McCall | 1f0fca5 | 2010-07-21 07:22:38 +0000 | [diff] [blame] | 1333 |         CGF.EHStack.pushCleanup<CallEndCatchForFinally>(NormalAndEHCleanup, | 
 | 1334 |                                                         ForEHVar, EndCatchFn); | 
| John McCall | 7719971 | 2010-07-21 05:47:49 +0000 | [diff] [blame] | 1335 |  | 
| John McCall | d96a8e7 | 2010-08-11 00:16:14 +0000 | [diff] [blame] | 1336 |       // Save the current cleanup destination in case there are | 
 | 1337 |       // cleanups in the finally block. | 
 | 1338 |       llvm::Value *SavedCleanupDest = | 
 | 1339 |         CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot(), | 
 | 1340 |                                "cleanup.dest.saved"); | 
 | 1341 |  | 
| John McCall | 7719971 | 2010-07-21 05:47:49 +0000 | [diff] [blame] | 1342 |       // Emit the finally block. | 
 | 1343 |       CGF.EmitStmt(Body); | 
 | 1344 |  | 
 | 1345 |       // If the end of the finally is reachable, check whether this was | 
 | 1346 |       // for EH.  If so, rethrow. | 
 | 1347 |       if (CGF.HaveInsertPoint()) { | 
 | 1348 |         llvm::BasicBlock *RethrowBB = CGF.createBasicBlock("finally.rethrow"); | 
 | 1349 |         llvm::BasicBlock *ContBB = CGF.createBasicBlock("finally.cont"); | 
 | 1350 |  | 
 | 1351 |         llvm::Value *ShouldRethrow = | 
 | 1352 |           CGF.Builder.CreateLoad(ForEHVar, "finally.shouldthrow"); | 
 | 1353 |         CGF.Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB); | 
 | 1354 |  | 
 | 1355 |         CGF.EmitBlock(RethrowBB); | 
 | 1356 |         if (SavedExnVar) { | 
| Jay Foad | 4c7d9f1 | 2011-07-15 08:37:34 +0000 | [diff] [blame] | 1357 |           CGF.EmitCallOrInvoke(RethrowFn, CGF.Builder.CreateLoad(SavedExnVar)); | 
| John McCall | 7719971 | 2010-07-21 05:47:49 +0000 | [diff] [blame] | 1358 |         } else { | 
| Jay Foad | 4c7d9f1 | 2011-07-15 08:37:34 +0000 | [diff] [blame] | 1359 |           CGF.EmitCallOrInvoke(RethrowFn); | 
| John McCall | 7719971 | 2010-07-21 05:47:49 +0000 | [diff] [blame] | 1360 |         } | 
 | 1361 |         CGF.Builder.CreateUnreachable(); | 
 | 1362 |  | 
 | 1363 |         CGF.EmitBlock(ContBB); | 
| John McCall | d96a8e7 | 2010-08-11 00:16:14 +0000 | [diff] [blame] | 1364 |  | 
 | 1365 |         // Restore the cleanup destination. | 
 | 1366 |         CGF.Builder.CreateStore(SavedCleanupDest, | 
 | 1367 |                                 CGF.getNormalCleanupDestSlot()); | 
| John McCall | 7719971 | 2010-07-21 05:47:49 +0000 | [diff] [blame] | 1368 |       } | 
 | 1369 |  | 
 | 1370 |       // Leave the end-catch cleanup.  As an optimization, pretend that | 
 | 1371 |       // the fallthrough path was inaccessible; we've dynamically proven | 
 | 1372 |       // that we're not in the EH case along that path. | 
 | 1373 |       if (EndCatchFn) { | 
 | 1374 |         CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); | 
 | 1375 |         CGF.PopCleanupBlock(); | 
 | 1376 |         CGF.Builder.restoreIP(SavedIP); | 
 | 1377 |       } | 
 | 1378 |      | 
 | 1379 |       // Now make sure we actually have an insertion point or the | 
 | 1380 |       // cleanup gods will hate us. | 
 | 1381 |       CGF.EnsureInsertPoint(); | 
 | 1382 |     } | 
 | 1383 |   }; | 
| John McCall | 55b20fc | 2010-07-21 00:52:03 +0000 | [diff] [blame] | 1384 | } | 
 | 1385 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1386 | /// Enters a finally block for an implementation using zero-cost | 
 | 1387 | /// exceptions.  This is mostly general, but hard-codes some | 
 | 1388 | /// language/ABI-specific behavior in the catch-all sections. | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1389 | void CodeGenFunction::FinallyInfo::enter(CodeGenFunction &CGF, | 
 | 1390 |                                          const Stmt *body, | 
 | 1391 |                                          llvm::Constant *beginCatchFn, | 
 | 1392 |                                          llvm::Constant *endCatchFn, | 
 | 1393 |                                          llvm::Constant *rethrowFn) { | 
 | 1394 |   assert((beginCatchFn != 0) == (endCatchFn != 0) && | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1395 |          "begin/end catch functions not paired"); | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1396 |   assert(rethrowFn && "rethrow function is required"); | 
 | 1397 |  | 
 | 1398 |   BeginCatchFn = beginCatchFn; | 
| Mike Stump | d88ea56 | 2009-12-09 03:35:49 +0000 | [diff] [blame] | 1399 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1400 |   // The rethrow function has one of the following two types: | 
 | 1401 |   //   void (*)() | 
 | 1402 |   //   void (*)(void*) | 
 | 1403 |   // In the latter case we need to pass it the exception object. | 
 | 1404 |   // But we can't use the exception slot because the @finally might | 
 | 1405 |   // have a landing pad (which would overwrite the exception slot). | 
| Chris Lattner | 2acc6e3 | 2011-07-18 04:24:23 +0000 | [diff] [blame] | 1406 |   llvm::FunctionType *rethrowFnTy = | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1407 |     cast<llvm::FunctionType>( | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1408 |       cast<llvm::PointerType>(rethrowFn->getType())->getElementType()); | 
 | 1409 |   SavedExnVar = 0; | 
 | 1410 |   if (rethrowFnTy->getNumParams()) | 
 | 1411 |     SavedExnVar = CGF.CreateTempAlloca(CGF.Int8PtrTy, "finally.exn"); | 
| Mike Stump | d88ea56 | 2009-12-09 03:35:49 +0000 | [diff] [blame] | 1412 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1413 |   // A finally block is a statement which must be executed on any edge | 
 | 1414 |   // out of a given scope.  Unlike a cleanup, the finally block may | 
 | 1415 |   // contain arbitrary control flow leading out of itself.  In | 
 | 1416 |   // addition, finally blocks should always be executed, even if there | 
 | 1417 |   // are no catch handlers higher on the stack.  Therefore, we | 
 | 1418 |   // surround the protected scope with a combination of a normal | 
 | 1419 |   // cleanup (to catch attempts to break out of the block via normal | 
 | 1420 |   // control flow) and an EH catch-all (semantically "outside" any try | 
 | 1421 |   // statement to which the finally block might have been attached). | 
 | 1422 |   // The finally block itself is generated in the context of a cleanup | 
 | 1423 |   // which conditionally leaves the catch-all. | 
| John McCall | 3d3ec1c | 2010-04-21 10:05:39 +0000 | [diff] [blame] | 1424 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1425 |   // Jump destination for performing the finally block on an exception | 
 | 1426 |   // edge.  We'll never actually reach this block, so unreachable is | 
 | 1427 |   // fine. | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1428 |   RethrowDest = CGF.getJumpDestInCurrentScope(CGF.getUnreachableBlock()); | 
| John McCall | 3d3ec1c | 2010-04-21 10:05:39 +0000 | [diff] [blame] | 1429 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1430 |   // Whether the finally block is being executed for EH purposes. | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1431 |   ForEHVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "finally.for-eh"); | 
 | 1432 |   CGF.Builder.CreateStore(CGF.Builder.getFalse(), ForEHVar); | 
| Mike Stump | d88ea56 | 2009-12-09 03:35:49 +0000 | [diff] [blame] | 1433 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1434 |   // Enter a normal cleanup which will perform the @finally block. | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1435 |   CGF.EHStack.pushCleanup<PerformFinally>(NormalCleanup, body, | 
 | 1436 |                                           ForEHVar, endCatchFn, | 
 | 1437 |                                           rethrowFn, SavedExnVar); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1438 |  | 
 | 1439 |   // Enter a catch-all scope. | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1440 |   llvm::BasicBlock *catchBB = CGF.createBasicBlock("finally.catchall"); | 
 | 1441 |   EHCatchScope *catchScope = CGF.EHStack.pushCatch(1); | 
 | 1442 |   catchScope->setCatchAllHandler(0, catchBB); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1443 | } | 
 | 1444 |  | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1445 | void CodeGenFunction::FinallyInfo::exit(CodeGenFunction &CGF) { | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1446 |   // Leave the finally catch-all. | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1447 |   EHCatchScope &catchScope = cast<EHCatchScope>(*CGF.EHStack.begin()); | 
 | 1448 |   llvm::BasicBlock *catchBB = catchScope.getHandler(0).Block; | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1449 |  | 
 | 1450 |   CGF.popCatchScope(); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1451 |  | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1452 |   // If there are any references to the catch-all block, emit it. | 
 | 1453 |   if (catchBB->use_empty()) { | 
 | 1454 |     delete catchBB; | 
 | 1455 |   } else { | 
 | 1456 |     CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveAndClearIP(); | 
 | 1457 |     CGF.EmitBlock(catchBB); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1458 |  | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1459 |     llvm::Value *exn = 0; | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1460 |  | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1461 |     // If there's a begin-catch function, call it. | 
 | 1462 |     if (BeginCatchFn) { | 
| Bill Wendling | ae27059 | 2011-09-15 18:57:19 +0000 | [diff] [blame] | 1463 |       exn = CGF.getExceptionFromSlot(); | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1464 |       CGF.Builder.CreateCall(BeginCatchFn, exn)->setDoesNotThrow(); | 
 | 1465 |     } | 
 | 1466 |  | 
 | 1467 |     // If we need to remember the exception pointer to rethrow later, do so. | 
 | 1468 |     if (SavedExnVar) { | 
| Bill Wendling | ae27059 | 2011-09-15 18:57:19 +0000 | [diff] [blame] | 1469 |       if (!exn) exn = CGF.getExceptionFromSlot(); | 
| John McCall | d768e9d | 2011-06-22 02:32:12 +0000 | [diff] [blame] | 1470 |       CGF.Builder.CreateStore(exn, SavedExnVar); | 
 | 1471 |     } | 
 | 1472 |  | 
 | 1473 |     // Tell the cleanups in the finally block that we're do this for EH. | 
 | 1474 |     CGF.Builder.CreateStore(CGF.Builder.getTrue(), ForEHVar); | 
 | 1475 |  | 
 | 1476 |     // Thread a jump through the finally cleanup. | 
 | 1477 |     CGF.EmitBranchThroughCleanup(RethrowDest); | 
 | 1478 |  | 
 | 1479 |     CGF.Builder.restoreIP(savedIP); | 
 | 1480 |   } | 
 | 1481 |  | 
 | 1482 |   // Finally, leave the @finally cleanup. | 
 | 1483 |   CGF.PopCleanupBlock(); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1484 | } | 
 | 1485 |  | 
 | 1486 | llvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() { | 
 | 1487 |   if (TerminateLandingPad) | 
 | 1488 |     return TerminateLandingPad; | 
 | 1489 |  | 
 | 1490 |   CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); | 
 | 1491 |  | 
 | 1492 |   // This will get inserted at the end of the function. | 
 | 1493 |   TerminateLandingPad = createBasicBlock("terminate.lpad"); | 
 | 1494 |   Builder.SetInsertPoint(TerminateLandingPad); | 
 | 1495 |  | 
 | 1496 |   // Tell the backend that this is a landing pad. | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 1497 |   const EHPersonality &Personality = EHPersonality::get(CGM.getLangOpts()); | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 1498 |   llvm::LandingPadInst *LPadInst = | 
 | 1499 |     Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty, NULL), | 
 | 1500 |                              getOpaquePersonalityFn(CGM, Personality), 0); | 
 | 1501 |   LPadInst->addClause(getCatchAllValue(*this)); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1502 |  | 
 | 1503 |   llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(*this)); | 
 | 1504 |   TerminateCall->setDoesNotReturn(); | 
 | 1505 |   TerminateCall->setDoesNotThrow(); | 
| John McCall | d16c2cf | 2011-02-08 08:22:06 +0000 | [diff] [blame] | 1506 |   Builder.CreateUnreachable(); | 
| Mike Stump | d88ea56 | 2009-12-09 03:35:49 +0000 | [diff] [blame] | 1507 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1508 |   // Restore the saved insertion state. | 
 | 1509 |   Builder.restoreIP(SavedIP); | 
| John McCall | 891f80e | 2010-04-30 00:06:43 +0000 | [diff] [blame] | 1510 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1511 |   return TerminateLandingPad; | 
| Mike Stump | d88ea56 | 2009-12-09 03:35:49 +0000 | [diff] [blame] | 1512 | } | 
| Mike Stump | 9b39c51 | 2009-12-09 22:59:31 +0000 | [diff] [blame] | 1513 |  | 
 | 1514 | llvm::BasicBlock *CodeGenFunction::getTerminateHandler() { | 
| Mike Stump | 182f383 | 2009-12-10 00:02:42 +0000 | [diff] [blame] | 1515 |   if (TerminateHandler) | 
 | 1516 |     return TerminateHandler; | 
 | 1517 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1518 |   CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); | 
| Mike Stump | 7695809 | 2009-12-09 23:31:35 +0000 | [diff] [blame] | 1519 |  | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1520 |   // Set up the terminate handler.  This block is inserted at the very | 
 | 1521 |   // end of the function by FinishFunction. | 
| Mike Stump | 182f383 | 2009-12-10 00:02:42 +0000 | [diff] [blame] | 1522 |   TerminateHandler = createBasicBlock("terminate.handler"); | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1523 |   Builder.SetInsertPoint(TerminateHandler); | 
 | 1524 |   llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(*this)); | 
| Mike Stump | 9b39c51 | 2009-12-09 22:59:31 +0000 | [diff] [blame] | 1525 |   TerminateCall->setDoesNotReturn(); | 
 | 1526 |   TerminateCall->setDoesNotThrow(); | 
 | 1527 |   Builder.CreateUnreachable(); | 
 | 1528 |  | 
| John McCall | 3d3ec1c | 2010-04-21 10:05:39 +0000 | [diff] [blame] | 1529 |   // Restore the saved insertion state. | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1530 |   Builder.restoreIP(SavedIP); | 
| Mike Stump | 7695809 | 2009-12-09 23:31:35 +0000 | [diff] [blame] | 1531 |  | 
| Mike Stump | 9b39c51 | 2009-12-09 22:59:31 +0000 | [diff] [blame] | 1532 |   return TerminateHandler; | 
 | 1533 | } | 
| John McCall | f1549f6 | 2010-07-06 01:34:17 +0000 | [diff] [blame] | 1534 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1535 | llvm::BasicBlock *CodeGenFunction::getEHResumeBlock() { | 
 | 1536 |   if (EHResumeBlock) return EHResumeBlock; | 
| John McCall | ff8e115 | 2010-07-23 21:56:41 +0000 | [diff] [blame] | 1537 |  | 
 | 1538 |   CGBuilderTy::InsertPoint SavedIP = Builder.saveIP(); | 
 | 1539 |  | 
 | 1540 |   // We emit a jump to a notional label at the outermost unwind state. | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1541 |   EHResumeBlock = createBasicBlock("eh.resume"); | 
 | 1542 |   Builder.SetInsertPoint(EHResumeBlock); | 
| John McCall | ff8e115 | 2010-07-23 21:56:41 +0000 | [diff] [blame] | 1543 |  | 
| David Blaikie | 4e4d084 | 2012-03-11 07:00:24 +0000 | [diff] [blame] | 1544 |   const EHPersonality &Personality = EHPersonality::get(CGM.getLangOpts()); | 
| John McCall | ff8e115 | 2010-07-23 21:56:41 +0000 | [diff] [blame] | 1545 |  | 
 | 1546 |   // This can always be a call because we necessarily didn't find | 
 | 1547 |   // anything on the EH stack which needs our help. | 
| Benjamin Kramer | af2771b | 2012-02-08 12:41:24 +0000 | [diff] [blame] | 1548 |   const char *RethrowName = Personality.CatchallRethrowFn; | 
 | 1549 |   if (RethrowName != 0) { | 
| John McCall | 93c332a | 2011-05-28 21:13:02 +0000 | [diff] [blame] | 1550 |     Builder.CreateCall(getCatchallRethrowFn(*this, RethrowName), | 
| Bill Wendling | ae27059 | 2011-09-15 18:57:19 +0000 | [diff] [blame] | 1551 |                        getExceptionFromSlot()) | 
| John McCall | 93c332a | 2011-05-28 21:13:02 +0000 | [diff] [blame] | 1552 |       ->setDoesNotReturn(); | 
 | 1553 |   } else { | 
| John McCall | 93c332a | 2011-05-28 21:13:02 +0000 | [diff] [blame] | 1554 |     switch (CleanupHackLevel) { | 
 | 1555 |     case CHL_MandatoryCatchall: | 
 | 1556 |       // In mandatory-catchall mode, we need to use | 
 | 1557 |       // _Unwind_Resume_or_Rethrow, or whatever the personality's | 
 | 1558 |       // equivalent is. | 
| Bill Wendling | cc1f918 | 2011-12-08 23:21:26 +0000 | [diff] [blame] | 1559 |       Builder.CreateCall(getUnwindResumeOrRethrowFn(), | 
 | 1560 |                          getExceptionFromSlot()) | 
| John McCall | 93c332a | 2011-05-28 21:13:02 +0000 | [diff] [blame] | 1561 |         ->setDoesNotReturn(); | 
 | 1562 |       break; | 
 | 1563 |     case CHL_MandatoryCleanup: { | 
| Bill Wendling | 285cfd8 | 2011-09-19 20:31:14 +0000 | [diff] [blame] | 1564 |       // In mandatory-cleanup mode, we should use 'resume'. | 
 | 1565 |  | 
 | 1566 |       // Recreate the landingpad's return value for the 'resume' instruction. | 
 | 1567 |       llvm::Value *Exn = getExceptionFromSlot(); | 
 | 1568 |       llvm::Value *Sel = getSelectorFromSlot(); | 
 | 1569 |  | 
 | 1570 |       llvm::Type *LPadType = llvm::StructType::get(Exn->getType(), | 
 | 1571 |                                                    Sel->getType(), NULL); | 
 | 1572 |       llvm::Value *LPadVal = llvm::UndefValue::get(LPadType); | 
 | 1573 |       LPadVal = Builder.CreateInsertValue(LPadVal, Exn, 0, "lpad.val"); | 
 | 1574 |       LPadVal = Builder.CreateInsertValue(LPadVal, Sel, 1, "lpad.val"); | 
 | 1575 |  | 
 | 1576 |       Builder.CreateResume(LPadVal); | 
 | 1577 |       Builder.restoreIP(SavedIP); | 
 | 1578 |       return EHResumeBlock; | 
| John McCall | 93c332a | 2011-05-28 21:13:02 +0000 | [diff] [blame] | 1579 |     } | 
 | 1580 |     case CHL_Ideal: | 
 | 1581 |       // In an idealized mode where we don't have to worry about the | 
 | 1582 |       // optimizer combining landing pads, we should just use | 
 | 1583 |       // _Unwind_Resume (or the personality's equivalent). | 
| Bill Wendling | cc1f918 | 2011-12-08 23:21:26 +0000 | [diff] [blame] | 1584 |       Builder.CreateCall(getUnwindResumeFn(), getExceptionFromSlot()) | 
| John McCall | 93c332a | 2011-05-28 21:13:02 +0000 | [diff] [blame] | 1585 |         ->setDoesNotReturn(); | 
 | 1586 |       break; | 
 | 1587 |     } | 
 | 1588 |   } | 
 | 1589 |  | 
| John McCall | ff8e115 | 2010-07-23 21:56:41 +0000 | [diff] [blame] | 1590 |   Builder.CreateUnreachable(); | 
 | 1591 |  | 
 | 1592 |   Builder.restoreIP(SavedIP); | 
 | 1593 |  | 
| John McCall | 777d6e5 | 2011-08-11 02:22:43 +0000 | [diff] [blame] | 1594 |   return EHResumeBlock; | 
| John McCall | ff8e115 | 2010-07-23 21:56:41 +0000 | [diff] [blame] | 1595 | } |