diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ExprClassification.cpp | 18 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGExprComplex.cpp | 127 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 46 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 7 |
5 files changed, 119 insertions, 82 deletions
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp index 1daa475b9e..60fbfd298f 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -171,11 +171,23 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { return Cl::CL_LValue; // GNU extensions, simply look through them. - case UO_Real: - case UO_Imag: case UO_Extension: return ClassifyInternal(Ctx, cast<UnaryOperator>(E)->getSubExpr()); + // Treat _Real and _Imag basically as if they were member + // expressions: l-value only if the operand is a true l-value. + case UO_Real: + case UO_Imag: { + const Expr *Op = cast<UnaryOperator>(E)->getSubExpr()->IgnoreParens(); + Cl::Kinds K = ClassifyInternal(Ctx, Op); + if (K != Cl::CL_LValue) return K; + + if (isa<ObjCPropertyRefExpr>(Op) || + isa<ObjCImplicitSetterGetterRefExpr>(Op)) + return Cl::CL_SubObjCPropertySetting; + return Cl::CL_LValue; + } + // C++ [expr.pre.incr]p1: The result is the updated operand; it is an // lvalue, [...] // Not so in C. @@ -343,7 +355,7 @@ static Cl::Kinds ClassifyMemberExpr(ASTContext &Ctx, const MemberExpr *E) { if (E->isArrow()) return Cl::CL_LValue; // ObjC property accesses are not lvalues, but get special treatment. - Expr *Base = E->getBase(); + Expr *Base = E->getBase()->IgnoreParens(); if (isa<ObjCPropertyRefExpr>(Base) || isa<ObjCImplicitSetterGetterRefExpr>(Base)) return Cl::CL_SubObjCPropertySetting; diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 2ef22b2401..0c24bf5d1a 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -87,8 +87,7 @@ RValue CodeGenFunction::EmitAnyExpr(const Expr *E, AggValueSlot AggSlot, if (!hasAggregateLLVMType(E->getType())) return RValue::get(EmitScalarExpr(E, IgnoreResult)); else if (E->getType()->isAnyComplexType()) - return RValue::getComplex(EmitComplexExpr(E, false, false, - IgnoreResult, IgnoreResult)); + return RValue::getComplex(EmitComplexExpr(E, IgnoreResult, IgnoreResult)); EmitAggExpr(E, AggSlot, IgnoreResult); return AggSlot.asRValue(); diff --git a/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index 5697a8b1bf..df65d5a3ac 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/lib/CodeGen/CGExprComplex.cpp @@ -35,14 +35,9 @@ class ComplexExprEmitter // True is we should ignore the value of a bool IgnoreReal; bool IgnoreImag; - // True if we should ignore the value of a=b - bool IgnoreRealAssign; - bool IgnoreImagAssign; public: - ComplexExprEmitter(CodeGenFunction &cgf, bool ir=false, bool ii=false, - bool irn=false, bool iin=false) - : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii), - IgnoreRealAssign(irn), IgnoreImagAssign(iin) { + ComplexExprEmitter(CodeGenFunction &cgf, bool ir=false, bool ii=false) + : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii) { } @@ -60,16 +55,6 @@ public: IgnoreImag = false; return I; } - bool TestAndClearIgnoreRealAssign() { - bool I = IgnoreRealAssign; - IgnoreRealAssign = false; - return I; - } - bool TestAndClearIgnoreImagAssign() { - bool I = IgnoreImagAssign; - IgnoreImagAssign = false; - return I; - } /// EmitLoadOfLValue - Given an expression with complex type that represents a /// value l-value, this method emits the address of the l-value, then loads @@ -174,8 +159,6 @@ public: ComplexPairTy VisitUnaryPlus (const UnaryOperator *E) { TestAndClearIgnoreReal(); TestAndClearIgnoreImag(); - TestAndClearIgnoreRealAssign(); - TestAndClearIgnoreImagAssign(); return Visit(E->getSubExpr()); } ComplexPairTy VisitUnaryMinus (const UnaryOperator *E); @@ -211,6 +194,10 @@ public: }; BinOpInfo EmitBinOps(const BinaryOperator *E); + LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E, + ComplexPairTy (ComplexExprEmitter::*Func) + (const BinOpInfo &), + ComplexPairTy &Val); ComplexPairTy EmitCompoundAssign(const CompoundAssignOperator *E, ComplexPairTy (ComplexExprEmitter::*Func) (const BinOpInfo &)); @@ -220,15 +207,15 @@ public: ComplexPairTy EmitBinMul(const BinOpInfo &Op); ComplexPairTy EmitBinDiv(const BinOpInfo &Op); - ComplexPairTy VisitBinMul(const BinaryOperator *E) { - return EmitBinMul(EmitBinOps(E)); - } ComplexPairTy VisitBinAdd(const BinaryOperator *E) { return EmitBinAdd(EmitBinOps(E)); } ComplexPairTy VisitBinSub(const BinaryOperator *E) { return EmitBinSub(EmitBinOps(E)); } + ComplexPairTy VisitBinMul(const BinaryOperator *E) { + return EmitBinMul(EmitBinOps(E)); + } ComplexPairTy VisitBinDiv(const BinaryOperator *E) { return EmitBinDiv(EmitBinOps(E)); } @@ -251,6 +238,9 @@ public: // Logical and/or always return int, never complex. // No comparisons produce a complex result. + + LValue EmitBinAssignLValue(const BinaryOperator *E, + ComplexPairTy &Val); ComplexPairTy VisitBinAssign (const BinaryOperator *E); ComplexPairTy VisitBinComma (const BinaryOperator *E); @@ -383,8 +373,6 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op, ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) { TestAndClearIgnoreReal(); TestAndClearIgnoreImag(); - TestAndClearIgnoreRealAssign(); - TestAndClearIgnoreImagAssign(); ComplexPairTy Op = Visit(E->getSubExpr()); llvm::Value *ResR, *ResI; @@ -401,8 +389,6 @@ ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) { ComplexPairTy ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *E) { TestAndClearIgnoreReal(); TestAndClearIgnoreImag(); - TestAndClearIgnoreRealAssign(); - TestAndClearIgnoreImagAssign(); // ~(a+ib) = a + i*-b ComplexPairTy Op = Visit(E->getSubExpr()); llvm::Value *ResI; @@ -516,8 +502,6 @@ ComplexExprEmitter::BinOpInfo ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) { TestAndClearIgnoreReal(); TestAndClearIgnoreImag(); - TestAndClearIgnoreRealAssign(); - TestAndClearIgnoreImagAssign(); BinOpInfo Ops; Ops.LHS = Visit(E->getLHS()); Ops.RHS = Visit(E->getRHS()); @@ -526,14 +510,12 @@ ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) { } -// Compound assignments. -ComplexPairTy ComplexExprEmitter:: -EmitCompoundAssign(const CompoundAssignOperator *E, - ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){ +LValue ComplexExprEmitter:: +EmitCompoundAssignLValue(const CompoundAssignOperator *E, + ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&), + ComplexPairTy &Val) { TestAndClearIgnoreReal(); TestAndClearIgnoreImag(); - bool ignreal = TestAndClearIgnoreRealAssign(); - bool ignimag = TestAndClearIgnoreImagAssign(); QualType LHSTy = E->getLHS()->getType(), RHSTy = E->getRHS()->getType(); BinOpInfo OpInfo; @@ -569,6 +551,7 @@ EmitCompoundAssign(const CompoundAssignOperator *E, // Truncate the result back to the LHS type. Result = EmitComplexToComplexCast(Result, OpInfo.Ty, LHSTy); + Val = Result; // Store the result value into the LHS lvalue. if (LHS.isPropertyRef()) @@ -579,30 +562,41 @@ EmitCompoundAssign(const CompoundAssignOperator *E, else EmitStoreOfComplex(Result, LHS.getAddress(), LHS.isVolatileQualified()); - // Restore the Ignore* flags. - IgnoreReal = ignreal; - IgnoreImag = ignimag; - IgnoreRealAssign = ignreal; - IgnoreImagAssign = ignimag; - + return LHS; +} + +// Compound assignments. +ComplexPairTy ComplexExprEmitter:: +EmitCompoundAssign(const CompoundAssignOperator *E, + ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){ + ComplexPairTy Val; + LValue LV = EmitCompoundAssignLValue(E, Func, Val); + + // The result of an assignment in C is the assigned r-value. + if (!CGF.getContext().getLangOptions().CPlusPlus) + return Val; + // Objective-C property assignment never reloads the value following a store. - if (LHS.isPropertyRef() || LHS.isKVCRef()) - return Result; + if (LV.isPropertyRef() || LV.isKVCRef()) + return Val; - // Otherwise, reload the value. - return EmitLoadOfComplex(LHS.getAddress(), LHS.isVolatileQualified()); + // If the lvalue is non-volatile, return the computed value of the assignment. + if (!LV.isVolatileQualified()) + return Val; + + return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified()); } -ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) { - TestAndClearIgnoreReal(); - TestAndClearIgnoreImag(); - bool ignreal = TestAndClearIgnoreRealAssign(); - bool ignimag = TestAndClearIgnoreImagAssign(); +LValue ComplexExprEmitter::EmitBinAssignLValue(const BinaryOperator *E, + ComplexPairTy &Val) { assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(), E->getRHS()->getType()) && "Invalid assignment"); + TestAndClearIgnoreReal(); + TestAndClearIgnoreImag(); + // Emit the RHS. - ComplexPairTy Val = Visit(E->getRHS()); + Val = Visit(E->getRHS()); // Compute the address to store into. LValue LHS = CGF.EmitLValue(E->getLHS()); @@ -615,13 +609,26 @@ ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) { else EmitStoreOfComplex(Val, LHS.getAddress(), LHS.isVolatileQualified()); - // Restore the Ignore* flags. - IgnoreReal = ignreal; - IgnoreImag = ignimag; - IgnoreRealAssign = ignreal; - IgnoreImagAssign = ignimag; + return LHS; +} - return Val; +ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) { + ComplexPairTy Val; + LValue LV = EmitBinAssignLValue(E, Val); + + // The result of an assignment in C is the assigned r-value. + if (!CGF.getContext().getLangOptions().CPlusPlus) + return Val; + + // Objective-C property assignment never reloads the value following a store. + if (LV.isPropertyRef() || LV.isKVCRef()) + return Val; + + // If the lvalue is non-volatile, return the computed value of the assignment. + if (!LV.isVolatileQualified()) + return Val; + + return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified()); } ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) { @@ -632,11 +639,8 @@ ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) { ComplexPairTy ComplexExprEmitter:: VisitConditionalOperator(const ConditionalOperator *E) { - TestAndClearIgnoreReal(); TestAndClearIgnoreImag(); - TestAndClearIgnoreRealAssign(); - TestAndClearIgnoreImagAssign(); llvm::BasicBlock *LHSBlock = CGF.createBasicBlock("cond.true"); llvm::BasicBlock *RHSBlock = CGF.createBasicBlock("cond.false"); llvm::BasicBlock *ContBlock = CGF.createBasicBlock("cond.end"); @@ -724,12 +728,11 @@ ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) { /// EmitComplexExpr - Emit the computation of the specified expression of /// complex type, ignoring the result. ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal, - bool IgnoreImag, bool IgnoreRealAssign, bool IgnoreImagAssign) { + bool IgnoreImag) { assert(E && E->getType()->isAnyComplexType() && "Invalid complex expression to emit"); - return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag, IgnoreRealAssign, - IgnoreImagAssign) + return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag) .Visit(const_cast<Expr*>(E)); } diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index a64debd6c1..0e09642931 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -1176,12 +1176,11 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) { case CK_FloatingComplexToReal: case CK_IntegralComplexToReal: - return CGF.EmitComplexExpr(E, false, true, false, true).first; + return CGF.EmitComplexExpr(E, false, true).first; case CK_FloatingComplexToBoolean: case CK_IntegralComplexToBoolean: { - CodeGenFunction::ComplexPairTy V - = CGF.EmitComplexExpr(E, false, false, false, false); + CodeGenFunction::ComplexPairTy V = CGF.EmitComplexExpr(E); // TODO: kill this function off, inline appropriate case here return EmitComplexToScalarConversion(V, E->getType(), DestTy); @@ -1471,21 +1470,38 @@ ScalarExprEmitter::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr *E) { Value *ScalarExprEmitter::VisitUnaryReal(const UnaryOperator *E) { Expr *Op = E->getSubExpr(); - if (Op->getType()->isAnyComplexType()) - return CGF.EmitComplexExpr(Op, false, true, false, true).first; + if (Op->getType()->isAnyComplexType()) { + // If it's an l-value, load through the appropriate subobject l-value. + // Note that we have to ask E because Op might be an l-value that + // this won't work for, e.g. an Obj-C property. + if (E->isLvalue(CGF.getContext()) == Expr::LV_Valid) + return CGF.EmitLoadOfLValue(CGF.EmitLValue(E), E->getType()) + .getScalarVal(); + + // Otherwise, calculate and project. + return CGF.EmitComplexExpr(Op, false, true).first; + } + return Visit(Op); } + Value *ScalarExprEmitter::VisitUnaryImag(const UnaryOperator *E) { Expr *Op = E->getSubExpr(); - if (Op->getType()->isAnyComplexType()) - return CGF.EmitComplexExpr(Op, true, false, true, false).second; + if (Op->getType()->isAnyComplexType()) { + // If it's an l-value, load through the appropriate subobject l-value. + // Note that we have to ask E because Op might be an l-value that + // this won't work for, e.g. an Obj-C property. + if (Op->isLvalue(CGF.getContext()) == Expr::LV_Valid) + return CGF.EmitLoadOfLValue(CGF.EmitLValue(E), E->getType()) + .getScalarVal(); + + // Otherwise, calculate and project. + return CGF.EmitComplexExpr(Op, true, false).second; + } // __imag on a scalar returns zero. Emit the subexpr to ensure side // effects are evaluated, but not the actual value. - if (E->isLvalue(CGF.getContext()) == Expr::LV_Valid) - CGF.EmitLValue(Op); - else - CGF.EmitScalarExpr(Op, true); + CGF.EmitScalarExpr(Op, true); return llvm::Constant::getNullValue(ConvertType(E->getType())); } @@ -1562,6 +1578,10 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, if (Ignore) return 0; + // The result of an assignment in C is the assigned r-value. + if (!CGF.getContext().getLangOptions().CPlusPlus) + return RHS; + // Objective-C property assignment never reloads the value following a store. if (LHS.isPropertyRef() || LHS.isKVCRef()) return RHS; @@ -2050,6 +2070,10 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) { if (Ignore) return 0; + // The result of an assignment in C is the assigned r-value. + if (!CGF.getContext().getLangOptions().CPlusPlus) + return RHS; + // Objective-C property assignment never reloads the value following a store. if (LHS.isPropertyRef() || LHS.isKVCRef()) return RHS; diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 2e9feefe0b..86a46deddd 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1593,10 +1593,9 @@ public: /// EmitComplexExpr - Emit the computation of the specified expression of /// complex type, returning the result. - ComplexPairTy EmitComplexExpr(const Expr *E, bool IgnoreReal = false, - bool IgnoreImag = false, - bool IgnoreRealAssign = false, - bool IgnoreImagAssign = false); + ComplexPairTy EmitComplexExpr(const Expr *E, + bool IgnoreReal = false, + bool IgnoreImag = false); /// EmitComplexExprIntoAddr - Emit the computation of the specified expression /// of complex type, storing into the specified Value*. |