diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp | 226 |
1 files changed, 80 insertions, 146 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp index 39a992a..1bbda5c 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp +++ b/contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp @@ -17,8 +17,8 @@ #include "TargetInfo.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "llvm/IR/CallSite.h" #include "llvm/IR/Intrinsics.h" -#include "llvm/Support/CallSite.h" using namespace clang; using namespace CodeGen; @@ -97,24 +97,6 @@ static llvm::Constant *getUnexpectedFn(CodeGenModule &CGM) { return CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected"); } -llvm::Constant *CodeGenFunction::getUnwindResumeFn() { - llvm::FunctionType *FTy = - llvm::FunctionType::get(VoidTy, Int8PtrTy, /*IsVarArgs=*/false); - - if (CGM.getLangOpts().SjLjExceptions) - return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume"); - return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume"); -} - -llvm::Constant *CodeGenFunction::getUnwindResumeOrRethrowFn() { - llvm::FunctionType *FTy = - llvm::FunctionType::get(VoidTy, Int8PtrTy, /*IsVarArgs=*/false); - - if (CGM.getLangOpts().SjLjExceptions) - return CGM.CreateRuntimeFunction(FTy, "_Unwind_SjLj_Resume_or_Rethrow"); - return CGM.CreateRuntimeFunction(FTy, "_Unwind_Resume_or_Rethrow"); -} - static llvm::Constant *getTerminateFn(CodeGenModule &CGM) { // void __terminate(); @@ -164,18 +146,21 @@ namespace { }; } -const EHPersonality EHPersonality::GNU_C = { "__gcc_personality_v0", 0 }; -const EHPersonality EHPersonality::GNU_C_SJLJ = { "__gcc_personality_sj0", 0 }; -const EHPersonality EHPersonality::NeXT_ObjC = { "__objc_personality_v0", 0 }; -const EHPersonality EHPersonality::GNU_CPlusPlus = { "__gxx_personality_v0", 0}; +const EHPersonality EHPersonality::GNU_C = { "__gcc_personality_v0", nullptr }; +const EHPersonality +EHPersonality::GNU_C_SJLJ = { "__gcc_personality_sj0", nullptr }; +const EHPersonality +EHPersonality::NeXT_ObjC = { "__objc_personality_v0", nullptr }; +const EHPersonality +EHPersonality::GNU_CPlusPlus = { "__gxx_personality_v0", nullptr }; const EHPersonality -EHPersonality::GNU_CPlusPlus_SJLJ = { "__gxx_personality_sj0", 0 }; +EHPersonality::GNU_CPlusPlus_SJLJ = { "__gxx_personality_sj0", nullptr }; const EHPersonality EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0", "objc_exception_throw"}; const EHPersonality -EHPersonality::GNU_ObjCXX = { "__gnustep_objcxx_personality_v0", 0 }; +EHPersonality::GNU_ObjCXX = { "__gnustep_objcxx_personality_v0", nullptr }; const EHPersonality -EHPersonality::GNUstep_ObjC = { "__gnustep_objc_personality_v0", 0 }; +EHPersonality::GNUstep_ObjC = { "__gnustep_objc_personality_v0", nullptr }; static const EHPersonality &getCPersonality(const LangOptions &L) { if (L.SjLjExceptions) @@ -263,12 +248,9 @@ static llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM, /// Check whether a personality function could reasonably be swapped /// for a C++ personality function. static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) { - for (llvm::Constant::use_iterator - I = Fn->use_begin(), E = Fn->use_end(); I != E; ++I) { - llvm::User *User = *I; - + for (llvm::User *U : Fn->users()) { // Conditionally white-list bitcasts. - if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(User)) { + if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(U)) { if (CE->getOpcode() != llvm::Instruction::BitCast) return false; if (!PersonalityHasOnlyCXXUses(CE)) return false; @@ -276,7 +258,7 @@ static bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) { } // Otherwise, it has to be a landingpad instruction. - llvm::LandingPadInst *LPI = dyn_cast<llvm::LandingPadInst>(User); + llvm::LandingPadInst *LPI = dyn_cast<llvm::LandingPadInst>(U); if (!LPI) return false; for (unsigned I = 0, E = LPI->getNumClauses(); I != E; ++I) { @@ -363,7 +345,7 @@ namespace { struct FreeException : EHScopeStack::Cleanup { llvm::Value *exn; FreeException(llvm::Value *exn) : exn(exn) {} - void Emit(CodeGenFunction &CGF, Flags flags) { + void Emit(CodeGenFunction &CGF, Flags flags) override { CGF.EmitNounwindRuntimeCall(getFreeExceptionFn(CGF.CGM), exn); } }; @@ -421,6 +403,11 @@ llvm::Value *CodeGenFunction::getSelectorFromSlot() { void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint) { + if (CGM.getTarget().getTriple().isWindowsMSVCEnvironment()) { + ErrorUnsupported(E, "throw expression"); + return; + } + if (!E->getSubExpr()) { EmitNoreturnRuntimeCallOrInvoke(getReThrowFn(CGM), ArrayRef<llvm::Value*>()); @@ -465,7 +452,7 @@ void CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E, // The address of the destructor. If the exception type has a // trivial destructor (or isn't a record), we just pass null. - llvm::Constant *Dtor = 0; + llvm::Constant *Dtor = nullptr; if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) { CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); if (!Record->hasTrivialDestructor()) { @@ -490,10 +477,16 @@ void CodeGenFunction::EmitStartEHSpec(const Decl *D) { return; const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); - if (FD == 0) + if (!FD) { + // Check if CapturedDecl is nothrow and create terminate scope for it. + if (const CapturedDecl* CD = dyn_cast_or_null<CapturedDecl>(D)) { + if (CD->isNothrow()) + EHStack.pushTerminate(); + } return; + } const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); - if (Proto == 0) + if (!Proto) return; ExceptionSpecificationType EST = Proto->getExceptionSpecType(); @@ -558,10 +551,16 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) { return; const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); - if (FD == 0) + if (!FD) { + // Check if CapturedDecl is nothrow and pop terminate scope for it. + if (const CapturedDecl* CD = dyn_cast_or_null<CapturedDecl>(D)) { + if (CD->isNothrow()) + EHStack.popTerminate(); + } return; + } const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); - if (Proto == 0) + if (!Proto) return; ExceptionSpecificationType EST = Proto->getExceptionSpecType(); @@ -577,6 +576,11 @@ void CodeGenFunction::EmitEndEHSpec(const Decl *D) { } void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { + if (CGM.getTarget().getTriple().isWindowsMSVCEnvironment()) { + ErrorUnsupported(&S, "try statement"); + return; + } + EnterCXXTryStmt(S); EmitStmt(S.getTryBlock()); ExitCXXTryStmt(S); @@ -600,7 +604,7 @@ void CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { QualType CaughtType = C->getCaughtType(); CaughtType = CaughtType.getNonReferenceType().getUnqualifiedType(); - llvm::Value *TypeInfo = 0; + llvm::Constant *TypeInfo = nullptr; if (CaughtType->isObjCObjectPointerType()) TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType); else @@ -678,7 +682,7 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() { assert(!EHStack.empty()); if (!CGM.getLangOpts().Exceptions) - return 0; + return nullptr; // Check the innermost scope for a cached landing pad. If this is // a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad. @@ -699,56 +703,6 @@ llvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() { return LP; } -// This code contains a hack to work around a design flaw in -// LLVM's EH IR which breaks semantics after inlining. This same -// hack is implemented in llvm-gcc. -// -// The LLVM EH abstraction is basically a thin veneer over the -// traditional GCC zero-cost design: for each range of instructions -// in the function, there is (at most) one "landing pad" with an -// associated chain of EH actions. A language-specific personality -// function interprets this chain of actions and (1) decides whether -// or not to resume execution at the landing pad and (2) if so, -// provides an integer indicating why it's stopping. In LLVM IR, -// the association of a landing pad with a range of instructions is -// achieved via an invoke instruction, the chain of actions becomes -// the arguments to the @llvm.eh.selector call, and the selector -// call returns the integer indicator. Other than the required -// presence of two intrinsic function calls in the landing pad, -// the IR exactly describes the layout of the output code. -// -// A principal advantage of this design is that it is completely -// language-agnostic; in theory, the LLVM optimizers can treat -// landing pads neutrally, and targets need only know how to lower -// the intrinsics to have a functioning exceptions system (assuming -// that platform exceptions follow something approximately like the -// GCC design). Unfortunately, landing pads cannot be combined in a -// language-agnostic way: given selectors A and B, there is no way -// to make a single landing pad which faithfully represents the -// semantics of propagating an exception first through A, then -// through B, without knowing how the personality will interpret the -// (lowered form of the) selectors. This means that inlining has no -// choice but to crudely chain invokes (i.e., to ignore invokes in -// the inlined function, but to turn all unwindable calls into -// invokes), which is only semantically valid if every unwind stops -// at every landing pad. -// -// Therefore, the invoke-inline hack is to guarantee that every -// landing pad has a catch-all. -enum CleanupHackLevel_t { - /// A level of hack that requires that all landing pads have - /// catch-alls. - CHL_MandatoryCatchall, - - /// A level of hack that requires that all landing pads handle - /// cleanups. - CHL_MandatoryCleanup, - - /// No hacks at all; ideal IR generation. - CHL_Ideal -}; -const CleanupHackLevel_t CleanupHackLevel = CHL_MandatoryCleanup; - llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { assert(EHStack.requiresLandingPad()); @@ -766,11 +720,9 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { // Save the current IR generation state. CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP(); - SourceLocation SavedLocation; - if (CGDebugInfo *DI = getDebugInfo()) { - SavedLocation = DI->getLocation(); + SaveAndRestoreLocation AutoRestoreLocation(*this, Builder); + if (CGDebugInfo *DI = getDebugInfo()) DI->EmitLocation(Builder, CurEHLocation); - } const EHPersonality &personality = EHPersonality::get(getLangOpts()); @@ -877,11 +829,8 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { LPadInst->setCleanup(true); // Otherwise, signal that we at least have cleanups. - } else if (CleanupHackLevel == CHL_MandatoryCatchall || hasCleanup) { - if (CleanupHackLevel == CHL_MandatoryCatchall) - LPadInst->addClause(getCatchAllValue(*this)); - else - LPadInst->setCleanup(true); + } else if (hasCleanup) { + LPadInst->setCleanup(true); } assert((LPadInst->getNumClauses() > 0 || LPadInst->isCleanup()) && @@ -892,8 +841,6 @@ llvm::BasicBlock *CodeGenFunction::EmitLandingPad() { // Restore the old IR generation state. Builder.restoreIP(savedIP); - if (CGDebugInfo *DI = getDebugInfo()) - DI->EmitLocation(Builder, SavedLocation); return lpad; } @@ -915,7 +862,7 @@ namespace { CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {} bool MightThrow; - void Emit(CodeGenFunction &CGF, Flags flags) { + void Emit(CodeGenFunction &CGF, Flags flags) override { if (!MightThrow) { CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM)); return; @@ -1244,6 +1191,7 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { // If the catch was not required, bail out now. if (!CatchScope.hasEHBranches()) { + CatchScope.clearHandlerBlocks(); EHStack.popCatch(); return; } @@ -1294,6 +1242,10 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { // Initialize the catch variable and set up the cleanups. BeginCatch(*this, C); + // Emit the PGO counter increment. + RegionCounter CatchCnt = getPGORegionCounter(C); + CatchCnt.beginRegion(Builder); + // Perform the body of the catch. EmitStmt(C->getHandlerBlock()); @@ -1320,7 +1272,9 @@ void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { Builder.CreateBr(ContBB); } + RegionCounter ContCnt = getPGORegionCounter(&S); EmitBlock(ContBB); + ContCnt.beginRegion(Builder); } namespace { @@ -1330,7 +1284,7 @@ namespace { CallEndCatchForFinally(llvm::Value *ForEHVar, llvm::Value *EndCatchFn) : ForEHVar(ForEHVar), EndCatchFn(EndCatchFn) {} - void Emit(CodeGenFunction &CGF, Flags flags) { + void Emit(CodeGenFunction &CGF, Flags flags) override { llvm::BasicBlock *EndCatchBB = CGF.createBasicBlock("finally.endcatch"); llvm::BasicBlock *CleanupContBB = CGF.createBasicBlock("finally.cleanup.cont"); @@ -1357,7 +1311,7 @@ namespace { : Body(Body), ForEHVar(ForEHVar), EndCatchFn(EndCatchFn), RethrowFn(RethrowFn), SavedExnVar(SavedExnVar) {} - void Emit(CodeGenFunction &CGF, Flags flags) { + void Emit(CodeGenFunction &CGF, Flags flags) override { // Enter a cleanup to call the end-catch function if one was provided. if (EndCatchFn) CGF.EHStack.pushCleanup<CallEndCatchForFinally>(NormalAndEHCleanup, @@ -1422,7 +1376,7 @@ void CodeGenFunction::FinallyInfo::enter(CodeGenFunction &CGF, llvm::Constant *beginCatchFn, llvm::Constant *endCatchFn, llvm::Constant *rethrowFn) { - assert((beginCatchFn != 0) == (endCatchFn != 0) && + assert((beginCatchFn != nullptr) == (endCatchFn != nullptr) && "begin/end catch functions not paired"); assert(rethrowFn && "rethrow function is required"); @@ -1437,7 +1391,7 @@ void CodeGenFunction::FinallyInfo::enter(CodeGenFunction &CGF, llvm::FunctionType *rethrowFnTy = cast<llvm::FunctionType>( cast<llvm::PointerType>(rethrowFn->getType())->getElementType()); - SavedExnVar = 0; + SavedExnVar = nullptr; if (rethrowFnTy->getNumParams()) SavedExnVar = CGF.CreateTempAlloca(CGF.Int8PtrTy, "finally.exn"); @@ -1487,7 +1441,7 @@ void CodeGenFunction::FinallyInfo::exit(CodeGenFunction &CGF) { CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveAndClearIP(); CGF.EmitBlock(catchBB); - llvm::Value *exn = 0; + llvm::Value *exn = nullptr; // If there's a begin-catch function, call it. if (BeginCatchFn) { @@ -1651,54 +1605,34 @@ llvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) { // This can always be a call because we necessarily didn't find // anything on the EH stack which needs our help. const char *RethrowName = Personality.CatchallRethrowFn; - if (RethrowName != 0 && !isCleanup) { + if (RethrowName != nullptr && !isCleanup) { EmitRuntimeCall(getCatchallRethrowFn(CGM, RethrowName), - getExceptionFromSlot()) + getExceptionFromSlot()) ->setDoesNotReturn(); - } else { - switch (CleanupHackLevel) { - case CHL_MandatoryCatchall: - // In mandatory-catchall mode, we need to use - // _Unwind_Resume_or_Rethrow, or whatever the personality's - // equivalent is. - EmitRuntimeCall(getUnwindResumeOrRethrowFn(), - getExceptionFromSlot()) - ->setDoesNotReturn(); - break; - case CHL_MandatoryCleanup: { - // In mandatory-cleanup mode, we should use 'resume'. - - // Recreate the landingpad's return value for the 'resume' instruction. - llvm::Value *Exn = getExceptionFromSlot(); - llvm::Value *Sel = getSelectorFromSlot(); - - llvm::Type *LPadType = llvm::StructType::get(Exn->getType(), - Sel->getType(), NULL); - llvm::Value *LPadVal = llvm::UndefValue::get(LPadType); - LPadVal = Builder.CreateInsertValue(LPadVal, Exn, 0, "lpad.val"); - LPadVal = Builder.CreateInsertValue(LPadVal, Sel, 1, "lpad.val"); - - Builder.CreateResume(LPadVal); - Builder.restoreIP(SavedIP); - return EHResumeBlock; - } - case CHL_Ideal: - // In an idealized mode where we don't have to worry about the - // optimizer combining landing pads, we should just use - // _Unwind_Resume (or the personality's equivalent). - EmitRuntimeCall(getUnwindResumeFn(), getExceptionFromSlot()) - ->setDoesNotReturn(); - break; - } + Builder.CreateUnreachable(); + Builder.restoreIP(SavedIP); + return EHResumeBlock; } - Builder.CreateUnreachable(); + // Recreate the landingpad's return value for the 'resume' instruction. + llvm::Value *Exn = getExceptionFromSlot(); + llvm::Value *Sel = getSelectorFromSlot(); - Builder.restoreIP(SavedIP); + llvm::Type *LPadType = llvm::StructType::get(Exn->getType(), + Sel->getType(), NULL); + llvm::Value *LPadVal = llvm::UndefValue::get(LPadType); + LPadVal = Builder.CreateInsertValue(LPadVal, Exn, 0, "lpad.val"); + LPadVal = Builder.CreateInsertValue(LPadVal, Sel, 1, "lpad.val"); + Builder.CreateResume(LPadVal); + Builder.restoreIP(SavedIP); return EHResumeBlock; } void CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) { CGM.ErrorUnsupported(&S, "SEH __try"); } + +void CodeGenFunction::EmitSEHLeaveStmt(const SEHLeaveStmt &S) { + CGM.ErrorUnsupported(&S, "SEH __leave"); +} |