diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 90 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 1 |
3 files changed, 82 insertions, 11 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 085113edf5..76ad40b2fc 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -478,6 +478,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) { return EmitObjCIsaExpr(cast<ObjCIsaExpr>(E)); case Expr::BinaryOperatorClass: return EmitBinaryOperatorLValue(cast<BinaryOperator>(E)); + case Expr::CompoundAssignOperatorClass: + return EmitCompoundAssignOperatorLValue(cast<CompoundAssignOperator>(E)); case Expr::CallExprClass: case Expr::CXXMemberCallExprClass: case Expr::CXXOperatorCallExprClass: diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index d1c0f8dc3d..e1e22cef56 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -314,6 +314,10 @@ public: } BinOpInfo EmitBinOps(const BinaryOperator *E); + LValue EmitCompoundAssignLValue(const CompoundAssignOperator *E, + Value *(ScalarExprEmitter::*F)(const BinOpInfo &), + Value *&BitFieldResult); + Value *EmitCompoundAssign(const CompoundAssignOperator *E, Value *(ScalarExprEmitter::*F)(const BinOpInfo &)); @@ -1103,22 +1107,24 @@ BinOpInfo ScalarExprEmitter::EmitBinOps(const BinaryOperator *E) { return Result; } -Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, - Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) { - bool Ignore = TestAndClearIgnoreResultAssign(); +LValue ScalarExprEmitter::EmitCompoundAssignLValue( + const CompoundAssignOperator *E, + Value *(ScalarExprEmitter::*Func)(const BinOpInfo &), + Value *&BitFieldResult) { QualType LHSTy = E->getLHS()->getType(); - + BitFieldResult = 0; BinOpInfo OpInfo; - + if (E->getComputationResultType()->isAnyComplexType()) { // This needs to go through the complex expression emitter, but it's a tad // complicated to do that... I'm leaving it out for now. (Note that we do // actually need the imaginary part of the RHS for multiplication and // division.) CGF.ErrorUnsupported(E, "complex compound assignment"); - return llvm::UndefValue::get(CGF.ConvertType(E->getType())); + llvm::UndefValue::get(CGF.ConvertType(E->getType())); + return LValue(); } - + // Emit the RHS first. __block variables need to have the rhs evaluated // first, plus this should improve codegen a little. OpInfo.RHS = Visit(E->getRHS()); @@ -1129,13 +1135,13 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, OpInfo.LHS = EmitLoadOfLValue(LHSLV, LHSTy); OpInfo.LHS = EmitScalarConversion(OpInfo.LHS, LHSTy, E->getComputationLHSType()); - + // Expand the binary operator. Value *Result = (this->*Func)(OpInfo); - + // Convert the result back to the LHS type. Result = EmitScalarConversion(Result, E->getComputationResultType(), LHSTy); - + // Store the result value into the LHS lvalue. Bit-fields are handled // specially because the result is altered by the store, i.e., [C99 6.5.16p1] // 'An assignment expression has the value of the left operand after the @@ -1144,11 +1150,23 @@ Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, if (!LHSLV.isVolatileQualified()) { CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, LHSTy, &Result); - return Result; + BitFieldResult = Result; + return LHSLV; } else CGF.EmitStoreThroughBitfieldLValue(RValue::get(Result), LHSLV, LHSTy); } else CGF.EmitStoreThroughLValue(RValue::get(Result), LHSLV, LHSTy); + return LHSLV; +} + +Value *ScalarExprEmitter::EmitCompoundAssign(const CompoundAssignOperator *E, + Value *(ScalarExprEmitter::*Func)(const BinOpInfo &)) { + bool Ignore = TestAndClearIgnoreResultAssign(); + Value *BitFieldResult; + LValue LHSLV = EmitCompoundAssignLValue(E, Func, BitFieldResult); + if (BitFieldResult) + return BitFieldResult; + if (Ignore) return 0; return EmitLoadOfLValue(LHSLV, E->getType()); @@ -1914,3 +1932,53 @@ LValue CodeGenFunction::EmitObjCIsaExpr(const ObjCIsaExpr *E) { return LV; } + +LValue CodeGenFunction::EmitCompoundAssignOperatorLValue( + const CompoundAssignOperator *E) { + ScalarExprEmitter Scalar(*this); + Value *BitFieldResult = 0; + switch (E->getOpcode()) { +#define COMPOUND_OP(Op) \ + case BinaryOperator::Op##Assign: \ + return Scalar.EmitCompoundAssignLValue(E, &ScalarExprEmitter::Emit##Op, \ + BitFieldResult) + COMPOUND_OP(Mul); + COMPOUND_OP(Div); + COMPOUND_OP(Rem); + COMPOUND_OP(Add); + COMPOUND_OP(Sub); + COMPOUND_OP(Shl); + COMPOUND_OP(Shr); + COMPOUND_OP(And); + COMPOUND_OP(Xor); + COMPOUND_OP(Or); +#undef COMPOUND_OP + + case BinaryOperator::PtrMemD: + case BinaryOperator::PtrMemI: + case BinaryOperator::Mul: + case BinaryOperator::Div: + case BinaryOperator::Rem: + case BinaryOperator::Add: + case BinaryOperator::Sub: + case BinaryOperator::Shl: + case BinaryOperator::Shr: + case BinaryOperator::LT: + case BinaryOperator::GT: + case BinaryOperator::LE: + case BinaryOperator::GE: + case BinaryOperator::EQ: + case BinaryOperator::NE: + case BinaryOperator::And: + case BinaryOperator::Xor: + case BinaryOperator::Or: + case BinaryOperator::LAnd: + case BinaryOperator::LOr: + case BinaryOperator::Assign: + case BinaryOperator::Comma: + assert(false && "Not valid compound assignment operators"); + break; + } + + llvm_unreachable("Unhandled compound assignment operator"); +} diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 302f9abd23..b421a38371 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -1043,6 +1043,7 @@ public: // Note: only availabe for agg return types LValue EmitBinaryOperatorLValue(const BinaryOperator *E); + LValue EmitCompoundAssignOperatorLValue(const CompoundAssignOperator *E); // Note: only available for agg return types LValue EmitCallExprLValue(const CallExpr *E); // Note: only available for agg return types |