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