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