diff options
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 147 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 93 |
2 files changed, 119 insertions, 121 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 8b3da0e196..1fab8d4064 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -721,101 +721,65 @@ static void EmitNewInitializer(CodeGenFunction &CGF, const CXXNewExpr *E, StoreAnyExprIntoOneUnit(CGF, E, NewPtr); } -namespace { -/// A utility class for saving an rvalue. -class SavedRValue { -public: - enum Kind { ScalarLiteral, ScalarAddress, - AggregateLiteral, AggregateAddress, - Complex }; - -private: - llvm::Value *Value; - Kind K; - - SavedRValue(llvm::Value *V, Kind K) : Value(V), K(K) {} - -public: - SavedRValue() {} - - static SavedRValue forScalarLiteral(llvm::Value *V) { - return SavedRValue(V, ScalarLiteral); - } - - static SavedRValue forScalarAddress(llvm::Value *Addr) { - return SavedRValue(Addr, ScalarAddress); - } - - static SavedRValue forAggregateLiteral(llvm::Value *V) { - return SavedRValue(V, AggregateLiteral); - } - - static SavedRValue forAggregateAddress(llvm::Value *Addr) { - return SavedRValue(Addr, AggregateAddress); - } - - static SavedRValue forComplexAddress(llvm::Value *Addr) { - return SavedRValue(Addr, Complex); - } - - Kind getKind() const { return K; } - llvm::Value *getValue() const { return Value; } -}; -} // end anonymous namespace +bool DominatingValue<RValue>::saved_type::needsSaving(RValue rv) { + if (rv.isScalar()) + return DominatingLLVMValue::needsSaving(rv.getScalarVal()); + if (rv.isAggregate()) + return DominatingLLVMValue::needsSaving(rv.getAggregateAddr()); + return true; +} -/// Given an r-value, perform the code necessary to make sure that a -/// future RestoreRValue will be able to load the value without -/// domination concerns. -static SavedRValue SaveRValue(CodeGenFunction &CGF, RValue RV) { - if (RV.isScalar()) { - llvm::Value *V = RV.getScalarVal(); +DominatingValue<RValue>::saved_type +DominatingValue<RValue>::saved_type::save(CodeGenFunction &CGF, RValue rv) { + if (rv.isScalar()) { + llvm::Value *V = rv.getScalarVal(); // These automatically dominate and don't need to be saved. - if (isa<llvm::Constant>(V) || isa<llvm::AllocaInst>(V)) - return SavedRValue::forScalarLiteral(V); + if (!DominatingLLVMValue::needsSaving(V)) + return saved_type(V, ScalarLiteral); // Everything else needs an alloca. - llvm::Value *Addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue"); - CGF.Builder.CreateStore(V, Addr); - return SavedRValue::forScalarAddress(Addr); + llvm::Value *addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue"); + CGF.Builder.CreateStore(V, addr); + return saved_type(addr, ScalarAddress); } - if (RV.isComplex()) { - CodeGenFunction::ComplexPairTy V = RV.getComplexVal(); + if (rv.isComplex()) { + CodeGenFunction::ComplexPairTy V = rv.getComplexVal(); const llvm::Type *ComplexTy = llvm::StructType::get(CGF.getLLVMContext(), V.first->getType(), V.second->getType(), (void*) 0); - llvm::Value *Addr = CGF.CreateTempAlloca(ComplexTy, "saved-complex"); - CGF.StoreComplexToAddr(V, Addr, /*volatile*/ false); - return SavedRValue::forComplexAddress(Addr); + llvm::Value *addr = CGF.CreateTempAlloca(ComplexTy, "saved-complex"); + CGF.StoreComplexToAddr(V, addr, /*volatile*/ false); + return saved_type(addr, ComplexAddress); } - assert(RV.isAggregate()); - llvm::Value *V = RV.getAggregateAddr(); // TODO: volatile? - if (isa<llvm::Constant>(V) || isa<llvm::AllocaInst>(V)) - return SavedRValue::forAggregateLiteral(V); + assert(rv.isAggregate()); + llvm::Value *V = rv.getAggregateAddr(); // TODO: volatile? + if (!DominatingLLVMValue::needsSaving(V)) + return saved_type(V, AggregateLiteral); - llvm::Value *Addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue"); - CGF.Builder.CreateStore(V, Addr); - return SavedRValue::forAggregateAddress(Addr); + llvm::Value *addr = CGF.CreateTempAlloca(V->getType(), "saved-rvalue"); + CGF.Builder.CreateStore(V, addr); + return saved_type(addr, AggregateAddress); } /// Given a saved r-value produced by SaveRValue, perform the code /// necessary to restore it to usability at the current insertion /// point. -static RValue RestoreRValue(CodeGenFunction &CGF, SavedRValue RV) { - switch (RV.getKind()) { - case SavedRValue::ScalarLiteral: - return RValue::get(RV.getValue()); - case SavedRValue::ScalarAddress: - return RValue::get(CGF.Builder.CreateLoad(RV.getValue())); - case SavedRValue::AggregateLiteral: - return RValue::getAggregate(RV.getValue()); - case SavedRValue::AggregateAddress: - return RValue::getAggregate(CGF.Builder.CreateLoad(RV.getValue())); - case SavedRValue::Complex: - return RValue::getComplex(CGF.LoadComplexFromAddr(RV.getValue(), false)); +RValue DominatingValue<RValue>::saved_type::restore(CodeGenFunction &CGF) { + switch (K) { + case ScalarLiteral: + return RValue::get(Value); + case ScalarAddress: + return RValue::get(CGF.Builder.CreateLoad(Value)); + case AggregateLiteral: + return RValue::getAggregate(Value); + case AggregateAddress: + return RValue::getAggregate(CGF.Builder.CreateLoad(Value)); + case ComplexAddress: + return RValue::getComplex(CGF.LoadComplexFromAddr(Value, false)); } llvm_unreachable("bad saved r-value kind"); @@ -883,26 +847,26 @@ namespace { class CallDeleteDuringConditionalNew : public EHScopeStack::Cleanup { size_t NumPlacementArgs; const FunctionDecl *OperatorDelete; - SavedRValue Ptr; - SavedRValue AllocSize; + DominatingValue<RValue>::saved_type Ptr; + DominatingValue<RValue>::saved_type AllocSize; - SavedRValue *getPlacementArgs() { - return reinterpret_cast<SavedRValue*>(this+1); + DominatingValue<RValue>::saved_type *getPlacementArgs() { + return reinterpret_cast<DominatingValue<RValue>::saved_type*>(this+1); } public: static size_t getExtraSize(size_t NumPlacementArgs) { - return NumPlacementArgs * sizeof(SavedRValue); + return NumPlacementArgs * sizeof(DominatingValue<RValue>::saved_type); } CallDeleteDuringConditionalNew(size_t NumPlacementArgs, const FunctionDecl *OperatorDelete, - SavedRValue Ptr, - SavedRValue AllocSize) + DominatingValue<RValue>::saved_type Ptr, + DominatingValue<RValue>::saved_type AllocSize) : NumPlacementArgs(NumPlacementArgs), OperatorDelete(OperatorDelete), Ptr(Ptr), AllocSize(AllocSize) {} - void setPlacementArg(unsigned I, SavedRValue Arg) { + void setPlacementArg(unsigned I, DominatingValue<RValue>::saved_type Arg) { assert(I < NumPlacementArgs && "index out of range"); getPlacementArgs()[I] = Arg; } @@ -917,17 +881,17 @@ namespace { // The first argument is always a void*. FunctionProtoType::arg_type_iterator AI = FPT->arg_type_begin(); - DeleteArgs.push_back(std::make_pair(RestoreRValue(CGF, Ptr), *AI++)); + DeleteArgs.push_back(std::make_pair(Ptr.restore(CGF), *AI++)); // A member 'operator delete' can take an extra 'size_t' argument. if (FPT->getNumArgs() == NumPlacementArgs + 2) { - RValue RV = RestoreRValue(CGF, AllocSize); + RValue RV = AllocSize.restore(CGF); DeleteArgs.push_back(std::make_pair(RV, *AI++)); } // Pass the rest of the arguments, which must match exactly. for (unsigned I = 0; I != NumPlacementArgs; ++I) { - RValue RV = RestoreRValue(CGF, getPlacementArgs()[I]); + RValue RV = getPlacementArgs()[I].restore(CGF); DeleteArgs.push_back(std::make_pair(RV, *AI++)); } @@ -961,8 +925,10 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, } // Otherwise, we need to save all this stuff. - SavedRValue SavedNewPtr = SaveRValue(CGF, RValue::get(NewPtr)); - SavedRValue SavedAllocSize = SaveRValue(CGF, RValue::get(AllocSize)); + DominatingValue<RValue>::saved_type SavedNewPtr = + DominatingValue<RValue>::save(CGF, RValue::get(NewPtr)); + DominatingValue<RValue>::saved_type SavedAllocSize = + DominatingValue<RValue>::save(CGF, RValue::get(AllocSize)); CallDeleteDuringConditionalNew *Cleanup = CGF.EHStack .pushCleanupWithExtra<CallDeleteDuringConditionalNew>(InactiveEHCleanup, @@ -971,7 +937,8 @@ static void EnterNewDeleteCleanup(CodeGenFunction &CGF, SavedNewPtr, SavedAllocSize); for (unsigned I = 0, N = E->getNumPlacementArgs(); I != N; ++I) - Cleanup->setPlacementArg(I, SaveRValue(CGF, NewArgs[I+1].first)); + Cleanup->setPlacementArg(I, + DominatingValue<RValue>::save(CGF, NewArgs[I+1].first)); CGF.ActivateCleanupBlock(CGF.EHStack.stable_begin()); } 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); } }; |