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