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