diff options
Diffstat (limited to 'lib/CodeGen/CodeGenFunction.h')
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 93 |
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); } }; |