diff options
author | John McCall <rjmccall@apple.com> | 2011-01-28 08:37:24 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-01-28 08:37:24 +0000 |
commit | 3ad32c8d93eb65d1d4943d7df567fc9b4f55d137 (patch) | |
tree | c70d2a10da7b400e2f6f02a32d9d0a59b9f8f8a6 /lib/CodeGen/CodeGenFunction.h | |
parent | 4867347e82648d3baf09524b98b09c297a5a198f (diff) |
Convert the exception-freeing cleanup over to the conditional cleanups code,
fixing a crash which probably nobody was ever going to see. In doing so,
fix a horrendous number of problems with the conditional-cleanups code.
Also, make conditional cleanups re-use the cleanup's activation variable,
which avoids some unfortunate repetitiveness.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@124481 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CodeGenFunction.h')
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 88 |
1 files changed, 59 insertions, 29 deletions
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 834a1cfa2f..995a1b0572 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -103,9 +103,12 @@ struct BranchFixup { template <class T, bool mustSave = - llvm::is_base_of<llvm::Value, llvm::remove_pointer<T> >::value - && !llvm::is_base_of<llvm::Constant, llvm::remove_pointer<T> >::value - && !llvm::is_base_of<llvm::BasicBlock, llvm::remove_pointer<T> >::value> + llvm::is_base_of<llvm::Value, + typename llvm::remove_pointer<T>::type>::value + && !llvm::is_base_of<llvm::Constant, + typename llvm::remove_pointer<T>::type>::value + && !llvm::is_base_of<llvm::BasicBlock, + typename llvm::remove_pointer<T>::type>::value> struct SavedValueInCond { typedef T type; typedef T saved_type; @@ -193,24 +196,18 @@ public: virtual void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) = 0; }; - /// A helper class for cleanups that execute conditionally. - class ConditionalCleanup : public Cleanup { - /// Either an i1 which directly indicates whether the cleanup - /// should be run or an i1* from which that should be loaded. - llvm::Value *cond; - + /// UnconditionalCleanupN stores its N parameters and just passes + /// them to the real cleanup function. + template <class T, class A0> + class UnconditionalCleanup1 : public Cleanup { + A0 a0; public: - virtual void Emit(CodeGenFunction &CGF, bool IsForEHCleanup); - - protected: - ConditionalCleanup(llvm::Value *cond) : cond(cond) {} - - /// Emit the non-conditional code for the cleanup. - virtual void EmitImpl(CodeGenFunction &CGF, bool IsForEHCleanup) = 0; + UnconditionalCleanup1(A0 a0) : a0(a0) {} + void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { + T::Emit(CGF, IsForEHCleanup, a0); + } }; - /// UnconditionalCleanupN stores its N parameters and just passes - /// them to the real cleanup function. template <class T, class A0, class A1> class UnconditionalCleanup2 : public Cleanup { A0 a0; A1 a1; @@ -223,22 +220,37 @@ public: /// ConditionalCleanupN stores the saved form of its N parameters, /// then restores them and performs the cleanup. + template <class T, class A0> + class ConditionalCleanup1 : public Cleanup { + typedef typename SavedValueInCond<A0>::saved_type A0_saved; + A0_saved a0_saved; + + void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { + A0 a0 = SavedValueInCond<A0>::restore(CGF, a0_saved); + T::Emit(CGF, IsForEHCleanup, a0); + } + + public: + ConditionalCleanup1(A0_saved a0) + : a0_saved(a0) {} + }; + template <class T, class A0, class A1> - class ConditionalCleanup2 : public ConditionalCleanup { + class ConditionalCleanup2 : public Cleanup { typedef typename SavedValueInCond<A0>::saved_type A0_saved; typedef typename SavedValueInCond<A1>::saved_type A1_saved; A0_saved a0_saved; A1_saved a1_saved; - void EmitImpl(CodeGenFunction &CGF, bool IsForEHCleanup) { + void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { A0 a0 = SavedValueInCond<A0>::restore(CGF, a0_saved); A1 a1 = SavedValueInCond<A1>::restore(CGF, a1_saved); T::Emit(CGF, IsForEHCleanup, a0, a1); } public: - ConditionalCleanup2(llvm::Value *cond, A0_saved a0, A1_saved a1) - : ConditionalCleanup(cond), a0_saved(a0), a1_saved(a1) {} + ConditionalCleanup2(A0_saved a0, A1_saved a1) + : a0_saved(a0), a1_saved(a1) {} }; private: @@ -602,8 +614,9 @@ public: llvm::BasicBlock *getInvokeDestImpl(); - /// Sets up a condition for a full-expression cleanup. - llvm::Value *initFullExprCleanup(); + /// Set up the last cleaup that was pushed as a conditional + /// full-expression cleanup. + void initFullExprCleanup(); template <class T> typename SavedValueInCond<T>::saved_type saveValueInCond(T value) { @@ -629,23 +642,40 @@ public: /// pushFullExprCleanup - Push a cleanup to be run at the end of the /// current full-expression. Safe against the possibility that /// we're currently inside a conditionally-evaluated expression. + template <class T, class A0> + void pushFullExprCleanup(CleanupKind kind, A0 a0) { + // If we're not in a conditional branch, or if none of the + // arguments requires saving, then use the unconditional cleanup. + if (!isInConditionalBranch()) { + typedef EHScopeStack::UnconditionalCleanup1<T, A0> CleanupType; + return EHStack.pushCleanup<CleanupType>(kind, a0); + } + + typename SavedValueInCond<A0>::saved_type a0_saved = saveValueInCond(a0); + + typedef EHScopeStack::ConditionalCleanup1<T, A0> CleanupType; + EHStack.pushCleanup<CleanupType>(kind, a0_saved); + initFullExprCleanup(); + } + + /// pushFullExprCleanup - Push a cleanup to be run at the end of the + /// current full-expression. Safe against the possibility that + /// we're currently inside a conditionally-evaluated expression. template <class T, class A0, class A1> void pushFullExprCleanup(CleanupKind kind, A0 a0, A1 a1) { // If we're not in a conditional branch, or if none of the // arguments requires saving, then use the unconditional cleanup. - if (!(isInConditionalBranch() || - SavedValueInCond<A0>::needsSaving(a0) || - SavedValueInCond<A1>::needsSaving(a1))) { + if (!isInConditionalBranch()) { typedef EHScopeStack::UnconditionalCleanup2<T, A0, A1> CleanupType; return EHStack.pushCleanup<CleanupType>(kind, a0, a1); } - llvm::Value *condVar = initFullExprCleanup(); typename SavedValueInCond<A0>::saved_type a0_saved = saveValueInCond(a0); typename SavedValueInCond<A1>::saved_type a1_saved = saveValueInCond(a1); typedef EHScopeStack::ConditionalCleanup2<T, A0, A1> CleanupType; - EHStack.pushCleanup<CleanupType>(kind, condVar, a0_saved, a1_saved); + EHStack.pushCleanup<CleanupType>(kind, a0_saved, a1_saved); + initFullExprCleanup(); } /// PushDestructorCleanup - Push a cleanup to call the |