GSaha567/seq_level_training_data
052
1text,length,is_long_context,metric_val,label_metric2"//===--- CGException.cpp - Emit LLVM Code for C++ exceptions --------------===//3//4// The LLVM Compiler Infrastructure5//6// This file is distributed under the University of Illinois Open Source7// License. See LICENSE.TXT for details.8//9//===----------------------------------------------------------------------===//10//11// This contains code dealing with C++ exception related code generation.12//13//===----------------------------------------------------------------------===//14 15#include ""CodeGenFunction.h""16#include ""CGCleanup.h""17#include ""CGObjCRuntime.h""18#include ""TargetInfo.h""19#include ""clang/AST/StmtCXX.h""20#include ""clang/AST/StmtObjC.h""21#include ""llvm/IR/Intrinsics.h""22#include ""llvm/Support/CallSite.h""23 24using namespace clang;25using namespace CodeGen;26 27static llvm::Constant *getAllocateExceptionFn(CodeGenModule &CGM) {28 // void *__cxa_allocate_exception(size_t thrown_size);29 30 llvm::FunctionType *FTy =31 llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*IsVarArgs=*/false);32 33 return CGM.CreateRuntimeFunction(FTy, ""__cxa_allocate_exception"");34}35 36static llvm::Constant *getFreeExceptionFn(CodeGenModule &CGM) {37 // void __cxa_free_exception(void *thrown_exception);38 39 llvm::FunctionType *FTy =40 llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);41 42 return CGM.CreateRuntimeFunction(FTy, ""__cxa_free_exception"");43}44 45static llvm::Constant *getThrowFn(CodeGenModule &CGM) {46 // void __cxa_throw(void *thrown_exception, std::type_info *tinfo,47 // void (*dest) (void *));48 49 llvm::Type *Args[3] = { CGM.Int8PtrTy, CGM.Int8PtrTy, CGM.Int8PtrTy };50 llvm::FunctionType *FTy =51 llvm::FunctionType::get(CGM.VoidTy, Args, /*IsVarArgs=*/false);52 53 return CGM.CreateRuntimeFunction(FTy, ""__cxa_throw"");54}55 56static llvm::Constant *getReThrowFn(CodeGenModule &CGM) {57 // void __cxa_rethrow();58 59 llvm::FunctionType *FTy =60 llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false);61 62 return CGM.CreateRuntimeFunction(FTy, ""__cxa_rethrow"");63}64 65static llvm::Constant *getGetExceptionPtrFn(CodeGenModule &CGM) {66 // void *__cxa_get_exception_ptr(void*);67 68 llvm::FunctionType *FTy =69 llvm::FunctionType::get(CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);70 71 return CGM.CreateRuntimeFunction(FTy, ""__cxa_get_exception_ptr"");72}73 74static llvm::Constant *getBeginCatchFn(CodeGenModule &CGM) {75 // void *__cxa_begin_catch(void*);76 77 llvm::FunctionType *FTy =78 llvm::FunctionType::get(CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);79 80 return CGM.CreateRuntimeFunction(FTy, ""__cxa_begin_catch"");81}82 83static llvm::Constant *getEndCatchFn(CodeGenModule &CGM) {84 // void __cxa_end_catch();85 86 llvm::FunctionType *FTy =87 llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false);88 89 return CGM.CreateRuntimeFunction(FTy, ""__cxa_end_catch"");90}91 92static llvm::Constant *getUnexpectedFn(CodeGenModule &CGM) {93 // void __cxa_call_unexpected(void *thrown_exception);94 95 llvm::FunctionType *FTy =96 llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);97 98 return CGM.CreateRuntimeFunction(FTy, ""__cxa_call_unexpected"");99}100 101llvm::Constant *CodeGenFunction::getUnwindResumeFn() {102 llvm::FunctionType *FTy =103 llvm::FunctionType::get(VoidTy, Int8PtrTy, /*IsVarArgs=*/false);104 105 if (CGM.getLangOpts().SjLjExceptions)106 return CGM.CreateRuntimeFunction(FTy, ""_Unwind_SjLj_Resume"");107 return CGM.CreateRuntimeFunction(FTy, ""_Unwind_Resume"");108}109 110llvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() {111 llvm::FunctionType *FTy =112 llvm::FunctionType::get(VoidTy, Int8PtrTy, /*IsVarArgs=*/false);113 114 if (CGM.getLangOpts().SjLjExceptions)115 return CGM.CreateRuntimeFunction(FTy, ""_Unwind_SjLj_Resume_or_Rethrow"");116 return CGM.CreateRuntimeFunction(FTy, ""_Unwind_Resume_or_Rethrow"");117}118 119static llvm::Constant *getTerminateFn(CodeGenModule &CGM) {120 // void __terminate();121 122 llvm::FunctionType *FTy =123 llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false);124 125 StringRef name;126 127 // In C++, use std::terminate().128 if (CGM.getLangOpts().CPlusPlus)129 name = ""_ZSt9terminatev""; // FIXME: mangling!130 else if (CGM.getLangOpts().ObjC1 &&131 CGM.getLangOpts().ObjCRuntime.hasTerminate())132 name = ""objc_terminate"";133 else134 name = ""abort"";135 return CGM.CreateRuntimeFunction(FTy, name);136}137 138static llvm::Constant *getCatchallRethrowFn(CodeGenModule &CGM,139 StringRef Name) {140 llvm::FunctionType *FTy =141 llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false);142 143 return CGM.CreateRuntimeFunction(FTy, Name);144}145 146namespace {147 /// The exceptions personality for a function.148 struct EHPersonality {149 const char *PersonalityFn;150 151 // If this is non-null, this personality requires a non-standard152 // function for rethrowing an exception after a catchall cleanup.153 // This function must have prototype void(void*).154 const char *CatchallRethrowFn;155 156 static const EHPersonality &get(const LangOptions &Lang);157 static const EHPersonality GNU_C;158 static const EHPersonality GNU_C_SJLJ;159 static const EHPersonality GNU_ObjC;160 static const EHPersonality GNUstep_ObjC;161 static const EHPersonality GNU_ObjCXX;162 static const EHPersonality NeXT_ObjC;163 static const EHPersonality GNU_CPlusPlus;164 static const EHPersonality GNU_CPlusPlus_SJLJ;165 };166}167 168const EHPersonality EHPersonality::GNU_C = { ""__gcc_personality_v0"", 0 };169const EHPersonality EHPersonality::GNU_C_SJLJ = { ""__gcc_personality_sj0"", 0 };170const EHPersonality EHPersonality::NeXT_ObjC = { ""__objc_personality_v0"", 0 };171const EHPersonality EHPersonality::GNU_CPlusPlus = { ""__gxx_personality_v0"", 0};172const EHPersonality173EHPersonality::GNU_CPlusPlus_SJLJ = { ""__gxx_personality_sj0"", 0 };174const EHPersonality175EHPersonality::GNU_ObjC = {""__gnu_objc_personality_v0"", ""objc_exception_throw""};176const EHPersonality177EHPersonality::GNU_ObjCXX = { ""__gnustep_objcxx_personality_v0"", 0 };178const EHPersonality179EHPersonality::GNUstep_ObjC = { ""__gnustep_objc_personality_v0"", 0 };180 181static const EHPersonality &getCPersonality(const LangOptions &L) {182 if (L.SjLjExceptions)183 return EHPersonality::GNU_C_SJLJ;184 return EHPersonality::GNU_C;185}186 187static const EHPersonality &getObjCPersonality(const LangOptions &L) {188 switch (L.ObjCRuntime.getKind()) {189 case ObjCRuntime::FragileMacOSX:190 return getCPersonality(L);191 case ObjCRuntime::MacOSX:192 case ObjCRuntime::iOS:193 return EHPersonality::NeXT_ObjC;194 case ObjCRuntime::GNUstep:195 if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7))196 return EHPersonality::GNUstep_ObjC;197 // fallthrough198 case ObjCRuntime::GCC:199 case ObjCRuntime::ObjFW:200 return EHPersonality::GNU_ObjC;201 }202 llvm_unreachable(""bad runtime kind"");203}204 205static const EHPersonality &getCXXPersonality(const LangOptions &L) {206 if (L.SjLjExceptions)207 return EHPersonality::GNU_CPlusPlus_SJLJ;208 else209 return EHPersonality::GNU_CPlusPlus;210}211 212/// Determines the personality function to use when both C++213/// and Objective-C exceptions are being caught.214static const EHPersonality &getObjCXXPersonality(const LangOptions &L) {215 switch (L.ObjCRuntime.getKind()) {216 // The ObjC personality defers to the C++ personality for non-ObjC217 // handlers. Unlike the C++ case, we use the same personality218 // function on targets using (backend-driven) SJLJ EH.219 case ObjCRuntime::MacOSX:220 case ObjCRuntime::iOS:221 return EHPersonality::NeXT_ObjC;222 223 // In the fragile ABI, just use C++ exception handling and hope224 // they're not doing crazy exception mixing.225 case ObjCRuntime::FragileMacOSX:226 return getCXXPersonality(L);227 228 // The GCC runtime's personality function inherently doesn't support229 // mixed EH. Use the C++ personality just to avoid returning null.230 case ObjCRuntime::GCC:231 case ObjCRuntime::ObjFW: // XXX: this will change soon232 return EHPersonality::GNU_ObjC;233 case ObjCRuntime::GNUstep:234 return EHPersonality::GNU_ObjCXX;235 }236 llvm_unreachable(""bad runtime kind"");237}238 239const EHPersonality &EHPersonality::get(const LangOptions &L) {240 if (L.CPlusPlus && L.ObjC1)241 return getObjCXXPersonality(L);242 else if (L.CPlusPlus)243 return getCXXPersonality(L);244 else if (L.ObjC1)245 return getObjCPersonality(L);246 else247 return getCPersonality(L);248}249 250static llvm::Constant *getPersonalityFn(CodeGenModule &CGM,251 const EHPersonality &Personality) {252 llvm::Constant *Fn =253 CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty, true),254 Personality.PersonalityFn);255 return Fn;256}257 258static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM,259 const EHPersonality &Personality) {260 llvm::Constant *Fn = getPersonalityFn(CGM, Personality);261 return llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy);262}263 264/// Check whether a personality function could reasonably be swapped265/// for a C++ personality function.266static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) {267 for (llvm::Constant::use_iterator268 I = Fn->use_begin(), E = Fn->use_end(); I != E; ++I) {269 llvm::User *User = *I;270 271 // Conditionally white-list bitcasts.272 if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(User)) {273 if (CE->getOpcode() != llvm::Instruction::BitCast) return false;274 if (!PersonalityHasOnlyCXXUses(CE))275 return false;276 continue;277 }278 279 // Otherwise, it has to be a landingpad instruction.280 llvm::LandingPadInst *LPI = dyn_cast<llvm::LandingPadInst>(User);281 if (!LPI) return false;282 283 for (unsigned I = 0, E = LPI->getNumClauses(); I != E; ++I) {284 // Look for something that would've been returned by the ObjC285 // runtime's GetEHType() method.286 llvm::Value *Val = LPI->getClause(I)->stripPointerCasts();287 if (LPI->isCatch(I)) {288 // Check if the catch value has the ObjC prefix.289 if (llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Val))290 // ObjC EH selector entries are always global variables with291 // names starting like this.292 if (GV->getName().startswith(""OBJC_EHTYPE""))293 return false;294 } else {295 // Check if any of the filter values have the ObjC prefix.296 llvm::Constant *CVal = cast<llvm::Constant>(Val);297 for (llvm::User::op_iterator298 II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) {299 if (llvm::GlobalVariable *GV =300 cast<llvm::GlobalVariable>((*II)->stripPointerCasts()))301 // ObjC EH selector entries are always global variables with302 // names starting like this.303 if (GV->getName().startswith(""OBJC_EHTYPE""))304 return false;305 }306 }307 }308 }309 310 return true;311}312 313/// Try to use the C++ personality function in ObjC++. Not doing this314/// can cause some incompatibilities with gcc, which is more315/// aggressive about only using the ObjC++ personality in a function316/// when it really needs it.317void CodeGenModule::SimplifyPersonality() {318 // If we're not in ObjC++ -fexceptions, there's nothing to do.319 if (!LangOpts.CPlusPlus || !LangOpts.ObjC1 || !LangOpts.Exceptions)320 return;321 322 // Both the problem this endeavors to fix and the way the logic323 // above works is specific to the NeXT runtime.324 if (!LangOpts.ObjCRuntime.isNeXTFamily())325 return;326 327 const EHPersonality &ObjCXX = EHPersonality::get(LangOpts);328 const EHPersonality &CXX = getCXXPersonality(LangOpts);329 if (&ObjCXX == &CXX)330 return;331 332 assert(std::strcmp(ObjCXX.PersonalityFn, CXX.PersonalityFn) != 0 &&333 ""Different EHPersonalities using the same personality function."");334 335 llvm::Function *Fn = getModule().getFunction(ObjCXX.PersonalityFn);336 337 // Nothing to do if it's unused.338 if (!Fn || Fn->use_empty()) return;339 340 // Can't do the optimization if it has non-C++ uses.341 if (!PersonalityHasOnlyCXXUses(Fn)) return;342 343 // Create the C++ personality function and kill off the old344 // function.345 llvm::Constant *CXXFn = getPersonalityFn(*this, CXX);346 347 // This can happen if the user is screwing with us.348 if (Fn->getType() != CXXFn->getType()) return;349 350 Fn->replaceAllUsesWith(CXXFn);351 Fn->eraseFromParent();352}353 354/// Returns the value to inject into a selector to indicate the355/// presence of a catch-all.356static llvm::Constant *getCatchAllValue(CodeGenFunction &CGF) {357 // Possibly we should use @llvm.eh.catch.all.value here.358 return llvm::ConstantPointerNull::get(CGF.Int8PtrTy);359}360 361namespace {362 /// A cleanup to free the exception object if its initialization363 /// throws.364 struct FreeException : EHScopeStack::Cleanup {365 llvm::Value *exn;366 FreeException(llvm::Value *exn) : exn(exn) {}367 void Emit(CodeGenFunction &CGF, Flags flags) {368 CGF.EmitNounwindRuntimeCall(getFreeExceptionFn(CGF.CGM), exn);369 }370 };371}372 373// Emits an exception expression into the given location. This374// differs from EmitAnyExprToMem only in that, if a final copy-ctor375// call is required, an exception within that copy ctor causes376// std::terminate to be invoked.377static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *e,378 llvm::Value *addr) {379 // Make sure the exception object is cleaned up if there's an380 // exception during initialization.381 CGF.pushFullExprCleanup<FreeException>(EHCleanup, addr);382 EHScopeStack::stable_iterator cleanup = CGF.EHStack.stable_begin();383 384 // __cxa_allocate_exception returns a void*; we need to cast this385 // to the appropriate type for the object.386 llvm::Type *ty = CGF.ConvertTypeForMem(e->getType())->getPointerTo();387 llvm::Value *typedAddr = CGF.Builder.CreateBitCast(addr, ty);388 389 // FIXME: this isn't quite right! If there's a final unelided call390 // to a copy constructor, then according to [except.terminate]p1 we391 // must call std::terminate() if that constructor throws, because392 // technically that copy occurs after the exception expression is393 // evaluated but before the exception is caught. But the best way394 // to handle that is to teach EmitAggExpr to do the final copy395 // differently if it can't be elided.396 CGF.EmitAnyExprToMem(e, typedAddr, e->getType().getQualifiers(), 397 /*IsInit*/ true);398 399 // Deactivate the cleanup block.400 CGF.DeactivateCleanupBlock(cleanup, cast<llvm::Instruction>(typedAddr));401}402 403llvm::Value *CodeGenFunction::getExceptionSlot() {404 if (!ExceptionSlot)405 ExceptionSlot = CreateTempAlloca(Int8PtrTy, ""exn.slot"");406 return ExceptionSlot;407}408 409llvm::Value *CodeGenFunction::getEHSelectorSlot() {410 if (!EHSelectorSlot)411 EHSelectorSlot = CreateTempAlloca(Int32Ty, ""ehselector.slot"");412 return EHSelectorSlot;413}414 415llvm::Value *CodeGenFunction::getExceptionFromSlot() {416 return Builder.CreateLoad(getExceptionSlot(), ""exn"");417}418 419llvm::Value *CodeGenFunction::getSelectorFromSlot() {420 return Builder.CreateLoad(getEHSelectorSlot(), ""sel"");421}422 423void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E,424 bool KeepInsertionPoint) {425 if (!E->getSubExpr()) {426 EmitNoreturnRuntimeCallOrInvoke(getReThrowFn(CGM),427 ArrayRef<llvm::Value*>());428 429 // throw is an expression, and the expression emitters expect us430 // to leave ourselves at a valid insertion point.431 if (KeepInsertionPoint)432 EmitBlock(createBasicBlock(""throw.cont""));433 434 return;435 }436 437 QualType ThrowType = E->getSubExpr()->getType();438 439 if (ThrowType->isObjCObjectPointerType()) {440 const Stmt *ThrowStmt = E->getSubExpr();441 const ObjCAtThrowStmt S(E->getExprLoc(),442 const_cast<Stmt *>(ThrowStmt));443 CGM.getObjCRuntime().EmitThrowStmt(*this, S, false);444 // This will clear insertion point which was not cleared in445 // call to EmitThrowStmt.446 if (KeepInsertionPoint)447 EmitBlock(createBasicBlock(""throw.cont""));448 return;449 }450 451 // Now allocate the exception object.452 llvm::Type *SizeTy = ConvertType(getContext().getSizeType());453 uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity();454 455 llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(CGM);456 llvm::CallInst *ExceptionPtr =457 EmitNounwindRuntimeCall(AllocExceptionFn,458 llvm::ConstantInt::get(SizeTy, TypeSize),459 ""exception"");460 461 EmitAnyExprToExn(*this, E->getSubExpr(), ExceptionPtr);462 463 // Now throw the exception.464 llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType, 465 /*ForEH=*/true);466 467 // The address of the destructor. If the exception type has a468 // trivial destructor (or isn't a record), we just pass null.469 llvm::Constant *Dtor = 0;470 if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) {471 CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());472 if (!Record->hasTrivialDestructor()) {473 CXXDestructorDecl *DtorD = Record->getDestructor();474 Dtor = CGM.GetAddrOfCXXDestructor(DtorD, Dtor_Complete);475 Dtor = llvm::ConstantExpr::getBitCast(Dtor, Int8PtrTy);476 }477 }478 if (!Dtor) Dtor = llvm::Constant::getNullValue(Int8PtrTy);479 480 llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor };481 EmitNoreturnRuntimeCallOrInvoke(getThrowFn(CGM), args);482 483 // throw is an expression, and the expression emitters expect us484 // to leave ourselves at a valid insertion point.485 if (KeepInsertionPoint)486 EmitBlock(createBasicBlock(""throw.cont""));487}488 489void CodeGenFunction::EmitStartEHSpec(const Decl *D) {490 if (!CGM.getLangOpts().CXXExceptions)491 return;492 493 const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);494 if (FD == 0)495 return;496 const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();497 if (Proto == 0)498 return;499 500 ExceptionSpecificationType EST = Proto->getExceptionSpecType();501 if (isNoexceptExceptionSpec(EST)) {502 if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) {503 // noexcept functions are simple terminate scopes.504 EHStack.pushTerminate();505 }506 } else if (EST == EST_Dynamic || EST == EST_DynamicNone) {507 unsigned NumExceptions = Proto->getNumExceptions();508 EHFilterScope *Filter = EHStack.pushFilter(NumExceptions);509 510 for (unsigned I = 0; I != NumExceptions; ++I) {511 QualType Ty = Proto->getExceptionType(I);512 QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType();513 llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType,514 /*ForEH=*/true);515 Filter->setFilter(I, EHType);516 }517 }518}519 520/// Emit the dispatch block for a filter scope if necessary.521static void emitFilterDispatchBlock(CodeGenFunction &CGF,522 EHFilterScope &filterScope) {523 llvm::BasicBlock *dispatchBlock = filterScope.getCachedEHDispatchBlock();524 if (!dispatchBlock) return;525 if (dispatchBlock->use_empty()) {526 delete dispatchBlock;527 return;528 }529 530 CGF.EmitBlockAfterUses(dispatchBlock);531 532 // If this isn't a catch-all filter, we need to check whether we got533 // here because the filter triggered.534 if (filterScope.getNumFilters()) {535 // Load the selector value.536 llvm::Value *selector = CGF.getSelectorFromSlot();537 llvm::BasicBlock *unexpectedBB = CGF.createBasicBlock(""ehspec.unexpected"");538 539 llvm::Value *zero = CGF.Builder.getInt32(0);540 llvm::Value *failsFilter =541 CGF.Builder.CreateICmpSLT(selector, zero, ""ehspec.fails"");542 CGF.Builder.CreateCondBr(failsFilter, unexpectedBB, CGF.getEHResumeBlock(false));543 544 CGF.EmitBlock(unexpectedBB);545 }546 547 // Call __cxa_call_unexpected. This doesn't need to be an invoke548 // because __cxa_call_unexpected magically filters exceptions549 // according to the last landing pad the exception was thrown550 // into. Seriously.551 llvm::Value *exn = CGF.getExceptionFromSlot();552 CGF.EmitRuntimeCall(getUnexpectedFn(CGF.CGM), exn)553 ->setDoesNotReturn();554 CGF.Builder.CreateUnreachable();555}556 557void CodeGenFunction::EmitEndEHSpec(const Decl *D) {558 if (!CGM.getLangOpts().CXXExceptions)559 return;560 561 const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D);562 if (FD == 0)563 return;564 const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>();565 if (Proto == 0)566 return;567 568 ExceptionSpecificationType EST = Proto->getExceptionSpecType();569 if (isNoexceptExceptionSpec(EST)) {570 if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) {571 EHStack.popTerminate();572 }573 } else if (EST == EST_Dynamic || EST == EST_DynamicNone) {574 EHFilterScope &filterScope = cast<EHFilterScope>(*EHStack.begin());575 emitFilterDispatchBlock(*this, filterScope);576 EHStack.popFilter();577 }578}579 580void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {581 EnterCXXTryStmt(S);582 EmitStmt(S.getTryBlock());583 ExitCXXTryStmt(S);584}585 586void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) {587 unsigned NumHandlers = S.getNumHandlers();588 EHCatchScope *CatchScope = EHStack.pushCatch(NumHandlers);589 590 for (unsigned I = 0; I != NumHandlers; ++I) {591 const CXXCatchStmt *C = S.getHandler(I);592 593 llvm::BasicBlock *Handler = createBasicBlock(""catch"");594 if (C->getExceptionDecl()) {595 // FIXME: Dropping the reference type on the type into makes it596 // impossible to correctly implement catch-by-reference597 // semantics for pointers. Unfortunately, this is what all598 // existing compilers do, and it's not clear that the standard599 // personality routine is capable of doing this right. See C++ DR 388:600 // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388601 QualType CaughtType = C->getCaughtType();602 CaughtType = CaughtType.getNonReferenceType().getUnqualifiedType();603 604 llvm::Value *TypeInfo = 0;605 if (CaughtType->isObjCObjectPointerType())606 TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType);607 else608 TypeInfo = CGM.GetAddrOfRTTIDescriptor(CaughtType, /*ForEH=*/true);609 CatchScope->setHandler(I, TypeInfo, Handler);610 } else {611 // No exception decl indicates '...', a catch-all.612 CatchScope->setCatchAllHandler(I, Handler);613 }614 }615}616 617llvm::BasicBlock *618CodeGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) {619 // The dispatch block for the end of the scope chain is a block that620 // just resumes unwinding.621 if (si == EHStack.stable_end())622 return getEHResumeBlock(true);623 624 // Otherwise, we should look at the actual scope.625 EHScope &scope = *EHStack.find(si);626 627 llvm::BasicBlock *dispatchBlock = scope.getCachedEHDispatchBlock();628 if (!dispatchBlock) {629 switch (scope.getKind()) {630 case EHScope::Catch: {631 // Apply a special case to a single catch-all.632 EHCatchScope &catchScope = cast<EHCatchScope>(scope);633 if (catchScope.getNumHandlers() == 1 &&634 catchScope.getHandler(0).isCatchAll()) {635 dispatchBlock = catchScope.getHandler(0).Block;636 637 // Otherwise, make a dispatch block.638 } else {639 dispatchBlock = createBasicBlock(""catch.dispatch"");640 }641 break;642 }643 644 case EHScope::Cleanup:645 dispatchBlock = createBasicBlock(""ehcleanup"");646 break;647 648 case EHScope::Filter:649 dispatchBlock = createBasicBlock(""filter.dispatch"");650 break;651 652 case EHScope::Terminate:653 dispatchBlock = getTerminateHandler();654 break;655 }656 scope.setCachedEHDispatchBlock(dispatchBlock);657 }658 return dispatchBlock;659}660 661/// Check whether this is a non-EH scope, i.e. a scope which doesn't662/// affect exception handling. Currently, the only non-EH scopes are663/// normal-only cleanup scopes.664static bool isNonEHScope(const EHScope &S) {665 switch (S.getKind()) {666 case EHScope::Cleanup:667 return !cast<EHCleanupScope>(S).isEHCleanup();668 case EHScope::Filter:669 case EHScope::Catch:670 case EHScope::Terminate:671 return false;672 }673 674 llvm_unreachable(""Invalid EHScope Kind!"");675}676 677llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() {678 assert(EHStack.requiresLandingPad());679 assert(!EHStack.empty());680 681 if (!CGM.getLangOpts().Exceptions)682 return 0;683 684 // Check the innermost scope for a cached landing pad. If this is685 // a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad.686 llvm::BasicBlock *LP = EHStack.begin()->getCachedLandingPad();687 if (LP) return LP;688 689 // Build the landing pad for this scope.690 LP = EmitLandingPad();691 assert(LP);692 693 // Cache the landing pad on the innermost scope. If this is a694 // non-EH scope, cache the landing pad on the enclosing scope, too.695 for (EHScopeStack::iterator ir = EHStack.begin(); true; ++ir) {696 ir->setCachedLandingPad(LP);697 if (!isNonEHScope(*ir)) break;698 }699 700 return LP;701}702 703// This code contains a hack to work around a design flaw in704// LLVM's EH IR which breaks semantics after inlining. This same705// hack is implemented in llvm-gcc.706//707// The LLVM EH abstraction is basically a thin veneer over the708// traditional GCC zero-cost design: for each range of instructions709// in the function, there is (at most) one ""landing pad"" with an710// associated chain of EH actions. A language-specific personality711// function interprets this chain of actions and (1) decides whether712// or not to resume execution at the landing pad and (2) if so,713// provides an integer indicating why it's stopping. In LLVM IR,714// the association of a landing pad with a range of instructions is715// achieved via an invoke instruction, the chain of actions becomes716// the arguments to the @llvm.eh.selector call, and the selector717// call returns the integer indicator. Other than the required718// presence of two intrinsic function calls in the landing pad,719// the IR exactly describes the layout of the output code.720//721// A principal advantage of this design is that it is completely722// language-agnostic; in theory, the LLVM optimizers can treat723// landing pads neutrally, and targets need only know how to lower724// the intrinsics to have a functioning exceptions system (assuming725// that platform exceptions follow something approximately like the726// GCC design). Unfortunately, landing pads cannot be combined in a727// language-agnostic way: given selectors A and B, there is no way728// to make a single landing pad which faithfully represents the729// semantics of propagating an exception first through A, then730// through B, without knowing how the personality will interpret the731// (lowered form of the) selectors. This means that inlining has no732// choice but to crudely chain invokes (i.e., to ignore invokes in733// the inlined function, but to turn all unwindable calls into734// invokes), which is only semantically valid if every unwind stops735// at every landing pad.736//737// Therefore, the invoke-inline hack is to guarantee that every738// landing pad has a catch-all.739enum CleanupHackLevel_t {740 /// A level of hack that requires that all landing pads have741 /// catch-alls.742 CHL_MandatoryCatchall,743 744 /// A level of hack that requires that all landing pads handle745 /// cleanups.746 CHL_MandatoryCleanup,747 748 /// No hacks at all; ideal IR generation.749 CHL_Ideal750};751const CleanupHackLevel_t CleanupHackLevel = CHL_MandatoryCleanup;752 753llvm::BasicBlock *CodeGenFunction::EmitLandingPad() {754 assert(EHStack.requiresLandingPad());755 756 EHScope &innermostEHScope = *EHStack.find(EHStack.getInnermostEHScope());757 switch (innermostEHScope.getKind()) {758 case EHScope::Terminate:759 return getTerminateLandingPad();760 761 case EHScope::Catch:762 case EHScope::Cleanup:763 case EHScope::Filter:764 if (llvm::BasicBlock *lpad = innermostEHScope.getCachedLandingPad())765 return lpad;766 }767 768 // Save the current IR generation state.769 CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP();770 SourceLocation SavedLocation;771 if (CGDebugInfo *DI = getDebugInfo()) {772 SavedLocation = DI->getLocation();773 DI->EmitLocation(Builder, CurEHLocation);774 }775 776 const EHPersonality &personality = EHPersonality::get(getLangOpts());777 778 // Create and configure the landing pad.779 llvm::BasicBlock *lpad = createBasicBlock(""lpad"");780 EmitBlock(lpad);781 782 llvm::LandingPadInst *LPadInst =783 Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty, NULL),784 getOpaquePersonalityFn(CGM, personality), 0);785 786 llvm::Value *LPadExn = Builder.CreateExtractValue(LPadInst, 0);787 Builder.CreateStore(LPadExn, getExceptionSlot());788 llvm::Value *LPadSel = Builder.CreateExtractValue(LPadInst, 1);789 Builder.CreateStore(LPadSel, getEHSelectorSlot());790 791 // Save the exception pointer. It's safe to use a single exception792 // pointer per function because EH cleanups can never have nested793 // try/catches.794 // Build the landingpad instruction.795 796 // Accumulate all the handlers in scope.797 bool hasCatchAll = false;798 bool hasCleanup = false;799 bool hasFilter = false;800 SmallVector<llvm::Value*, 4> filterTypes;801 llvm::SmallPtrSet<llvm::Value*, 4> catchTypes;802 for (EHScopeStack::iterator I = EHStack.begin(), E = EHStack.end();803 I != E; ++I) {804 805 switch (I->getKind()) {806 case EHScope::Cleanup:807 // If we have a cleanup, remember that.808 hasCleanup = (hasCleanup || cast<EHCleanupScope>(*I).isEHCleanup());809 continue;810 811 case EHScope::Filter: {812 assert(I.next() == EHStack.end() && ""EH filter is not end of EH stack"");813 assert(!hasCatchAll && ""EH filter reached after catch-all"");814 815 // Filter scopes get added to the landingpad in weird ways.816 EHFilterScope &filter = cast<EHFilterScope>(*I);817 hasFilter = true;818 819 // Add all the filter values.820 for (unsigned i = 0, e = filter.getNumFilters(); i != e; ++i)821 filterTypes.push_back(filter.getFilter(i));822 goto done;823 }824 825 case EHScope::Terminate:826 // Terminate scopes are basically catch-alls.827 assert(!hasCatchAll);828 hasCatchAll = true;829 goto done;830 831 case EHScope::Catch:832 break;833 }834 835 EHCatchScope &catchScope = cast<EHCatchScope>(*I);836 for (unsigned hi = 0, he = catchScope.getNumHandlers(); hi != he; ++hi) {837 EHCatchScope::Handler handler = catchScope.getHandler(hi);838 839 // If this is a catch-all, register that and abort.840 if (!handler.Type) {841 assert(!hasCatchAll);842 hasCatchAll = true;843 goto done;844 }845 846 // Check whether we already have a handler for this type.847 if (catchTypes.insert(handler.Type))848 // If not, add it directly to the landingpad.849 LPadInst->addClause(handler.Type);850 }851 }852 853 done:854 // If we have a catch-all, add null to the landingpad.855 assert(!(hasCatchAll && hasFilter));856 if (hasCatchAll) {857 LPadInst->addClause(getCatchAllValue(*this));858 859 // If we have an EH filter, we need to add those handlers in the860 // right place in the landingpad, which is to say, at the end.861 } else if (hasFilter) {862 // Create a filter expression: a constant array indicating which filter863 // types there are. The personality routine only lands here if the filter864 // doesn't match.865 SmallVector<llvm::Constant*, 8> Filters;866 llvm::ArrayType *AType =867 llvm::ArrayType::get(!filterTypes.empty() ?868 filterTypes[0]->getType() : Int8PtrTy,869 filterTypes.size());870 871 for (unsigned i = 0, e = filterTypes.size(); i != e; ++i)872 Filters.push_back(cast<llvm::Constant>(filterTypes[i]));873 llvm::Constant *FilterArray = llvm::ConstantArray::get(AType, Filters);874 LPadInst->addClause(FilterArray);875 876 // Also check whether we need a cleanup.877 if (hasCleanup)878 LPadInst->setCleanup(true);879 880 // Otherwise, signal that we at least have cleanups.881 } else if (CleanupHackLevel == CHL_MandatoryCatchall || hasCleanup) {882 if (CleanupHackLevel == CHL_MandatoryCatchall)883 LPadInst->addClause(getCatchAllValue(*this));884 else885 LPadInst->setCleanup(true);886 }887 888 assert((LPadInst->getNumClauses() > 0 || LPadInst->isCleanup()) &&889 ""landingpad instruction has no clauses!"");890 891 // Tell the backend how to generate the landing pad.892 Builder.CreateBr(getEHDispatchBlock(EHStack.getInnermostEHScope()));893 894 // Restore the old IR generation state.895 Builder.restoreIP(savedIP);896 if (CGDebugInfo *DI = getDebugInfo())897 DI->EmitLocation(Builder, SavedLocation);898 899 return lpad;900}901 902namespace {903 /// A cleanup to call __cxa_end_catch. In many cases, the caught904 /// exception type lets us state definitively that the thrown exception905 /// type does not have a destructor. In particular:906 /// - Catch-alls tell us nothing, so we have to conservatively907 /// assume that the thrown exception might have a destructor.908 /// - Catches by reference behave according to their base types.909 /// - Catches of non-record types will only trigger for exceptions910 /// of non-record types, which never have destructors.911 /// - Catches of record types can trigger for arbitrary subclasses912 /// of the caught type, so we have to assume the actual thrown913 /// exception type might have a throwing destructor, even if the914 /// caught type's destructor is trivial or nothrow.915 struct CallEndCatch : EHScopeStack::Cleanup {916 CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}917 bool MightThrow;918 919 void Emit(CodeGenFunction &CGF, Flags flags) {920 if (!MightThrow) {921 CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM));922 return;923 }924 925 CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM));926 }927 };928}929 930/// Emits a call to __cxa_begin_catch and enters a cleanup to call931/// __cxa_end_catch.932///933/// \\param EndMightThrow - true if __cxa_end_catch might throw934static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,935 llvm::Value *Exn,936 bool EndMightThrow) {937 llvm::CallInst *call =938 CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn);939 940 CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow);941 942 return call;943}944 945/// A ""special initializer"" callback for initializing a catch946/// parameter during catch initialization.947static void InitCatchParam(CodeGenFunction &CGF,948 const VarDecl &CatchParam,949 llvm::Value *ParamAddr,950 SourceLocation Loc) {951 // Load the exception from where the landing pad saved it.952 llvm::Value *Exn = CGF.getExceptionFromSlot();953 954 CanQualType CatchType =955 CGF.CGM.getContext().getCanonicalType(CatchParam.getType());956 llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType);957 958 // If we're catching by reference, we can just cast the object959 // pointer to the appropriate pointer.960 if (isa<ReferenceType>(CatchType)) {961 QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType();962 bool EndCatchMightThrow = CaughtType->isRecordType();963 964 // __cxa_begin_catch returns the adjusted object pointer.965 llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow);966 967 // We have no way to tell the personality function that we're968 // catching by reference, so if we're catching a pointer,969 // __cxa_begin_catch will actually return that pointer by value.970 if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) {971 QualType PointeeType = PT->getPointeeType();972 973 // When catching by reference, generally we should just ignore974 // this by-value pointer and use the exception object instead.975 if (!PointeeType->isRecordType()) {976 977 // Exn points to the struct _Unwind_Exception header, which978 // we have to skip past in order to reach the exception data.979 unsigned HeaderSize =980 CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();981 AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize);982 983 // However, if we're catching a pointer-to-record type that won't984 // work, because the personality function might have adjusted985 // the pointer. There's actually no way for us to fully satisfy986 // the language/ABI contract here: we can't use Exn because it987 // might have the wrong adjustment, but we can't use the by-value988 // pointer because it's off by a level of abstraction.989 //990 // The current solution is to dump the adjusted pointer into an991 // alloca, which breaks language semantics (because changing the992 // pointer doesn't change the exception) but at least works.993 // The better solution would be to filter out non-exact matches994 // and rethrow them, but this is tricky because the rethrow995 // really needs to be catchable by other sites at this landing996 // pad. The best solution is to fix the personality function.997 } else {998 // Pull the pointer for the reference type off.999 llvm::Type *PtrTy =1000 cast<llvm::PointerType>(LLVMCatchTy)->getElementType();1001 1002 // Create the temporary and write the adjusted pointer into it.1003 llvm::Value *ExnPtrTmp = CGF.CreateTempAlloca(PtrTy, ""exn.byref.tmp"");1004 llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);1005 CGF.Builder.CreateStore(Casted, ExnPtrTmp);1006 1007 // Bind the reference to the temporary.1008 AdjustedExn = ExnPtrTmp;1009 }1010 }1011 1012 llvm::Value *ExnCast =1013 CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, ""exn.byref"");1014 CGF.Builder.CreateStore(ExnCast, ParamAddr);1015 return;1016 }1017 1018 // Scalars and complexes.1019 TypeEvaluationKind TEK = CGF.getEvaluationKind(CatchType);1020 if (TEK != TEK_Aggregate) {1021 llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false);1022 1023 // If the catch type is a pointer type, __cxa_begin_catch returns1024 // the pointer by value.1025 if (CatchType->hasPointerRepresentation()) {1026 llvm::Value *CastExn =1027 CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, ""exn.casted"");1028 1029 switch (CatchType.getQualifiers().getObjCLifetime()) {1030 case Qualifiers::OCL_Strong:1031 CastExn = CGF.EmitARCRetainNonBlock(CastExn);1032 // fallthrough1033 1034 case Qualifiers::OCL_None:1035 case Qualifiers::OCL_ExplicitNone:1036 case Qualifiers::OCL_Autoreleasing:1037 CGF.Builder.CreateStore(CastExn, ParamAddr);1038 return;1039 1040 case Qualifiers::OCL_Weak:1041 CGF.EmitARCInitWeak(ParamAddr, CastExn);1042 return;1043 }1044 llvm_unreachable(""bad ownership qualifier!"");1045 }1046 1047 // Otherwise, it returns a pointer into the exception object.1048 1049 llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok1050 llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);1051 1052 LValue srcLV = CGF.MakeNaturalAlignAddrLValue(Cast, CatchType);1053 LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType,1054 CGF.getContext().getDeclAlign(&CatchParam));1055 switch (TEK) {1056 case TEK_Complex:1057 CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV, Loc), destLV,1058 /*init*/ true);1059 return;1060 case TEK_Scalar: {1061 llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV, Loc);1062 CGF.EmitStoreOfScalar(ExnLoad, destLV, /*init*/ true);1063 return;1064 }1065 case TEK_Aggregate:1066 llvm_unreachable(""evaluation kind filtered out!"");1067 }1068 llvm_unreachable(""bad evaluation kind"");1069 }1070 1071 assert(isa<RecordType>(CatchType) && ""unexpected catch type!"");1072 1073 llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok1074 1075 // Check for a copy expression. If we don't have a copy expression,1076 // that means a trivial copy is okay.1077 const Expr *copyExpr = CatchParam.getInit();1078 if (!copyExpr) {1079 llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true);1080 llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);1081 CGF.EmitAggregateCopy(ParamAddr, adjustedExn, CatchType);1082 return;1083 }1084 1085 // We have to call __cxa_get_exception_ptr to get the adjusted1086 // pointer before copying.1087 llvm::CallInst *rawAdjustedExn =1088 CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);1089 1090 // Cast that to the appropriate type.1091 llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy);1092 1093 // The copy expression is defined in terms of an OpaqueValueExpr.1094 // Find it and map it to the adjusted expression.1095 CodeGenFunction::OpaqueValueMapping1096 opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),1097 CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));1098 1099 // Call the copy ctor in a terminate scope.1100 CGF.EHStack.pushTerminate();1101 1102 // Perform the copy construction.1103 CharUnits Alignment = CGF.getContext().getDeclAlign(&CatchParam);1104 CGF.EmitAggExpr(copyExpr,1105 AggValueSlot::forAddr(ParamAddr, Alignment, Qualifiers(),1106 AggValueSlot::IsNotDestructed,1107 AggValueSlot::DoesNotNeedGCBarriers,1108 AggValueSlot::IsNotAliased));1109 1110 // Leave the terminate scope.1111 CGF.EHStack.popTerminate();1112 1113 // Undo the opaque value mapping.1114 opaque.pop();1115 1116 // Finally we can call __cxa_begin_catch.1117 CallBeginCatch(CGF, Exn, true);1118}1119 1120/// Begins a catch statement by initializing the catch variable and1121/// calling __cxa_begin_catch.1122static void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) {1123 // We have to be very careful with the ordering of cleanups here:1124 // C++ [except.throw]p4:1125 // The destruction [of the exception temporary] occurs1126 // immediately after the destruction of the object declared in1127 // the exception-declaration in the handler.1128 //1129 // So the precise ordering is:1130 // 1. Construct catch variable.1131 // 2. __cxa_begin_catch1132 // 3. Enter __cxa_end_catch cleanup1133 // 4. Enter dtor cleanup1134 //1135 // We do this by using a slightly abnormal initialization process.1136 // Delegation sequence:1137 // - ExitCXXTryStmt opens a RunCleanupsScope1138 // - EmitAutoVarAlloca creates the variable and debug info1139 // - InitCatchParam initializes the variable from the exception1140 // - CallBeginCatch calls __cxa_begin_catch1141 // - CallBeginCatch enters the __cxa_end_catch cleanup1142 // - EmitAutoVarCleanups enters the variable destructor cleanup1143 // - EmitCXXTryStmt emits the code for the catch body1144 // - EmitCXXTryStmt close the RunCleanupsScope1145 1146 VarDecl *CatchParam = S->getExceptionDecl();1147 if (!CatchParam) {1148 llvm::Value *Exn = CGF.getExceptionFromSlot();1149 CallBeginCatch(CGF, Exn, true);1150 return;1151 }1152 1153 // Emit the local.1154 CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam);1155 InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getLocStart());1156 CGF.EmitAutoVarCleanups(var);1157}1158 1159/// Emit the structure of the dispatch block for the given catch scope.1160/// It is an invariant that the dispatch block already exists.1161static void emitCatchDispatchBlock(CodeGenFunction &CGF,1162 EHCatchScope &catchScope) {1163 llvm::BasicBlock *dispatchBlock = catchScope.getCachedEHDispatchBlock();1164 assert(dispatchBlock);1165 1166 // If there's only a single catch-all, getEHDispatchBlock returned1167 // that catch-all as the dispatch block.1168 if (catchScope.getNumHandlers() == 1 &&1169 catchScope.getHandler(0).isCatchAll()) {1170 assert(dispatchBlock == catchScope.getHandler(0).Block);1171 return;1172 }1173 1174 CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP();1175 CGF.EmitBlockAfterUses(dispatchBlock);1176 1177 // Select the right handler.1178 llvm::Value *llvm_eh_typeid_for =1179 CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for);1180 1181 // Load the selector value.1182 llvm::Value *selector = CGF.getSelectorFromSlot();1183 1184 // Test against each of the exception types we claim to catch.1185 for (unsigned i = 0, e = catchScope.getNumHandlers(); ; ++i) {1186 assert(i < e && ""ran off end of handlers!"");1187 const EHCatchScope::Handler &handler = catchScope.getHandler(i);1188 1189 llvm::Value *typeValue = handler.Type;1190 assert(typeValue && ""fell into catch-all case!"");1191 typeValue = CGF.Builder.CreateBitCast(typeValue, CGF.Int8PtrTy);1192 1193 // Figure out the next block.1194 bool nextIsEnd;1195 llvm::BasicBlock *nextBlock;1196 1197 // If this is the last handler, we're at the end, and the next1198 // block is the block for the enclosing EH scope.1199 if (i + 1 == e) {1200 nextBlock = CGF.getEHDispatchBlock(catchScope.getEnclosingEHScope());