aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CodeGenFunction.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CodeGenFunction.h')
-rw-r--r--lib/CodeGen/CodeGenFunction.h93
1 files changed, 62 insertions, 31 deletions
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 995a1b0572..4683c96974 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -97,26 +97,27 @@ struct BranchFixup {
llvm::BranchInst *InitialBranch;
};
-/// A metaprogramming class which decides whether a type is a subclass
-/// of llvm::Value that needs to be saved if it's used in a
-/// conditional cleanup.
-template
- <class T,
- bool mustSave =
- 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 {
+template <class T> struct InvariantValue {
typedef T type;
typedef T saved_type;
static bool needsSaving(type value) { return false; }
static saved_type save(CodeGenFunction &CGF, type value) { return value; }
static type restore(CodeGenFunction &CGF, saved_type value) { return value; }
};
-// Partial specialization for true arguments at end of file.
+
+/// A metaprogramming class for ensuring that a value will dominate an
+/// arbitrary position in a function.
+template <class T> struct DominatingValue : InvariantValue<T> {};
+
+template <class T, bool mightBeInstruction =
+ llvm::is_base_of<llvm::Value, T>::value &&
+ !llvm::is_base_of<llvm::Constant, T>::value &&
+ !llvm::is_base_of<llvm::BasicBlock, T>::value>
+struct DominatingPointer;
+template <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {};
+// template <class T> struct DominatingPointer<T,true> at end of file
+
+template <class T> struct DominatingValue<T*> : DominatingPointer<T> {};
enum CleanupKind {
EHCleanup = 0x1,
@@ -222,11 +223,11 @@ public:
/// then restores them and performs the cleanup.
template <class T, class A0>
class ConditionalCleanup1 : public Cleanup {
- typedef typename SavedValueInCond<A0>::saved_type A0_saved;
+ typedef typename DominatingValue<A0>::saved_type A0_saved;
A0_saved a0_saved;
void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
- A0 a0 = SavedValueInCond<A0>::restore(CGF, a0_saved);
+ A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
T::Emit(CGF, IsForEHCleanup, a0);
}
@@ -237,14 +238,14 @@ public:
template <class T, class A0, class A1>
class ConditionalCleanup2 : public Cleanup {
- typedef typename SavedValueInCond<A0>::saved_type A0_saved;
- typedef typename SavedValueInCond<A1>::saved_type A1_saved;
+ typedef typename DominatingValue<A0>::saved_type A0_saved;
+ typedef typename DominatingValue<A1>::saved_type A1_saved;
A0_saved a0_saved;
A1_saved a1_saved;
void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
- A0 a0 = SavedValueInCond<A0>::restore(CGF, a0_saved);
- A1 a1 = SavedValueInCond<A1>::restore(CGF, a1_saved);
+ A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
+ A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
T::Emit(CGF, IsForEHCleanup, a0, a1);
}
@@ -619,8 +620,8 @@ public:
void initFullExprCleanup();
template <class T>
- typename SavedValueInCond<T>::saved_type saveValueInCond(T value) {
- return SavedValueInCond<T>::save(*this, value);
+ typename DominatingValue<T>::saved_type saveValueInCond(T value) {
+ return DominatingValue<T>::save(*this, value);
}
public:
@@ -651,7 +652,7 @@ public:
return EHStack.pushCleanup<CleanupType>(kind, a0);
}
- typename SavedValueInCond<A0>::saved_type a0_saved = saveValueInCond(a0);
+ typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
typedef EHScopeStack::ConditionalCleanup1<T, A0> CleanupType;
EHStack.pushCleanup<CleanupType>(kind, a0_saved);
@@ -670,8 +671,8 @@ public:
return EHStack.pushCleanup<CleanupType>(kind, a0, a1);
}
- typename SavedValueInCond<A0>::saved_type a0_saved = saveValueInCond(a0);
- typename SavedValueInCond<A1>::saved_type a1_saved = saveValueInCond(a1);
+ typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
+ typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1);
typedef EHScopeStack::ConditionalCleanup2<T, A0, A1> CleanupType;
EHStack.pushCleanup<CleanupType>(kind, a0_saved, a1_saved);
@@ -1946,7 +1947,7 @@ private:
/// Helper class with most of the code for saving a value for a
/// conditional expression cleanup.
-struct SavedValueInCondImpl {
+struct DominatingLLVMValue {
typedef llvm::PointerIntPair<llvm::Value*, 1, bool> saved_type;
/// Answer whether the given value needs extra work to be saved.
@@ -1977,12 +1978,42 @@ struct SavedValueInCondImpl {
}
};
-/// Partial specialization of SavedValueInCond for when a value really
-/// requires saving.
-template <class T> struct SavedValueInCond<T,true> : SavedValueInCondImpl {
- typedef T type;
+/// A partial specialization of DominatingValue for llvm::Values that
+/// might be llvm::Instructions.
+template <class T> struct DominatingPointer<T,true> : DominatingLLVMValue {
+ typedef T *type;
+ static type restore(CodeGenFunction &CGF, saved_type value) {
+ return static_cast<T*>(DominatingLLVMValue::restore(CGF, value));
+ }
+};
+
+/// A specialization of DominatingValue for RValue.
+template <> struct DominatingValue<RValue> {
+ typedef RValue type;
+ class saved_type {
+ enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral,
+ AggregateAddress, ComplexAddress };
+
+ llvm::Value *Value;
+ Kind K;
+ saved_type(llvm::Value *v, Kind k) : Value(v), K(k) {}
+
+ public:
+ static bool needsSaving(RValue value);
+ static saved_type save(CodeGenFunction &CGF, RValue value);
+ RValue restore(CodeGenFunction &CGF);
+
+ // implementations in CGExprCXX.cpp
+ };
+
+ static bool needsSaving(type value) {
+ return saved_type::needsSaving(value);
+ }
+ static saved_type save(CodeGenFunction &CGF, type value) {
+ return saved_type::save(CGF, value);
+ }
static type restore(CodeGenFunction &CGF, saved_type value) {
- return static_cast<T>(SavedValueInCondImpl::restore(CGF, value));
+ return value.restore(CGF);
}
};