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