@@ -57,6 +57,55 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> {
5757 mlir::Value
5858 VisitSubstNonTypeTemplateParmExpr (SubstNonTypeTemplateParmExpr *e);
5959 mlir::Value VisitUnaryDeref (const Expr *e);
60+
61+ struct BinOpInfo {
62+ mlir::Location loc;
63+ mlir::Value lhs{};
64+ mlir::Value rhs{};
65+ QualType ty{}; // Computation Type.
66+ FPOptions fpFeatures{};
67+ };
68+
69+ BinOpInfo emitBinOps (const BinaryOperator *e,
70+ QualType promotionTy = QualType());
71+
72+ mlir::Value emitPromoted (const Expr *e, QualType promotionTy);
73+
74+ mlir::Value emitPromotedComplexOperand (const Expr *e, QualType promotionTy);
75+
76+ mlir::Value emitBinAdd (const BinOpInfo &op);
77+
78+ QualType getPromotionType (QualType ty, bool isDivOpCode = false ) {
79+ if (auto *complexTy = ty->getAs <ComplexType>()) {
80+ QualType elementTy = complexTy->getElementType ();
81+ if (isDivOpCode && elementTy->isFloatingType () &&
82+ cgf.getLangOpts ().getComplexRange () ==
83+ LangOptions::ComplexRangeKind::CX_Promoted) {
84+ cgf.cgm .errorNYI (" HigherPrecisionTypeForComplexArithmetic" );
85+ return QualType ();
86+ }
87+
88+ if (elementTy.UseExcessPrecision (cgf.getContext ()))
89+ return cgf.getContext ().getComplexType (cgf.getContext ().FloatTy );
90+ }
91+
92+ if (ty.UseExcessPrecision (cgf.getContext ()))
93+ return cgf.getContext ().FloatTy ;
94+ return QualType ();
95+ }
96+
97+ #define HANDLEBINOP (OP ) \
98+ mlir::Value VisitBin##OP(const BinaryOperator *e) { \
99+ QualType promotionTy = getPromotionType ( \
100+ e->getType (), e->getOpcode () == BinaryOperatorKind::BO_Div); \
101+ mlir::Value result = emitBin##OP (emitBinOps (e, promotionTy)); \
102+ if (!promotionTy.isNull ()) \
103+ cgf.cgm .errorNYI (" Binop emitUnPromotedValue" ); \
104+ return result; \
105+ }
106+
107+ HANDLEBINOP (Add)
108+ #undef HANDLEBINOP
60109};
61110} // namespace
62111
@@ -291,6 +340,60 @@ mlir::Value ComplexExprEmitter::VisitUnaryDeref(const Expr *e) {
291340 return emitLoadOfLValue (e);
292341}
293342
343+ mlir::Value ComplexExprEmitter::emitPromoted (const Expr *e,
344+ QualType promotionTy) {
345+ e = e->IgnoreParens ();
346+ if (const auto *bo = dyn_cast<BinaryOperator>(e)) {
347+ switch (bo->getOpcode ()) {
348+ #define HANDLE_BINOP (OP ) \
349+ case BO_##OP: \
350+ return emitBin##OP (emitBinOps (bo, promotionTy));
351+ HANDLE_BINOP (Add)
352+ #undef HANDLE_BINOP
353+ default :
354+ break ;
355+ }
356+ } else if (isa<UnaryOperator>(e)) {
357+ cgf.cgm .errorNYI (" emitPromoted UnaryOperator" );
358+ return {};
359+ }
360+
361+ mlir::Value result = Visit (const_cast <Expr *>(e));
362+ if (!promotionTy.isNull ())
363+ cgf.cgm .errorNYI (" emitPromoted emitPromotedValue" );
364+
365+ return result;
366+ }
367+
368+ mlir::Value
369+ ComplexExprEmitter::emitPromotedComplexOperand (const Expr *e,
370+ QualType promotionTy) {
371+ if (e->getType ()->isAnyComplexType ()) {
372+ if (!promotionTy.isNull ())
373+ return cgf.emitPromotedComplexExpr (e, promotionTy);
374+ return Visit (const_cast <Expr *>(e));
375+ }
376+
377+ cgf.cgm .errorNYI (" emitPromotedComplexOperand non-complex type" );
378+ return {};
379+ }
380+
381+ ComplexExprEmitter::BinOpInfo
382+ ComplexExprEmitter::emitBinOps (const BinaryOperator *e, QualType promotionTy) {
383+ BinOpInfo binOpInfo{cgf.getLoc (e->getExprLoc ())};
384+ binOpInfo.lhs = emitPromotedComplexOperand (e->getLHS (), promotionTy);
385+ binOpInfo.rhs = emitPromotedComplexOperand (e->getRHS (), promotionTy);
386+ binOpInfo.ty = promotionTy.isNull () ? e->getType () : promotionTy;
387+ binOpInfo.fpFeatures = e->getFPFeaturesInEffect (cgf.getLangOpts ());
388+ return binOpInfo;
389+ }
390+
391+ mlir::Value ComplexExprEmitter::emitBinAdd (const BinOpInfo &op) {
392+ assert (!cir::MissingFeatures::fastMathFlags ());
393+ assert (!cir::MissingFeatures::cgFPOptionsRAII ());
394+ return builder.create <cir::ComplexAddOp>(op.loc , op.lhs , op.rhs );
395+ }
396+
294397LValue CIRGenFunction::emitComplexAssignmentLValue (const BinaryOperator *e) {
295398 assert (e->getOpcode () == BO_Assign && " Expected assign op" );
296399
@@ -313,3 +416,8 @@ void CIRGenFunction::emitStoreOfComplex(mlir::Location loc, mlir::Value v,
313416 LValue dest, bool isInit) {
314417 ComplexExprEmitter (*this ).emitStoreOfComplex (loc, v, dest, isInit);
315418}
419+
420+ mlir::Value CIRGenFunction::emitPromotedComplexExpr (const Expr *e,
421+ QualType promotionType) {
422+ return ComplexExprEmitter (*this ).emitPromoted (e, promotionType);
423+ }
0 commit comments