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