summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGExprComplex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGExprComplex.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprComplex.cpp130
1 files changed, 108 insertions, 22 deletions
diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp
index 618e446bf1c..6f8dc2c8393 100644
--- a/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/clang/lib/CodeGen/CGExprComplex.cpp
@@ -33,8 +33,17 @@ class VISIBILITY_HIDDEN ComplexExprEmitter
: public StmtVisitor<ComplexExprEmitter, ComplexPairTy> {
CodeGenFunction &CGF;
CGBuilderTy &Builder;
+ // 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) : CGF(cgf), Builder(CGF.Builder) {
+ 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) {
}
@@ -42,6 +51,27 @@ public:
// Utilities
//===--------------------------------------------------------------------===//
+ bool TestAndClearIgnoreReal() {
+ bool I = IgnoreReal;
+ IgnoreReal = false;
+ return I;
+ }
+ bool TestAndClearIgnoreImag() {
+ bool I = IgnoreImag;
+ 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.
@@ -111,6 +141,10 @@ public:
}
ComplexPairTy VisitUnaryDeref(const Expr *E) { return EmitLoadOfLValue(E); }
ComplexPairTy VisitUnaryPlus (const UnaryOperator *E) {
+ TestAndClearIgnoreReal();
+ TestAndClearIgnoreImag();
+ TestAndClearIgnoreRealAssign();
+ TestAndClearIgnoreImagAssign();
return Visit(E->getSubExpr());
}
ComplexPairTy VisitUnaryMinus (const UnaryOperator *E);
@@ -206,19 +240,25 @@ ComplexPairTy ComplexExprEmitter::EmitLoadOfComplex(llvm::Value *SrcPtr,
llvm::SmallString<64> Name(SrcPtr->getNameStart(),
SrcPtr->getNameStart()+SrcPtr->getNameLen());
- Name += ".realp";
- llvm::Value *RealPtr = Builder.CreateStructGEP(SrcPtr, 0, Name.c_str());
+ llvm::Value *Real=0, *Imag=0;
- Name.pop_back(); // .realp -> .real
- llvm::Value *Real = Builder.CreateLoad(RealPtr, isVolatile, Name.c_str());
+ if (!IgnoreReal) {
+ Name += ".realp";
+ llvm::Value *RealPtr = Builder.CreateStructGEP(SrcPtr, 0, Name.c_str());
+
+ Name.pop_back(); // .realp -> .real
+ Real = Builder.CreateLoad(RealPtr, isVolatile, Name.c_str());
+ Name.resize(Name.size()-4); // .real -> .imagp
+ }
- Name.resize(Name.size()-4); // .real -> .imagp
- Name += "imagp";
+ if (!IgnoreImag) {
+ Name += "imagp";
- llvm::Value *ImagPtr = Builder.CreateStructGEP(SrcPtr, 1, Name.c_str());
+ llvm::Value *ImagPtr = Builder.CreateStructGEP(SrcPtr, 1, Name.c_str());
- Name.pop_back(); // .imagp -> .imag
- llvm::Value *Imag = Builder.CreateLoad(ImagPtr, isVolatile, Name.c_str());
+ Name.pop_back(); // .imagp -> .imag
+ Imag = Builder.CreateLoad(ImagPtr, isVolatile, Name.c_str());
+ }
return ComplexPairTy(Real, Imag);
}
@@ -331,6 +371,10 @@ ComplexPairTy ComplexExprEmitter::VisitPrePostIncDec(const UnaryOperator *E,
}
ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E) {
+ TestAndClearIgnoreReal();
+ TestAndClearIgnoreImag();
+ TestAndClearIgnoreRealAssign();
+ TestAndClearIgnoreImagAssign();
ComplexPairTy Op = Visit(E->getSubExpr());
llvm::Value *ResR = Builder.CreateNeg(Op.first, "neg.r");
llvm::Value *ResI = Builder.CreateNeg(Op.second, "neg.i");
@@ -338,6 +382,10 @@ 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 = Builder.CreateNeg(Op.second, "conj.i");
@@ -404,6 +452,10 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
ComplexExprEmitter::BinOpInfo
ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) {
+ TestAndClearIgnoreReal();
+ TestAndClearIgnoreImag();
+ TestAndClearIgnoreRealAssign();
+ TestAndClearIgnoreImagAssign();
BinOpInfo Ops;
Ops.LHS = Visit(E->getLHS());
Ops.RHS = Visit(E->getRHS());
@@ -416,21 +468,28 @@ ComplexExprEmitter::EmitBinOps(const BinaryOperator *E) {
ComplexPairTy ComplexExprEmitter::
EmitCompoundAssign(const CompoundAssignOperator *E,
ComplexPairTy (ComplexExprEmitter::*Func)(const BinOpInfo&)){
+ TestAndClearIgnoreReal();
+ TestAndClearIgnoreImag();
+ bool ignreal = TestAndClearIgnoreRealAssign();
+ bool ignimag = TestAndClearIgnoreImagAssign();
QualType LHSTy = E->getLHS()->getType(), RHSTy = E->getRHS()->getType();
-
- // Load the LHS and RHS operands.
- LValue LHSLV = CGF.EmitLValue(E->getLHS());
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.
OpInfo.Ty = E->getComputationResultType();
+ OpInfo.RHS = EmitCast(E->getRHS(), OpInfo.Ty);
+
+ LValue LHSLV = CGF.EmitLValue(E->getLHS());
+
// We know the LHS is a complex lvalue.
- OpInfo.LHS = EmitLoadOfComplex(LHSLV.getAddress(), LHSLV.isVolatileQualified());
- OpInfo.LHS = EmitComplexToComplexCast(OpInfo.LHS, LHSTy, OpInfo.Ty);
+ OpInfo.LHS=EmitLoadOfComplex(LHSLV.getAddress(),LHSLV.isVolatileQualified());
+ OpInfo.LHS=EmitComplexToComplexCast(OpInfo.LHS, LHSTy, OpInfo.Ty);
- // It is possible for the RHS to be complex or scalar.
- OpInfo.RHS = EmitCast(E->getRHS(), OpInfo.Ty);
-
// Expand the binary operator.
ComplexPairTy Result = (this->*Func)(OpInfo);
@@ -439,10 +498,19 @@ EmitCompoundAssign(const CompoundAssignOperator *E,
// Store the result value into the LHS lvalue.
EmitStoreOfComplex(Result, LHSLV.getAddress(), LHSLV.isVolatileQualified());
- return Result;
+ // And now return the LHS
+ IgnoreReal = ignreal;
+ IgnoreImag = ignimag;
+ IgnoreRealAssign = ignreal;
+ IgnoreImagAssign = ignimag;
+ return EmitLoadOfComplex(LHSLV.getAddress(), LHSLV.isVolatileQualified());
}
ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
+ TestAndClearIgnoreReal();
+ TestAndClearIgnoreImag();
+ bool ignreal = TestAndClearIgnoreRealAssign();
+ bool ignimag = TestAndClearIgnoreImagAssign();
assert(CGF.getContext().getCanonicalType(E->getLHS()->getType()) ==
CGF.getContext().getCanonicalType(E->getRHS()->getType()) &&
"Invalid assignment");
@@ -454,7 +522,12 @@ ComplexPairTy ComplexExprEmitter::VisitBinAssign(const BinaryOperator *E) {
// Store into it.
EmitStoreOfComplex(Val, LHS.getAddress(), LHS.isVolatileQualified());
- return Val;
+ // And now return the LHS
+ IgnoreReal = ignreal;
+ IgnoreImag = ignimag;
+ IgnoreRealAssign = ignreal;
+ IgnoreImagAssign = ignimag;
+ return EmitLoadOfComplex(LHS.getAddress(), LHS.isVolatileQualified());
}
ComplexPairTy ComplexExprEmitter::VisitBinComma(const BinaryOperator *E) {
@@ -465,6 +538,10 @@ 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");
@@ -509,6 +586,12 @@ ComplexPairTy ComplexExprEmitter::VisitChooseExpr(ChooseExpr *E) {
}
ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
+ bool Ignore = TestAndClearIgnoreReal();
+ (void)Ignore;
+ assert (Ignore == false && "init list ignored");
+ Ignore = TestAndClearIgnoreImag();
+ (void)Ignore;
+ assert (Ignore == false && "init list ignored");
if (E->getNumInits())
return Visit(E->getInit(0));
@@ -541,11 +624,14 @@ 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) {
+ComplexPairTy CodeGenFunction::EmitComplexExpr(const Expr *E, bool IgnoreReal,
+ bool IgnoreImag, bool IgnoreRealAssign, bool IgnoreImagAssign) {
assert(E && E->getType()->isAnyComplexType() &&
"Invalid complex expression to emit");
- return ComplexExprEmitter(*this).Visit(const_cast<Expr*>(E));
+ return ComplexExprEmitter(*this, IgnoreReal, IgnoreImag, IgnoreRealAssign,
+ IgnoreImagAssign)
+ .Visit(const_cast<Expr*>(E));
}
/// EmitComplexExprIntoAddr - Emit the computation of the specified expression
OpenPOWER on IntegriCloud