From 3ad32c8d93eb65d1d4943d7df567fc9b4f55d137 Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 28 Jan 2011 08:37:24 +0000 Subject: 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 --- lib/CodeGen/CodeGenFunction.h | 88 +++++++++++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 29 deletions(-) (limited to 'lib/CodeGen/CodeGenFunction.h') 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 >::value - && !llvm::is_base_of >::value - && !llvm::is_base_of >::value> + llvm::is_base_of::type>::value + && !llvm::is_base_of::type>::value + && !llvm::is_base_of::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 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 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 ConditionalCleanup1 : public Cleanup { + typedef typename SavedValueInCond::saved_type A0_saved; + A0_saved a0_saved; + + void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) { + A0 a0 = SavedValueInCond::restore(CGF, a0_saved); + T::Emit(CGF, IsForEHCleanup, a0); + } + + public: + ConditionalCleanup1(A0_saved a0) + : a0_saved(a0) {} + }; + template - class ConditionalCleanup2 : public ConditionalCleanup { + class ConditionalCleanup2 : public Cleanup { typedef typename SavedValueInCond::saved_type A0_saved; typedef typename SavedValueInCond::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::restore(CGF, a0_saved); A1 a1 = SavedValueInCond::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 typename SavedValueInCond::saved_type saveValueInCond(T value) { @@ -626,6 +639,25 @@ public: llvm::Constant *RethrowFn); void ExitFinallyBlock(FinallyInfo &FinallyInfo); + /// 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 + 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 CleanupType; + return EHStack.pushCleanup(kind, a0); + } + + typename SavedValueInCond::saved_type a0_saved = saveValueInCond(a0); + + typedef EHScopeStack::ConditionalCleanup1 CleanupType; + EHStack.pushCleanup(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. @@ -633,19 +665,17 @@ public: 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::needsSaving(a0) || - SavedValueInCond::needsSaving(a1))) { + if (!isInConditionalBranch()) { typedef EHScopeStack::UnconditionalCleanup2 CleanupType; return EHStack.pushCleanup(kind, a0, a1); } - llvm::Value *condVar = initFullExprCleanup(); typename SavedValueInCond::saved_type a0_saved = saveValueInCond(a0); typename SavedValueInCond::saved_type a1_saved = saveValueInCond(a1); typedef EHScopeStack::ConditionalCleanup2 CleanupType; - EHStack.pushCleanup(kind, condVar, a0_saved, a1_saved); + EHStack.pushCleanup(kind, a0_saved, a1_saved); + initFullExprCleanup(); } /// PushDestructorCleanup - Push a cleanup to call the -- cgit v1.2.3-18-g5258