diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp | 293 |
1 files changed, 163 insertions, 130 deletions
diff --git a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp b/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp index 79e9dd4..7b0292b 100644 --- a/contrib/llvm/tools/clang/lib/CodeGen/CGExprComplex.cpp +++ b/contrib/llvm/tools/clang/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,36 +55,36 @@ 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 /// and returns the result. ComplexPairTy EmitLoadOfLValue(const Expr *E) { - LValue LV = CGF.EmitLValue(E); + return EmitLoadOfLValue(CGF.EmitLValue(E)); + } + + ComplexPairTy EmitLoadOfLValue(LValue LV) { if (LV.isSimple()) return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified()); - if (LV.isPropertyRef()) - return CGF.EmitObjCPropertyGet(LV.getPropertyRefExpr()).getComplexVal(); - - assert(LV.isKVCRef() && "Unknown LValue type!"); - return CGF.EmitObjCPropertyGet(LV.getKVCRefExpr()).getComplexVal(); + assert(LV.isPropertyRef() && "Unknown LValue type!"); + return CGF.EmitLoadOfPropertyRefLValue(LV).getComplexVal(); } /// EmitLoadOfComplex - Given a pointer to a complex value, emit code to load /// the real and imaginary pieces. ComplexPairTy EmitLoadOfComplex(llvm::Value *SrcPtr, bool isVolatile); + /// EmitStoreThroughLValue - Given an l-value of complex type, store + /// a complex number into it. + void EmitStoreThroughLValue(ComplexPairTy Val, LValue LV) { + if (LV.isSimple()) + return EmitStoreOfComplex(Val, LV.getAddress(), LV.isVolatileQualified()); + + assert(LV.isPropertyRef() && "Unknown LValue type!"); + CGF.EmitStoreThroughPropertyRefLValue(RValue::getComplex(Val), LV); + } + /// EmitStoreOfComplex - Store the specified real/imag parts into the /// specified value pointer. void EmitStoreOfComplex(ComplexPairTy Val, llvm::Value *ResPtr, bool isVol); @@ -102,6 +97,10 @@ public: // Visitor Methods //===--------------------------------------------------------------------===// + ComplexPairTy Visit(Expr *E) { + return StmtVisitor<ComplexExprEmitter, ComplexPairTy>::Visit(E); + } + ComplexPairTy VisitStmt(Stmt *S) { S->dump(CGF.getContext().getSourceManager()); assert(0 && "Stmt can't have complex result type!"); @@ -117,10 +116,7 @@ public: return EmitLoadOfLValue(E); } ComplexPairTy VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { - return EmitLoadOfLValue(E); - } - ComplexPairTy VisitObjCImplicitSetterGetterRefExpr( - ObjCImplicitSetterGetterRefExpr *E) { + assert(E->getObjectKind() == OK_Ordinary); return EmitLoadOfLValue(E); } ComplexPairTy VisitObjCMessageExpr(ObjCMessageExpr *E) { @@ -128,6 +124,11 @@ public: } ComplexPairTy VisitArraySubscriptExpr(Expr *E) { return EmitLoadOfLValue(E); } ComplexPairTy VisitMemberExpr(const Expr *E) { return EmitLoadOfLValue(E); } + ComplexPairTy VisitOpaqueValueExpr(OpaqueValueExpr *E) { + if (E->isGLValue()) + return EmitLoadOfLValue(CGF.getOpaqueLValueMapping(E)); + return CGF.getOpaqueRValueMapping(E).getComplexVal(); + } // FIXME: CompoundLiteralExpr @@ -165,8 +166,6 @@ public: ComplexPairTy VisitUnaryPlus (const UnaryOperator *E) { TestAndClearIgnoreReal(); TestAndClearIgnoreImag(); - TestAndClearIgnoreRealAssign(); - TestAndClearIgnoreImagAssign(); return Visit(E->getSubExpr()); } ComplexPairTy VisitUnaryMinus (const UnaryOperator *E); @@ -178,8 +177,8 @@ public: ComplexPairTy VisitCXXDefaultArgExpr(CXXDefaultArgExpr *DAE) { return Visit(DAE->getExpr()); } - ComplexPairTy VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) { - return CGF.EmitCXXExprWithTemporaries(E).getComplexVal(); + ComplexPairTy VisitExprWithCleanups(ExprWithCleanups *E) { + return CGF.EmitExprWithCleanups(E).getComplexVal(); } ComplexPairTy VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *E) { assert(E->getType()->isAnyComplexType() && "Expected complex type!"); @@ -202,6 +201,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 &)); @@ -211,15 +214,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)); } @@ -242,11 +245,15 @@ 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); - ComplexPairTy VisitConditionalOperator(const ConditionalOperator *CO); + ComplexPairTy + VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO); ComplexPairTy VisitChooseExpr(ChooseExpr *CE); ComplexPairTy VisitInitListExpr(InitListExpr *E); @@ -265,13 +272,13 @@ ComplexPairTy ComplexExprEmitter::EmitLoadOfComplex(llvm::Value *SrcPtr, bool isVolatile) { llvm::Value *Real=0, *Imag=0; - if (!IgnoreReal) { + if (!IgnoreReal || isVolatile) { llvm::Value *RealP = Builder.CreateStructGEP(SrcPtr, 0, SrcPtr->getName() + ".realp"); Real = Builder.CreateLoad(RealP, isVolatile, SrcPtr->getName() + ".real"); } - if (!IgnoreImag) { + if (!IgnoreImag || isVolatile) { llvm::Value *ImagP = Builder.CreateStructGEP(SrcPtr, 1, SrcPtr->getName() + ".imagp"); Imag = Builder.CreateLoad(ImagP, isVolatile, SrcPtr->getName() + ".imag"); @@ -307,8 +314,7 @@ ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) { ComplexPairTy ComplexExprEmitter:: VisitImaginaryLiteral(const ImaginaryLiteral *IL) { llvm::Value *Imag = CGF.EmitScalarExpr(IL->getSubExpr()); - return - ComplexPairTy(llvm::Constant::getNullValue(Imag->getType()), Imag); + return ComplexPairTy(llvm::Constant::getNullValue(Imag->getType()), Imag); } @@ -320,6 +326,7 @@ ComplexPairTy ComplexExprEmitter::VisitCallExpr(const CallExpr *E) { } ComplexPairTy ComplexExprEmitter::VisitStmtExpr(const StmtExpr *E) { + CodeGenFunction::StmtExprEvaluation eval(CGF); return CGF.EmitCompoundStmt(*E->getSubStmt(), true).getComplexVal(); } @@ -341,6 +348,22 @@ ComplexPairTy ComplexExprEmitter::EmitComplexToComplexCast(ComplexPairTy Val, ComplexPairTy ComplexExprEmitter::EmitCast(CastExpr::CastKind CK, Expr *Op, QualType DestTy) { + switch (CK) { + case CK_GetObjCProperty: { + LValue LV = CGF.EmitLValue(Op); + assert(LV.isPropertyRef() && "Unknown LValue type!"); + return CGF.EmitLoadOfPropertyRefLValue(LV).getComplexVal(); + } + + case CK_NoOp: + case CK_LValueToRValue: + return Visit(Op); + + // TODO: do all of these + default: + break; + } + // Two cases here: cast from (complex to complex) and (scalar to complex). if (Op->getType()->isAnyComplexType()) return EmitComplexToComplexCast(Visit(Op), Op->getType(), DestTy); @@ -372,8 +395,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; @@ -390,8 +411,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; @@ -505,8 +524,6 @@ ComplexExprEmitter::BinOpInfo ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) { TestAndClearIgnoreReal(); TestAndClearIgnoreImag(); - TestAndClearIgnoreRealAssign(); - TestAndClearIgnoreImagAssign(); BinOpInfo Ops; Ops.LHS = Visit(E->getLHS()); Ops.RHS = Visit(E->getRHS()); @@ -515,37 +532,31 @@ 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(); + QualType LHSTy = E->getLHS()->getType(); BinOpInfo OpInfo; // Load the RHS and LHS operands. // __block variables need to have the rhs evaluated first, plus this should - // improve codegen a little. It is possible for the RHS to be complex or - // scalar. + // improve codegen a little. OpInfo.Ty = E->getComputationResultType(); - OpInfo.RHS = EmitCast(CK_Unknown, E->getRHS(), OpInfo.Ty); + + // The RHS should have been converted to the computation type. + assert(OpInfo.Ty->isAnyComplexType()); + assert(CGF.getContext().hasSameUnqualifiedType(OpInfo.Ty, + E->getRHS()->getType())); + OpInfo.RHS = Visit(E->getRHS()); LValue LHS = CGF.EmitLValue(E->getLHS()); - // We know the LHS is a complex lvalue. - ComplexPairTy LHSComplexPair; - if (LHS.isPropertyRef()) - LHSComplexPair = - CGF.EmitObjCPropertyGet(LHS.getPropertyRefExpr()).getComplexVal(); - else if (LHS.isKVCRef()) - LHSComplexPair = - CGF.EmitObjCPropertyGet(LHS.getKVCRefExpr()).getComplexVal(); - else - LHSComplexPair = EmitLoadOfComplex(LHS.getAddress(), - LHS.isVolatileQualified()); + + // Load from the l-value. + ComplexPairTy LHSComplexPair = EmitLoadOfLValue(LHS); OpInfo.LHS = EmitComplexToComplexCast(LHSComplexPair, LHSTy, OpInfo.Ty); @@ -554,108 +565,107 @@ 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()) - CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), - RValue::getComplex(Result)); - else if (LHS.isKVCRef()) - CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(), RValue::getComplex(Result)); - else - EmitStoreOfComplex(Result, LHS.getAddress(), LHS.isVolatileQualified()); - - // Restore the Ignore* flags. - IgnoreReal = ignreal; - IgnoreImag = ignimag; - IgnoreRealAssign = ignreal; - IgnoreImagAssign = ignimag; - + EmitStoreThroughLValue(Result, LHS); + + 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()) + 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"); - // Emit the RHS. - ComplexPairTy Val = Visit(E->getRHS()); + TestAndClearIgnoreReal(); + TestAndClearIgnoreImag(); + + // Emit the RHS. __block variables need the RHS evaluated first. + Val = Visit(E->getRHS()); // Compute the address to store into. LValue LHS = CGF.EmitLValue(E->getLHS()); // Store the result value into the LHS lvalue. - if (LHS.isPropertyRef()) - CGF.EmitObjCPropertySet(LHS.getPropertyRefExpr(), RValue::getComplex(Val)); - else if (LHS.isKVCRef()) - CGF.EmitObjCPropertySet(LHS.getKVCRefExpr(), RValue::getComplex(Val)); - else - EmitStoreOfComplex(Val, LHS.getAddress(), LHS.isVolatileQualified()); + EmitStoreThroughLValue(Val, LHS); + + return LHS; +} - // Restore the Ignore* flags. - IgnoreReal = ignreal; - IgnoreImag = ignimag; - IgnoreRealAssign = ignreal; - IgnoreImagAssign = ignimag; +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 (LHS.isPropertyRef() || LHS.isKVCRef()) + if (LV.isPropertyRef()) + return Val; + + // If the lvalue is non-volatile, return the computed value of the assignment. + if (!LV.isVolatileQualified()) return Val; - // Otherwise, reload the value. - return EmitLoadOfComplex(LHS.getAddress(), LHS.isVolatileQualified()); + return EmitLoadOfComplex(LV.getAddress(), LV.isVolatileQualified()); } ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) { - CGF.EmitStmt(E->getLHS()); - CGF.EnsureInsertPoint(); + CGF.EmitIgnoredExpr(E->getLHS()); return Visit(E->getRHS()); } ComplexPairTy ComplexExprEmitter:: -VisitConditionalOperator(const ConditionalOperator *E) { - if (!E->getLHS()) { - CGF.ErrorUnsupported(E, "conditional operator with missing LHS"); - const llvm::Type *EltTy = - CGF.ConvertType(E->getType()->getAs<ComplexType>()->getElementType()); - llvm::Value *U = llvm::UndefValue::get(EltTy); - return ComplexPairTy(U, U); - } - +VisitAbstractConditionalOperator(const AbstractConditionalOperator *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"); + // Bind the common expression if necessary. + CodeGenFunction::OpaqueValueMapping binding(CGF, E); + + CodeGenFunction::ConditionalEvaluation eval(CGF); CGF.EmitBranchOnBoolExpr(E->getCond(), LHSBlock, RHSBlock); + eval.begin(CGF); CGF.EmitBlock(LHSBlock); - - // Handle the GNU extension for missing LHS. - assert(E->getLHS() && "Must have LHS for complex value"); - - ComplexPairTy LHS = Visit(E->getLHS()); + ComplexPairTy LHS = Visit(E->getTrueExpr()); LHSBlock = Builder.GetInsertBlock(); CGF.EmitBranch(ContBlock); + eval.end(CGF); + eval.begin(CGF); CGF.EmitBlock(RHSBlock); - - ComplexPairTy RHS = Visit(E->getRHS()); + ComplexPairTy RHS = Visit(E->getFalseExpr()); RHSBlock = Builder.GetInsertBlock(); - CGF.EmitBranch(ContBlock); - CGF.EmitBlock(ContBlock); + eval.end(CGF); // Create a PHI node for the real part. llvm::PHINode *RealPN = Builder.CreatePHI(LHS.first->getType(), "cond.r"); @@ -716,12 +726,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)); } @@ -749,3 +758,27 @@ ComplexPairTy CodeGenFunction::LoadComplexFromAddr(llvm::Value *SrcAddr, bool SrcIsVolatile) { return ComplexExprEmitter(*this).EmitLoadOfComplex(SrcAddr, SrcIsVolatile); } + +LValue CodeGenFunction::EmitComplexAssignmentLValue(const BinaryOperator *E) { + assert(E->getOpcode() == BO_Assign); + ComplexPairTy Val; // ignored + return ComplexExprEmitter(*this).EmitBinAssignLValue(E, Val); +} + +LValue CodeGenFunction:: +EmitComplexCompoundAssignmentLValue(const CompoundAssignOperator *E) { + ComplexPairTy(ComplexExprEmitter::*Op)(const ComplexExprEmitter::BinOpInfo &); + switch (E->getOpcode()) { + case BO_MulAssign: Op = &ComplexExprEmitter::EmitBinMul; break; + case BO_DivAssign: Op = &ComplexExprEmitter::EmitBinDiv; break; + case BO_SubAssign: Op = &ComplexExprEmitter::EmitBinSub; break; + case BO_AddAssign: Op = &ComplexExprEmitter::EmitBinAdd; break; + + default: + llvm_unreachable("unexpected complex compound assignment"); + Op = 0; + } + + ComplexPairTy Val; // ignored + return ComplexExprEmitter(*this).EmitCompoundAssignLValue(E, Op, Val); +} |