diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 18:11:16 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 18:11:16 +0000 | 
| commit | 59d1ed5b206db2a86b3b5bb851f393c43b568ce2 (patch) | |
| tree | d4426858455f04d0d8c25a2f9eb9ea5582ffe1b6 /contrib/llvm/tools/clang/lib/CodeGen/CGException.cpp | |
| parent | 91bc56ed825ba56b3cc264aa5c95ab84f86832ab (diff) | |
| parent | 9f4dbff6669c8037f3b036bcf580d14f1a4f12a5 (diff) | |
Notes
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 39a992aab17d..1bbda5cbf09c 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"); +}  | 
