aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CodeGenFunction.h
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-01-28 08:37:24 +0000
committerJohn McCall <rjmccall@apple.com>2011-01-28 08:37:24 +0000
commit3ad32c8d93eb65d1d4943d7df567fc9b4f55d137 (patch)
treec70d2a10da7b400e2f6f02a32d9d0a59b9f8f8a6 /lib/CodeGen/CodeGenFunction.h
parent4867347e82648d3baf09524b98b09c297a5a198f (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.h88
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