diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 12 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGException.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 45 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 157 | ||||
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 36 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/CGTemporaries.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGValue.h | 63 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 37 |
14 files changed, 213 insertions, 170 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index d4e703ce03..35a2ada974 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -352,7 +352,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { SourceLocation()); } - RValue r = EmitAnyExpr(E, Addr, false); + RValue r = EmitAnyExpr(E, AggValueSlot::forAddr(Addr, false, true)); if (r.isScalar()) { llvm::Value *Loc = r.getScalarVal(); const llvm::Type *Ty = Types[i+BlockFields]; diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index bf26799b83..a6ac0acfb9 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -362,7 +362,9 @@ static void EmitBaseInitializer(CodeGenFunction &CGF, BaseClassDecl, isBaseVirtual); - CGF.EmitAggExpr(BaseInit->getInit(), V, false, false, true); + AggValueSlot AggSlot = AggValueSlot::forAddr(V, false, /*Lifetime*/ true); + + CGF.EmitAggExpr(BaseInit->getInit(), AggSlot); if (CGF.Exceptions && !BaseClassDecl->hasTrivialDestructor()) CGF.EHStack.pushCleanup<CallBaseDtor>(EHCleanup, BaseClassDecl, @@ -388,11 +390,11 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF, Next = CGF.Builder.CreateAdd(ArrayIndex, Next, "inc"); CGF.Builder.CreateStore(Next, ArrayIndexVar); } + + AggValueSlot Slot = AggValueSlot::forAddr(Dest, LHS.isVolatileQualified(), + /*Lifetime*/ true); - CGF.EmitAggExpr(MemberInit->getInit(), Dest, - LHS.isVolatileQualified(), - /*IgnoreResult*/ false, - /*IsInitializer*/ true); + CGF.EmitAggExpr(MemberInit->getInit(), Slot); return; } diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 965400135e..b743c0c6b4 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -761,7 +761,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D, } else if (Init->getType()->isAnyComplexType()) { EmitComplexExprIntoAddr(Init, Loc, isVolatile); } else { - EmitAggExpr(Init, Loc, isVolatile); + EmitAggExpr(Init, AggValueSlot::forAddr(Loc, isVolatile, true)); } } diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index 565c865c34..1b42f6189e 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -38,7 +38,7 @@ static void EmitDeclInit(CodeGenFunction &CGF, const VarDecl &D, } else if (T->isAnyComplexType()) { CGF.EmitComplexExprIntoAddr(Init, DeclPtr, isVolatile); } else { - CGF.EmitAggExpr(Init, DeclPtr, isVolatile); + CGF.EmitAggExpr(Init, AggValueSlot::forAddr(DeclPtr, isVolatile, true)); } } diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 7fb616e5a1..1063e28b84 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -457,7 +457,7 @@ static void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *E, // evaluated but before the exception is caught. But the best way // to handle that is to teach EmitAggExpr to do the final copy // differently if it can't be elided. - CGF.EmitAnyExprToMem(E, TypedExnLoc, /*Volatile*/ false); + CGF.EmitAnyExprToMem(E, TypedExnLoc, /*Volatile*/ false, /*IsInit*/ true); CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(CGF.getLLVMContext()), ShouldFreeVar); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index bb0462f963..9c1a3cf249 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -78,35 +78,31 @@ llvm::Value *CodeGenFunction::EvaluateExprAsBool(const Expr *E) { return EmitComplexToScalarConversion(EmitComplexExpr(E), E->getType(),BoolTy); } -/// EmitAnyExpr - Emit code to compute the specified expression which can have -/// any type. The result is returned as an RValue struct. If this is an -/// aggregate expression, the aggloc/agglocvolatile arguments indicate where the +/// EmitAnyExpr - Emit code to compute the specified expression which +/// can have any type. The result is returned as an RValue struct. +/// If this is an aggregate expression, AggSlot indicates where the /// result should be returned. -RValue CodeGenFunction::EmitAnyExpr(const Expr *E, llvm::Value *AggLoc, - bool IsAggLocVolatile, bool IgnoreResult, - bool IsInitializer) { +RValue CodeGenFunction::EmitAnyExpr(const Expr *E, AggValueSlot AggSlot, + bool IgnoreResult) { if (!hasAggregateLLVMType(E->getType())) return RValue::get(EmitScalarExpr(E, IgnoreResult)); else if (E->getType()->isAnyComplexType()) return RValue::getComplex(EmitComplexExpr(E, false, false, IgnoreResult, IgnoreResult)); - EmitAggExpr(E, AggLoc, IsAggLocVolatile, IgnoreResult, IsInitializer); - return RValue::getAggregate(AggLoc, IsAggLocVolatile); + EmitAggExpr(E, AggSlot, IgnoreResult); + return AggSlot.asRValue(); } /// EmitAnyExprToTemp - Similary to EmitAnyExpr(), however, the result will /// always be accessible even if no aggregate location is provided. -RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E, - bool IsAggLocVolatile, - bool IsInitializer) { - llvm::Value *AggLoc = 0; +RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E) { + AggValueSlot AggSlot = AggValueSlot::ignored(); if (hasAggregateLLVMType(E->getType()) && !E->getType()->isAnyComplexType()) - AggLoc = CreateMemTemp(E->getType(), "agg.tmp"); - return EmitAnyExpr(E, AggLoc, IsAggLocVolatile, /*IgnoreResult=*/false, - IsInitializer); + AggSlot = CreateAggTemp(E->getType(), "agg.tmp"); + return EmitAnyExpr(E, AggSlot); } /// EmitAnyExprToMem - Evaluate an expression into a given memory @@ -118,7 +114,7 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E, if (E->getType()->isComplexType()) EmitComplexExprIntoAddr(E, Location, IsLocationVolatile); else if (hasAggregateLLVMType(E->getType())) - EmitAggExpr(E, Location, IsLocationVolatile, /*Ignore*/ false, IsInit); + EmitAggExpr(E, AggValueSlot::forAddr(Location, IsLocationVolatile, IsInit)); else { RValue RV = RValue::get(EmitScalarExpr(E, /*Ignore*/ false)); LValue LV = MakeAddrLValue(Location, E->getType()); @@ -247,13 +243,16 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, } // Create a reference temporary if necessary. + AggValueSlot AggSlot = AggValueSlot::ignored(); if (CGF.hasAggregateLLVMType(E->getType()) && - !E->getType()->isAnyComplexType()) + !E->getType()->isAnyComplexType()) { ReferenceTemporary = CreateReferenceTemporary(CGF, E->getType(), InitializedDecl); + AggSlot = AggValueSlot::forAddr(ReferenceTemporary, false, + InitializedDecl != 0); + } - RV = CGF.EmitAnyExpr(E, ReferenceTemporary, /*IsAggLocVolatile=*/false, - /*IgnoreResult=*/false, InitializedDecl); + RV = CGF.EmitAnyExpr(E, AggSlot); if (InitializedDecl) { // Get the destructor for the reference temporary. @@ -1673,7 +1672,7 @@ LValue CodeGenFunction::EmitCompoundLiteralLValue(const CompoundLiteralExpr *E){ const Expr *InitExpr = E->getInitializer(); LValue Result = MakeAddrLValue(DeclPtr, E->getType()); - EmitAnyExprToMem(InitExpr, DeclPtr, /*Volatile*/ false); + EmitAnyExprToMem(InitExpr, DeclPtr, /*Volatile*/ false, /*Init*/ true); return Result; } @@ -1965,9 +1964,9 @@ LValue CodeGenFunction::EmitVAArgExprLValue(const VAArgExpr *E) { } LValue CodeGenFunction::EmitCXXConstructLValue(const CXXConstructExpr *E) { - llvm::Value *Temp = CreateMemTemp(E->getType(), "tmp"); - EmitCXXConstructExpr(Temp, E); - return MakeAddrLValue(Temp, E->getType()); + AggValueSlot Slot = CreateAggTemp(E->getType(), "tmp"); + EmitCXXConstructExpr(E, Slot); + return MakeAddrLValue(Slot.getAddr(), E->getType()); } LValue diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index f1bc692cf4..9ed20f382e 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -32,10 +32,8 @@ namespace { class AggExprEmitter : public StmtVisitor<AggExprEmitter> { CodeGenFunction &CGF; CGBuilderTy &Builder; - llvm::Value *DestPtr; - bool VolatileDest; + AggValueSlot Dest; bool IgnoreResult; - bool IsInitializer; bool RequiresGCollection; ReturnValueSlot getReturnValueSlot() const { @@ -44,15 +42,19 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> { // API. if (RequiresGCollection) return ReturnValueSlot(); - return ReturnValueSlot(DestPtr, VolatileDest); + return ReturnValueSlot(Dest.getAddr(), Dest.isVolatile()); + } + + AggValueSlot EnsureSlot(QualType T) { + if (!Dest.isIgnored()) return Dest; + return CGF.CreateAggTemp(T, "agg.tmp.ensured"); } public: - AggExprEmitter(CodeGenFunction &cgf, llvm::Value *destPtr, bool v, - bool ignore, bool isinit, bool requiresGCollection) - : CGF(cgf), Builder(CGF.Builder), - DestPtr(destPtr), VolatileDest(v), IgnoreResult(ignore), - IsInitializer(isinit), RequiresGCollection(requiresGCollection) { + AggExprEmitter(CodeGenFunction &cgf, AggValueSlot Dest, + bool ignore, bool requiresGCollection) + : CGF(cgf), Builder(CGF.Builder), Dest(Dest), + IgnoreResult(ignore), RequiresGCollection(requiresGCollection) { } //===--------------------------------------------------------------------===// @@ -182,7 +184,7 @@ void AggExprEmitter::EmitGCMove(const Expr *E, RValue Src) { unsigned long size = TypeInfo.first/8; const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size); - CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, DestPtr, + CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, Dest.getAddr(), Src.getAggregateAddr(), SizeVal); } @@ -192,13 +194,13 @@ void AggExprEmitter::EmitGCMove(const Expr *E, RValue Src) { void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore) { assert(Src.isAggregate() && "value must be aggregate value!"); - // If DestPtr is null, then we're evaluating an aggregate expression + // If Dest is ignored, then we're evaluating an aggregate expression // in a context (like an expression statement) that doesn't care // about the result. C says that an lvalue-to-rvalue conversion is // performed in these cases; C++ says that it is not. In either // case, we don't actually need to do anything unless the value is // volatile. - if (DestPtr == 0) { + if (Dest.isIgnored()) { if (!Src.isVolatileQualified() || CGF.CGM.getLangOptions().CPlusPlus || (IgnoreResult && Ignore)) @@ -206,7 +208,7 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore) { // If the source is volatile, we must read from it; to do that, we need // some place to put it. - DestPtr = CGF.CreateMemTemp(E->getType(), "agg.tmp"); + Dest = CGF.CreateAggTemp(E->getType(), "agg.tmp"); } if (RequiresGCollection) { @@ -216,16 +218,17 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, RValue Src, bool Ignore) { const llvm::Type *SizeTy = CGF.ConvertType(CGF.getContext().getSizeType()); llvm::Value *SizeVal = llvm::ConstantInt::get(SizeTy, size); CGF.CGM.getObjCRuntime().EmitGCMemmoveCollectable(CGF, - DestPtr, Src.getAggregateAddr(), - SizeVal); + Dest.getAddr(), + Src.getAggregateAddr(), + SizeVal); return; } // If the result of the assignment is used, copy the LHS there also. // FIXME: Pass VolatileDest as well. I think we also need to merge volatile // from the source as well, as we can't eliminate it if either operand // is volatile, unless copy has volatile for both source and destination.. - CGF.EmitAggregateCopy(DestPtr, Src.getAggregateAddr(), E->getType(), - VolatileDest|Src.isVolatileQualified()); + CGF.EmitAggregateCopy(Dest.getAddr(), Src.getAggregateAddr(), E->getType(), + Dest.isVolatile()|Src.isVolatileQualified()); } /// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired. @@ -242,7 +245,7 @@ void AggExprEmitter::EmitFinalDestCopy(const Expr *E, LValue Src, bool Ignore) { //===----------------------------------------------------------------------===// void AggExprEmitter::VisitCastExpr(CastExpr *E) { - if (!DestPtr && E->getCastKind() != CK_Dynamic) { + if (Dest.isIgnored() && E->getCastKind() != CK_Dynamic) { Visit(E->getSubExpr()); return; } @@ -259,8 +262,8 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { else CGF.CGM.ErrorUnsupported(E, "non-simple lvalue dynamic_cast"); - if (DestPtr) - CGF.CGM.ErrorUnsupported(E, "lvalue dynamic_cast with a destination"); + if (!Dest.isIgnored()) + CGF.CGM.ErrorUnsupported(E, "lvalue dynamic_cast with a destination"); break; } @@ -268,7 +271,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { // GCC union extension QualType Ty = E->getSubExpr()->getType(); QualType PtrTy = CGF.getContext().getPointerType(Ty); - llvm::Value *CastPtr = Builder.CreateBitCast(DestPtr, + llvm::Value *CastPtr = Builder.CreateBitCast(Dest.getAddr(), CGF.ConvertType(PtrTy)); EmitInitializationToLValue(E->getSubExpr(), CGF.MakeAddrLValue(CastPtr, Ty), Ty); @@ -327,13 +330,12 @@ void AggExprEmitter::VisitObjCImplicitSetterGetterRefExpr( } void AggExprEmitter::VisitBinComma(const BinaryOperator *E) { - CGF.EmitAnyExpr(E->getLHS(), 0, false, true); - CGF.EmitAggExpr(E->getRHS(), DestPtr, VolatileDest, - /*IgnoreResult=*/false, IsInitializer); + CGF.EmitAnyExpr(E->getLHS(), AggValueSlot::ignored(), true); + Visit(E->getRHS()); } void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) { - CGF.EmitCompoundStmt(*E->getSubStmt(), true, DestPtr, VolatileDest); + CGF.EmitCompoundStmt(*E->getSubStmt(), true, Dest); } void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) { @@ -360,27 +362,21 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { // We have to special case property setters, otherwise we must have // a simple lvalue (no aggregates inside vectors, bitfields). if (LHS.isPropertyRef()) { - llvm::Value *AggLoc = DestPtr; - if (!AggLoc) - AggLoc = CGF.CreateMemTemp(E->getRHS()->getType()); - CGF.EmitAggExpr(E->getRHS(), AggLoc, VolatileDest); - CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), - RValue::getAggregate(AggLoc, VolatileDest)); + AggValueSlot Slot = EnsureSlot(E->getRHS()->getType()); + CGF.EmitAggExpr(E->getRHS(), Slot); + CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), Slot.asRValue()); } else if (LHS.isKVCRef()) { - llvm::Value *AggLoc = DestPtr; - if (!AggLoc) - AggLoc = CGF.CreateMemTemp(E->getRHS()->getType()); - CGF.EmitAggExpr(E->getRHS(), AggLoc, VolatileDest); - CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(), - RValue::getAggregate(AggLoc, VolatileDest)); + AggValueSlot Slot = EnsureSlot(E->getRHS()->getType()); + CGF.EmitAggExpr(E->getRHS(), Slot); + CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(), Slot.asRValue()); } else { bool RequiresGCollection = false; if (CGF.getContext().getLangOptions().getGCMode()) RequiresGCollection = TypeRequiresGCollection(E->getLHS()->getType()); // Codegen the RHS so that it stores directly into the LHS. - CGF.EmitAggExpr(E->getRHS(), LHS.getAddress(), LHS.isVolatileQualified(), - false, false, RequiresGCollection); + AggValueSlot LHSSlot = AggValueSlot::forLValue(LHS, true); + CGF.EmitAggExpr(E->getRHS(), LHSSlot, false, RequiresGCollection); EmitFinalDestCopy(E, LHS, true); } } @@ -434,58 +430,40 @@ void AggExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { } void AggExprEmitter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E) { - llvm::Value *Val = DestPtr; - - if (!Val) { - // Create a temporary variable. - Val = CGF.CreateMemTemp(E->getType(), "tmp"); - - // FIXME: volatile - CGF.EmitAggExpr(E->getSubExpr(), Val, false); - } else - Visit(E->getSubExpr()); - - // Don't make this a live temporary if we're emitting an initializer expr. - if (!IsInitializer) - CGF.EmitCXXTemporary(E->getTemporary(), Val); + // Ensure that we have a slot, but if we already do, remember + // whether its lifetime was externally managed. + bool WasManaged = Dest.isLifetimeExternallyManaged(); + Dest = EnsureSlot(E->getType()); + Dest.setLifetimeExternallyManaged(); + + Visit(E->getSubExpr()); + + // Set up the temporary's destructor if its lifetime wasn't already + // being managed. + if (!WasManaged) + CGF.EmitCXXTemporary(E->getTemporary(), Dest.getAddr()); } void AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) { - llvm::Value *Val = DestPtr; - - if (!Val) // Create a temporary variable. - Val = CGF.CreateMemTemp(E->getType(), "tmp"); - - CGF.EmitCXXConstructExpr(Val, E); + AggValueSlot Slot = EnsureSlot(E->getType()); + CGF.EmitCXXConstructExpr(E, Slot); } void AggExprEmitter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { - llvm::Value *Val = DestPtr; - - CGF.EmitCXXExprWithTemporaries(E, Val, VolatileDest, IsInitializer); + CGF.EmitCXXExprWithTemporaries(E, Dest); } void AggExprEmitter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { - llvm::Value *Val = DestPtr; - - if (!Val) { - // Create a temporary variable. - Val = CGF.CreateMemTemp(E->getType(), "tmp"); - } - EmitNullInitializationToLValue(CGF.MakeAddrLValue(Val, E->getType()), - E->getType()); + QualType T = E->getType(); + AggValueSlot Slot = EnsureSlot(T); + EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddr(), T), T); } void AggExprEmitter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *E) { - llvm::Value *Val = DestPtr; - - if (!Val) { - // Create a temporary variable. - Val = CGF.CreateMemTemp(E->getType(), "tmp"); - } - EmitNullInitializationToLValue(CGF.MakeAddrLValue(Val, E->getType()), - E->getType()); + QualType T = E->getType(); + AggValueSlot Slot = EnsureSlot(T); + EmitNullInitializationToLValue(CGF.MakeAddrLValue(Slot.getAddr(), T), T); } void @@ -500,7 +478,7 @@ AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV, QualType T) { } else if (T->isAnyComplexType()) { CGF.EmitComplexExprIntoAddr(E, LV.getAddress(), false); } else if (CGF.hasAggregateLLVMType(T)) { - CGF.EmitAnyExpr(E, LV.getAddress(), false); + CGF.EmitAggExpr(E, AggValueSlot::forAddr(LV.getAddress(), false, true)); } else { CGF.EmitStoreThroughLValue(CGF.EmitAnyExpr(E), LV, T); } @@ -537,6 +515,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { if (E->hadArrayRangeDesignator()) CGF.ErrorUnsupported(E, "GNU array range designator extension"); + llvm::Value *DestPtr = Dest.getAddr(); + // Handle initialization of an array. if (E->getType()->isArrayType()) { const llvm::PointerType *APType = @@ -660,19 +640,20 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { /// type. The result is computed into DestPtr. Note that if DestPtr is null, /// the value of the aggregate expression is not needed. If VolatileDest is /// true, DestPtr cannot be 0. +/// +/// \param IsInitializer - true if this evaluation is initializing an +/// object whose lifetime is already being managed. // // FIXME: Take Qualifiers object. -void CodeGenFunction::EmitAggExpr(const Expr *E, llvm::Value *DestPtr, - bool VolatileDest, bool IgnoreResult, - bool IsInitializer, +void CodeGenFunction::EmitAggExpr(const Expr *E, AggValueSlot Slot, + bool IgnoreResult, bool RequiresGCollection) { assert(E && hasAggregateLLVMType(E->getType()) && "Invalid aggregate expression to emit"); - assert ((DestPtr != 0 || VolatileDest == false) - && "volatile aggregate can't be 0"); + assert((Slot.getAddr() != 0 || Slot.isIgnored()) + && "slot has bits but no address"); - AggExprEmitter(*this, DestPtr, VolatileDest, IgnoreResult, IsInitializer, - RequiresGCollection) + AggExprEmitter(*this, Slot, IgnoreResult, RequiresGCollection) .Visit(const_cast<Expr*>(E)); } @@ -680,7 +661,9 @@ LValue CodeGenFunction::EmitAggExprToLValue(const Expr *E) { assert(hasAggregateLLVMType(E->getType()) && "Invalid argument!"); llvm::Value *Temp = CreateMemTemp(E->getType()); LValue LV = MakeAddrLValue(Temp, E->getType()); - EmitAggExpr(E, Temp, LV.isVolatileQualified()); + AggValueSlot Slot + = AggValueSlot::forAddr(Temp, LV.isVolatileQualified(), false); + EmitAggExpr(E, Slot); return LV; } diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 10e29d199c..584f6c099b 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -219,16 +219,12 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, LValue LV = EmitLValue(E->getArg(0)); llvm::Value *This; if (LV.isPropertyRef() || LV.isKVCRef()) { - llvm::Value *AggLoc = CreateMemTemp(E->getArg(1)->getType()); - EmitAggExpr(E->getArg(1), AggLoc, false /*VolatileDest*/); + AggValueSlot Slot = CreateAggTemp(E->getArg(1)->getType()); + EmitAggExpr(E->getArg(1), Slot); if (LV.isPropertyRef()) - EmitObjCPropertySet(LV.getPropertyRefExpr(), - RValue::getAggregate(AggLoc, - false /*VolatileDest*/)); + EmitObjCPropertySet(LV.getPropertyRefExpr(), Slot.asRValue()); else - EmitObjCPropertySet(LV.getKVCRefExpr(), - RValue::getAggregate(AggLoc, - false /*VolatileDest*/)); + EmitObjCPropertySet(LV.getKVCRefExpr(), Slot.asRValue()); return RValue::getAggregate(0, false); } else @@ -269,17 +265,16 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, } void -CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, - const CXXConstructExpr *E) { - assert(Dest && "Must have a destination!"); +CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E, + AggValueSlot Dest) { + assert(!Dest.isIgnored() && "Must have a destination!"); const CXXConstructorDecl *CD = E->getConstructor(); // If we require zero initialization before (or instead of) calling the // constructor, as can be the case with a non-user-provided default // constructor, emit the zero initialization now. if (E->requiresZeroInitialization()) - EmitNullInitialization(Dest, E->getType()); - + EmitNullInitialization(Dest.getAddr(), E->getType()); // If this is a call to a trivial default constructor, do nothing. if (CD->isTrivial() && CD->isDefaultConstructor()) @@ -289,8 +284,8 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, // its first argument instead, if in fact that argument is a temporary // object. if (getContext().getLangOptions().ElideConstructors && E->isElidable()) { - if (const Expr *Arg = E->getArg(0)->getTemporaryObject()) { - EmitAggExpr(Arg, Dest, false); + if (E->getArg(0)->isTemporaryObject(getContext(), CD->getParent())) { + EmitAggExpr(E->getArg(0), Dest); return; } } @@ -302,7 +297,7 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, const llvm::Type *BasePtr = ConvertType(BaseElementTy); BasePtr = llvm::PointerType::getUnqual(BasePtr); llvm::Value *BaseAddrPtr = - Builder.CreateBitCast(Dest, BasePtr); + Builder.CreateBitCast(Dest.getAddr(), BasePtr); EmitCXXAggrConstructorCall(CD, Array, BaseAddrPtr, E->arg_begin(), E->arg_end()); @@ -315,7 +310,7 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest, E->getConstructionKind() == CXXConstructExpr::CK_VirtualBase; // Call the constructor. - EmitCXXConstructorCall(CD, Type, ForVirtualBase, Dest, + EmitCXXConstructorCall(CD, Type, ForVirtualBase, Dest.getAddr(), E->arg_begin(), E->arg_end()); } } @@ -539,8 +534,11 @@ static void StoreAnyExprIntoOneUnit(CodeGenFunction &CGF, const CXXNewExpr *E, else if (AllocType->isAnyComplexType()) CGF.EmitComplexExprIntoAddr(Init, NewPtr, AllocType.isVolatileQualified()); - else - CGF.EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified()); + else { + AggValueSlot Slot + = AggValueSlot::forAddr(NewPtr, AllocType.isVolatileQualified(), true); + CGF.EmitAggExpr(Init, Slot); + } } void diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 45c5fb9f0b..d4b1bd940c 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1063,7 +1063,7 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) { CGF.EmitLoadOfKVCRefLValue(LV, E->getType()); } else - CGF.EmitAnyExpr(E, 0, false, true); + CGF.EmitAnyExpr(E, AggValueSlot::ignored(), true); return 0; } case CK_VectorSplat: { @@ -1127,7 +1127,7 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) { // Okay, this is a cast from an aggregate. It must be a cast to void. Just // evaluate the result and return. - CGF.EmitAggExpr(E, 0, false, true); + CGF.EmitAggExpr(E, AggValueSlot::ignored(), true); return 0; } diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 5b0c2630a0..8abcbea5d0 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -386,8 +386,7 @@ void CodeGenFunction::GenerateObjCSetter(ObjCImplementationDecl *IMP, FunctionType::ExtInfo()), GetCopyStructFn, ReturnValueSlot(), Args); } else if (PID->getSetterCXXAssignment()) { - EmitAnyExpr(PID->getSetterCXXAssignment(), (llvm::Value *)0, false, true, - false); + EmitAnyExpr(PID->getSetterCXXAssignment(), AggValueSlot::ignored(), true); } else { // FIXME: Find a clean way to avoid AST node creation. @@ -438,8 +437,7 @@ void CodeGenFunction::GenerateObjCCtorDtorMethod(ObjCImplementationDecl *IMP, ObjCIvarDecl *Ivar = cast<ObjCIvarDecl>(Field); LValue LV = EmitLValueForIvar(TypeOfSelfObject(), LoadObjCSelf(), Ivar, 0); - EmitAggExpr(IvarInit->getInit(), LV.getAddress(), - LV.isVolatileQualified(), false, true); + EmitAggExpr(IvarInit->getInit(), AggValueSlot::forLValue(LV, true)); } // constructor returns 'self'. CodeGenTypes &Types = CGM.getTypes(); diff --git a/lib/CodeGen/CGStmt.cpp b/lib/CodeGen/CGStmt.cpp index 16145f766a..a70534d2ca 100644 --- a/lib/CodeGen/CGStmt.cpp +++ b/lib/CodeGen/CGStmt.cpp @@ -75,7 +75,7 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { if (!isa<Expr>(S)) ErrorUnsupported(S, "statement"); - EmitAnyExpr(cast<Expr>(S), 0, false, true); + EmitAnyExpr(cast<Expr>(S), AggValueSlot::ignored(), true); // Expression emitters don't handle unreachable blocks yet, so look for one // explicitly here. This handles the common case of a call to a noreturn @@ -146,7 +146,7 @@ bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) { /// this captures the expression result of the last sub-statement and returns it /// (for use by the statement expression extension). RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, - llvm::Value *AggLoc, bool isAggVol) { + AggValueSlot AggSlot) { PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),S.getLBracLoc(), "LLVM IR generation of compound statement ('{}')"); @@ -184,7 +184,7 @@ RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast, EnsureInsertPoint(); - RV = EmitAnyExpr(cast<Expr>(LastStmt), AggLoc); + RV = EmitAnyExpr(cast<Expr>(LastStmt), AggSlot); } return RV; @@ -643,7 +643,7 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { } else if (RV->getType()->isAnyComplexType()) { EmitComplexExprIntoAddr(RV, ReturnValue, false); } else { - EmitAggExpr(RV, ReturnValue, false); + EmitAggExpr(RV, AggValueSlot::forAddr(ReturnValue, false, true)); } EmitBranchThroughCleanup(ReturnBlock); diff --git a/lib/CodeGen/CGTemporaries.cpp b/lib/CodeGen/CGTemporaries.cpp index dfb8dc63c5..ba01b72e54 100644 --- a/lib/CodeGen/CGTemporaries.cpp +++ b/lib/CodeGen/CGTemporaries.cpp @@ -77,12 +77,9 @@ void CodeGenFunction::EmitCXXTemporary(const CXXTemporary *Temporary, RValue CodeGenFunction::EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E, - llvm::Value *AggLoc, - bool IsAggLocVolatile, - bool IsInitializer) { + AggValueSlot Slot) { RunCleanupsScope Scope(*this); - return EmitAnyExpr(E->getSubExpr(), AggLoc, IsAggLocVolatile, - /*IgnoreResult=*/false, IsInitializer); + return EmitAnyExpr(E->getSubExpr(), Slot); } LValue CodeGenFunction::EmitCXXExprWithTemporariesLValue( diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h index f57ecd245f..42b8335ecd 100644 --- a/lib/CodeGen/CGValue.h +++ b/lib/CodeGen/CGValue.h @@ -321,6 +321,69 @@ public: } }; +/// An aggregate value slot. +class AggValueSlot { + /// The address and associated flags. + uintptr_t AddrAndFlags; + + static const uintptr_t VolatileFlag = 0x1; + static const uintptr_t LifetimeFlag = 0x2; + static const uintptr_t AddrMask = ~(VolatileFlag | LifetimeFlag); + +public: + /// ignored - Returns an aggregate value slot indicating that the + /// aggregate value is being ignored. + static AggValueSlot ignored() { + AggValueSlot AV; + AV.AddrAndFlags = 0; + return AV; + } + + /// forAddr - Make a slot for an aggregate value. + /// + /// \param Volatile - true if the slot should be volatile-initialized + /// \param LifetimeExternallyManaged - true if the slot's lifetime + /// is being externally managed; false if a destructor should be + /// registered for any temporaries evaluated into the slot + static AggValueSlot forAddr(llvm::Value *Addr, bool Volatile, + bool LifetimeExternallyManaged) { + AggValueSlot AV; + AV.AddrAndFlags = reinterpret_cast<uintptr_t>(Addr); + if (Volatile) AV.AddrAndFlags |= VolatileFlag; + if (LifetimeExternallyManaged) AV.AddrAndFlags |= LifetimeFlag; + return AV; + } + + static AggValueSlot forLValue(LValue LV, bool LifetimeExternallyManaged) { + return forAddr(LV.getAddress(), LV.isVolatileQualified(), + LifetimeExternallyManaged); + } + + bool isLifetimeExternallyManaged() const { + return AddrAndFlags & LifetimeFlag; + } + void setLifetimeExternallyManaged() { + AddrAndFlags |= LifetimeFlag; + } + + bool isVolatile() const { + return AddrAndFlags & VolatileFlag; + } + + llvm::Value *getAddr() const { + return reinterpret_cast<llvm::Value*>(AddrAndFlags & AddrMask); + } + + bool isIgnored() const { + return AddrAndFlags == 0; + } + + RValue asRValue() const { + return RValue::getAggregate(getAddr(), isVolatile()); + } + +}; + } // end namespace CodeGen } // end namespace clang diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 715be3ce17..d19827bf4f 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1024,6 +1024,12 @@ public: /// appropriate alignment. llvm::AllocaInst *CreateMemTemp(QualType T, const llvm::Twine &Name = "tmp"); + /// CreateAggTemp - Create a temporary memory object for the given + /// aggregate type. + AggValueSlot CreateAggTemp(QualType T, const llvm::Twine &Name = "tmp") { + return AggValueSlot::forAddr(CreateMemTemp(T, Name), false, false); + } + /// EvaluateExprAsBool - Perform the usual unary conversions on the specified /// expression and compare the result against zero, returning an Int1Ty value. llvm::Value *EvaluateExprAsBool(const Expr *E); @@ -1034,9 +1040,9 @@ public: /// the result should be returned. /// /// \param IgnoreResult - True if the resulting value isn't used. - RValue EmitAnyExpr(const Expr *E, llvm::Value *AggLoc = 0, - bool IsAggLocVolatile = false, bool IgnoreResult = false, - bool IsInitializer = false); + RValue EmitAnyExpr(const Expr *E, + AggValueSlot AggSlot = AggValueSlot::ignored(), + bool IgnoreResult = false); |