CGException.cpp revision a994ee4b197554282ae6b222c3284ccaa3a6484c
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 103// FIXME: Eventually this will all go into the backend. Set from the target for 104// now. 105static int using_sjlj_exceptions = 0; 106 107static llvm::Constant *getUnwindResumeOrRethrowFn(CodeGenFunction &CGF) { 108 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGF.getLLVMContext()); 109 std::vector<const llvm::Type*> Args(1, Int8PtrTy); 110 111 const llvm::FunctionType *FTy = 112 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), Args, 113 false); 114 115 if (using_sjlj_exceptions) 116 return CGF.CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume"); 117 return CGF.CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow"); 118} 119 120static llvm::Constant *getTerminateFn(CodeGenFunction &CGF) { 121 // void __terminate(); 122 123 const llvm::FunctionType *FTy = 124 llvm::FunctionType::get(llvm::Type::getVoidTy(CGF.getLLVMContext()), false); 125 126 return CGF.CGM.CreateRuntimeFunction(FTy, "_ZSt9terminatev"); 127} 128 129// CopyObject - Utility to copy an object. Calls copy constructor as necessary. 130// DestPtr is casted to the right type. 131static void CopyObject(CodeGenFunction &CGF, const Expr *E, 132 llvm::Value *DestPtr, llvm::Value *ExceptionPtrPtr) { 133 QualType ObjectType = E->getType(); 134 135 // Store the throw exception in the exception object. 136 if (!CGF.hasAggregateLLVMType(ObjectType)) { 137 llvm::Value *Value = CGF.EmitScalarExpr(E); 138 const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo(); 139 140 CGF.Builder.CreateStore(Value, 141 CGF.Builder.CreateBitCast(DestPtr, ValuePtrTy)); 142 } else { 143 const llvm::Type *Ty = CGF.ConvertType(ObjectType)->getPointerTo(); 144 const CXXRecordDecl *RD = 145 cast<CXXRecordDecl>(ObjectType->getAs<RecordType>()->getDecl()); 146 147 llvm::Value *This = CGF.Builder.CreateBitCast(DestPtr, Ty); 148 if (RD->hasTrivialCopyConstructor()) { 149 CGF.EmitAggExpr(E, This, false); 150 } else if (CXXConstructorDecl *CopyCtor 151 = RD->getCopyConstructor(CGF.getContext(), 0)) { 152 llvm::Value *CondPtr = 0; 153 if (CGF.Exceptions) { 154 CodeGenFunction::EHCleanupBlock Cleanup(CGF); 155 llvm::Constant *FreeExceptionFn = getFreeExceptionFn(CGF); 156 157 llvm::BasicBlock *CondBlock = CGF.createBasicBlock("cond.free"); 158 llvm::BasicBlock *Cont = CGF.createBasicBlock("cont"); 159 CondPtr = CGF.CreateTempAlloca(llvm::Type::getInt1Ty(CGF.getLLVMContext()), 160 "doEHfree"); 161 162 CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CondPtr), 163 CondBlock, Cont); 164 CGF.EmitBlock(CondBlock); 165 166 // Load the exception pointer. 167 llvm::Value *ExceptionPtr = CGF.Builder.CreateLoad(ExceptionPtrPtr); 168 CGF.Builder.CreateCall(FreeExceptionFn, ExceptionPtr); 169 170 CGF.EmitBlock(Cont); 171 } 172 173 if (CondPtr) 174 CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(CGF.getLLVMContext()), 175 CondPtr); 176 177 llvm::Value *Src = CGF.EmitLValue(E).getAddress(); 178 179 if (CondPtr) 180 CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(CGF.getLLVMContext()), 181 CondPtr); 182 183 llvm::BasicBlock *TerminateHandler = CGF.getTerminateHandler(); 184 llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest(); 185 CGF.setInvokeDest(TerminateHandler); 186 187 // Stolen from EmitClassAggrMemberwiseCopy 188 llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor, 189 Ctor_Complete); 190 CallArgList CallArgs; 191 CallArgs.push_back(std::make_pair(RValue::get(This), 192 CopyCtor->getThisType(CGF.getContext()))); 193 194 // Push the Src ptr. 195 CallArgs.push_back(std::make_pair(RValue::get(Src), 196 CopyCtor->getParamDecl(0)->getType())); 197 const FunctionProtoType *FPT 198 = CopyCtor->getType()->getAs<FunctionProtoType>(); 199 CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(CallArgs, FPT), 200 Callee, ReturnValueSlot(), CallArgs, CopyCtor); 201 CGF.setInvokeDest(PrevLandingPad); 202 } else 203 llvm_unreachable("uncopyable object"); 204 } 205} 206 207// CopyObject - Utility to copy an object. Calls copy constructor as necessary. 208// N is casted to the right type. 209static void CopyObject(CodeGenFunction &CGF, QualType ObjectType, 210 bool WasPointer, bool WasPointerReference, 211 llvm::Value *E, llvm::Value *N) { 212 // Store the throw exception in the exception object. 213 if (WasPointer || !CGF.hasAggregateLLVMType(ObjectType)) { 214 llvm::Value *Value = E; 215 if (!WasPointer) 216 Value = CGF.Builder.CreateLoad(Value); 217 const llvm::Type *ValuePtrTy = Value->getType()->getPointerTo(0); 218 if (WasPointerReference) { 219 llvm::Value *Tmp = CGF.CreateTempAlloca(Value->getType(), "catch.param"); 220 CGF.Builder.CreateStore(Value, Tmp); 221 Value = Tmp; 222 ValuePtrTy = Value->getType()->getPointerTo(0); 223 } 224 N = CGF.Builder.CreateBitCast(N, ValuePtrTy); 225 CGF.Builder.CreateStore(Value, N); 226 } else { 227 const llvm::Type *Ty = CGF.ConvertType(ObjectType)->getPointerTo(0); 228 const CXXRecordDecl *RD; 229 RD = cast<CXXRecordDecl>(ObjectType->getAs<RecordType>()->getDecl()); 230 llvm::Value *This = CGF.Builder.CreateBitCast(N, Ty); 231 if (RD->hasTrivialCopyConstructor()) { 232 CGF.EmitAggregateCopy(This, E, ObjectType); 233 } else if (CXXConstructorDecl *CopyCtor 234 = RD->getCopyConstructor(CGF.getContext(), 0)) { 235 llvm::Value *Src = E; 236 237 // Stolen from EmitClassAggrMemberwiseCopy 238 llvm::Value *Callee = CGF.CGM.GetAddrOfCXXConstructor(CopyCtor, 239 Ctor_Complete); 240 CallArgList CallArgs; 241 CallArgs.push_back(std::make_pair(RValue::get(This), 242 CopyCtor->getThisType(CGF.getContext()))); 243 244 // Push the Src ptr. 245 CallArgs.push_back(std::make_pair(RValue::get(Src), 246 CopyCtor->getParamDecl(0)->getType())); 247 248 const FunctionProtoType *FPT 249 = CopyCtor->getType()->getAs<FunctionProtoType>(); 250 CGF.EmitCall(CGF.CGM.getTypes().getFunctionInfo(CallArgs, FPT), 251 Callee, ReturnValueSlot(), CallArgs, CopyCtor); 252 } else 253 llvm_unreachable("uncopyable object"); 254 } 255} 256 257void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E) { 258 if (!E->getSubExpr()) { 259 if (getInvokeDest()) { 260 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); 261 Builder.CreateInvoke(getReThrowFn(*this), Cont, getInvokeDest()) 262 ->setDoesNotReturn(); 263 EmitBlock(Cont); 264 } else 265 Builder.CreateCall(getReThrowFn(*this))->setDoesNotReturn(); 266 Builder.CreateUnreachable(); 267 268 // Clear the insertion point to indicate we are in unreachable code. 269 Builder.ClearInsertionPoint(); 270 return; 271 } 272 273 QualType ThrowType = E->getSubExpr()->getType(); 274 275 // Now allocate the exception object. 276 const llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); 277 uint64_t TypeSize = getContext().getTypeSize(ThrowType) / 8; 278 279 llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(*this); 280 llvm::Value *ExceptionPtr = 281 Builder.CreateCall(AllocExceptionFn, 282 llvm::ConstantInt::get(SizeTy, TypeSize), 283 "exception"); 284 285 llvm::Value *ExceptionPtrPtr = 286 CreateTempAlloca(ExceptionPtr->getType(), "exception.ptr"); 287 Builder.CreateStore(ExceptionPtr, ExceptionPtrPtr); 288 289 290 CopyObject(*this, E->getSubExpr(), ExceptionPtr, ExceptionPtrPtr); 291 292 // Now throw the exception. 293 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); 294 llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType); 295 llvm::Constant *Dtor = llvm::Constant::getNullValue(Int8PtrTy); 296 297 if (getInvokeDest()) { 298 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); 299 llvm::InvokeInst *ThrowCall = 300 Builder.CreateInvoke3(getThrowFn(*this), Cont, getInvokeDest(), 301 ExceptionPtr, TypeInfo, Dtor); 302 ThrowCall->setDoesNotReturn(); 303 EmitBlock(Cont); 304 } else { 305 llvm::CallInst *ThrowCall = 306 Builder.CreateCall3(getThrowFn(*this), ExceptionPtr, TypeInfo, Dtor); 307 ThrowCall->setDoesNotReturn(); 308 } 309 Builder.CreateUnreachable(); 310 311 // Clear the insertion point to indicate we are in unreachable code. 312 Builder.ClearInsertionPoint(); 313 314 // FIXME: For now, emit a dummy basic block because expr emitters in generally 315 // are not ready to handle emitting expressions at unreachable points. 316 EnsureInsertPoint(); 317} 318 319void CodeGenFunction::EmitStartEHSpec(const Decl *D) { 320 if (!Exceptions) 321 return; 322 323 const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); 324 if (FD == 0) 325 return; 326 const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); 327 if (Proto == 0) 328 return; 329 330 assert(!Proto->hasAnyExceptionSpec() && "function with parameter pack"); 331 332 if (!Proto->hasExceptionSpec()) 333 return; 334 335 llvm::Constant *Personality = 336 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty 337 (VMContext), 338 true), 339 "__gxx_personality_v0"); 340 Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty); 341 llvm::Value *llvm_eh_exception = 342 CGM.getIntrinsic(llvm::Intrinsic::eh_exception); 343 llvm::Value *llvm_eh_selector = 344 CGM.getIntrinsic(llvm::Intrinsic::eh_selector); 345 const llvm::IntegerType *Int8Ty; 346 const llvm::PointerType *PtrToInt8Ty; 347 Int8Ty = llvm::Type::getInt8Ty(VMContext); 348 // C string type. Used in lots of places. 349 PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty); 350 llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty); 351 llvm::SmallVector<llvm::Value*, 8> SelectorArgs; 352 353 llvm::BasicBlock *PrevLandingPad = getInvokeDest(); 354 llvm::BasicBlock *EHSpecHandler = createBasicBlock("ehspec.handler"); 355 llvm::BasicBlock *Match = createBasicBlock("match"); 356 llvm::BasicBlock *Unwind = 0; 357 358 assert(PrevLandingPad == 0 && "EHSpec has invoke context"); 359 (void)PrevLandingPad; 360 361 llvm::BasicBlock *Cont = createBasicBlock("cont"); 362 363 EmitBranchThroughCleanup(Cont); 364 365 // Emit the statements in the try {} block 366 setInvokeDest(EHSpecHandler); 367 368 EmitBlock(EHSpecHandler); 369 // Exception object 370 llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc"); 371 llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow"); 372 373 SelectorArgs.push_back(Exc); 374 SelectorArgs.push_back(Personality); 375 SelectorArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 376 Proto->getNumExceptions()+1)); 377 378 for (unsigned i = 0; i < Proto->getNumExceptions(); ++i) { 379 QualType Ty = Proto->getExceptionType(i); 380 QualType ExceptType 381 = Ty.getNonReferenceType().getUnqualifiedType(); 382 llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType); 383 SelectorArgs.push_back(EHType); 384 } 385 if (Proto->getNumExceptions()) 386 SelectorArgs.push_back(Null); 387 388 // Find which handler was matched. 389 llvm::Value *Selector 390 = Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(), 391 SelectorArgs.end(), "selector"); 392 if (Proto->getNumExceptions()) { 393 Unwind = createBasicBlock("Unwind"); 394 395 Builder.CreateStore(Exc, RethrowPtr); 396 Builder.CreateCondBr(Builder.CreateICmpSLT(Selector, 397 llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 398 0)), 399 Match, Unwind); 400 401 EmitBlock(Match); 402 } 403 Builder.CreateCall(getUnexpectedFn(*this), Exc)->setDoesNotReturn(); 404 Builder.CreateUnreachable(); 405 406 if (Proto->getNumExceptions()) { 407 EmitBlock(Unwind); 408 Builder.CreateCall(getUnwindResumeOrRethrowFn(*this), 409 Builder.CreateLoad(RethrowPtr)); 410 Builder.CreateUnreachable(); 411 } 412 413 EmitBlock(Cont); 414} 415 416void CodeGenFunction::EmitEndEHSpec(const Decl *D) { 417 if (!Exceptions) 418 return; 419 420 const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); 421 if (FD == 0) 422 return; 423 const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); 424 if (Proto == 0) 425 return; 426 427 if (!Proto->hasExceptionSpec()) 428 return; 429 430 setInvokeDest(0); 431} 432 433void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { 434 // Pointer to the personality function 435 llvm::Constant *Personality = 436 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty 437 (VMContext), 438 true), 439 "__gxx_personality_v0"); 440 Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty); 441 llvm::Value *llvm_eh_exception = 442 CGM.getIntrinsic(llvm::Intrinsic::eh_exception); 443 llvm::Value *llvm_eh_selector = 444 CGM.getIntrinsic(llvm::Intrinsic::eh_selector); 445 446 llvm::BasicBlock *PrevLandingPad = getInvokeDest(); 447 llvm::BasicBlock *TryHandler = createBasicBlock("try.handler"); 448 llvm::BasicBlock *FinallyBlock = createBasicBlock("finally"); 449 llvm::BasicBlock *FinallyRethrow = createBasicBlock("finally.throw"); 450 llvm::BasicBlock *FinallyEnd = createBasicBlock("finally.end"); 451 452 // Push an EH context entry, used for handling rethrows. 453 PushCleanupBlock(FinallyBlock); 454 455 // Emit the statements in the try {} block 456 setInvokeDest(TryHandler); 457 458 // FIXME: We should not have to do this here. The AST should have the member 459 // initializers under the CXXTryStmt's TryBlock. 460 if (OuterTryBlock == &S) { 461 GlobalDecl GD = CurGD; 462 const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); 463 464 if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) { 465 size_t OldCleanupStackSize = CleanupEntries.size(); 466 EmitCtorPrologue(CD, CurGD.getCtorType()); 467 EmitStmt(S.getTryBlock()); 468 469 // If any of the member initializers are temporaries bound to references 470 // make sure to emit their destructors. 471 EmitCleanupBlocks(OldCleanupStackSize); 472 } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) { 473 llvm::BasicBlock *DtorEpilogue = createBasicBlock("dtor.epilogue"); 474 PushCleanupBlock(DtorEpilogue); 475 476 EmitStmt(S.getTryBlock()); 477 478 CleanupBlockInfo Info = PopCleanupBlock(); 479 480 assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!"); 481 EmitBlock(DtorEpilogue); 482 EmitDtorEpilogue(DD, GD.getDtorType()); 483 484 if (Info.SwitchBlock) 485 EmitBlock(Info.SwitchBlock); 486 if (Info.EndBlock) 487 EmitBlock(Info.EndBlock); 488 } else 489 EmitStmt(S.getTryBlock()); 490 } else 491 EmitStmt(S.getTryBlock()); 492 493 // Jump to end if there is no exception 494 EmitBranchThroughCleanup(FinallyEnd); 495 496 llvm::BasicBlock *TerminateHandler = getTerminateHandler(); 497 498 // Emit the handlers 499 EmitBlock(TryHandler); 500 501 const llvm::IntegerType *Int8Ty; 502 const llvm::PointerType *PtrToInt8Ty; 503 Int8Ty = llvm::Type::getInt8Ty(VMContext); 504 // C string type. Used in lots of places. 505 PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty); 506 llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty); 507 llvm::SmallVector<llvm::Value*, 8> SelectorArgs; 508 llvm::Value *llvm_eh_typeid_for = 509 CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); 510 // Exception object 511 llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc"); 512 llvm::Value *RethrowPtr = CreateTempAlloca(Exc->getType(), "_rethrow"); 513 514 llvm::SmallVector<llvm::Value*, 8> Args; 515 Args.clear(); 516 SelectorArgs.push_back(Exc); 517 SelectorArgs.push_back(Personality); 518 519 bool HasCatchAll = false; 520 for (unsigned i = 0; i<S.getNumHandlers(); ++i) { 521 const CXXCatchStmt *C = S.getHandler(i); 522 VarDecl *CatchParam = C->getExceptionDecl(); 523 if (CatchParam) { 524 // C++ [except.handle]p3 indicates that top-level cv-qualifiers 525 // are ignored. 526 QualType CaughtType = C->getCaughtType().getNonReferenceType(); 527 llvm::Value *EHTypeInfo 528 = CGM.GetAddrOfRTTIDescriptor(CaughtType.getUnqualifiedType()); 529 SelectorArgs.push_back(EHTypeInfo); 530 } else { 531 // null indicates catch all 532 SelectorArgs.push_back(Null); 533 HasCatchAll = true; 534 } 535 } 536 537 // We use a cleanup unless there was already a catch all. 538 if (!HasCatchAll) { 539 SelectorArgs.push_back(Null); 540 } 541 542 // Find which handler was matched. 543 llvm::Value *Selector 544 = Builder.CreateCall(llvm_eh_selector, SelectorArgs.begin(), 545 SelectorArgs.end(), "selector"); 546 for (unsigned i = 0; i<S.getNumHandlers(); ++i) { 547 const CXXCatchStmt *C = S.getHandler(i); 548 VarDecl *CatchParam = C->getExceptionDecl(); 549 Stmt *CatchBody = C->getHandlerBlock(); 550 551 llvm::BasicBlock *Next = 0; 552 553 if (SelectorArgs[i+2] != Null) { 554 llvm::BasicBlock *Match = createBasicBlock("match"); 555 Next = createBasicBlock("catch.next"); 556 const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext()); 557 llvm::Value *Id 558 = Builder.CreateCall(llvm_eh_typeid_for, 559 Builder.CreateBitCast(SelectorArgs[i+2], 560 Int8PtrTy)); 561 Builder.CreateCondBr(Builder.CreateICmpEQ(Selector, Id), 562 Match, Next); 563 EmitBlock(Match); 564 } 565 566 llvm::BasicBlock *MatchEnd = createBasicBlock("match.end"); 567 llvm::BasicBlock *MatchHandler = createBasicBlock("match.handler"); 568 569 PushCleanupBlock(MatchEnd); 570 setInvokeDest(MatchHandler); 571 572 llvm::Value *ExcObject = Builder.CreateCall(getBeginCatchFn(*this), Exc); 573 574 { 575 CleanupScope CatchScope(*this); 576 // Bind the catch parameter if it exists. 577 if (CatchParam) { 578 QualType CatchType = CatchParam->getType().getNonReferenceType(); 579 setInvokeDest(TerminateHandler); 580 bool WasPointer = true; 581 bool WasPointerReference = false; 582 CatchType = CGM.getContext().getCanonicalType(CatchType); 583 if (CatchType.getTypePtr()->isPointerType()) { 584 if (isa<ReferenceType>(CatchParam->getType())) 585 WasPointerReference = true; 586 } else { 587 if (!isa<ReferenceType>(CatchParam->getType())) 588 WasPointer = false; 589 CatchType = getContext().getPointerType(CatchType); 590 } 591 ExcObject = Builder.CreateBitCast(ExcObject, ConvertType(CatchType)); 592 EmitLocalBlockVarDecl(*CatchParam); 593 // FIXME: we need to do this sooner so that the EH region for the 594 // cleanup doesn't start until after the ctor completes, use a decl 595 // init? 596 CopyObject(*this, CatchParam->getType().getNonReferenceType(), 597 WasPointer, WasPointerReference, ExcObject, 598 GetAddrOfLocalVar(CatchParam)); 599 setInvokeDest(MatchHandler); 600 } 601 602 EmitStmt(CatchBody); 603 } 604 605 EmitBranchThroughCleanup(FinallyEnd); 606 607 EmitBlock(MatchHandler); 608 609 llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc"); 610 // We are required to emit this call to satisfy LLVM, even 611 // though we don't use the result. 612 Args.clear(); 613 Args.push_back(Exc); 614 Args.push_back(Personality); 615 Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 616 0)); 617 Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end()); 618 Builder.CreateStore(Exc, RethrowPtr); 619 EmitBranchThroughCleanup(FinallyRethrow); 620 621 CodeGenFunction::CleanupBlockInfo Info = PopCleanupBlock(); 622 623 EmitBlock(MatchEnd); 624 625 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); 626 Builder.CreateInvoke(getEndCatchFn(*this), 627 Cont, TerminateHandler, 628 Args.begin(), Args.begin()); 629 EmitBlock(Cont); 630 if (Info.SwitchBlock) 631 EmitBlock(Info.SwitchBlock); 632 if (Info.EndBlock) 633 EmitBlock(Info.EndBlock); 634 635 Exc = Builder.CreateCall(llvm_eh_exception, "exc"); 636 Builder.CreateStore(Exc, RethrowPtr); 637 EmitBranchThroughCleanup(FinallyRethrow); 638 639 if (Next) 640 EmitBlock(Next); 641 } 642 if (!HasCatchAll) { 643 Builder.CreateStore(Exc, RethrowPtr); 644 EmitBranchThroughCleanup(FinallyRethrow); 645 } 646 647 CodeGenFunction::CleanupBlockInfo Info = PopCleanupBlock(); 648 649 setInvokeDest(PrevLandingPad); 650 651 EmitBlock(FinallyBlock); 652 653 if (Info.SwitchBlock) 654 EmitBlock(Info.SwitchBlock); 655 if (Info.EndBlock) 656 EmitBlock(Info.EndBlock); 657 658 // Branch around the rethrow code. 659 EmitBranch(FinallyEnd); 660 661 EmitBlock(FinallyRethrow); 662 // FIXME: Eventually we can chain the handlers together and just do a call 663 // here. 664 if (getInvokeDest()) { 665 llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); 666 Builder.CreateInvoke(getUnwindResumeOrRethrowFn(*this), Cont, 667 getInvokeDest(), 668 Builder.CreateLoad(RethrowPtr)); 669 EmitBlock(Cont); 670 } else 671 Builder.CreateCall(getUnwindResumeOrRethrowFn(*this), 672 Builder.CreateLoad(RethrowPtr)); 673 674 Builder.CreateUnreachable(); 675 676 EmitBlock(FinallyEnd); 677} 678 679CodeGenFunction::EHCleanupBlock::~EHCleanupBlock() { 680 llvm::BasicBlock *Cont1 = CGF.createBasicBlock("cont"); 681 CGF.EmitBranch(Cont1); 682 CGF.setInvokeDest(PreviousInvokeDest); 683 684 685 CGF.EmitBlock(CleanupHandler); 686 687 llvm::Constant *Personality = 688 CGF.CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty 689 (CGF.VMContext), 690 true), 691 "__gxx_personality_v0"); 692 Personality = llvm::ConstantExpr::getBitCast(Personality, CGF.PtrToInt8Ty); 693 llvm::Value *llvm_eh_exception = 694 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_exception); 695 llvm::Value *llvm_eh_selector = 696 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_selector); 697 698 llvm::Value *Exc = CGF.Builder.CreateCall(llvm_eh_exception, "exc"); 699 const llvm::IntegerType *Int8Ty; 700 const llvm::PointerType *PtrToInt8Ty; 701 Int8Ty = llvm::Type::getInt8Ty(CGF.VMContext); 702 // C string type. Used in lots of places. 703 PtrToInt8Ty = llvm::PointerType::getUnqual(Int8Ty); 704 llvm::Constant *Null = llvm::ConstantPointerNull::get(PtrToInt8Ty); 705 llvm::SmallVector<llvm::Value*, 8> Args; 706 Args.clear(); 707 Args.push_back(Exc); 708 Args.push_back(Personality); 709 Args.push_back(Null); 710 CGF.Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end()); 711 712 CGF.EmitBlock(CleanupEntryBB); 713 714 CGF.EmitBlock(Cont1); 715 716 if (CGF.getInvokeDest()) { 717 llvm::BasicBlock *Cont = CGF.createBasicBlock("invoke.cont"); 718 CGF.Builder.CreateInvoke(getUnwindResumeOrRethrowFn(CGF), Cont, 719 CGF.getInvokeDest(), Exc); 720 CGF.EmitBlock(Cont); 721 } else 722 CGF.Builder.CreateCall(getUnwindResumeOrRethrowFn(CGF), Exc); 723 724 CGF.Builder.CreateUnreachable(); 725 726 CGF.EmitBlock(Cont); 727 if (CGF.Exceptions) 728 CGF.setInvokeDest(CleanupHandler); 729} 730 731llvm::BasicBlock *CodeGenFunction::getTerminateHandler() { 732 if (TerminateHandler) 733 return TerminateHandler; 734 735 llvm::BasicBlock *Cont = 0; 736 737 if (HaveInsertPoint()) { 738 Cont = createBasicBlock("cont"); 739 EmitBranch(Cont); 740 } 741 742 llvm::Constant *Personality = 743 CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty 744 (VMContext), 745 true), 746 "__gxx_personality_v0"); 747 Personality = llvm::ConstantExpr::getBitCast(Personality, PtrToInt8Ty); 748 llvm::Value *llvm_eh_exception = 749 CGM.getIntrinsic(llvm::Intrinsic::eh_exception); 750 llvm::Value *llvm_eh_selector = 751 CGM.getIntrinsic(llvm::Intrinsic::eh_selector); 752 753 // Set up terminate handler 754 TerminateHandler = createBasicBlock("terminate.handler"); 755 EmitBlock(TerminateHandler); 756 llvm::Value *Exc = Builder.CreateCall(llvm_eh_exception, "exc"); 757 // We are required to emit this call to satisfy LLVM, even 758 // though we don't use the result. 759 llvm::SmallVector<llvm::Value*, 8> Args; 760 Args.push_back(Exc); 761 Args.push_back(Personality); 762 Args.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 763 1)); 764 Builder.CreateCall(llvm_eh_selector, Args.begin(), Args.end()); 765 llvm::CallInst *TerminateCall = 766 Builder.CreateCall(getTerminateFn(*this)); 767 TerminateCall->setDoesNotReturn(); 768 TerminateCall->setDoesNotThrow(); 769 Builder.CreateUnreachable(); 770 771 // Clear the insertion point to indicate we are in unreachable code. 772 Builder.ClearInsertionPoint(); 773 774 if (Cont) 775 EmitBlock(Cont); 776 777 return TerminateHandler; 778} 779