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