@@ -116,6 +116,15 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
116116
117117 mlir::Value emitPromotedComplexOperand (const Expr *e, QualType promotionTy);
118118
119+ LValue emitCompoundAssignLValue (
120+ const CompoundAssignOperator *e,
121+ mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &),
122+ RValue &value);
123+
124+ mlir::Value emitCompoundAssign (
125+ const CompoundAssignOperator *e,
126+ mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &));
127+
119128 mlir::Value emitBinAdd (const BinOpInfo &op);
120129 mlir::Value emitBinSub (const BinOpInfo &op);
121130 mlir::Value emitBinMul (const BinOpInfo &op);
@@ -153,6 +162,15 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
153162 HANDLEBINOP(Sub)
154163 HANDLEBINOP(Mul)
155164#undef HANDLEBINOP
165+
166+ // Compound assignments.
167+ mlir::Value VisitBinAddAssign (const CompoundAssignOperator *e) {
168+ return emitCompoundAssign (e, &ComplexExprEmitter::emitBinAdd);
169+ }
170+
171+ mlir::Value VisitBinSubAssign (const CompoundAssignOperator *e) {
172+ return emitCompoundAssign (e, &ComplexExprEmitter::emitBinSub);
173+ }
156174};
157175} // namespace
158176
@@ -166,6 +184,12 @@ static const ComplexType *getComplexType(QualType type) {
166184}
167185#endif // NDEBUG
168186
187+ static mlir::Value createComplexFromReal (CIRGenBuilderTy &builder,
188+ mlir::Location loc, mlir::Value real) {
189+ mlir::Value imag = builder.getNullValue (real.getType (), loc);
190+ return builder.createComplexCreate (loc, real, imag);
191+ }
192+
169193LValue ComplexExprEmitter::emitBinAssignLValue (const BinaryOperator *e,
170194 mlir::Value &value) {
171195 assert (cgf.getContext ().hasSameUnqualifiedType (e->getLHS ()->getType (),
@@ -602,7 +626,7 @@ mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e,
602626
603627 mlir::Value result = Visit (const_cast <Expr *>(e));
604628 if (!promotionTy.isNull ())
605- cgf.cgm . errorNYI ( " emitPromoted emitPromotedValue " );
629+ return cgf.emitPromotedValue (result, promotionTy );
606630
607631 return result;
608632}
@@ -630,6 +654,104 @@ ComplexExprEmitter::emitBinOps(const BinaryOperator *e, QualType promotionTy) {
630654 return binOpInfo;
631655}
632656
657+ LValue ComplexExprEmitter::emitCompoundAssignLValue (
658+ const CompoundAssignOperator *e,
659+ mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &), RValue &value) {
660+ QualType lhsTy = e->getLHS ()->getType ();
661+ QualType rhsTy = e->getRHS ()->getType ();
662+ SourceLocation exprLoc = e->getExprLoc ();
663+ mlir::Location loc = cgf.getLoc (exprLoc);
664+
665+ if (lhsTy->getAs <AtomicType>()) {
666+ cgf.cgm .errorNYI (" emitCompoundAssignLValue AtmoicType" );
667+ return {};
668+ }
669+
670+ BinOpInfo opInfo{loc};
671+ opInfo.fpFeatures = e->getFPFeaturesInEffect (cgf.getLangOpts ());
672+
673+ assert (!cir::MissingFeatures::cgFPOptionsRAII ());
674+
675+ // Load the RHS and LHS operands.
676+ // __block variables need to have the rhs evaluated first, plus this should
677+ // improve codegen a little.
678+ QualType promotionTypeCR = getPromotionType (e->getComputationResultType ());
679+ opInfo.ty = promotionTypeCR.isNull () ? e->getComputationResultType ()
680+ : promotionTypeCR;
681+
682+ QualType complexElementTy =
683+ opInfo.ty ->castAs <ComplexType>()->getElementType ();
684+ QualType promotionTypeRHS = getPromotionType (rhsTy);
685+
686+ // The RHS should have been converted to the computation type.
687+ if (e->getRHS ()->getType ()->isRealFloatingType ()) {
688+ if (!promotionTypeRHS.isNull ()) {
689+ opInfo.rhs = createComplexFromReal (
690+ cgf.getBuilder (), loc,
691+ cgf.emitPromotedScalarExpr (e->getRHS (), promotionTypeRHS));
692+ } else {
693+ assert (cgf.getContext ().hasSameUnqualifiedType (complexElementTy, rhsTy));
694+ opInfo.rhs = createComplexFromReal (cgf.getBuilder (), loc,
695+ cgf.emitScalarExpr (e->getRHS ()));
696+ }
697+ } else {
698+ if (!promotionTypeRHS.isNull ()) {
699+ opInfo.rhs = cgf.emitPromotedComplexExpr (e->getRHS (), promotionTypeRHS);
700+ } else {
701+ assert (cgf.getContext ().hasSameUnqualifiedType (opInfo.ty , rhsTy));
702+ opInfo.rhs = Visit (e->getRHS ());
703+ }
704+ }
705+
706+ LValue lhs = cgf.emitLValue (e->getLHS ());
707+
708+ // Load from the l-value and convert it.
709+ QualType promotionTypeLHS = getPromotionType (e->getComputationLHSType ());
710+ if (lhsTy->isAnyComplexType ()) {
711+ mlir::Value lhsValue = emitLoadOfLValue (lhs, exprLoc);
712+ QualType destTy = promotionTypeLHS.isNull () ? opInfo.ty : promotionTypeLHS;
713+ opInfo.lhs = emitComplexToComplexCast (lhsValue, lhsTy, destTy, exprLoc);
714+ } else {
715+ cgf.cgm .errorNYI (" emitCompoundAssignLValue emitLoadOfScalar" );
716+ return {};
717+ }
718+
719+ // Expand the binary operator.
720+ mlir::Value result = (this ->*func)(opInfo);
721+
722+ // Truncate the result and store it into the LHS lvalue.
723+ if (lhsTy->isAnyComplexType ()) {
724+ mlir::Value resultValue =
725+ emitComplexToComplexCast (result, opInfo.ty , lhsTy, exprLoc);
726+ emitStoreOfComplex (loc, resultValue, lhs, /* isInit*/ false );
727+ value = RValue::getComplex (resultValue);
728+ } else {
729+ mlir::Value resultValue =
730+ cgf.emitComplexToScalarConversion (result, opInfo.ty , lhsTy, exprLoc);
731+ cgf.emitStoreOfScalar (resultValue, lhs, /* isInit*/ false );
732+ value = RValue::get (resultValue);
733+ }
734+
735+ return lhs;
736+ }
737+
738+ mlir::Value ComplexExprEmitter::emitCompoundAssign (
739+ const CompoundAssignOperator *e,
740+ mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &)) {
741+ RValue val;
742+ LValue lv = emitCompoundAssignLValue (e, func, val);
743+
744+ // The result of an assignment in C is the assigned r-value.
745+ if (!cgf.getLangOpts ().CPlusPlus )
746+ return val.getComplexValue ();
747+
748+ // If the lvalue is non-volatile, return the computed value of the assignment.
749+ if (!lv.isVolatileQualified ())
750+ return val.getComplexValue ();
751+
752+ return emitLoadOfLValue (lv, e->getExprLoc ());
753+ }
754+
633755mlir::Value ComplexExprEmitter::emitBinAdd (const BinOpInfo &op) {
634756 assert (!cir::MissingFeatures::fastMathFlags ());
635757 assert (!cir::MissingFeatures::cgFPOptionsRAII ());
@@ -685,6 +807,31 @@ mlir::Value CIRGenFunction::emitComplexExpr(const Expr *e) {
685807 return ComplexExprEmitter (*this ).Visit (const_cast <Expr *>(e));
686808}
687809
810+ using CompoundFunc =
811+ mlir::Value (ComplexExprEmitter::*)(const ComplexExprEmitter::BinOpInfo &);
812+
813+ static CompoundFunc getComplexOp (BinaryOperatorKind op) {
814+ switch (op) {
815+ case BO_MulAssign:
816+ llvm_unreachable (" getComplexOp: BO_MulAssign" );
817+ case BO_DivAssign:
818+ llvm_unreachable (" getComplexOp: BO_DivAssign" );
819+ case BO_SubAssign:
820+ return &ComplexExprEmitter::emitBinSub;
821+ case BO_AddAssign:
822+ return &ComplexExprEmitter::emitBinAdd;
823+ default :
824+ llvm_unreachable (" unexpected complex compound assignment" );
825+ }
826+ }
827+
828+ LValue CIRGenFunction::emitComplexCompoundAssignmentLValue (
829+ const CompoundAssignOperator *e) {
830+ CompoundFunc op = getComplexOp (e->getOpcode ());
831+ RValue val;
832+ return ComplexExprEmitter (*this ).emitCompoundAssignLValue (e, op, val);
833+ }
834+
688835mlir::Value CIRGenFunction::emitComplexPrePostIncDec (const UnaryOperator *e,
689836 LValue lv,
690837 cir::UnaryOpKind op,
@@ -729,3 +876,11 @@ mlir::Value CIRGenFunction::emitPromotedComplexExpr(const Expr *e,
729876 QualType promotionType) {
730877 return ComplexExprEmitter (*this ).emitPromoted (e, promotionType);
731878}
879+
880+ mlir::Value CIRGenFunction::emitPromotedValue (mlir::Value result,
881+ QualType promotionType) {
882+ assert (!mlir::cast<cir::ComplexType>(result.getType ()).isIntegerComplex () &&
883+ " integral complex will never be promoted" );
884+ return builder.createCast (cir::CastKind::float_complex, result,
885+ convertType (promotionType));
886+ }
0 commit comments