CGException.cpp revision 79a9ad8e5eec3696989354be13a74a1106f64f72
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 "clang/AST/StmtCXX.h" 15 16#include "llvm/Intrinsics.h" 17 18#include "CodeGenFunction.h" 19using namespace clang; 20using namespace CodeGen; 21 22static llvm::Constant *getAllocateExceptionFn(CodeGenFunction &CGF) { 23 // void *__cxa_allocate_exception(size_t thrown_size); 24 const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); 25 std::vector<const llvm::Type*> Args(1, SizeTy); 26 27 const llvm::FunctionType *FTy = 28 llvm::FunctionType::get(llvm::Type::getInt8PtrTy(CGF.getLLVMContext()), 29 Args, false); 30 31 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception"); 32} 33 34static llvm::Constant *getFreeExceptionFn(CodeGenFunction &CGF) { 35 // void __cxa_free_exception(void *thrown_exception); 36 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 37 std::vector<const llvm::Type*> Args(1, Int8PtrTy); 38 39 const llvm::FunctionType *FTy = 40 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 41 Args, false); 42 43 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception"); 44} 45 46static llvm::Constant *getThrowFn(CodeGenFunction &CGF) { 47 // void __cxa_throw(void *thrown_exception, std::type_info *tinfo, 48 // void (*dest) (void *)); 49 50 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 51 std::vector<const llvm::Type*> Args(3, Int8PtrTy); 52 53 const llvm::FunctionType *FTy = 54 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 55 Args, false); 56 57 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_throw"); 58} 59 60static llvm::Constant *getReThrowFn(CodeGenFunction &CGF) { 61 // void __cxa_rethrow(); 62 63 const llvm::FunctionType *FTy = 64 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false); 65 66 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow"); 67} 68 69static llvm::Constant *getBeginCatchFn(CodeGenFunction &CGF) { 70 // void* __cxa_begin_catch(); 71 72 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 73 std::vector<const llvm::Type*> Args(1, Int8PtrTy); 74 75 const llvm::FunctionType *FTy = 76 llvm::FunctionType::get(Int8PtrTy, Args, false); 77 78 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); 79} 80 81static llvm::Constant *getEndCatchFn(CodeGenFunction &CGF) { 82 // void __cxa_end_catch(); 83 84 const llvm::FunctionType *FTy = 85 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false); 86 87 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); 88} 89 90static llvm::Constant *getUnexpectedFn(CodeGenFunction &CGF) { 91 // void __cxa_call_unexepcted(void *thrown_exception); 92 93 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 94 std::vector<const llvm::Type*> Args(1, Int8PtrTy); 95 96 const llvm::FunctionType *FTy = 97 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), 98 Args, false); 99 100 return CGF.CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected"); 101} 102 103llvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() { 104 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); 105 std::vector<const llvm::Type*> Args(1, Int8PtrTy); 106 107 const llvm::FunctionType *FTy = 108 llvm::FunctionType::get(llvm::Type::getVoidTy(getLLVMContext()), Args, 109 false); 110 111 if (CGM.getLangOptions().SjLjExceptions) 112 return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume"); 113 return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow"); 114} 115 116static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) { 117 // void __terminate(); 118 119 const llvm::FunctionType *FTy = 120 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false); 121 122 return CGF.CGM.CreateRuntimeFunction(FTy, 123 CGF.CGM.getLangOptions().CPlusPlus ? "_ZSt9terminatev" : "abort"); 124} 125 126static llvm::Constant *getPersonalityFn(CodeGenModule &CGM) { 127 const char *PersonalityFnName = "__gcc_personality_v0"; 128 LangOptions Opts = CGM.getLangOptions(); 129 if (Opts.CPlusPlus) 130 PersonalityFnName = "__gxx_personality_v0"; 131 else if (Opts.ObjC1) 132 if (Opts.NeXTRuntime) { 133 if (Opts.ObjCNonFragileABI) 134 PersonalityFnName = "__gcc_personality_v0"; 135 } else 136 PersonalityFnName = "__gnu_objc_personality_v0"; 137 138 llvm::Constant *Personality = 139 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty( 140 CGM.getLLVMContext()), 141 true), 142 PersonalityFnName); 143 return llvm::ConstantExpr::getBitCast(Personality, CGM.PtrToInt8Ty); 144} 145 146// Emits an exception expression into the given location. This 147// differs from EmitAnyExprToMem only in that, if a final copy-ctor 148// call is required, an exception within that copy ctor causes 149// std::terminate to be invoked. 150static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *E, 151 llvm::Value *ExnLoc) { 152 // We want to release the allocated exception object if this 153 // expression throws. We do this by pushing an EH-only cleanup 154 // block which, furthermore, deactivates itself after the expression 155 // is complete. 156 llvm::AllocaInst *ShouldFreeVar = 157 CGF.CreateTempAlloca(llvm::Type::getInt1Ty(CGF.getLLVMContext()), 158 "should-free-exnobj.var"); 159 CGF.InitTempAlloca(ShouldFreeVar, 160 llvm::ConstantInt::getFalse(CGF.getLLVMContext())); 161 162 // A variable holding the exception pointer. This is necessary 163 // because the throw expression does not necessarily dominate the 164 // cleanup, for example if it appears in a conditional expression. 165 llvm::AllocaInst *ExnLocVar = 166 CGF.CreateTempAlloca(ExnLoc->getType(), "exnobj.var"); 167 168 llvm::BasicBlock *SavedInvokeDest = CGF.getInvokeDest(); 169 { 170 CodeGenFunction::EHCleanupBlock Cleanup(CGF); 171 llvm::BasicBlock *FreeBB = CGF.createBasicBlock("free-exnobj"); 172 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("free-exnobj.done"); 173 174 llvm::Value *ShouldFree = CGF.Builder.CreateLoad(ShouldFreeVar, 175 "should-free-exnobj"); 176 CGF.Builder.CreateCondBr(ShouldFree, FreeBB, DoneBB); 177 CGF.EmitBlock(FreeBB); 178 llvm::Value *ExnLocLocal = CGF.Builder.CreateLoad(ExnLocVar, "exnobj"); 179 CGF.Builder.CreateCall(getFreeExceptionFn(CGF), ExnLocLocal); 180 CGF.EmitBlock(DoneBB); 181 } 182 llvm::BasicBlock *Cleanup = CGF.getInvokeDest(); 183 184 CGF.Builder.CreateStore(ExnLoc, ExnLocVar); 185 CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(CGF.getLLVMContext()), 186 ShouldFreeVar); 187 188 // __cxa_allocate_exception returns a void*; we need to cast this 189 // to the appropriate type for the object. 190 const llvm::Type *Ty = CGF.ConvertType(E->getType())->getPointerTo(); 191 llvm::Value *TypedExnLoc = CGF.Builder.CreateBitCast(ExnLoc, Ty); 192 193 // FIXME: this isn't quite right! If there's a final unelided call 194 // to a copy constructor, then according to [except.terminate]p1 we 195 // must call std::terminate() if that constructor throws, because 196 // technically that copy occurs after the exception expression is 197 // evaluated but before the exception is caught. But the best way 198 // to handle that is to teach EmitAggExpr to do the final copy 199 // differently if it can't be elided. 200 CGF.EmitAnyExprToMem(E, TypedExnLoc, /*Volatile*/ false); 201 202 CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(CGF.getLLVMContext()), 203 ShouldFreeVar); 204 205 // Pop the cleanup block if it's still the top of the cleanup stack. 206 // Otherwise, temporaries have been created and our cleanup will get 207 // properly removed in time. 208 // TODO: this is not very resilient. 209 if (CGF.getInvokeDest() == Cleanup) 210 CGF.setInvokeDest(SavedInvokeDest); 211} 212 213// CopyObject - Utility to copy an object. Calls copy constructor as necessary. 214// N is casted to the right type. 215static void CopyObject(CodeGenFunction &CGF, QualType ObjectType, 216 bool WasPointer, bool WasPointerReference, 217 llvm::Value *E, llvm::Value *N) { 218 // Store the throw exception in the exception object. 219 if (WasPointer || !CGF.hasAggregateLLVMType(ObjectType)) { 220 llvm::Value *Value = E; 221 if (!WasPointer) 222 Value = CGF.Builder.CreateLoad(Value); 223 const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo(0); 224 if (WasPointerReference) { 225 llvm::Value *Tmp = CGF.CreateTempAlloca(Value->getType(), "catch.param"); 226 CGF.Builder.CreateStore(Value, Tmp); 227 Value = Tmp; 228 ValuePtrTy = Value->getType()->getPointerTo(0); 229 } 230 N = CGF.Builder.CreateBitCast(N, ValuePtrTy); 231 CGF.Builder.CreateStore(Value, N); 232 } else { 233 const llvm::Type *Ty = CGF.ConvertType(ObjectType)->getPointerTo(0); 234 const CXXRecordDecl *RD; 235 RD = cast<CXXRecordDecl>(ObjectType->getAs<RecordType>()->getDecl()); 236 llvm::Value *This = CGF.Builder.CreateBitCast(N, Ty); 237 if (RD->hasTrivialCopyConstructor()) { 238 CGF.EmitAggregateCopy(This, E, ObjectType); 239 } else if (CXXConstructorDecl *CopyCtor 240 = RD->getCopyConstructor(CGF.getContext(), 0)) { 241 llvm::Value *Src = E; 242 243 // Stolen from EmitClassAggrMemberwiseCopy 244 llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor, 245 Ctor_Complete); 246 CallArgList CallArgs; 247 CallArgs.push_back(std::make_pair(RValue::get(This), 248 CopyCtor->getThisType(CGF.getContext()))); 249 250 // Push the Src ptr. 251 CallArgs.push_back(std::make_pair(RValue::get(Src), 252 CopyCtor->getParamDecl(0)->getType())); 253 254 const FunctionProtoType *FPT 255 = CopyCtor->getType()->getAs<FunctionProtoType>(); 256 CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(CallArgs, FPT), 257 Callee, ReturnValueSlot(), CallArgs, CopyCtor); 258 } else 259 llvm_unreachable("uncopyable object"); 260 } 261} 262 263void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { 264 if (!E->getSubExpr()) { 265 if (getInvokeDest()) { 266 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); 267 Builder.CreateInvoke(getReThrowFn(*this), Cont, getInvokeDest()) 268 ->setDoesNotReturn(); 269 EmitBlock(Cont); 270 } else 271 Builder.CreateCall(getReThrowFn(*this))->setDoesNotReturn(); 272 Builder.CreateUnreachable(); 273 274 // Clear the insertion point to indicate we are in unreachable code. 275 Builder.ClearInsertionPoint(); 276 return; 277 } 278 279 QualType ThrowType = E->getSubExpr()->getType(); 280 281 // Now allocate the exception object. 282 const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); 283 uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity(); 284 285 llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(*this); 286 llvm::Value *ExceptionPtr = 287 Builder.CreateCall(AllocExceptionFn, 288 llvm::ConstantInt::get(SizeTy, TypeSize), 289 "exception"); 290 291 EmitAnyExprToExn(*this, E->getSubExpr(), ExceptionPtr); 292 293 // Now throw the exception. 294 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); 295 llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType, true); 296 297 // The address of the destructor. If the exception type has a 298 // trivial destructor (or isn't a record), we just pass null. 299 llvm::Constant *Dtor = 0; 300 if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) { 301 CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); 302 if (!Record->hasTrivialDestructor()) { 303 CXXDestructorDecl *DtorD = Record->getDestructor(getContext()); 304 Dtor = CGM.GetAddrOfCXXDestructor(DtorD, Dtor_Complete); 305 Dtor = llvm::ConstantExpr::getBitCast(Dtor, Int8PtrTy); 306 } 307 } 308 if (!Dtor) Dtor = llvm::Constant::getNullValue(Int8PtrTy); 309 310 if (getInvokeDest()) { 311 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); 312 llvm::InvokeInst *ThrowCall = 313 Builder.CreateInvoke3(getThrowFn(*this), Cont, getInvokeDest(), 314 ExceptionPtr, TypeInfo, Dtor); 315 ThrowCall->setDoesNotReturn(); 316 EmitBlock(Cont); 317 } else { 318 llvm::CallInst *ThrowCall = 319 Builder.CreateCall3(getThrowFn(*this), ExceptionPtr, TypeInfo, Dtor); 320 ThrowCall->setDoesNotReturn(); 321 } 322 Builder.CreateUnreachable(); 323 324 // Clear the insertion point to indicate we are in unreachable code. 325 Builder.ClearInsertionPoint(); 326 327 // FIXME: For now, emit a dummy basic block because expr emitters in generally 328 // are not ready to handle emitting expressions at unreachable points. 329 EnsureInsertPoint(); 330} 331 332void CodeGenFunction::EmitStartEHSpec(const Decl *D) { 333 if (!Exceptions) 334 return; 335 336 const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); 337 if (FD == 0) 338 return; 339 const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); 340 if (Proto == 0) 341 return; 342 343 assert(!Proto->hasAnyExceptionSpec() && "function with parameter pack"); 344 345 if (!Proto->hasExceptionSpec()) 346 return; 347 348 llvm::Constant *Personality = getPersonalityFn(CGM); 349 llvm::Value *llvm_eh_exception = 350 CGM.getIntrinsic(llvm::Intrinsic::eh_exception); 351 llvm::Value *llvm_eh_selector = 352 CGM.getIntrinsic(llvm::Intrinsic::eh_selector); 353 const llvm::IntegerType *Int8Ty; 354 const llvm::PointerType *PtrToInt8Ty; 355 Int8Ty = llvm::Type::getInt8Ty(VMContext); 356 // C string type. Used in lots of places. 357 PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty); 358 llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty); 359 llvm::SmallVector<llvm::Value*, 8> SelectorArgs; 360 361 llvm::BasicBlock *PrevLandingPad = getInvokeDest(); 362 llvm::BasicBlock *EHSpecHandler = createBasicBlock("ehspec.handler"); 363 llvm::BasicBlock *Match = createBasicBlock("match"); 364 llvm::BasicBlock *Unwind = 0; 365 366 assert(PrevLandingPad == 0 && "EHSpec has invoke context"); 367 (void)PrevLandingPad; 368 369 llvm::BasicBlock *Cont = createBasicBlock("cont"); 370 371 EmitBranchThroughCleanup(Cont); 372 373 // Emit the statements in the try {} block 374 setInvokeDest(EHSpecHandler); 375 376 EmitBlock(EHSpecHandler); 377 // Exception object 378 llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc"); 379 llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow"); 380 381 SelectorArgs.push_back(Exc); 382 SelectorArgs.push_back(Personality); 383 SelectorArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 384 Proto->getNumExceptions()+1)); 385 386 for (unsigned i = 0; i < Proto->getNumExceptions(); ++i) { 387 QualType Ty = Proto->getExceptionType(i); 388 QualType ExceptType 389 = Ty.getNonReferenceType().getUnqualifiedType(); 390 llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType, true); 391 SelectorArgs.push_back(EHType); 392 } 393 if (Proto->getNumExceptions()) 394 SelectorArgs.push_back(Null); 395 396 // Find which handler was matched. 397 llvm::Value *Selector 398 = Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(), 399 SelectorArgs.end(), "selector"); 400 if (Proto->getNumExceptions()) { 401 Unwind = createBasicBlock("Unwind"); 402 403 Builder.CreateStore(Exc, RethrowPtr); 404 Builder.CreateCondBr(Builder.CreateICmpSLT(Selector, 405 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 406 0)), 407 Match, Unwind); 408 409 EmitBlock(Match); 410 } 411 Builder.CreateCall(getUnexpectedFn(*this), Exc)->setDoesNotReturn(); 412 Builder.CreateUnreachable(); 413 414 if (Proto->getNumExceptions()) { 415 EmitBlock(Unwind); 416 Builder.CreateCall(getUnwindResumeOrRethrowFn(), 417 Builder.CreateLoad(RethrowPtr)); 418 Builder.CreateUnreachable(); 419 } 420 421 EmitBlock(Cont); 422} 423 424void CodeGenFunction::EmitEndEHSpec(const Decl *D) { 425 if (!Exceptions) 426 return; 427 428 const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); 429 if (FD == 0) 430 return; 431 const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); 432 if (Proto == 0) 433 return; 434 435 if (!Proto->hasExceptionSpec()) 436 return; 437 438 setInvokeDest(0); 439} 440 441void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { 442 CXXTryStmtInfo Info = EnterCXXTryStmt(S); 443 EmitStmt(S.getTryBlock()); 444 ExitCXXTryStmt(S, Info); 445} 446 447CodeGenFunction::CXXTryStmtInfo 448CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S) { 449 CXXTryStmtInfo Info; 450 Info.SavedLandingPad = getInvokeDest(); 451 Info.HandlerBlock = createBasicBlock("try.handler"); 452 Info.FinallyBlock = createBasicBlock("finally"); 453 454 PushCleanupBlock(Info.FinallyBlock); 455 setInvokeDest(Info.HandlerBlock); 456 457 return Info; 458} 459 460void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, 461 CXXTryStmtInfo TryInfo) { 462 // Pointer to the personality function 463 llvm::Constant *Personality = getPersonalityFn(CGM); 464 llvm::Value *llvm_eh_exception = 465 CGM.getIntrinsic(llvm::Intrinsic::eh_exception); 466 llvm::Value *llvm_eh_selector = 467 CGM.getIntrinsic(llvm::Intrinsic::eh_selector); 468 469 llvm::BasicBlock *PrevLandingPad = TryInfo.SavedLandingPad; 470 llvm::BasicBlock *TryHandler = TryInfo.HandlerBlock; 471 llvm::BasicBlock *FinallyBlock = TryInfo.FinallyBlock; 472 llvm::BasicBlock *FinallyRethrow = createBasicBlock("finally.throw"); 473 llvm::BasicBlock *FinallyEnd = createBasicBlock("finally.end"); 474 475 // Jump to end if there is no exception 476 EmitBranchThroughCleanup(FinallyEnd); 477 478 llvm::BasicBlock *TerminateHandler = getTerminateHandler(); 479 480 // Emit the handlers 481 EmitBlock(TryHandler); 482 483 const llvm::IntegerType *Int8Ty; 484 const llvm::PointerType *PtrToInt8Ty; 485 Int8Ty = llvm::Type::getInt8Ty(VMContext); 486 // C string type. Used in lots of places. 487 PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty); 488 llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty); 489 llvm::SmallVector<llvm::Value*, 8> SelectorArgs; 490 llvm::Value *llvm_eh_typeid_for = 491 CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); 492 // Exception object 493 llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc"); 494 llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow"); 495 496 SelectorArgs.push_back(Exc); 497 SelectorArgs.push_back(Personality); 498 499 bool HasCatchAll = false; 500 for (unsigned i = 0; i<S.getNumHandlers(); ++i) { 501 const CXXCatchStmt *C = S.getHandler(i); 502 VarDecl *CatchParam = C->getExceptionDecl(); 503 if (CatchParam) { 504 // C++ [except.handle]p3 indicates that top-level cv-qualifiers 505 // are ignored. 506 QualType CaughtType = C->getCaughtType().getNonReferenceType(); 507 llvm::Value *EHTypeInfo 508 = CGM.GetAddrOfRTTIDescriptor(CaughtType.getUnqualifiedType(), true); 509 SelectorArgs.push_back(EHTypeInfo); 510 } else { 511 // null indicates catch all 512 SelectorArgs.push_back(Null); 513 HasCatchAll = true; 514 } 515 } 516 517 // We use a cleanup unless there was already a catch all. 518 if (!HasCatchAll) { 519 SelectorArgs.push_back(Null); 520 } 521 522 // Find which handler was matched. 523 llvm::Value *Selector 524 = Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(), 525 SelectorArgs.end(), "selector"); 526 for (unsigned i = 0; i<S.getNumHandlers(); ++i) { 527 const CXXCatchStmt *C = S.getHandler(i); 528 VarDecl *CatchParam = C->getExceptionDecl(); 529 Stmt *CatchBody = C->getHandlerBlock(); 530 531 llvm::BasicBlock *Next = 0; 532 533 if (SelectorArgs[i+2] != Null) { 534 llvm::BasicBlock *Match = createBasicBlock("match"); 535 Next = createBasicBlock("catch.next"); 536 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); 537 llvm::Value *Id 538 = Builder.CreateCall(llvm_eh_typeid_for, 539 Builder.CreateBitCast(SelectorArgs[i+2], 540 Int8PtrTy)); 541 Builder.CreateCondBr(Builder.CreateICmpEQ(Selector, Id), 542 Match, Next); 543 EmitBlock(Match); 544 } 545 546 llvm::BasicBlock *MatchEnd = createBasicBlock("match.end"); 547 llvm::BasicBlock *MatchHandler = createBasicBlock("match.handler"); 548 549 PushCleanupBlock(MatchEnd); 550 setInvokeDest(MatchHandler); 551 552 llvm::Value *ExcObject = Builder.CreateCall(getBeginCatchFn(*this), Exc); 553 554 { 555 CleanupScope CatchScope(*this); 556 // Bind the catch parameter if it exists. 557 if (CatchParam) { 558 QualType CatchType = CatchParam->getType().getNonReferenceType(); 559 setInvokeDest(TerminateHandler); 560 bool WasPointer = true; 561 bool WasPointerReference = false; 562 CatchType = CGM.getContext().getCanonicalType(CatchType); 563 if (CatchType.getTypePtr()->isPointerType()) { 564 if (isa<ReferenceType>(CatchParam->getType())) 565 WasPointerReference = true; 566 } else { 567 if (!isa<ReferenceType>(CatchParam->getType())) 568 WasPointer = false; 569 CatchType = getContext().getPointerType(CatchType); 570 } 571 ExcObject = Builder.CreateBitCast(ExcObject, ConvertType(CatchType)); 572 EmitLocalBlockVarDecl(*CatchParam); 573 // FIXME: we need to do this sooner so that the EH region for the 574 // cleanup doesn't start until after the ctor completes, use a decl 575 // init? 576 CopyObject(*this, CatchParam->getType().getNonReferenceType(), 577 WasPointer, WasPointerReference, ExcObject, 578 GetAddrOfLocalVar(CatchParam)); 579 setInvokeDest(MatchHandler); 580 } 581 582 EmitStmt(CatchBody); 583 } 584 585 EmitBranchThroughCleanup(FinallyEnd); 586 587 EmitBlock(MatchHandler); 588 589 llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc"); 590 // We are required to emit this call to satisfy LLVM, even 591 // though we don't use the result. 592 llvm::Value *Args[] = { 593 Exc, Personality, 594 llvm::ConstantInt::getNullValue(llvm::Type::getInt32Ty(VMContext)) 595 }; 596 Builder.CreateCall(llvm_eh_selector, &Args[0], llvm::array_endof(Args)); 597 Builder.CreateStore(Exc, RethrowPtr); 598 EmitBranchThroughCleanup(FinallyRethrow); 599 600 CodeGenFunction::CleanupBlockInfo Info = PopCleanupBlock(); 601 602 EmitBlock(MatchEnd); 603 604 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); 605 Builder.CreateInvoke(getEndCatchFn(*this), 606 Cont, TerminateHandler, 607 &Args[0], &Args[0]); 608 EmitBlock(Cont); 609 if (Info.SwitchBlock) 610 EmitBlock(Info.SwitchBlock); 611 if (Info.EndBlock) 612 EmitBlock(Info.EndBlock); 613 614 Exc = Builder.CreateCall(llvm_eh_exception, "exc"); 615 Builder.CreateStore(Exc, RethrowPtr); 616 EmitBranchThroughCleanup(FinallyRethrow); 617 618 if (Next) 619 EmitBlock(Next); 620 } 621 if (!HasCatchAll) { 622 Builder.CreateStore(Exc, RethrowPtr); 623 EmitBranchThroughCleanup(FinallyRethrow); 624 } 625 626 CodeGenFunction::CleanupBlockInfo Info = PopCleanupBlock(); 627 628 setInvokeDest(PrevLandingPad); 629 630 EmitBlock(FinallyBlock); 631 632 if (Info.SwitchBlock) 633 EmitBlock(Info.SwitchBlock); 634 if (Info.EndBlock) 635 EmitBlock(Info.EndBlock); 636 637 // Branch around the rethrow code. 638 EmitBranch(FinallyEnd); 639 640 EmitBlock(FinallyRethrow); 641 // FIXME: Eventually we can chain the handlers together and just do a call 642 // here. 643 if (getInvokeDest()) { 644 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); 645 Builder.CreateInvoke(getUnwindResumeOrRethrowFn(), Cont, 646 getInvokeDest(), 647 Builder.CreateLoad(RethrowPtr)); 648 EmitBlock(Cont); 649 } else 650 Builder.CreateCall(getUnwindResumeOrRethrowFn(), 651 Builder.CreateLoad(RethrowPtr)); 652 653 Builder.CreateUnreachable(); 654 655 EmitBlock(FinallyEnd); 656} 657 658CodeGenFunction::EHCleanupBlock::~EHCleanupBlock() { 659 CGF.setInvokeDest(PreviousInvokeDest); 660 661 llvm::BasicBlock *EndOfCleanup = CGF.Builder.GetInsertBlock(); 662 663 // Jump to the beginning of the cleanup. 664 CGF.Builder.SetInsertPoint(CleanupHandler, CleanupHandler->begin()); 665 666 // The libstdc++ personality function. 667 // TODO: generalize to work with other libraries. 668 llvm::Constant *Personality = getPersonalityFn(CGF.CGM); 669 670 // %exception = call i8* @llvm.eh.exception() 671 // Magic intrinsic which tells gives us a handle to the caught 672 // exception. 673 llvm::Value *llvm_eh_exception = 674 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception); 675 llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); 676 677 llvm::Constant *Null = llvm::ConstantPointerNull::get(CGF.PtrToInt8Ty); 678 679 // %ignored = call i32 @llvm.eh.selector(i8* %exception, 680 // i8* @__gxx_personality_v0, 681 // i8* null) 682 // Magic intrinsic which tells LLVM that this invoke landing pad is 683 // just a cleanup block. 684 llvm::Value *Args[] = { Exc, Personality, Null }; 685 llvm::Value *llvm_eh_selector = 686 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector); 687 CGF.Builder.CreateCall(llvm_eh_selector, &Args[0], llvm::array_endof(Args)); 688 689 // And then we fall through into the code that the user put there. 690 // Jump back to the end of the cleanup. 691 CGF.Builder.SetInsertPoint(EndOfCleanup); 692 693 // Rethrow the exception. 694 if (CGF.getInvokeDest()) { 695 llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont"); 696 CGF.Builder.CreateInvoke(CGF.getUnwindResumeOrRethrowFn(), Cont, 697 CGF.getInvokeDest(), Exc); 698 CGF.EmitBlock(Cont); 699 } else 700 CGF.Builder.CreateCall(CGF.getUnwindResumeOrRethrowFn(), Exc); 701 CGF.Builder.CreateUnreachable(); 702 703 // Resume inserting where we started, but put the new cleanup 704 // handler in place. 705 if (PreviousInsertionBlock) 706 CGF.Builder.SetInsertPoint(PreviousInsertionBlock); 707 else 708 CGF.Builder.ClearInsertionPoint(); 709 710 if (CGF.Exceptions) 711 CGF.setInvokeDest(CleanupHandler); 712} 713 714llvm::BasicBlock *CodeGenFunction::getTerminateHandler() { 715 if (TerminateHandler) 716 return TerminateHandler; 717 718 // We don't want to change anything at the current location, so 719 // save it aside and clear the insert point. 720 llvm::BasicBlock *SavedInsertBlock = Builder.GetInsertBlock(); 721 llvm::BasicBlock::iterator SavedInsertPoint = Builder.GetInsertPoint(); 722 Builder.ClearInsertionPoint(); 723 724 llvm::Constant *Personality = getPersonalityFn(CGM); 725 llvm::Value *llvm_eh_exception = 726 CGM.getIntrinsic(llvm::Intrinsic::eh_exception); 727 llvm::Value *llvm_eh_selector = 728 CGM.getIntrinsic(llvm::Intrinsic::eh_selector); 729 730 // Set up terminate handler 731 TerminateHandler = createBasicBlock("terminate.handler"); 732 EmitBlock(TerminateHandler); 733 llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc"); 734 // We are required to emit this call to satisfy LLVM, even 735 // though we don't use the result. 736 llvm::Value *Args[] = { 737 Exc, Personality, 738 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 1) 739 }; 740 Builder.CreateCall(llvm_eh_selector, &Args[0], llvm::array_endof(Args)); 741 llvm::CallInst *TerminateCall = 742 Builder.CreateCall(getTerminateFn(*this)); 743 TerminateCall->setDoesNotReturn(); 744 TerminateCall->setDoesNotThrow(); 745 Builder.CreateUnreachable(); 746 747 // Restore the saved insertion state. 748 Builder.SetInsertPoint(SavedInsertBlock, SavedInsertPoint); 749 750 return TerminateHandler; 751} 752