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