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