CGException.cpp revision 223017
1198893Srdivacky//===--- CGException.cpp - Emit LLVM Code for C++ exceptions --------------===// 2198893Srdivacky// 3198893Srdivacky// The LLVM Compiler Infrastructure 4198893Srdivacky// 5198893Srdivacky// This file is distributed under the University of Illinois Open Source 6198893Srdivacky// License. See LICENSE.TXT for details. 7198893Srdivacky// 8198893Srdivacky//===----------------------------------------------------------------------===// 9198893Srdivacky// 10198893Srdivacky// This contains code dealing with C++ exception related code generation. 11198893Srdivacky// 12198893Srdivacky//===----------------------------------------------------------------------===// 13198893Srdivacky 14199990Srdivacky#include "clang/AST/StmtCXX.h" 15199990Srdivacky 16199990Srdivacky#include "llvm/Intrinsics.h" 17218893Sdim#include "llvm/IntrinsicInst.h" 18210299Sed#include "llvm/Support/CallSite.h" 19199990Srdivacky 20212904Sdim#include "CGObjCRuntime.h" 21198893Srdivacky#include "CodeGenFunction.h" 22210299Sed#include "CGException.h" 23218893Sdim#include "CGCleanup.h" 24212904Sdim#include "TargetInfo.h" 25210299Sed 26198893Srdivackyusing namespace clang; 27198893Srdivackyusing namespace CodeGen; 28198893Srdivacky 29198893Srdivackystatic llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) { 30198893Srdivacky // void *__cxa_allocate_exception(size_t thrown_size); 31221345Sdim 32198893Srdivacky const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); 33200583Srdivacky const llvm::FunctionType *FTy = 34221345Sdim llvm::FunctionType::get(llvm::Type::getInt8PtrTy(CGF.getLLVMContext()), 35221345Sdim SizeTy, /*IsVarArgs=*/false); 36200583Srdivacky 37198893Srdivacky return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception"); 38198893Srdivacky} 39198893Srdivacky 40200583Srdivackystatic llvm::Constant *getFreeExceptionFn(CodeGenFunction &CGF) { 41200583Srdivacky // void __cxa_free_exception(void *thrown_exception); 42221345Sdim 43200583Srdivacky const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 44200583Srdivacky const llvm::FunctionType *FTy = 45221345Sdim llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 46221345Sdim Int8PtrTy, /*IsVarArgs=*/false); 47200583Srdivacky 48200583Srdivacky return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception"); 49200583Srdivacky} 50200583Srdivacky 51198893Srdivackystatic llvm::Constant *getThrowFn(CodeGenFunction &CGF) { 52200583Srdivacky // void __cxa_throw(void *thrown_exception, std::type_info *tinfo, 53200583Srdivacky // void (*dest) (void *)); 54198893Srdivacky 55198893Srdivacky const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 56221345Sdim const llvm::Type *Args[3] = { Int8PtrTy, Int8PtrTy, Int8PtrTy }; 57200583Srdivacky const llvm::FunctionType *FTy = 58199990Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 59221345Sdim Args, /*IsVarArgs=*/false); 60200583Srdivacky 61198893Srdivacky return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_throw"); 62198893Srdivacky} 63198893Srdivacky 64199990Srdivackystatic llvm::Constant *getReThrowFn(CodeGenFunction &CGF) { 65200583Srdivacky // void __cxa_rethrow(); 66199990Srdivacky 67200583Srdivacky const llvm::FunctionType *FTy = 68221345Sdim llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 69221345Sdim /*IsVarArgs=*/false); 70200583Srdivacky 71199990Srdivacky return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow"); 72199990Srdivacky} 73199990Srdivacky 74210299Sedstatic llvm::Constant *getGetExceptionPtrFn(CodeGenFunction &CGF) { 75210299Sed // void *__cxa_get_exception_ptr(void*); 76221345Sdim 77210299Sed const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 78210299Sed const llvm::FunctionType *FTy = 79221345Sdim llvm::FunctionType::get(Int8PtrTy, Int8PtrTy, /*IsVarArgs=*/false); 80210299Sed 81210299Sed return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr"); 82210299Sed} 83210299Sed 84199990Srdivackystatic llvm::Constant *getBeginCatchFn(CodeGenFunction &CGF) { 85210299Sed // void *__cxa_begin_catch(void*); 86199990Srdivacky 87199990Srdivacky const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 88200583Srdivacky const llvm::FunctionType *FTy = 89221345Sdim llvm::FunctionType::get(Int8PtrTy, Int8PtrTy, /*IsVarArgs=*/false); 90200583Srdivacky 91199990Srdivacky return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); 92199990Srdivacky} 93199990Srdivacky 94199990Srdivackystatic llvm::Constant *getEndCatchFn(CodeGenFunction &CGF) { 95200583Srdivacky // void __cxa_end_catch(); 96199990Srdivacky 97200583Srdivacky const llvm::FunctionType *FTy = 98221345Sdim llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 99221345Sdim /*IsVarArgs=*/false); 100200583Srdivacky 101199990Srdivacky return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); 102199990Srdivacky} 103199990Srdivacky 104200583Srdivackystatic llvm::Constant *getUnexpectedFn(CodeGenFunction &CGF) { 105200583Srdivacky // void __cxa_call_unexepcted(void *thrown_exception); 106200583Srdivacky 107200583Srdivacky const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 108200583Srdivacky const llvm::FunctionType *FTy = 109200583Srdivacky llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 110221345Sdim Int8PtrTy, /*IsVarArgs=*/false); 111200583Srdivacky 112200583Srdivacky return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected"); 113200583Srdivacky} 114200583Srdivacky 115223017Sdimllvm::Constant *CodeGenFunction::getUnwindResumeFn() { 116223017Sdim const llvm::FunctionType *FTy = 117223017Sdim llvm::FunctionType::get(VoidTy, Int8PtrTy, /*IsVarArgs=*/false); 118223017Sdim 119223017Sdim if (CGM.getLangOptions().SjLjExceptions) 120223017Sdim return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume"); 121223017Sdim return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume"); 122223017Sdim} 123223017Sdim 124208600Srdivackyllvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() { 125200583Srdivacky const llvm::FunctionType *FTy = 126223017Sdim llvm::FunctionType::get(VoidTy, Int8PtrTy, /*IsVarArgs=*/false); 127200583Srdivacky 128208600Srdivacky if (CGM.getLangOptions().SjLjExceptions) 129212904Sdim return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume_or_Rethrow"); 130208600Srdivacky return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow"); 131199990Srdivacky} 132199990Srdivacky 133200583Srdivackystatic llvm::Constant *getTerminateFn(CodeGenFunction &CGF) { 134200583Srdivacky // void __terminate(); 135200583Srdivacky 136200583Srdivacky const llvm::FunctionType *FTy = 137221345Sdim llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 138221345Sdim /*IsVarArgs=*/false); 139200583Srdivacky 140208600Srdivacky return CGF.CGM.CreateRuntimeFunction(FTy, 141208600Srdivacky CGF.CGM.getLangOptions().CPlusPlus ? "_ZSt9terminatev" : "abort"); 142200583Srdivacky} 143200583Srdivacky 144212904Sdimstatic llvm::Constant *getCatchallRethrowFn(CodeGenFunction &CGF, 145218893Sdim llvm::StringRef Name) { 146212904Sdim const llvm::Type *Int8PtrTy = 147212904Sdim llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 148212904Sdim const llvm::Type *VoidTy = llvm::Type::getVoidTy(CGF.getLLVMContext()); 149221345Sdim const llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, Int8PtrTy, 150221345Sdim /*IsVarArgs=*/false); 151212904Sdim 152212904Sdim return CGF.CGM.CreateRuntimeFunction(FTy, Name); 153210299Sed} 154210299Sed 155212904Sdimconst EHPersonality EHPersonality::GNU_C("__gcc_personality_v0"); 156218893Sdimconst EHPersonality EHPersonality::GNU_C_SJLJ("__gcc_personality_sj0"); 157212904Sdimconst EHPersonality EHPersonality::NeXT_ObjC("__objc_personality_v0"); 158212904Sdimconst EHPersonality EHPersonality::GNU_CPlusPlus("__gxx_personality_v0"); 159212904Sdimconst EHPersonality EHPersonality::GNU_CPlusPlus_SJLJ("__gxx_personality_sj0"); 160212904Sdimconst EHPersonality EHPersonality::GNU_ObjC("__gnu_objc_personality_v0", 161212904Sdim "objc_exception_throw"); 162221345Sdimconst EHPersonality EHPersonality::GNU_ObjCXX("__gnustep_objcxx_personality_v0"); 163212904Sdim 164212904Sdimstatic const EHPersonality &getCPersonality(const LangOptions &L) { 165218893Sdim if (L.SjLjExceptions) 166218893Sdim return EHPersonality::GNU_C_SJLJ; 167212904Sdim return EHPersonality::GNU_C; 168212904Sdim} 169212904Sdim 170212904Sdimstatic const EHPersonality &getObjCPersonality(const LangOptions &L) { 171212904Sdim if (L.NeXTRuntime) { 172212904Sdim if (L.ObjCNonFragileABI) return EHPersonality::NeXT_ObjC; 173212904Sdim else return getCPersonality(L); 174210299Sed } else { 175212904Sdim return EHPersonality::GNU_ObjC; 176208600Srdivacky } 177210299Sed} 178208600Srdivacky 179212904Sdimstatic const EHPersonality &getCXXPersonality(const LangOptions &L) { 180212904Sdim if (L.SjLjExceptions) 181212904Sdim return EHPersonality::GNU_CPlusPlus_SJLJ; 182210299Sed else 183212904Sdim return EHPersonality::GNU_CPlusPlus; 184210299Sed} 185210299Sed 186210299Sed/// Determines the personality function to use when both C++ 187210299Sed/// and Objective-C exceptions are being caught. 188212904Sdimstatic const EHPersonality &getObjCXXPersonality(const LangOptions &L) { 189210299Sed // The ObjC personality defers to the C++ personality for non-ObjC 190210299Sed // handlers. Unlike the C++ case, we use the same personality 191210299Sed // function on targets using (backend-driven) SJLJ EH. 192212904Sdim if (L.NeXTRuntime) { 193212904Sdim if (L.ObjCNonFragileABI) 194212904Sdim return EHPersonality::NeXT_ObjC; 195210299Sed 196210299Sed // In the fragile ABI, just use C++ exception handling and hope 197210299Sed // they're not doing crazy exception mixing. 198210299Sed else 199212904Sdim return getCXXPersonality(L); 200210299Sed } 201210299Sed 202212904Sdim // The GNU runtime's personality function inherently doesn't support 203212904Sdim // mixed EH. Use the C++ personality just to avoid returning null. 204221345Sdim return EHPersonality::GNU_ObjCXX; 205210299Sed} 206210299Sed 207212904Sdimconst EHPersonality &EHPersonality::get(const LangOptions &L) { 208212904Sdim if (L.CPlusPlus && L.ObjC1) 209212904Sdim return getObjCXXPersonality(L); 210212904Sdim else if (L.CPlusPlus) 211212904Sdim return getCXXPersonality(L); 212212904Sdim else if (L.ObjC1) 213212904Sdim return getObjCPersonality(L); 214210299Sed else 215212904Sdim return getCPersonality(L); 216212904Sdim} 217210299Sed 218218893Sdimstatic llvm::Constant *getPersonalityFn(CodeGenModule &CGM, 219212904Sdim const EHPersonality &Personality) { 220212904Sdim llvm::Constant *Fn = 221218893Sdim CGM.CreateRuntimeFunction(llvm::FunctionType::get( 222218893Sdim llvm::Type::getInt32Ty(CGM.getLLVMContext()), 223218893Sdim true), 224218893Sdim Personality.getPersonalityFnName()); 225218893Sdim return Fn; 226208600Srdivacky} 227208600Srdivacky 228218893Sdimstatic llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM, 229218893Sdim const EHPersonality &Personality) { 230218893Sdim llvm::Constant *Fn = getPersonalityFn(CGM, Personality); 231218893Sdim return llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 232218893Sdim} 233218893Sdim 234218893Sdim/// Check whether a personality function could reasonably be swapped 235218893Sdim/// for a C++ personality function. 236218893Sdimstatic bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) { 237218893Sdim for (llvm::Constant::use_iterator 238218893Sdim I = Fn->use_begin(), E = Fn->use_end(); I != E; ++I) { 239218893Sdim llvm::User *User = *I; 240218893Sdim 241218893Sdim // Conditionally white-list bitcasts. 242218893Sdim if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(User)) { 243218893Sdim if (CE->getOpcode() != llvm::Instruction::BitCast) return false; 244218893Sdim if (!PersonalityHasOnlyCXXUses(CE)) 245218893Sdim return false; 246218893Sdim continue; 247218893Sdim } 248218893Sdim 249218893Sdim // Otherwise, it has to be a selector call. 250218893Sdim if (!isa<llvm::EHSelectorInst>(User)) return false; 251218893Sdim 252218893Sdim llvm::EHSelectorInst *Selector = cast<llvm::EHSelectorInst>(User); 253218893Sdim for (unsigned I = 2, E = Selector->getNumArgOperands(); I != E; ++I) { 254218893Sdim // Look for something that would've been returned by the ObjC 255218893Sdim // runtime's GetEHType() method. 256218893Sdim llvm::GlobalVariable *GV 257218893Sdim = dyn_cast<llvm::GlobalVariable>(Selector->getArgOperand(I)); 258218893Sdim if (!GV) continue; 259218893Sdim 260218893Sdim // ObjC EH selector entries are always global variables with 261218893Sdim // names starting like this. 262218893Sdim if (GV->getName().startswith("OBJC_EHTYPE")) 263218893Sdim return false; 264218893Sdim } 265218893Sdim } 266218893Sdim 267218893Sdim return true; 268218893Sdim} 269218893Sdim 270218893Sdim/// Try to use the C++ personality function in ObjC++. Not doing this 271218893Sdim/// can cause some incompatibilities with gcc, which is more 272218893Sdim/// aggressive about only using the ObjC++ personality in a function 273218893Sdim/// when it really needs it. 274218893Sdimvoid CodeGenModule::SimplifyPersonality() { 275218893Sdim // For now, this is really a Darwin-specific operation. 276221345Sdim if (!Context.Target.getTriple().isOSDarwin()) 277218893Sdim return; 278218893Sdim 279218893Sdim // If we're not in ObjC++ -fexceptions, there's nothing to do. 280218893Sdim if (!Features.CPlusPlus || !Features.ObjC1 || !Features.Exceptions) 281218893Sdim return; 282218893Sdim 283218893Sdim const EHPersonality &ObjCXX = EHPersonality::get(Features); 284218893Sdim const EHPersonality &CXX = getCXXPersonality(Features); 285218893Sdim if (&ObjCXX == &CXX || 286218893Sdim ObjCXX.getPersonalityFnName() == CXX.getPersonalityFnName()) 287218893Sdim return; 288218893Sdim 289218893Sdim llvm::Function *Fn = 290218893Sdim getModule().getFunction(ObjCXX.getPersonalityFnName()); 291218893Sdim 292218893Sdim // Nothing to do if it's unused. 293218893Sdim if (!Fn || Fn->use_empty()) return; 294218893Sdim 295218893Sdim // Can't do the optimization if it has non-C++ uses. 296218893Sdim if (!PersonalityHasOnlyCXXUses(Fn)) return; 297218893Sdim 298218893Sdim // Create the C++ personality function and kill off the old 299218893Sdim // function. 300218893Sdim llvm::Constant *CXXFn = getPersonalityFn(*this, CXX); 301218893Sdim 302218893Sdim // This can happen if the user is screwing with us. 303218893Sdim if (Fn->getType() != CXXFn->getType()) return; 304218893Sdim 305218893Sdim Fn->replaceAllUsesWith(CXXFn); 306218893Sdim Fn->eraseFromParent(); 307218893Sdim} 308218893Sdim 309210299Sed/// Returns the value to inject into a selector to indicate the 310210299Sed/// presence of a catch-all. 311210299Sedstatic llvm::Constant *getCatchAllValue(CodeGenFunction &CGF) { 312210299Sed // Possibly we should use @llvm.eh.catch.all.value here. 313218893Sdim return llvm::ConstantPointerNull::get(CGF.Int8PtrTy); 314210299Sed} 315210299Sed 316210299Sed/// Returns the value to inject into a selector to indicate the 317210299Sed/// presence of a cleanup. 318210299Sedstatic llvm::Constant *getCleanupValue(CodeGenFunction &CGF) { 319210299Sed return llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); 320210299Sed} 321210299Sed 322210299Sednamespace { 323210299Sed /// A cleanup to free the exception object if its initialization 324210299Sed /// throws. 325218893Sdim struct FreeException { 326218893Sdim static void Emit(CodeGenFunction &CGF, bool forEH, 327218893Sdim llvm::Value *exn) { 328218893Sdim CGF.Builder.CreateCall(getFreeExceptionFn(CGF), exn) 329210299Sed ->setDoesNotThrow(); 330210299Sed } 331210299Sed }; 332210299Sed} 333210299Sed 334207619Srdivacky// Emits an exception expression into the given location. This 335207619Srdivacky// differs from EmitAnyExprToMem only in that, if a final copy-ctor 336207619Srdivacky// call is required, an exception within that copy ctor causes 337207619Srdivacky// std::terminate to be invoked. 338218893Sdimstatic void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *e, 339218893Sdim llvm::Value *addr) { 340210299Sed // Make sure the exception object is cleaned up if there's an 341210299Sed // exception during initialization. 342218893Sdim CGF.pushFullExprCleanup<FreeException>(EHCleanup, addr); 343218893Sdim EHScopeStack::stable_iterator cleanup = CGF.EHStack.stable_begin(); 344201361Srdivacky 345207619Srdivacky // __cxa_allocate_exception returns a void*; we need to cast this 346207619Srdivacky // to the appropriate type for the object. 347218893Sdim const llvm::Type *ty = CGF.ConvertTypeForMem(e->getType())->getPointerTo(); 348218893Sdim llvm::Value *typedAddr = CGF.Builder.CreateBitCast(addr, ty); 349200583Srdivacky 350207619Srdivacky // FIXME: this isn't quite right! If there's a final unelided call 351207619Srdivacky // to a copy constructor, then according to [except.terminate]p1 we 352207619Srdivacky // must call std::terminate() if that constructor throws, because 353207619Srdivacky // technically that copy occurs after the exception expression is 354207619Srdivacky // evaluated but before the exception is caught. But the best way 355207619Srdivacky // to handle that is to teach EmitAggExpr to do the final copy 356207619Srdivacky // differently if it can't be elided. 357218893Sdim CGF.EmitAnyExprToMem(e, typedAddr, /*Volatile*/ false, /*IsInit*/ true); 358201361Srdivacky 359218893Sdim // Deactivate the cleanup block. 360218893Sdim CGF.DeactivateCleanupBlock(cleanup); 361199990Srdivacky} 362199990Srdivacky 363210299Sedllvm::Value *CodeGenFunction::getExceptionSlot() { 364223017Sdim if (!ExceptionSlot) 365223017Sdim ExceptionSlot = CreateTempAlloca(Int8PtrTy, "exn.slot"); 366210299Sed return ExceptionSlot; 367199990Srdivacky} 368199990Srdivacky 369223017Sdimllvm::Value *CodeGenFunction::getEHSelectorSlot() { 370223017Sdim if (!EHSelectorSlot) 371223017Sdim EHSelectorSlot = CreateTempAlloca(Int32Ty, "ehselector.slot"); 372223017Sdim return EHSelectorSlot; 373223017Sdim} 374223017Sdim 375198893Srdivackyvoid CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { 376198893Srdivacky if (!E->getSubExpr()) { 377200583Srdivacky if (getInvokeDest()) { 378210299Sed Builder.CreateInvoke(getReThrowFn(*this), 379210299Sed getUnreachableBlock(), 380210299Sed getInvokeDest()) 381200583Srdivacky ->setDoesNotReturn(); 382210299Sed } else { 383200583Srdivacky Builder.CreateCall(getReThrowFn(*this))->setDoesNotReturn(); 384210299Sed Builder.CreateUnreachable(); 385210299Sed } 386199990Srdivacky 387218893Sdim // throw is an expression, and the expression emitters expect us 388218893Sdim // to leave ourselves at a valid insertion point. 389218893Sdim EmitBlock(createBasicBlock("throw.cont")); 390218893Sdim 391198893Srdivacky return; 392198893Srdivacky } 393200583Srdivacky 394198893Srdivacky QualType ThrowType = E->getSubExpr()->getType(); 395200583Srdivacky 396198893Srdivacky // Now allocate the exception object. 397198893Srdivacky const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); 398207619Srdivacky uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity(); 399200583Srdivacky 400198893Srdivacky llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(*this); 401210299Sed llvm::CallInst *ExceptionPtr = 402200583Srdivacky Builder.CreateCall(AllocExceptionFn, 403198893Srdivacky llvm::ConstantInt::get(SizeTy, TypeSize), 404198893Srdivacky "exception"); 405210299Sed ExceptionPtr->setDoesNotThrow(); 406200583Srdivacky 407207619Srdivacky EmitAnyExprToExn(*this, E->getSubExpr(), ExceptionPtr); 408198893Srdivacky 409198893Srdivacky // Now throw the exception. 410198893Srdivacky const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); 411218893Sdim llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType, 412218893Sdim /*ForEH=*/true); 413200583Srdivacky 414207619Srdivacky // The address of the destructor. If the exception type has a 415207619Srdivacky // trivial destructor (or isn't a record), we just pass null. 416207619Srdivacky llvm::Constant *Dtor = 0; 417207619Srdivacky if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) { 418207619Srdivacky CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); 419207619Srdivacky if (!Record->hasTrivialDestructor()) { 420210299Sed CXXDestructorDecl *DtorD = Record->getDestructor(); 421207619Srdivacky Dtor = CGM.GetAddrOfCXXDestructor(DtorD, Dtor_Complete); 422207619Srdivacky Dtor = llvm::ConstantExpr::getBitCast(Dtor, Int8PtrTy); 423207619Srdivacky } 424207619Srdivacky } 425207619Srdivacky if (!Dtor) Dtor = llvm::Constant::getNullValue(Int8PtrTy); 426207619Srdivacky 427200583Srdivacky if (getInvokeDest()) { 428200583Srdivacky llvm::InvokeInst *ThrowCall = 429210299Sed Builder.CreateInvoke3(getThrowFn(*this), 430210299Sed getUnreachableBlock(), getInvokeDest(), 431200583Srdivacky ExceptionPtr, TypeInfo, Dtor); 432200583Srdivacky ThrowCall->setDoesNotReturn(); 433200583Srdivacky } else { 434200583Srdivacky llvm::CallInst *ThrowCall = 435200583Srdivacky Builder.CreateCall3(getThrowFn(*this), ExceptionPtr, TypeInfo, Dtor); 436200583Srdivacky ThrowCall->setDoesNotReturn(); 437210299Sed Builder.CreateUnreachable(); 438200583Srdivacky } 439200583Srdivacky 440218893Sdim // throw is an expression, and the expression emitters expect us 441218893Sdim // to leave ourselves at a valid insertion point. 442218893Sdim EmitBlock(createBasicBlock("throw.cont")); 443198893Srdivacky} 444199990Srdivacky 445200583Srdivackyvoid CodeGenFunction::EmitStartEHSpec(const Decl *D) { 446221345Sdim if (!CGM.getLangOptions().CXXExceptions) 447203955Srdivacky return; 448203955Srdivacky 449200583Srdivacky const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); 450200583Srdivacky if (FD == 0) 451200583Srdivacky return; 452200583Srdivacky const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); 453200583Srdivacky if (Proto == 0) 454200583Srdivacky return; 455200583Srdivacky 456221345Sdim ExceptionSpecificationType EST = Proto->getExceptionSpecType(); 457221345Sdim if (isNoexceptExceptionSpec(EST)) { 458221345Sdim if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) { 459221345Sdim // noexcept functions are simple terminate scopes. 460221345Sdim EHStack.pushTerminate(); 461221345Sdim } 462221345Sdim } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { 463221345Sdim unsigned NumExceptions = Proto->getNumExceptions(); 464221345Sdim EHFilterScope *Filter = EHStack.pushFilter(NumExceptions); 465200583Srdivacky 466221345Sdim for (unsigned I = 0; I != NumExceptions; ++I) { 467221345Sdim QualType Ty = Proto->getExceptionType(I); 468221345Sdim QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType(); 469221345Sdim llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType, 470221345Sdim /*ForEH=*/true); 471221345Sdim Filter->setFilter(I, EHType); 472221345Sdim } 473200583Srdivacky } 474200583Srdivacky} 475200583Srdivacky 476200583Srdivackyvoid CodeGenFunction::EmitEndEHSpec(const Decl *D) { 477221345Sdim if (!CGM.getLangOptions().CXXExceptions) 478203955Srdivacky return; 479203955Srdivacky 480200583Srdivacky const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); 481200583Srdivacky if (FD == 0) 482200583Srdivacky return; 483200583Srdivacky const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); 484200583Srdivacky if (Proto == 0) 485200583Srdivacky return; 486200583Srdivacky 487221345Sdim ExceptionSpecificationType EST = Proto->getExceptionSpecType(); 488221345Sdim if (isNoexceptExceptionSpec(EST)) { 489221345Sdim if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) { 490221345Sdim EHStack.popTerminate(); 491221345Sdim } 492221345Sdim } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { 493221345Sdim EHStack.popFilter(); 494221345Sdim } 495200583Srdivacky} 496200583Srdivacky 497199990Srdivackyvoid CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { 498210299Sed EnterCXXTryStmt(S); 499204643Srdivacky EmitStmt(S.getTryBlock()); 500210299Sed ExitCXXTryStmt(S); 501204643Srdivacky} 502204643Srdivacky 503210299Sedvoid CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { 504210299Sed unsigned NumHandlers = S.getNumHandlers(); 505210299Sed EHCatchScope *CatchScope = EHStack.pushCatch(NumHandlers); 506204643Srdivacky 507210299Sed for (unsigned I = 0; I != NumHandlers; ++I) { 508210299Sed const CXXCatchStmt *C = S.getHandler(I); 509204643Srdivacky 510210299Sed llvm::BasicBlock *Handler = createBasicBlock("catch"); 511210299Sed if (C->getExceptionDecl()) { 512210299Sed // FIXME: Dropping the reference type on the type into makes it 513210299Sed // impossible to correctly implement catch-by-reference 514210299Sed // semantics for pointers. Unfortunately, this is what all 515210299Sed // existing compilers do, and it's not clear that the standard 516210299Sed // personality routine is capable of doing this right. See C++ DR 388: 517210299Sed // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388 518210299Sed QualType CaughtType = C->getCaughtType(); 519210299Sed CaughtType = CaughtType.getNonReferenceType().getUnqualifiedType(); 520212904Sdim 521212904Sdim llvm::Value *TypeInfo = 0; 522212904Sdim if (CaughtType->isObjCObjectPointerType()) 523212904Sdim TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType); 524212904Sdim else 525218893Sdim TypeInfo = CGM.GetAddrOfRTTIDescriptor(CaughtType, /*ForEH=*/true); 526210299Sed CatchScope->setHandler(I, TypeInfo, Handler); 527210299Sed } else { 528210299Sed // No exception decl indicates '...', a catch-all. 529210299Sed CatchScope->setCatchAllHandler(I, Handler); 530210299Sed } 531210299Sed } 532204643Srdivacky} 533204643Srdivacky 534210299Sed/// Check whether this is a non-EH scope, i.e. a scope which doesn't 535210299Sed/// affect exception handling. Currently, the only non-EH scopes are 536210299Sed/// normal-only cleanup scopes. 537210299Sedstatic bool isNonEHScope(const EHScope &S) { 538210299Sed switch (S.getKind()) { 539210299Sed case EHScope::Cleanup: 540210299Sed return !cast<EHCleanupScope>(S).isEHCleanup(); 541210299Sed case EHScope::Filter: 542210299Sed case EHScope::Catch: 543210299Sed case EHScope::Terminate: 544210299Sed return false; 545210299Sed } 546199990Srdivacky 547210299Sed // Suppress warning. 548210299Sed return false; 549210299Sed} 550199990Srdivacky 551210299Sedllvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() { 552210299Sed assert(EHStack.requiresLandingPad()); 553210299Sed assert(!EHStack.empty()); 554199990Srdivacky 555221345Sdim if (!CGM.getLangOptions().Exceptions) 556210299Sed return 0; 557200583Srdivacky 558210299Sed // Check the innermost scope for a cached landing pad. If this is 559210299Sed // a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad. 560210299Sed llvm::BasicBlock *LP = EHStack.begin()->getCachedLandingPad(); 561210299Sed if (LP) return LP; 562200583Srdivacky 563210299Sed // Build the landing pad for this scope. 564210299Sed LP = EmitLandingPad(); 565210299Sed assert(LP); 566199990Srdivacky 567210299Sed // Cache the landing pad on the innermost scope. If this is a 568210299Sed // non-EH scope, cache the landing pad on the enclosing scope, too. 569210299Sed for (EHScopeStack::iterator ir = EHStack.begin(); true; ++ir) { 570210299Sed ir->setCachedLandingPad(LP); 571210299Sed if (!isNonEHScope(*ir)) break; 572210299Sed } 573199990Srdivacky 574210299Sed return LP; 575210299Sed} 576210299Sed 577223017Sdim// This code contains a hack to work around a design flaw in 578223017Sdim// LLVM's EH IR which breaks semantics after inlining. This same 579223017Sdim// hack is implemented in llvm-gcc. 580223017Sdim// 581223017Sdim// The LLVM EH abstraction is basically a thin veneer over the 582223017Sdim// traditional GCC zero-cost design: for each range of instructions 583223017Sdim// in the function, there is (at most) one "landing pad" with an 584223017Sdim// associated chain of EH actions. A language-specific personality 585223017Sdim// function interprets this chain of actions and (1) decides whether 586223017Sdim// or not to resume execution at the landing pad and (2) if so, 587223017Sdim// provides an integer indicating why it's stopping. In LLVM IR, 588223017Sdim// the association of a landing pad with a range of instructions is 589223017Sdim// achieved via an invoke instruction, the chain of actions becomes 590223017Sdim// the arguments to the @llvm.eh.selector call, and the selector 591223017Sdim// call returns the integer indicator. Other than the required 592223017Sdim// presence of two intrinsic function calls in the landing pad, 593223017Sdim// the IR exactly describes the layout of the output code. 594223017Sdim// 595223017Sdim// A principal advantage of this design is that it is completely 596223017Sdim// language-agnostic; in theory, the LLVM optimizers can treat 597223017Sdim// landing pads neutrally, and targets need only know how to lower 598223017Sdim// the intrinsics to have a functioning exceptions system (assuming 599223017Sdim// that platform exceptions follow something approximately like the 600223017Sdim// GCC design). Unfortunately, landing pads cannot be combined in a 601223017Sdim// language-agnostic way: given selectors A and B, there is no way 602223017Sdim// to make a single landing pad which faithfully represents the 603223017Sdim// semantics of propagating an exception first through A, then 604223017Sdim// through B, without knowing how the personality will interpret the 605223017Sdim// (lowered form of the) selectors. This means that inlining has no 606223017Sdim// choice but to crudely chain invokes (i.e., to ignore invokes in 607223017Sdim// the inlined function, but to turn all unwindable calls into 608223017Sdim// invokes), which is only semantically valid if every unwind stops 609223017Sdim// at every landing pad. 610223017Sdim// 611223017Sdim// Therefore, the invoke-inline hack is to guarantee that every 612223017Sdim// landing pad has a catch-all. 613223017Sdimenum CleanupHackLevel_t { 614223017Sdim /// A level of hack that requires that all landing pads have 615223017Sdim /// catch-alls. 616223017Sdim CHL_MandatoryCatchall, 617223017Sdim 618223017Sdim /// A level of hack that requires that all landing pads handle 619223017Sdim /// cleanups. 620223017Sdim CHL_MandatoryCleanup, 621223017Sdim 622223017Sdim /// No hacks at all; ideal IR generation. 623223017Sdim CHL_Ideal 624223017Sdim}; 625223017Sdimconst CleanupHackLevel_t CleanupHackLevel = CHL_MandatoryCleanup; 626223017Sdim 627210299Sedllvm::BasicBlock *CodeGenFunction::EmitLandingPad() { 628210299Sed assert(EHStack.requiresLandingPad()); 629210299Sed 630210299Sed for (EHScopeStack::iterator ir = EHStack.begin(); ; ) { 631210299Sed assert(ir != EHStack.end() && 632210299Sed "stack requiring landing pad is nothing but non-EH scopes?"); 633210299Sed 634210299Sed // If this is a terminate scope, just use the singleton terminate 635210299Sed // landing pad. 636210299Sed if (isa<EHTerminateScope>(*ir)) 637210299Sed return getTerminateLandingPad(); 638210299Sed 639210299Sed // If this isn't an EH scope, iterate; otherwise break out. 640210299Sed if (!isNonEHScope(*ir)) break; 641210299Sed ++ir; 642210299Sed 643210299Sed // We haven't checked this scope for a cached landing pad yet. 644210299Sed if (llvm::BasicBlock *LP = ir->getCachedLandingPad()) 645210299Sed return LP; 646210299Sed } 647210299Sed 648210299Sed // Save the current IR generation state. 649210299Sed CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 650210299Sed 651218893Sdim const EHPersonality &Personality = EHPersonality::get(getLangOptions()); 652212904Sdim 653210299Sed // Create and configure the landing pad. 654210299Sed llvm::BasicBlock *LP = createBasicBlock("lpad"); 655210299Sed EmitBlock(LP); 656210299Sed 657210299Sed // Save the exception pointer. It's safe to use a single exception 658210299Sed // pointer per function because EH cleanups can never have nested 659210299Sed // try/catches. 660210299Sed llvm::CallInst *Exn = 661210299Sed Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn"); 662210299Sed Exn->setDoesNotThrow(); 663210299Sed Builder.CreateStore(Exn, getExceptionSlot()); 664210299Sed 665210299Sed // Build the selector arguments. 666210299Sed llvm::SmallVector<llvm::Value*, 8> EHSelector; 667210299Sed EHSelector.push_back(Exn); 668218893Sdim EHSelector.push_back(getOpaquePersonalityFn(CGM, Personality)); 669210299Sed 670210299Sed // Accumulate all the handlers in scope. 671212904Sdim llvm::DenseMap<llvm::Value*, UnwindDest> EHHandlers; 672212904Sdim UnwindDest CatchAll; 673210299Sed bool HasEHCleanup = false; 674210299Sed bool HasEHFilter = false; 675210299Sed llvm::SmallVector<llvm::Value*, 8> EHFilters; 676210299Sed for (EHScopeStack::iterator I = EHStack.begin(), E = EHStack.end(); 677210299Sed I != E; ++I) { 678210299Sed 679210299Sed switch (I->getKind()) { 680210299Sed case EHScope::Cleanup: 681210299Sed if (!HasEHCleanup) 682210299Sed HasEHCleanup = cast<EHCleanupScope>(*I).isEHCleanup(); 683210299Sed // We otherwise don't care about cleanups. 684210299Sed continue; 685210299Sed 686210299Sed case EHScope::Filter: { 687210299Sed assert(I.next() == EHStack.end() && "EH filter is not end of EH stack"); 688212904Sdim assert(!CatchAll.isValid() && "EH filter reached after catch-all"); 689210299Sed 690221345Sdim // Filter scopes get added to the selector in weird ways. 691210299Sed EHFilterScope &Filter = cast<EHFilterScope>(*I); 692210299Sed HasEHFilter = true; 693210299Sed 694210299Sed // Add all the filter values which we aren't already explicitly 695210299Sed // catching. 696210299Sed for (unsigned I = 0, E = Filter.getNumFilters(); I != E; ++I) { 697210299Sed llvm::Value *FV = Filter.getFilter(I); 698210299Sed if (!EHHandlers.count(FV)) 699210299Sed EHFilters.push_back(FV); 700210299Sed } 701210299Sed goto done; 702199990Srdivacky } 703210299Sed 704210299Sed case EHScope::Terminate: 705210299Sed // Terminate scopes are basically catch-alls. 706212904Sdim assert(!CatchAll.isValid()); 707212904Sdim CatchAll = UnwindDest(getTerminateHandler(), 708212904Sdim EHStack.getEnclosingEHCleanup(I), 709212904Sdim cast<EHTerminateScope>(*I).getDestIndex()); 710210299Sed goto done; 711210299Sed 712210299Sed case EHScope::Catch: 713210299Sed break; 714210299Sed } 715210299Sed 716210299Sed EHCatchScope &Catch = cast<EHCatchScope>(*I); 717210299Sed for (unsigned HI = 0, HE = Catch.getNumHandlers(); HI != HE; ++HI) { 718210299Sed EHCatchScope::Handler Handler = Catch.getHandler(HI); 719210299Sed 720210299Sed // Catch-all. We should only have one of these per catch. 721210299Sed if (!Handler.Type) { 722212904Sdim assert(!CatchAll.isValid()); 723212904Sdim CatchAll = UnwindDest(Handler.Block, 724212904Sdim EHStack.getEnclosingEHCleanup(I), 725212904Sdim Handler.Index); 726210299Sed continue; 727210299Sed } 728210299Sed 729210299Sed // Check whether we already have a handler for this type. 730212904Sdim UnwindDest &Dest = EHHandlers[Handler.Type]; 731212904Sdim if (Dest.isValid()) continue; 732210299Sed 733210299Sed EHSelector.push_back(Handler.Type); 734212904Sdim Dest = UnwindDest(Handler.Block, 735212904Sdim EHStack.getEnclosingEHCleanup(I), 736212904Sdim Handler.Index); 737210299Sed } 738210299Sed 739210299Sed // Stop if we found a catch-all. 740212904Sdim if (CatchAll.isValid()) break; 741199990Srdivacky } 742199990Srdivacky 743210299Sed done: 744210299Sed unsigned LastToEmitInLoop = EHSelector.size(); 745210299Sed 746210299Sed // If we have a catch-all, add null to the selector. 747212904Sdim if (CatchAll.isValid()) { 748218893Sdim EHSelector.push_back(getCatchAllValue(*this)); 749210299Sed 750210299Sed // If we have an EH filter, we need to add those handlers in the 751210299Sed // right place in the selector, which is to say, at the end. 752210299Sed } else if (HasEHFilter) { 753210299Sed // Create a filter expression: an integer constant saying how many 754210299Sed // filters there are (+1 to avoid ambiguity with 0 for cleanup), 755210299Sed // followed by the filter types. The personality routine only 756210299Sed // lands here if the filter doesn't match. 757210299Sed EHSelector.push_back(llvm::ConstantInt::get(Builder.getInt32Ty(), 758210299Sed EHFilters.size() + 1)); 759210299Sed EHSelector.append(EHFilters.begin(), EHFilters.end()); 760210299Sed 761210299Sed // Also check whether we need a cleanup. 762223017Sdim if (CleanupHackLevel == CHL_MandatoryCatchall || HasEHCleanup) 763223017Sdim EHSelector.push_back(CleanupHackLevel == CHL_MandatoryCatchall 764218893Sdim ? getCatchAllValue(*this) 765218893Sdim : getCleanupValue(*this)); 766210299Sed 767210299Sed // Otherwise, signal that we at least have cleanups. 768223017Sdim } else if (CleanupHackLevel == CHL_MandatoryCatchall || HasEHCleanup) { 769223017Sdim EHSelector.push_back(CleanupHackLevel == CHL_MandatoryCatchall 770218893Sdim ? getCatchAllValue(*this) 771218893Sdim : getCleanupValue(*this)); 772223017Sdim 773223017Sdim // At the MandatoryCleanup hack level, we don't need to actually 774223017Sdim // spuriously tell the unwinder that we have cleanups, but we do 775223017Sdim // need to always be prepared to handle cleanups. 776223017Sdim } else if (CleanupHackLevel == CHL_MandatoryCleanup) { 777223017Sdim // Just don't decrement LastToEmitInLoop. 778223017Sdim 779210299Sed } else { 780210299Sed assert(LastToEmitInLoop > 2); 781210299Sed LastToEmitInLoop--; 782199990Srdivacky } 783199990Srdivacky 784210299Sed assert(EHSelector.size() >= 3 && "selector call has only two arguments!"); 785199990Srdivacky 786210299Sed // Tell the backend how to generate the landing pad. 787210299Sed llvm::CallInst *Selection = 788210299Sed Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector), 789210299Sed EHSelector.begin(), EHSelector.end(), "eh.selector"); 790210299Sed Selection->setDoesNotThrow(); 791223017Sdim 792223017Sdim // Save the selector value in mandatory-cleanup mode. 793223017Sdim if (CleanupHackLevel == CHL_MandatoryCleanup) 794223017Sdim Builder.CreateStore(Selection, getEHSelectorSlot()); 795210299Sed 796210299Sed // Select the right handler. 797210299Sed llvm::Value *llvm_eh_typeid_for = 798210299Sed CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); 799199990Srdivacky 800210299Sed // The results of llvm_eh_typeid_for aren't reliable --- at least 801210299Sed // not locally --- so we basically have to do this as an 'if' chain. 802210299Sed // We walk through the first N-1 catch clauses, testing and chaining, 803210299Sed // and then fall into the final clause (which is either a cleanup, a 804210299Sed // filter (possibly with a cleanup), a catch-all, or another catch). 805210299Sed for (unsigned I = 2; I != LastToEmitInLoop; ++I) { 806210299Sed llvm::Value *Type = EHSelector[I]; 807212904Sdim UnwindDest Dest = EHHandlers[Type]; 808212904Sdim assert(Dest.isValid() && "no handler entry for value in selector?"); 809210299Sed 810210299Sed // Figure out where to branch on a match. As a debug code-size 811210299Sed // optimization, if the scope depth matches the innermost cleanup, 812210299Sed // we branch directly to the catch handler. 813212904Sdim llvm::BasicBlock *Match = Dest.getBlock(); 814212904Sdim bool MatchNeedsCleanup = 815212904Sdim Dest.getScopeDepth() != EHStack.getInnermostEHCleanup(); 816210299Sed if (MatchNeedsCleanup) 817210299Sed Match = createBasicBlock("eh.match"); 818210299Sed 819210299Sed llvm::BasicBlock *Next = createBasicBlock("eh.next"); 820210299Sed 821210299Sed // Check whether the exception matches. 822210299Sed llvm::CallInst *Id 823210299Sed = Builder.CreateCall(llvm_eh_typeid_for, 824218893Sdim Builder.CreateBitCast(Type, Int8PtrTy)); 825210299Sed Id->setDoesNotThrow(); 826210299Sed Builder.CreateCondBr(Builder.CreateICmpEQ(Selection, Id), 827210299Sed Match, Next); 828210299Sed 829210299Sed // Emit match code if necessary. 830210299Sed if (MatchNeedsCleanup) { 831199990Srdivacky EmitBlock(Match); 832210299Sed EmitBranchThroughEHCleanup(Dest); 833199990Srdivacky } 834199990Srdivacky 835210299Sed // Continue to the next match. 836210299Sed EmitBlock(Next); 837210299Sed } 838199990Srdivacky 839210299Sed // Emit the final case in the selector. 840210299Sed // This might be a catch-all.... 841212904Sdim if (CatchAll.isValid()) { 842210299Sed assert(isa<llvm::ConstantPointerNull>(EHSelector.back())); 843210299Sed EmitBranchThroughEHCleanup(CatchAll); 844199990Srdivacky 845210299Sed // ...or an EH filter... 846210299Sed } else if (HasEHFilter) { 847210299Sed llvm::Value *SavedSelection = Selection; 848199990Srdivacky 849210299Sed // First, unwind out to the outermost scope if necessary. 850210299Sed if (EHStack.hasEHCleanups()) { 851210299Sed // The end here might not dominate the beginning, so we might need to 852210299Sed // save the selector if we need it. 853210299Sed llvm::AllocaInst *SelectorVar = 0; 854210299Sed if (HasEHCleanup) { 855210299Sed SelectorVar = CreateTempAlloca(Builder.getInt32Ty(), "selector.var"); 856210299Sed Builder.CreateStore(Selection, SelectorVar); 857200583Srdivacky } 858200583Srdivacky 859210299Sed llvm::BasicBlock *CleanupContBB = createBasicBlock("ehspec.cleanup.cont"); 860212904Sdim EmitBranchThroughEHCleanup(UnwindDest(CleanupContBB, EHStack.stable_end(), 861212904Sdim EHStack.getNextEHDestIndex())); 862210299Sed EmitBlock(CleanupContBB); 863210299Sed 864210299Sed if (HasEHCleanup) 865210299Sed SavedSelection = Builder.CreateLoad(SelectorVar, "ehspec.saved-selector"); 866199990Srdivacky } 867199990Srdivacky 868210299Sed // If there was a cleanup, we'll need to actually check whether we 869210299Sed // landed here because the filter triggered. 870223017Sdim if (CleanupHackLevel != CHL_Ideal || HasEHCleanup) { 871210299Sed llvm::BasicBlock *UnexpectedBB = createBasicBlock("ehspec.unexpected"); 872199990Srdivacky 873223017Sdim llvm::Constant *Zero = llvm::ConstantInt::get(Int32Ty, 0); 874210299Sed llvm::Value *FailsFilter = 875210299Sed Builder.CreateICmpSLT(SavedSelection, Zero, "ehspec.fails"); 876223017Sdim Builder.CreateCondBr(FailsFilter, UnexpectedBB, getRethrowDest().getBlock()); 877199990Srdivacky 878210299Sed EmitBlock(UnexpectedBB); 879210299Sed } 880199990Srdivacky 881210299Sed // Call __cxa_call_unexpected. This doesn't need to be an invoke 882210299Sed // because __cxa_call_unexpected magically filters exceptions 883210299Sed // according to the last landing pad the exception was thrown 884210299Sed // into. Seriously. 885210299Sed Builder.CreateCall(getUnexpectedFn(*this), 886210299Sed Builder.CreateLoad(getExceptionSlot())) 887210299Sed ->setDoesNotReturn(); 888210299Sed Builder.CreateUnreachable(); 889199990Srdivacky 890210299Sed // ...or a normal catch handler... 891223017Sdim } else if (CleanupHackLevel == CHL_Ideal && !HasEHCleanup) { 892210299Sed llvm::Value *Type = EHSelector.back(); 893210299Sed EmitBranchThroughEHCleanup(EHHandlers[Type]); 894199990Srdivacky 895210299Sed // ...or a cleanup. 896210299Sed } else { 897212904Sdim EmitBranchThroughEHCleanup(getRethrowDest()); 898199990Srdivacky } 899210299Sed 900210299Sed // Restore the old IR generation state. 901210299Sed Builder.restoreIP(SavedIP); 902210299Sed 903210299Sed return LP; 904210299Sed} 905210299Sed 906210299Sednamespace { 907210299Sed /// A cleanup to call __cxa_end_catch. In many cases, the caught 908210299Sed /// exception type lets us state definitively that the thrown exception 909210299Sed /// type does not have a destructor. In particular: 910210299Sed /// - Catch-alls tell us nothing, so we have to conservatively 911210299Sed /// assume that the thrown exception might have a destructor. 912210299Sed /// - Catches by reference behave according to their base types. 913210299Sed /// - Catches of non-record types will only trigger for exceptions 914210299Sed /// of non-record types, which never have destructors. 915210299Sed /// - Catches of record types can trigger for arbitrary subclasses 916210299Sed /// of the caught type, so we have to assume the actual thrown 917210299Sed /// exception type might have a throwing destructor, even if the 918210299Sed /// caught type's destructor is trivial or nothrow. 919212904Sdim struct CallEndCatch : EHScopeStack::Cleanup { 920210299Sed CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {} 921210299Sed bool MightThrow; 922210299Sed 923210299Sed void Emit(CodeGenFunction &CGF, bool IsForEH) { 924210299Sed if (!MightThrow) { 925210299Sed CGF.Builder.CreateCall(getEndCatchFn(CGF))->setDoesNotThrow(); 926210299Sed return; 927210299Sed } 928210299Sed 929210299Sed CGF.EmitCallOrInvoke(getEndCatchFn(CGF), 0, 0); 930210299Sed } 931210299Sed }; 932210299Sed} 933210299Sed 934210299Sed/// Emits a call to __cxa_begin_catch and enters a cleanup to call 935210299Sed/// __cxa_end_catch. 936210299Sed/// 937210299Sed/// \param EndMightThrow - true if __cxa_end_catch might throw 938210299Sedstatic llvm::Value *CallBeginCatch(CodeGenFunction &CGF, 939210299Sed llvm::Value *Exn, 940210299Sed bool EndMightThrow) { 941210299Sed llvm::CallInst *Call = CGF.Builder.CreateCall(getBeginCatchFn(CGF), Exn); 942210299Sed Call->setDoesNotThrow(); 943210299Sed 944212904Sdim CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow); 945210299Sed 946210299Sed return Call; 947210299Sed} 948210299Sed 949210299Sed/// A "special initializer" callback for initializing a catch 950210299Sed/// parameter during catch initialization. 951210299Sedstatic void InitCatchParam(CodeGenFunction &CGF, 952210299Sed const VarDecl &CatchParam, 953210299Sed llvm::Value *ParamAddr) { 954210299Sed // Load the exception from where the landing pad saved it. 955210299Sed llvm::Value *Exn = CGF.Builder.CreateLoad(CGF.getExceptionSlot(), "exn"); 956210299Sed 957210299Sed CanQualType CatchType = 958210299Sed CGF.CGM.getContext().getCanonicalType(CatchParam.getType()); 959210299Sed const llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType); 960210299Sed 961210299Sed // If we're catching by reference, we can just cast the object 962210299Sed // pointer to the appropriate pointer. 963210299Sed if (isa<ReferenceType>(CatchType)) { 964212904Sdim QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType(); 965212904Sdim bool EndCatchMightThrow = CaughtType->isRecordType(); 966210299Sed 967210299Sed // __cxa_begin_catch returns the adjusted object pointer. 968210299Sed llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow); 969212904Sdim 970212904Sdim // We have no way to tell the personality function that we're 971212904Sdim // catching by reference, so if we're catching a pointer, 972212904Sdim // __cxa_begin_catch will actually return that pointer by value. 973212904Sdim if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) { 974212904Sdim QualType PointeeType = PT->getPointeeType(); 975212904Sdim 976212904Sdim // When catching by reference, generally we should just ignore 977212904Sdim // this by-value pointer and use the exception object instead. 978212904Sdim if (!PointeeType->isRecordType()) { 979212904Sdim 980212904Sdim // Exn points to the struct _Unwind_Exception header, which 981212904Sdim // we have to skip past in order to reach the exception data. 982212904Sdim unsigned HeaderSize = 983212904Sdim CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException(); 984212904Sdim AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize); 985212904Sdim 986212904Sdim // However, if we're catching a pointer-to-record type that won't 987212904Sdim // work, because the personality function might have adjusted 988212904Sdim // the pointer. There's actually no way for us to fully satisfy 989212904Sdim // the language/ABI contract here: we can't use Exn because it 990212904Sdim // might have the wrong adjustment, but we can't use the by-value 991212904Sdim // pointer because it's off by a level of abstraction. 992212904Sdim // 993212904Sdim // The current solution is to dump the adjusted pointer into an 994212904Sdim // alloca, which breaks language semantics (because changing the 995212904Sdim // pointer doesn't change the exception) but at least works. 996212904Sdim // The better solution would be to filter out non-exact matches 997212904Sdim // and rethrow them, but this is tricky because the rethrow 998212904Sdim // really needs to be catchable by other sites at this landing 999212904Sdim // pad. The best solution is to fix the personality function. 1000212904Sdim } else { 1001212904Sdim // Pull the pointer for the reference type off. 1002212904Sdim const llvm::Type *PtrTy = 1003212904Sdim cast<llvm::PointerType>(LLVMCatchTy)->getElementType(); 1004212904Sdim 1005212904Sdim // Create the temporary and write the adjusted pointer into it. 1006212904Sdim llvm::Value *ExnPtrTmp = CGF.CreateTempAlloca(PtrTy, "exn.byref.tmp"); 1007212904Sdim llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); 1008212904Sdim CGF.Builder.CreateStore(Casted, ExnPtrTmp); 1009212904Sdim 1010212904Sdim // Bind the reference to the temporary. 1011212904Sdim AdjustedExn = ExnPtrTmp; 1012212904Sdim } 1013212904Sdim } 1014212904Sdim 1015210299Sed llvm::Value *ExnCast = 1016210299Sed CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref"); 1017210299Sed CGF.Builder.CreateStore(ExnCast, ParamAddr); 1018210299Sed return; 1019200583Srdivacky } 1020199990Srdivacky 1021210299Sed // Non-aggregates (plus complexes). 1022210299Sed bool IsComplex = false; 1023210299Sed if (!CGF.hasAggregateLLVMType(CatchType) || 1024210299Sed (IsComplex = CatchType->isAnyComplexType())) { 1025210299Sed llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false); 1026210299Sed 1027210299Sed // If the catch type is a pointer type, __cxa_begin_catch returns 1028210299Sed // the pointer by value. 1029210299Sed if (CatchType->hasPointerRepresentation()) { 1030210299Sed llvm::Value *CastExn = 1031210299Sed CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted"); 1032210299Sed CGF.Builder.CreateStore(CastExn, ParamAddr); 1033210299Sed return; 1034210299Sed } 1035199990Srdivacky 1036210299Sed // Otherwise, it returns a pointer into the exception object. 1037199990Srdivacky 1038210299Sed const llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok 1039210299Sed llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); 1040199990Srdivacky 1041210299Sed if (IsComplex) { 1042210299Sed CGF.StoreComplexToAddr(CGF.LoadComplexFromAddr(Cast, /*volatile*/ false), 1043210299Sed ParamAddr, /*volatile*/ false); 1044210299Sed } else { 1045212904Sdim unsigned Alignment = 1046212904Sdim CGF.getContext().getDeclAlign(&CatchParam).getQuantity(); 1047210299Sed llvm::Value *ExnLoad = CGF.Builder.CreateLoad(Cast, "exn.scalar"); 1048212904Sdim CGF.EmitStoreOfScalar(ExnLoad, ParamAddr, /*volatile*/ false, Alignment, 1049212904Sdim CatchType); 1050210299Sed } 1051210299Sed return; 1052210299Sed } 1053199990Srdivacky 1054218893Sdim assert(isa<RecordType>(CatchType) && "unexpected catch type!"); 1055199990Srdivacky 1056210299Sed const llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok 1057199990Srdivacky 1058218893Sdim // Check for a copy expression. If we don't have a copy expression, 1059218893Sdim // that means a trivial copy is okay. 1060218893Sdim const Expr *copyExpr = CatchParam.getInit(); 1061218893Sdim if (!copyExpr) { 1062218893Sdim llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true); 1063218893Sdim llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy); 1064218893Sdim CGF.EmitAggregateCopy(ParamAddr, adjustedExn, CatchType); 1065210299Sed return; 1066210299Sed } 1067210299Sed 1068210299Sed // We have to call __cxa_get_exception_ptr to get the adjusted 1069210299Sed // pointer before copying. 1070218893Sdim llvm::CallInst *rawAdjustedExn = 1071210299Sed CGF.Builder.CreateCall(getGetExceptionPtrFn(CGF), Exn); 1072218893Sdim rawAdjustedExn->setDoesNotThrow(); 1073210299Sed 1074218893Sdim // Cast that to the appropriate type. 1075218893Sdim llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy); 1076210299Sed 1077218893Sdim // The copy expression is defined in terms of an OpaqueValueExpr. 1078218893Sdim // Find it and map it to the adjusted expression. 1079218893Sdim CodeGenFunction::OpaqueValueMapping 1080218893Sdim opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr), 1081218893Sdim CGF.MakeAddrLValue(adjustedExn, CatchParam.getType())); 1082210299Sed 1083210299Sed // Call the copy ctor in a terminate scope. 1084210299Sed CGF.EHStack.pushTerminate(); 1085218893Sdim 1086218893Sdim // Perform the copy construction. 1087218893Sdim CGF.EmitAggExpr(copyExpr, AggValueSlot::forAddr(ParamAddr, false, false)); 1088218893Sdim 1089218893Sdim // Leave the terminate scope. 1090210299Sed CGF.EHStack.popTerminate(); 1091210299Sed 1092218893Sdim // Undo the opaque value mapping. 1093218893Sdim opaque.pop(); 1094218893Sdim 1095210299Sed // Finally we can call __cxa_begin_catch. 1096210299Sed CallBeginCatch(CGF, Exn, true); 1097199990Srdivacky} 1098200583Srdivacky 1099210299Sed/// Begins a catch statement by initializing the catch variable and 1100210299Sed/// calling __cxa_begin_catch. 1101218893Sdimstatic void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) { 1102210299Sed // We have to be very careful with the ordering of cleanups here: 1103210299Sed // C++ [except.throw]p4: 1104210299Sed // The destruction [of the exception temporary] occurs 1105210299Sed // immediately after the destruction of the object declared in 1106210299Sed // the exception-declaration in the handler. 1107210299Sed // 1108210299Sed // So the precise ordering is: 1109210299Sed // 1. Construct catch variable. 1110210299Sed // 2. __cxa_begin_catch 1111210299Sed // 3. Enter __cxa_end_catch cleanup 1112210299Sed // 4. Enter dtor cleanup 1113210299Sed // 1114219077Sdim // We do this by using a slightly abnormal initialization process. 1115219077Sdim // Delegation sequence: 1116210299Sed // - ExitCXXTryStmt opens a RunCleanupsScope 1117219077Sdim // - EmitAutoVarAlloca creates the variable and debug info 1118210299Sed // - InitCatchParam initializes the variable from the exception 1119219077Sdim // - CallBeginCatch calls __cxa_begin_catch 1120219077Sdim // - CallBeginCatch enters the __cxa_end_catch cleanup 1121219077Sdim // - EmitAutoVarCleanups enters the variable destructor cleanup 1122210299Sed // - EmitCXXTryStmt emits the code for the catch body 1123210299Sed // - EmitCXXTryStmt close the RunCleanupsScope 1124200583Srdivacky 1125210299Sed VarDecl *CatchParam = S->getExceptionDecl(); 1126210299Sed if (!CatchParam) { 1127210299Sed llvm::Value *Exn = CGF.Builder.CreateLoad(CGF.getExceptionSlot(), "exn"); 1128210299Sed CallBeginCatch(CGF, Exn, true); 1129210299Sed return; 1130210299Sed } 1131200583Srdivacky 1132210299Sed // Emit the local. 1133219077Sdim CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); 1134219077Sdim InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF)); 1135219077Sdim CGF.EmitAutoVarCleanups(var); 1136210299Sed} 1137207619Srdivacky 1138210299Sednamespace { 1139212904Sdim struct CallRethrow : EHScopeStack::Cleanup { 1140210299Sed void Emit(CodeGenFunction &CGF, bool IsForEH) { 1141210299Sed CGF.EmitCallOrInvoke(getReThrowFn(CGF), 0, 0); 1142210299Sed } 1143210299Sed }; 1144210299Sed} 1145207619Srdivacky 1146210299Sedvoid CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { 1147210299Sed unsigned NumHandlers = S.getNumHandlers(); 1148210299Sed EHCatchScope &CatchScope = cast<EHCatchScope>(*EHStack.begin()); 1149210299Sed assert(CatchScope.getNumHandlers() == NumHandlers); 1150207619Srdivacky 1151210299Sed // Copy the handler blocks off before we pop the EH stack. Emitting 1152210299Sed // the handlers might scribble on this memory. 1153210299Sed llvm::SmallVector<EHCatchScope::Handler, 8> Handlers(NumHandlers); 1154210299Sed memcpy(Handlers.data(), CatchScope.begin(), 1155210299Sed NumHandlers * sizeof(EHCatchScope::Handler)); 1156210299Sed EHStack.popCatch(); 1157200583Srdivacky 1158210299Sed // The fall-through block. 1159210299Sed llvm::BasicBlock *ContBB = createBasicBlock("try.cont"); 1160200583Srdivacky 1161210299Sed // We just emitted the body of the try; jump to the continue block. 1162210299Sed if (HaveInsertPoint()) 1163210299Sed Builder.CreateBr(ContBB); 1164210299Sed 1165210299Sed // Determine if we need an implicit rethrow for all these catch handlers. 1166210299Sed bool ImplicitRethrow = false; 1167210299Sed if (IsFnTryBlock) 1168210299Sed ImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) || 1169210299Sed isa<CXXConstructorDecl>(CurCodeDecl); 1170210299Sed 1171210299Sed for (unsigned I = 0; I != NumHandlers; ++I) { 1172210299Sed llvm::BasicBlock *CatchBlock = Handlers[I].Block; 1173210299Sed EmitBlock(CatchBlock); 1174210299Sed 1175210299Sed // Catch the exception if this isn't a catch-all. 1176210299Sed const CXXCatchStmt *C = S.getHandler(I); 1177210299Sed 1178210299Sed // Enter a cleanup scope, including the catch variable and the 1179210299Sed // end-catch. 1180210299Sed RunCleanupsScope CatchScope(*this); 1181210299Sed 1182210299Sed // Initialize the catch variable and set up the cleanups. 1183210299Sed BeginCatch(*this, C); 1184210299Sed 1185210299Sed // If there's an implicit rethrow, push a normal "cleanup" to call 1186210299Sed // _cxa_rethrow. This needs to happen before __cxa_end_catch is 1187210299Sed // called, and so it is pushed after BeginCatch. 1188210299Sed if (ImplicitRethrow) 1189212904Sdim EHStack.pushCleanup<CallRethrow>(NormalCleanup); 1190210299Sed 1191210299Sed // Perform the body of the catch. 1192210299Sed EmitStmt(C->getHandlerBlock()); 1193210299Sed 1194210299Sed // Fall out through the catch cleanups. 1195210299Sed CatchScope.ForceCleanup(); 1196210299Sed 1197210299Sed // Branch out of the try. 1198210299Sed if (HaveInsertPoint()) 1199210299Sed Builder.CreateBr(ContBB); 1200210299Sed } 1201210299Sed 1202210299Sed EmitBlock(ContBB); 1203210299Sed} 1204210299Sed 1205212904Sdimnamespace { 1206212904Sdim struct CallEndCatchForFinally : EHScopeStack::Cleanup { 1207212904Sdim llvm::Value *ForEHVar; 1208212904Sdim llvm::Value *EndCatchFn; 1209212904Sdim CallEndCatchForFinally(llvm::Value *ForEHVar, llvm::Value *EndCatchFn) 1210212904Sdim : ForEHVar(ForEHVar), EndCatchFn(EndCatchFn) {} 1211212904Sdim 1212212904Sdim void Emit(CodeGenFunction &CGF, bool IsForEH) { 1213212904Sdim llvm::BasicBlock *EndCatchBB = CGF.createBasicBlock("finally.endcatch"); 1214212904Sdim llvm::BasicBlock *CleanupContBB = 1215212904Sdim CGF.createBasicBlock("finally.cleanup.cont"); 1216212904Sdim 1217212904Sdim llvm::Value *ShouldEndCatch = 1218212904Sdim CGF.Builder.CreateLoad(ForEHVar, "finally.endcatch"); 1219212904Sdim CGF.Builder.CreateCondBr(ShouldEndCatch, EndCatchBB, CleanupContBB); 1220212904Sdim CGF.EmitBlock(EndCatchBB); 1221212904Sdim CGF.EmitCallOrInvoke(EndCatchFn, 0, 0); // catch-all, so might throw 1222212904Sdim CGF.EmitBlock(CleanupContBB); 1223212904Sdim } 1224212904Sdim }; 1225212904Sdim 1226212904Sdim struct PerformFinally : EHScopeStack::Cleanup { 1227212904Sdim const Stmt *Body; 1228212904Sdim llvm::Value *ForEHVar; 1229212904Sdim llvm::Value *EndCatchFn; 1230212904Sdim llvm::Value *RethrowFn; 1231212904Sdim llvm::Value *SavedExnVar; 1232212904Sdim 1233212904Sdim PerformFinally(const Stmt *Body, llvm::Value *ForEHVar, 1234212904Sdim llvm::Value *EndCatchFn, 1235212904Sdim llvm::Value *RethrowFn, llvm::Value *SavedExnVar) 1236212904Sdim : Body(Body), ForEHVar(ForEHVar), EndCatchFn(EndCatchFn), 1237212904Sdim RethrowFn(RethrowFn), SavedExnVar(SavedExnVar) {} 1238212904Sdim 1239212904Sdim void Emit(CodeGenFunction &CGF, bool IsForEH) { 1240212904Sdim // Enter a cleanup to call the end-catch function if one was provided. 1241212904Sdim if (EndCatchFn) 1242212904Sdim CGF.EHStack.pushCleanup<CallEndCatchForFinally>(NormalAndEHCleanup, 1243212904Sdim ForEHVar, EndCatchFn); 1244212904Sdim 1245212904Sdim // Save the current cleanup destination in case there are 1246212904Sdim // cleanups in the finally block. 1247212904Sdim llvm::Value *SavedCleanupDest = 1248212904Sdim CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot(), 1249212904Sdim "cleanup.dest.saved"); 1250212904Sdim 1251212904Sdim // Emit the finally block. 1252212904Sdim CGF.EmitStmt(Body); 1253212904Sdim 1254212904Sdim // If the end of the finally is reachable, check whether this was 1255212904Sdim // for EH. If so, rethrow. 1256212904Sdim if (CGF.HaveInsertPoint()) { 1257212904Sdim llvm::BasicBlock *RethrowBB = CGF.createBasicBlock("finally.rethrow"); 1258212904Sdim llvm::BasicBlock *ContBB = CGF.createBasicBlock("finally.cont"); 1259212904Sdim 1260212904Sdim llvm::Value *ShouldRethrow = 1261212904Sdim CGF.Builder.CreateLoad(ForEHVar, "finally.shouldthrow"); 1262212904Sdim CGF.Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB); 1263212904Sdim 1264212904Sdim CGF.EmitBlock(RethrowBB); 1265212904Sdim if (SavedExnVar) { 1266212904Sdim llvm::Value *Args[] = { CGF.Builder.CreateLoad(SavedExnVar) }; 1267212904Sdim CGF.EmitCallOrInvoke(RethrowFn, Args, Args+1); 1268212904Sdim } else { 1269212904Sdim CGF.EmitCallOrInvoke(RethrowFn, 0, 0); 1270212904Sdim } 1271212904Sdim CGF.Builder.CreateUnreachable(); 1272212904Sdim 1273212904Sdim CGF.EmitBlock(ContBB); 1274212904Sdim 1275212904Sdim // Restore the cleanup destination. 1276212904Sdim CGF.Builder.CreateStore(SavedCleanupDest, 1277212904Sdim CGF.getNormalCleanupDestSlot()); 1278212904Sdim } 1279212904Sdim 1280212904Sdim // Leave the end-catch cleanup. As an optimization, pretend that 1281212904Sdim // the fallthrough path was inaccessible; we've dynamically proven 1282212904Sdim // that we're not in the EH case along that path. 1283212904Sdim if (EndCatchFn) { 1284212904Sdim CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); 1285212904Sdim CGF.PopCleanupBlock(); 1286212904Sdim CGF.Builder.restoreIP(SavedIP); 1287212904Sdim } 1288212904Sdim 1289212904Sdim // Now make sure we actually have an insertion point or the 1290212904Sdim // cleanup gods will hate us. 1291212904Sdim CGF.EnsureInsertPoint(); 1292212904Sdim } 1293212904Sdim }; 1294212904Sdim} 1295212904Sdim 1296210299Sed/// Enters a finally block for an implementation using zero-cost 1297210299Sed/// exceptions. This is mostly general, but hard-codes some 1298210299Sed/// language/ABI-specific behavior in the catch-all sections. 1299210299SedCodeGenFunction::FinallyInfo 1300210299SedCodeGenFunction::EnterFinallyBlock(const Stmt *Body, 1301210299Sed llvm::Constant *BeginCatchFn, 1302210299Sed llvm::Constant *EndCatchFn, 1303210299Sed llvm::Constant *RethrowFn) { 1304210299Sed assert((BeginCatchFn != 0) == (EndCatchFn != 0) && 1305210299Sed "begin/end catch functions not paired"); 1306210299Sed assert(RethrowFn && "rethrow function is required"); 1307210299Sed 1308210299Sed // The rethrow function has one of the following two types: 1309210299Sed // void (*)() 1310210299Sed // void (*)(void*) 1311210299Sed // In the latter case we need to pass it the exception object. 1312210299Sed // But we can't use the exception slot because the @finally might 1313210299Sed // have a landing pad (which would overwrite the exception slot). 1314210299Sed const llvm::FunctionType *RethrowFnTy = 1315210299Sed cast<llvm::FunctionType>( 1316210299Sed cast<llvm::PointerType>(RethrowFn->getType()) 1317210299Sed ->getElementType()); 1318210299Sed llvm::Value *SavedExnVar = 0; 1319210299Sed if (RethrowFnTy->getNumParams()) 1320210299Sed SavedExnVar = CreateTempAlloca(Builder.getInt8PtrTy(), "finally.exn"); 1321210299Sed 1322210299Sed // A finally block is a statement which must be executed on any edge 1323210299Sed // out of a given scope. Unlike a cleanup, the finally block may 1324210299Sed // contain arbitrary control flow leading out of itself. In 1325210299Sed // addition, finally blocks should always be executed, even if there 1326210299Sed // are no catch handlers higher on the stack. Therefore, we 1327210299Sed // surround the protected scope with a combination of a normal 1328210299Sed // cleanup (to catch attempts to break out of the block via normal 1329210299Sed // control flow) and an EH catch-all (semantically "outside" any try 1330210299Sed // statement to which the finally block might have been attached). 1331210299Sed // The finally block itself is generated in the context of a cleanup 1332210299Sed // which conditionally leaves the catch-all. 1333210299Sed 1334210299Sed FinallyInfo Info; 1335210299Sed 1336210299Sed // Jump destination for performing the finally block on an exception 1337210299Sed // edge. We'll never actually reach this block, so unreachable is 1338210299Sed // fine. 1339210299Sed JumpDest RethrowDest = getJumpDestInCurrentScope(getUnreachableBlock()); 1340210299Sed 1341210299Sed // Whether the finally block is being executed for EH purposes. 1342218893Sdim llvm::AllocaInst *ForEHVar = CreateTempAlloca(Builder.getInt1Ty(), 1343210299Sed "finally.for-eh"); 1344210299Sed InitTempAlloca(ForEHVar, llvm::ConstantInt::getFalse(getLLVMContext())); 1345210299Sed 1346210299Sed // Enter a normal cleanup which will perform the @finally block. 1347212904Sdim EHStack.pushCleanup<PerformFinally>(NormalCleanup, Body, 1348212904Sdim ForEHVar, EndCatchFn, 1349212904Sdim RethrowFn, SavedExnVar); 1350210299Sed 1351210299Sed // Enter a catch-all scope. 1352210299Sed llvm::BasicBlock *CatchAllBB = createBasicBlock("finally.catchall"); 1353210299Sed CGBuilderTy::InsertPoint SavedIP = Builder.saveIP(); 1354210299Sed Builder.SetInsertPoint(CatchAllBB); 1355210299Sed 1356210299Sed // If there's a begin-catch function, call it. 1357210299Sed if (BeginCatchFn) { 1358210299Sed Builder.CreateCall(BeginCatchFn, Builder.CreateLoad(getExceptionSlot())) 1359210299Sed ->setDoesNotThrow(); 1360210299Sed } 1361210299Sed 1362210299Sed // If we need to remember the exception pointer to rethrow later, do so. 1363210299Sed if (SavedExnVar) { 1364210299Sed llvm::Value *SavedExn = Builder.CreateLoad(getExceptionSlot()); 1365210299Sed Builder.CreateStore(SavedExn, SavedExnVar); 1366210299Sed } 1367210299Sed 1368210299Sed // Tell the finally block that we're in EH. 1369210299Sed Builder.CreateStore(llvm::ConstantInt::getTrue(getLLVMContext()), ForEHVar); 1370210299Sed 1371210299Sed // Thread a jump through the finally cleanup. 1372210299Sed EmitBranchThroughCleanup(RethrowDest); 1373210299Sed 1374210299Sed Builder.restoreIP(SavedIP); 1375210299Sed 1376210299Sed EHCatchScope *CatchScope = EHStack.pushCatch(1); 1377210299Sed CatchScope->setCatchAllHandler(0, CatchAllBB); 1378210299Sed 1379210299Sed return Info; 1380210299Sed} 1381210299Sed 1382210299Sedvoid CodeGenFunction::ExitFinallyBlock(FinallyInfo &Info) { 1383210299Sed // Leave the finally catch-all. 1384210299Sed EHCatchScope &Catch = cast<EHCatchScope>(*EHStack.begin()); 1385210299Sed llvm::BasicBlock *CatchAllBB = Catch.getHandler(0).Block; 1386210299Sed EHStack.popCatch(); 1387210299Sed 1388210299Sed // And leave the normal cleanup. 1389210299Sed PopCleanupBlock(); 1390210299Sed 1391210299Sed CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 1392210299Sed EmitBlock(CatchAllBB, true); 1393210299Sed 1394210299Sed Builder.restoreIP(SavedIP); 1395210299Sed} 1396210299Sed 1397210299Sedllvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() { 1398210299Sed if (TerminateLandingPad) 1399210299Sed return TerminateLandingPad; 1400210299Sed 1401210299Sed CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 1402210299Sed 1403210299Sed // This will get inserted at the end of the function. 1404210299Sed TerminateLandingPad = createBasicBlock("terminate.lpad"); 1405210299Sed Builder.SetInsertPoint(TerminateLandingPad); 1406210299Sed 1407210299Sed // Tell the backend that this is a landing pad. 1408210299Sed llvm::CallInst *Exn = 1409210299Sed Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_exception), "exn"); 1410210299Sed Exn->setDoesNotThrow(); 1411212904Sdim 1412212904Sdim const EHPersonality &Personality = EHPersonality::get(CGM.getLangOptions()); 1413210299Sed 1414210299Sed // Tell the backend what the exception table should be: 1415210299Sed // nothing but a catch-all. 1416218893Sdim llvm::Value *Args[3] = { Exn, getOpaquePersonalityFn(CGM, Personality), 1417210299Sed getCatchAllValue(*this) }; 1418210299Sed Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::eh_selector), 1419210299Sed Args, Args+3, "eh.selector") 1420210299Sed ->setDoesNotThrow(); 1421210299Sed 1422210299Sed llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(*this)); 1423210299Sed TerminateCall->setDoesNotReturn(); 1424210299Sed TerminateCall->setDoesNotThrow(); 1425218893Sdim Builder.CreateUnreachable(); 1426200583Srdivacky 1427210299Sed // Restore the saved insertion state. 1428210299Sed Builder.restoreIP(SavedIP); 1429207619Srdivacky 1430210299Sed return TerminateLandingPad; 1431200583Srdivacky} 1432200583Srdivacky 1433200583Srdivackyllvm::BasicBlock *CodeGenFunction::getTerminateHandler() { 1434200583Srdivacky if (TerminateHandler) 1435200583Srdivacky return TerminateHandler; 1436200583Srdivacky 1437210299Sed CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 1438200583Srdivacky 1439210299Sed // Set up the terminate handler. This block is inserted at the very 1440210299Sed // end of the function by FinishFunction. 1441200583Srdivacky TerminateHandler = createBasicBlock("terminate.handler"); 1442210299Sed Builder.SetInsertPoint(TerminateHandler); 1443210299Sed llvm::CallInst *TerminateCall = Builder.CreateCall(getTerminateFn(*this)); 1444200583Srdivacky TerminateCall->setDoesNotReturn(); 1445200583Srdivacky TerminateCall->setDoesNotThrow(); 1446200583Srdivacky Builder.CreateUnreachable(); 1447200583Srdivacky 1448207619Srdivacky // Restore the saved insertion state. 1449210299Sed Builder.restoreIP(SavedIP); 1450200583Srdivacky 1451200583Srdivacky return TerminateHandler; 1452200583Srdivacky} 1453210299Sed 1454212904SdimCodeGenFunction::UnwindDest CodeGenFunction::getRethrowDest() { 1455212904Sdim if (RethrowBlock.isValid()) return RethrowBlock; 1456210299Sed 1457212904Sdim CGBuilderTy::InsertPoint SavedIP = Builder.saveIP(); 1458210299Sed 1459212904Sdim // We emit a jump to a notional label at the outermost unwind state. 1460212904Sdim llvm::BasicBlock *Unwind = createBasicBlock("eh.resume"); 1461212904Sdim Builder.SetInsertPoint(Unwind); 1462210299Sed 1463212904Sdim const EHPersonality &Personality = EHPersonality::get(CGM.getLangOptions()); 1464210299Sed 1465212904Sdim // This can always be a call because we necessarily didn't find 1466212904Sdim // anything on the EH stack which needs our help. 1467218893Sdim llvm::StringRef RethrowName = Personality.getCatchallRethrowFnName(); 1468223017Sdim if (!RethrowName.empty()) { 1469223017Sdim Builder.CreateCall(getCatchallRethrowFn(*this, RethrowName), 1470223017Sdim Builder.CreateLoad(getExceptionSlot())) 1471223017Sdim ->setDoesNotReturn(); 1472223017Sdim } else { 1473223017Sdim llvm::Value *Exn = Builder.CreateLoad(getExceptionSlot()); 1474210299Sed 1475223017Sdim switch (CleanupHackLevel) { 1476223017Sdim case CHL_MandatoryCatchall: 1477223017Sdim // In mandatory-catchall mode, we need to use 1478223017Sdim // _Unwind_Resume_or_Rethrow, or whatever the personality's 1479223017Sdim // equivalent is. 1480223017Sdim Builder.CreateCall(getUnwindResumeOrRethrowFn(), Exn) 1481223017Sdim ->setDoesNotReturn(); 1482223017Sdim break; 1483223017Sdim case CHL_MandatoryCleanup: { 1484223017Sdim // In mandatory-cleanup mode, we should use llvm.eh.resume. 1485223017Sdim llvm::Value *Selector = Builder.CreateLoad(getEHSelectorSlot()); 1486223017Sdim Builder.CreateCall2(CGM.getIntrinsic(llvm::Intrinsic::eh_resume), 1487223017Sdim Exn, Selector) 1488223017Sdim ->setDoesNotReturn(); 1489223017Sdim break; 1490223017Sdim } 1491223017Sdim case CHL_Ideal: 1492223017Sdim // In an idealized mode where we don't have to worry about the 1493223017Sdim // optimizer combining landing pads, we should just use 1494223017Sdim // _Unwind_Resume (or the personality's equivalent). 1495223017Sdim Builder.CreateCall(getUnwindResumeFn(), Exn) 1496223017Sdim ->setDoesNotReturn(); 1497223017Sdim break; 1498223017Sdim } 1499223017Sdim } 1500223017Sdim 1501212904Sdim Builder.CreateUnreachable(); 1502210299Sed 1503212904Sdim Builder.restoreIP(SavedIP); 1504210299Sed 1505212904Sdim RethrowBlock = UnwindDest(Unwind, EHStack.stable_end(), 0); 1506212904Sdim return RethrowBlock; 1507210299Sed} 1508210299Sed 1509