Author: Amr Hesham Date: 2025-09-02T18:44:03+02:00 New Revision: 3e5f49af266e3c277a794b724cd6d115a0d5766c
URL: https://github.com/llvm/llvm-project/commit/3e5f49af266e3c277a794b724cd6d115a0d5766c DIFF: https://github.com/llvm/llvm-project/commit/3e5f49af266e3c277a794b724cd6d115a0d5766c.diff LOG: [CIR][NFC] Reorder GenExprComplex and add errors for unhandled visitors (#156241) - Reorder the CIRGenExprComplex functions to be similar to OCG. - Add errors for unhandled visitors. - Rename the test file to be similar to `complex-mul-div`. Issue: https://github.com/llvm/llvm-project/issues/141365 Added: clang/test/CIR/CodeGen/complex-plus-minus.cpp Modified: clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp Removed: clang/test/CIR/CodeGen/complex-arithmetic.cpp ################################################################################ diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index cbdd525068f5d..36ea5d08c2948 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -6,6 +6,16 @@ using namespace clang; using namespace clang::CIRGen; +#ifndef NDEBUG +/// Return the complex type that we are meant to emit. +static const ComplexType *getComplexType(QualType type) { + type = type.getCanonicalType(); + if (const ComplexType *comp = dyn_cast<ComplexType>(type)) + return comp; + return cast<ComplexType>(cast<AtomicType>(type)->getValueType()); +} +#endif // NDEBUG + namespace { class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { CIRGenFunction &cgf; @@ -19,13 +29,6 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { // Utilities //===--------------------------------------------------------------------===// - LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val); - - mlir::Value emitCast(CastKind ck, Expr *op, QualType destTy); - - mlir::Value emitConstant(const CIRGenFunction::ConstantEmission &constant, - Expr *e); - /// 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. @@ -48,20 +51,75 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { mlir::Value emitScalarToComplexCast(mlir::Value value, QualType srcType, QualType destType, SourceLocation loc); + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// + + mlir::Value Visit(Expr *e) { + return StmtVisitor<ComplexExprEmitter, mlir::Value>::Visit(e); + } + + mlir::Value VisitStmt(Stmt *s) { + cgf.cgm.errorNYI(s->getBeginLoc(), "ComplexExprEmitter VisitStmt"); + return {}; + } + + mlir::Value VisitExpr(Expr *e); + mlir::Value VisitConstantExpr(ConstantExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitConstantExpr"); + return {}; + } + + mlir::Value VisitParenExpr(ParenExpr *pe) { return Visit(pe->getSubExpr()); } + mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *ge) { + return Visit(ge->getResultExpr()); + } + mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il); mlir::Value - VisitAbstractConditionalOperator(const AbstractConditionalOperator *e); - mlir::Value VisitArraySubscriptExpr(Expr *e); - mlir::Value VisitBinAssign(const BinaryOperator *e); - mlir::Value VisitBinComma(const BinaryOperator *e); - mlir::Value VisitCallExpr(const CallExpr *e); - mlir::Value VisitCastExpr(CastExpr *e); - mlir::Value VisitChooseExpr(ChooseExpr *e); - mlir::Value VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e); - mlir::Value VisitDeclRefExpr(DeclRefExpr *e); - mlir::Value VisitGenericSelectionExpr(GenericSelectionExpr *e); - mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e); - mlir::Value VisitInitListExpr(InitListExpr *e); + VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *pe) { + return Visit(pe->getReplacement()); + } + mlir::Value VisitCoawaitExpr(CoawaitExpr *s) { + cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoawaitExpr"); + return {}; + } + mlir::Value VisitCoyieldExpr(CoyieldExpr *s) { + cgf.cgm.errorNYI(s->getExprLoc(), "ComplexExprEmitter VisitCoyieldExpr"); + return {}; + } + mlir::Value VisitUnaryCoawait(const UnaryOperator *e) { + cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitUnaryCoawait"); + return {}; + } + + mlir::Value emitConstant(const CIRGenFunction::ConstantEmission &constant, + Expr *e) { + assert(constant && "not a constant"); + if (constant.isReference()) + return emitLoadOfLValue(constant.getReferenceLValue(cgf, e), + e->getExprLoc()); + + mlir::TypedAttr valueAttr = constant.getValue(); + return builder.getConstant(cgf.getLoc(e->getSourceRange()), valueAttr); + } + // l-values. + mlir::Value VisitDeclRefExpr(DeclRefExpr *e) { + if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e)) + return emitConstant(constant, e); + return emitLoadOfLValue(e); + } + mlir::Value VisitObjCIvarRefExpr(ObjCIvarRefExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitObjCIvarRefExpr"); + return {}; + } + mlir::Value VisitObjCMessageExpr(ObjCMessageExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitObjCMessageExpr"); + return {}; + } + mlir::Value VisitArraySubscriptExpr(Expr *e) { return emitLoadOfLValue(e); } mlir::Value VisitMemberExpr(MemberExpr *me) { if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(me)) { cgf.emitIgnoredExpr(me->getBase()); @@ -69,45 +127,99 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { } return emitLoadOfLValue(me); } + mlir::Value VisitOpaqueValueExpr(OpaqueValueExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitOpaqueValueExpr"); + return {}; + } - mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) { - return emitLoadOfLValue(e); + mlir::Value VisitPseudoObjectExpr(PseudoObjectExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitPseudoObjectExpr"); + return {}; } - mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il); - mlir::Value VisitParenExpr(ParenExpr *e); - mlir::Value - VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *e); + mlir::Value emitCast(CastKind ck, Expr *op, QualType destTy); + mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e) { + // Unlike for scalars, we don't have to worry about function->ptr demotion + // here. + if (e->changesVolatileQualification()) + return emitLoadOfLValue(e); + return emitCast(e->getCastKind(), e->getSubExpr(), e->getType()); + } + mlir::Value VisitCastExpr(CastExpr *e) { + if (const auto *ece = dyn_cast<ExplicitCastExpr>(e)) { + // Bind VLAs in the cast type. + if (ece->getType()->isVariablyModifiedType()) { + cgf.cgm.errorNYI(e->getExprLoc(), + "VisitCastExpr Bind VLAs in the cast type"); + return {}; + } + } - mlir::Value VisitPrePostIncDec(const UnaryOperator *e, cir::UnaryOpKind op, - bool isPre); + if (e->changesVolatileQualification()) + return emitLoadOfLValue(e); + + return emitCast(e->getCastKind(), e->getSubExpr(), e->getType()); + } + mlir::Value VisitCallExpr(const CallExpr *e); + mlir::Value VisitStmtExpr(const StmtExpr *e); + // Operators. + mlir::Value VisitPrePostIncDec(const UnaryOperator *e, cir::UnaryOpKind op, + bool isPre) { + LValue lv = cgf.emitLValue(e->getSubExpr()); + return cgf.emitComplexPrePostIncDec(e, lv, op, isPre); + } mlir::Value VisitUnaryPostDec(const UnaryOperator *e) { return VisitPrePostIncDec(e, cir::UnaryOpKind::Dec, false); } - mlir::Value VisitUnaryPostInc(const UnaryOperator *e) { return VisitPrePostIncDec(e, cir::UnaryOpKind::Inc, false); } - mlir::Value VisitUnaryPreDec(const UnaryOperator *e) { return VisitPrePostIncDec(e, cir::UnaryOpKind::Dec, true); } - mlir::Value VisitUnaryPreInc(const UnaryOperator *e) { return VisitPrePostIncDec(e, cir::UnaryOpKind::Inc, true); } - - mlir::Value VisitUnaryDeref(const Expr *e); + mlir::Value VisitUnaryDeref(const Expr *e) { return emitLoadOfLValue(e); } mlir::Value VisitUnaryPlus(const UnaryOperator *e); - + mlir::Value VisitUnaryMinus(const UnaryOperator *e); mlir::Value VisitPlusMinus(const UnaryOperator *e, cir::UnaryOpKind kind, QualType promotionType); - - mlir::Value VisitUnaryMinus(const UnaryOperator *e); - mlir::Value VisitUnaryNot(const UnaryOperator *e); + // LNot,Real,Imag never return complex. + mlir::Value VisitUnaryExtension(const UnaryOperator *e) { + cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitUnaryExtension"); + return {}; + } + mlir::Value VisitCXXDefaultArgExpr(CXXDefaultArgExpr *dae) { + cgf.cgm.errorNYI(dae->getExprLoc(), + "ComplexExprEmitter VisitCXXDefaultArgExpr"); + return {}; + } + mlir::Value VisitCXXDefaultInitExpr(CXXDefaultInitExpr *die) { + cgf.cgm.errorNYI(die->getExprLoc(), + "ComplexExprEmitter VisitCXXDefaultInitExpr"); + return {}; + } + mlir::Value VisitExprWithCleanups(ExprWithCleanups *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitExprWithCleanups"); + return {}; + } + mlir::Value VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) { + mlir::Location loc = cgf.getLoc(e->getExprLoc()); + mlir::Type complexTy = cgf.convertType(e->getType()); + return builder.getNullValue(complexTy, loc); + } + mlir::Value VisitImplicitValueInitExpr(ImplicitValueInitExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitImplicitValueInitExpr"); + return {}; + } struct BinOpInfo { mlir::Location loc; @@ -121,14 +233,11 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { QualType promotionTy = QualType()); mlir::Value emitPromoted(const Expr *e, QualType promotionTy); - mlir::Value emitPromotedComplexOperand(const Expr *e, QualType promotionTy); - LValue emitCompoundAssignLValue( const CompoundAssignOperator *e, mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &), RValue &value); - mlir::Value emitCompoundAssign( const CompoundAssignOperator *e, mlir::Value (ComplexExprEmitter::*func)(const BinOpInfo &)); @@ -166,52 +275,179 @@ class ComplexExprEmitter : public StmtVisitor<ComplexExprEmitter, mlir::Value> { HANDLEBINOP(Div) #undef HANDLEBINOP + mlir::Value VisitCXXRewrittenBinaryOperator(CXXRewrittenBinaryOperator *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitCXXRewrittenBinaryOperator"); + return {}; + } + // Compound assignments. mlir::Value VisitBinAddAssign(const CompoundAssignOperator *e) { return emitCompoundAssign(e, &ComplexExprEmitter::emitBinAdd); } - mlir::Value VisitBinSubAssign(const CompoundAssignOperator *e) { return emitCompoundAssign(e, &ComplexExprEmitter::emitBinSub); } - mlir::Value VisitBinMulAssign(const CompoundAssignOperator *e) { return emitCompoundAssign(e, &ComplexExprEmitter::emitBinMul); } - mlir::Value VisitBinDivAssign(const CompoundAssignOperator *e) { return emitCompoundAssign(e, &ComplexExprEmitter::emitBinDiv); } + // GCC rejects rem/and/or/xor for integer complex. + // Logical and/or always return int, never complex. + + // No comparisons produce a complex result. + + LValue emitBinAssignLValue(const BinaryOperator *e, mlir::Value &val); + mlir::Value VisitBinAssign(const BinaryOperator *e); + mlir::Value VisitBinComma(const BinaryOperator *e); + + mlir::Value + VisitAbstractConditionalOperator(const AbstractConditionalOperator *e); + mlir::Value VisitChooseExpr(ChooseExpr *e); + + mlir::Value VisitInitListExpr(InitListExpr *e); + + mlir::Value VisitCompoundLiteralExpr(CompoundLiteralExpr *e) { + return emitLoadOfLValue(e); + } + mlir::Value VisitVAArgExpr(VAArgExpr *e); + + mlir::Value VisitAtomicExpr(AtomicExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitAtomicExpr"); + return {}; + } + + mlir::Value VisitPackIndexingExpr(PackIndexingExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), + "ComplexExprEmitter VisitPackIndexingExpr"); + return {}; + } }; } // namespace -#ifndef NDEBUG -// Only used in asserts -static const ComplexType *getComplexType(QualType type) { - type = type.getCanonicalType(); - if (const ComplexType *comp = dyn_cast<ComplexType>(type)) - return comp; - return cast<ComplexType>(cast<AtomicType>(type)->getValueType()); +//===----------------------------------------------------------------------===// +// Utilities +//===----------------------------------------------------------------------===// + +/// EmitLoadOfLValue - Given an RValue reference for a complex, emit code to +/// load the real and imaginary pieces, returning them as Real/Imag. +mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv, + SourceLocation loc) { + assert(lv.isSimple() && "non-simple complex l-value?"); + if (lv.getType()->isAtomicType()) + cgf.cgm.errorNYI(loc, "emitLoadOfLValue with Atomic LV"); + + const Address srcAddr = lv.getAddress(); + return builder.createLoad(cgf.getLoc(loc), srcAddr); } -#endif // NDEBUG -LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e, - mlir::Value &value) { - assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(), - e->getRHS()->getType()) && - "Invalid assignment"); +/// EmitStoreOfComplex - Store the specified real/imag parts into the +/// specified value pointer. +void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val, + LValue lv, bool isInit) { + if (lv.getType()->isAtomicType() || + (!isInit && cgf.isLValueSuitableForInlineAtomic(lv))) { + cgf.cgm.errorNYI(loc, "StoreOfComplex with Atomic LV"); + return; + } - // Emit the RHS. __block variables need the RHS evaluated first. - value = Visit(e->getRHS()); + const Address destAddr = lv.getAddress(); + builder.createStore(loc, val, destAddr); +} - // Compute the address to store into. - LValue lhs = cgf.emitLValue(e->getLHS()); +//===----------------------------------------------------------------------===// +// Visitor Methods +//===----------------------------------------------------------------------===// - // Store the result value into the LHS lvalue. - emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs, /*isInit*/ false); - return lhs; +mlir::Value ComplexExprEmitter::VisitExpr(Expr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitExpr"); + return {}; +} + +mlir::Value +ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *il) { + auto ty = mlir::cast<cir::ComplexType>(cgf.convertType(il->getType())); + mlir::Type elementTy = ty.getElementType(); + mlir::Location loc = cgf.getLoc(il->getExprLoc()); + + mlir::TypedAttr realValueAttr; + mlir::TypedAttr imagValueAttr; + + if (mlir::isa<cir::IntType>(elementTy)) { + llvm::APInt imagValue = cast<IntegerLiteral>(il->getSubExpr())->getValue(); + realValueAttr = cir::IntAttr::get(elementTy, 0); + imagValueAttr = cir::IntAttr::get(elementTy, imagValue); + } else { + assert(mlir::isa<cir::FPTypeInterface>(elementTy) && + "Expected complex element type to be floating-point"); + + llvm::APFloat imagValue = + cast<FloatingLiteral>(il->getSubExpr())->getValue(); + realValueAttr = cir::FPAttr::get( + elementTy, llvm::APFloat::getZero(imagValue.getSemantics())); + imagValueAttr = cir::FPAttr::get(elementTy, imagValue); + } + + auto complexAttr = cir::ConstComplexAttr::get(realValueAttr, imagValueAttr); + return builder.create<cir::ConstantOp>(loc, complexAttr); +} + +mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) { + if (e->getCallReturnType(cgf.getContext())->isReferenceType()) + return emitLoadOfLValue(e); + return cgf.emitCallExpr(e).getComplexValue(); +} + +mlir::Value ComplexExprEmitter::VisitStmtExpr(const StmtExpr *e) { + cgf.cgm.errorNYI(e->getExprLoc(), "ComplexExprEmitter VisitExpr"); + return {}; +} + +mlir::Value ComplexExprEmitter::emitComplexToComplexCast(mlir::Value val, + QualType srcType, + QualType destType, + SourceLocation loc) { + if (srcType == destType) + return val; + + // Get the src/dest element type. + QualType srcElemTy = srcType->castAs<ComplexType>()->getElementType(); + QualType destElemTy = destType->castAs<ComplexType>()->getElementType(); + + cir::CastKind castOpKind; + if (srcElemTy->isFloatingType() && destElemTy->isFloatingType()) + castOpKind = cir::CastKind::float_complex; + else if (srcElemTy->isFloatingType() && destElemTy->isIntegerType()) + castOpKind = cir::CastKind::float_complex_to_int_complex; + else if (srcElemTy->isIntegerType() && destElemTy->isFloatingType()) + castOpKind = cir::CastKind::int_complex_to_float_complex; + else if (srcElemTy->isIntegerType() && destElemTy->isIntegerType()) + castOpKind = cir::CastKind::int_complex; + else + llvm_unreachable("unexpected src type or dest type"); + + return builder.createCast(cgf.getLoc(loc), castOpKind, val, + cgf.convertType(destType)); +} + +mlir::Value ComplexExprEmitter::emitScalarToComplexCast(mlir::Value val, + QualType srcType, + QualType destType, + SourceLocation loc) { + cir::CastKind castOpKind; + if (srcType->isFloatingType()) + castOpKind = cir::CastKind::float_to_complex; + else if (srcType->isIntegerType()) + castOpKind = cir::CastKind::int_to_complex; + else + llvm_unreachable("unexpected src type"); + + return builder.createCast(cgf.getLoc(loc), castOpKind, val, + cgf.convertType(destType)); } mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op, @@ -334,6 +570,14 @@ mlir::Value ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *e) { return result; } +mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) { + QualType promotionTy = getPromotionType(e->getSubExpr()->getType()); + mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Minus, promotionTy); + if (!promotionTy.isNull()) + return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType()); + return result; +} + mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e, cir::UnaryOpKind kind, QualType promotionType) { @@ -349,258 +593,149 @@ mlir::Value ComplexExprEmitter::VisitPlusMinus(const UnaryOperator *e, return builder.createUnaryOp(cgf.getLoc(e->getExprLoc()), kind, op); } -mlir::Value ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *e) { - QualType promotionTy = getPromotionType(e->getSubExpr()->getType()); - mlir::Value result = VisitPlusMinus(e, cir::UnaryOpKind::Minus, promotionTy); - if (!promotionTy.isNull()) - return cgf.emitUnPromotedValue(result, e->getSubExpr()->getType()); - return result; +mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) { + mlir::Value op = Visit(e->getSubExpr()); + return builder.createNot(op); } -mlir::Value ComplexExprEmitter::emitConstant( - const CIRGenFunction::ConstantEmission &constant, Expr *e) { - assert(constant && "not a constant"); - if (constant.isReference()) - return emitLoadOfLValue(constant.getReferenceLValue(cgf, e), - e->getExprLoc()); - - mlir::TypedAttr valueAttr = constant.getValue(); - return builder.getConstant(cgf.getLoc(e->getSourceRange()), valueAttr); -} +mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) { + assert(!cir::MissingFeatures::fastMathFlags()); + assert(!cir::MissingFeatures::cgFPOptionsRAII()); -mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv, - SourceLocation loc) { - assert(lv.isSimple() && "non-simple complex l-value?"); - if (lv.getType()->isAtomicType()) - cgf.cgm.errorNYI(loc, "emitLoadOfLValue with Atomic LV"); - - const Address srcAddr = lv.getAddress(); - return builder.createLoad(cgf.getLoc(loc), srcAddr); -} + if (mlir::isa<cir::ComplexType>(op.lhs.getType()) && + mlir::isa<cir::ComplexType>(op.rhs.getType())) + return builder.create<cir::ComplexAddOp>(op.loc, op.lhs, op.rhs); -void ComplexExprEmitter::emitStoreOfComplex(mlir::Location loc, mlir::Value val, - LValue lv, bool isInit) { - if (lv.getType()->isAtomicType() || - (!isInit && cgf.isLValueSuitableForInlineAtomic(lv))) { - cgf.cgm.errorNYI(loc, "StoreOfComplex with Atomic LV"); - return; + if (mlir::isa<cir::ComplexType>(op.lhs.getType())) { + mlir::Value real = builder.createComplexReal(op.loc, op.lhs); + mlir::Value imag = builder.createComplexImag(op.loc, op.lhs); + mlir::Value newReal = builder.createAdd(op.loc, real, op.rhs); + return builder.createComplexCreate(op.loc, newReal, imag); } - const Address destAddr = lv.getAddress(); - builder.createStore(loc, val, destAddr); -} - -mlir::Value ComplexExprEmitter::emitComplexToComplexCast(mlir::Value val, - QualType srcType, - QualType destType, - SourceLocation loc) { - if (srcType == destType) - return val; - - // Get the src/dest element type. - QualType srcElemTy = srcType->castAs<ComplexType>()->getElementType(); - QualType destElemTy = destType->castAs<ComplexType>()->getElementType(); - - cir::CastKind castOpKind; - if (srcElemTy->isFloatingType() && destElemTy->isFloatingType()) - castOpKind = cir::CastKind::float_complex; - else if (srcElemTy->isFloatingType() && destElemTy->isIntegerType()) - castOpKind = cir::CastKind::float_complex_to_int_complex; - else if (srcElemTy->isIntegerType() && destElemTy->isFloatingType()) - castOpKind = cir::CastKind::int_complex_to_float_complex; - else if (srcElemTy->isIntegerType() && destElemTy->isIntegerType()) - castOpKind = cir::CastKind::int_complex; - else - llvm_unreachable("unexpected src type or dest type"); - - return builder.createCast(cgf.getLoc(loc), castOpKind, val, - cgf.convertType(destType)); -} - -mlir::Value ComplexExprEmitter::emitScalarToComplexCast(mlir::Value val, - QualType srcType, - QualType destType, - SourceLocation loc) { - cir::CastKind castOpKind; - if (srcType->isFloatingType()) - castOpKind = cir::CastKind::float_to_complex; - else if (srcType->isIntegerType()) - castOpKind = cir::CastKind::int_to_complex; - else - llvm_unreachable("unexpected src type"); - - return builder.createCast(cgf.getLoc(loc), castOpKind, val, - cgf.convertType(destType)); -} - -mlir::Value ComplexExprEmitter::VisitAbstractConditionalOperator( - const AbstractConditionalOperator *e) { - mlir::Value condValue = Visit(e->getCond()); - mlir::Location loc = cgf.getLoc(e->getSourceRange()); - - return builder - .create<cir::TernaryOp>( - loc, condValue, - /*thenBuilder=*/ - [&](mlir::OpBuilder &b, mlir::Location loc) { - mlir::Value trueValue = Visit(e->getTrueExpr()); - b.create<cir::YieldOp>(loc, trueValue); - }, - /*elseBuilder=*/ - [&](mlir::OpBuilder &b, mlir::Location loc) { - mlir::Value falseValue = Visit(e->getFalseExpr()); - b.create<cir::YieldOp>(loc, falseValue); - }) - .getResult(); -} - -mlir::Value ComplexExprEmitter::VisitArraySubscriptExpr(Expr *e) { - return emitLoadOfLValue(e); -} - -mlir::Value ComplexExprEmitter::VisitBinAssign(const BinaryOperator *e) { - mlir::Value value; - LValue lv = emitBinAssignLValue(e, value); - - // The result of an assignment in C is the assigned r-value. - if (!cgf.getLangOpts().CPlusPlus) - return value; - - // If the lvalue is non-volatile, return the computed value of the - // assignment. - if (!lv.isVolatile()) - return value; - - return emitLoadOfLValue(lv, e->getExprLoc()); + assert(mlir::isa<cir::ComplexType>(op.rhs.getType())); + mlir::Value real = builder.createComplexReal(op.loc, op.rhs); + mlir::Value imag = builder.createComplexImag(op.loc, op.rhs); + mlir::Value newReal = builder.createAdd(op.loc, op.lhs, real); + return builder.createComplexCreate(op.loc, newReal, imag); } -mlir::Value ComplexExprEmitter::VisitBinComma(const BinaryOperator *e) { - cgf.emitIgnoredExpr(e->getLHS()); - return Visit(e->getRHS()); -} +mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) { + assert(!cir::MissingFeatures::fastMathFlags()); + assert(!cir::MissingFeatures::cgFPOptionsRAII()); -mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) { - if (e->getCallReturnType(cgf.getContext())->isReferenceType()) - return emitLoadOfLValue(e); - return cgf.emitCallExpr(e).getComplexValue(); -} + if (mlir::isa<cir::ComplexType>(op.lhs.getType()) && + mlir::isa<cir::ComplexType>(op.rhs.getType())) + return builder.create<cir::ComplexSubOp>(op.loc, op.lhs, op.rhs); -mlir::Value ComplexExprEmitter::VisitCastExpr(CastExpr *e) { - if (const auto *ece = dyn_cast<ExplicitCastExpr>(e)) { - // Bind VLAs in the cast type. - if (ece->getType()->isVariablyModifiedType()) { - cgf.cgm.errorNYI("VisitCastExpr Bind VLAs in the cast type"); - return {}; - } + if (mlir::isa<cir::ComplexType>(op.lhs.getType())) { + mlir::Value real = builder.createComplexReal(op.loc, op.lhs); + mlir::Value imag = builder.createComplexImag(op.loc, op.lhs); + mlir::Value newReal = builder.createSub(op.loc, real, op.rhs); + return builder.createComplexCreate(op.loc, newReal, imag); } - if (e->changesVolatileQualification()) - return emitLoadOfLValue(e); - - return emitCast(e->getCastKind(), e->getSubExpr(), e->getType()); -} - -mlir::Value ComplexExprEmitter::VisitChooseExpr(ChooseExpr *e) { - return Visit(e->getChosenSubExpr()); -} - -mlir::Value -ComplexExprEmitter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *e) { - mlir::Location loc = cgf.getLoc(e->getExprLoc()); - mlir::Type complexTy = cgf.convertType(e->getType()); - return builder.getNullValue(complexTy, loc); -} - -mlir::Value ComplexExprEmitter::VisitDeclRefExpr(DeclRefExpr *e) { - if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e)) - return emitConstant(constant, e); - return emitLoadOfLValue(e); -} - -mlir::Value -ComplexExprEmitter::VisitGenericSelectionExpr(GenericSelectionExpr *e) { - return Visit(e->getResultExpr()); -} - -mlir::Value ComplexExprEmitter::VisitImplicitCastExpr(ImplicitCastExpr *e) { - // Unlike for scalars, we don't have to worry about function->ptr demotion - // here. - if (e->changesVolatileQualification()) - return emitLoadOfLValue(e); - return emitCast(e->getCastKind(), e->getSubExpr(), e->getType()); + assert(mlir::isa<cir::ComplexType>(op.rhs.getType())); + mlir::Value real = builder.createComplexReal(op.loc, op.rhs); + mlir::Value imag = builder.createComplexImag(op.loc, op.rhs); + mlir::Value newReal = builder.createSub(op.loc, op.lhs, real); + return builder.createComplexCreate(op.loc, newReal, imag); } -mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) { - mlir::Location loc = cgf.getLoc(e->getExprLoc()); - if (e->getNumInits() == 2) { - mlir::Value real = cgf.emitScalarExpr(e->getInit(0)); - mlir::Value imag = cgf.emitScalarExpr(e->getInit(1)); - return builder.createComplexCreate(loc, real, imag); +static cir::ComplexRangeKind +getComplexRangeAttr(LangOptions::ComplexRangeKind range) { + switch (range) { + case LangOptions::CX_Full: + return cir::ComplexRangeKind::Full; + case LangOptions::CX_Improved: + return cir::ComplexRangeKind::Improved; + case LangOptions::CX_Promoted: + return cir::ComplexRangeKind::Promoted; + case LangOptions::CX_Basic: + return cir::ComplexRangeKind::Basic; + case LangOptions::CX_None: + // The default value for ComplexRangeKind is Full if no option is selected + return cir::ComplexRangeKind::Full; } - - if (e->getNumInits() == 1) - return Visit(e->getInit(0)); - - assert(e->getNumInits() == 0 && "Unexpected number of inits"); - mlir::Type complexTy = cgf.convertType(e->getType()); - return builder.getNullValue(complexTy, loc); } -mlir::Value -ComplexExprEmitter::VisitImaginaryLiteral(const ImaginaryLiteral *il) { - auto ty = mlir::cast<cir::ComplexType>(cgf.convertType(il->getType())); - mlir::Type elementTy = ty.getElementType(); - mlir::Location loc = cgf.getLoc(il->getExprLoc()); - - mlir::TypedAttr realValueAttr; - mlir::TypedAttr imagValueAttr; +mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo &op) { + assert(!cir::MissingFeatures::fastMathFlags()); + assert(!cir::MissingFeatures::cgFPOptionsRAII()); - if (mlir::isa<cir::IntType>(elementTy)) { - llvm::APInt imagValue = cast<IntegerLiteral>(il->getSubExpr())->getValue(); - realValueAttr = cir::IntAttr::get(elementTy, 0); - imagValueAttr = cir::IntAttr::get(elementTy, imagValue); - } else { - assert(mlir::isa<cir::FPTypeInterface>(elementTy) && - "Expected complex element type to be floating-point"); + if (mlir::isa<cir::ComplexType>(op.lhs.getType()) && + mlir::isa<cir::ComplexType>(op.rhs.getType())) { + cir::ComplexRangeKind rangeKind = + getComplexRangeAttr(op.fpFeatures.getComplexRange()); + return builder.create<cir::ComplexMulOp>(op.loc, op.lhs, op.rhs, rangeKind); + } - llvm::APFloat imagValue = - cast<FloatingLiteral>(il->getSubExpr())->getValue(); - realValueAttr = cir::FPAttr::get( - elementTy, llvm::APFloat::getZero(imagValue.getSemantics())); - imagValueAttr = cir::FPAttr::get(elementTy, imagValue); + if (mlir::isa<cir::ComplexType>(op.lhs.getType())) { + mlir::Value real = builder.createComplexReal(op.loc, op.lhs); + mlir::Value imag = builder.createComplexImag(op.loc, op.lhs); + mlir::Value newReal = builder.createMul(op.loc, real, op.rhs); + mlir::Value newImag = builder.createMul(op.loc, imag, op.rhs); + return builder.createComplexCreate(op.loc, newReal, newImag); } - auto complexAttr = cir::ConstComplexAttr::get(realValueAttr, imagValueAttr); - return builder.create<cir::ConstantOp>(loc, complexAttr); + assert(mlir::isa<cir::ComplexType>(op.rhs.getType())); + mlir::Value real = builder.createComplexReal(op.loc, op.rhs); + mlir::Value imag = builder.createComplexImag(op.loc, op.rhs); + mlir::Value newReal = builder.createMul(op.loc, op.lhs, real); + mlir::Value newImag = builder.createMul(op.loc, op.lhs, imag); + return builder.createComplexCreate(op.loc, newReal, newImag); } -mlir::Value ComplexExprEmitter::VisitParenExpr(ParenExpr *e) { - return Visit(e->getSubExpr()); -} +mlir::Value ComplexExprEmitter::emitBinDiv(const BinOpInfo &op) { + assert(!cir::MissingFeatures::fastMathFlags()); + assert(!cir::MissingFeatures::cgFPOptionsRAII()); -mlir::Value ComplexExprEmitter::VisitSubstNonTypeTemplateParmExpr( - SubstNonTypeTemplateParmExpr *e) { - return Visit(e->getReplacement()); -} + // Handle division between two complex values. In the case of complex integer + // types mixed with scalar integers, the scalar integer type will always be + // promoted to a complex integer value with a zero imaginary component when + // the AST is formed. + if (mlir::isa<cir::ComplexType>(op.lhs.getType()) && + mlir::isa<cir::ComplexType>(op.rhs.getType())) { + cir::ComplexRangeKind rangeKind = + getComplexRangeAttr(op.fpFeatures.getComplexRange()); + return cir::ComplexDivOp::create(builder, op.loc, op.lhs, op.rhs, + rangeKind); + } -mlir::Value ComplexExprEmitter::VisitPrePostIncDec(const UnaryOperator *e, - cir::UnaryOpKind op, - bool isPre) { - LValue lv = cgf.emitLValue(e->getSubExpr()); - return cgf.emitComplexPrePostIncDec(e, lv, op, isPre); -} + // The C99 standard (G.5.1) defines division of a complex value by a real + // value in the following simplified form. + if (mlir::isa<cir::ComplexType>(op.lhs.getType())) { + assert(mlir::cast<cir::ComplexType>(op.lhs.getType()).getElementType() == + op.rhs.getType()); + mlir::Value real = builder.createComplexReal(op.loc, op.lhs); + mlir::Value imag = builder.createComplexImag(op.loc, op.lhs); + mlir::Value newReal = builder.createFDiv(op.loc, real, op.rhs); + mlir::Value newImag = builder.createFDiv(op.loc, imag, op.rhs); + return builder.createComplexCreate(op.loc, newReal, newImag); + } -mlir::Value ComplexExprEmitter::VisitUnaryDeref(const Expr *e) { - return emitLoadOfLValue(e); + assert(mlir::isa<cir::ComplexType>(op.rhs.getType())); + cir::ConstantOp nullValue = builder.getNullValue(op.lhs.getType(), op.loc); + mlir::Value lhs = builder.createComplexCreate(op.loc, op.lhs, nullValue); + cir::ComplexRangeKind rangeKind = + getComplexRangeAttr(op.fpFeatures.getComplexRange()); + return cir::ComplexDivOp::create(builder, op.loc, lhs, op.rhs, rangeKind); } -mlir::Value ComplexExprEmitter::VisitUnaryNot(const UnaryOperator *e) { - mlir::Value op = Visit(e->getSubExpr()); - return builder.createNot(op); +mlir::Value CIRGenFunction::emitUnPromotedValue(mlir::Value result, + QualType unPromotionType) { + assert(!mlir::cast<cir::ComplexType>(result.getType()).isIntegerComplex() && + "integral complex will never be promoted"); + return builder.createCast(cir::CastKind::float_complex, result, + convertType(unPromotionType)); } -mlir::Value ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *e) { - return cgf.emitVAArg(e); +mlir::Value CIRGenFunction::emitPromotedValue(mlir::Value result, + QualType promotionType) { + assert(!mlir::cast<cir::ComplexType>(result.getType()).isIntegerComplex() && + "integral complex will never be promoted"); + return builder.createCast(cir::CastKind::float_complex, result, + convertType(promotionType)); } mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e, @@ -638,6 +773,11 @@ mlir::Value ComplexExprEmitter::emitPromoted(const Expr *e, return result; } +mlir::Value CIRGenFunction::emitPromotedComplexExpr(const Expr *e, + QualType promotionType) { + return ComplexExprEmitter(*this).emitPromoted(e, promotionType); +} + mlir::Value ComplexExprEmitter::emitPromotedComplexOperand(const Expr *e, QualType promotionTy) { @@ -779,128 +919,120 @@ mlir::Value ComplexExprEmitter::emitCompoundAssign( return emitLoadOfLValue(lv, e->getExprLoc()); } -mlir::Value ComplexExprEmitter::emitBinAdd(const BinOpInfo &op) { - assert(!cir::MissingFeatures::fastMathFlags()); - assert(!cir::MissingFeatures::cgFPOptionsRAII()); +LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e, + mlir::Value &value) { + assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(), + e->getRHS()->getType()) && + "Invalid assignment"); - if (mlir::isa<cir::ComplexType>(op.lhs.getType()) && - mlir::isa<cir::ComplexType>(op.rhs.getType())) - return builder.create<cir::ComplexAddOp>(op.loc, op.lhs, op.rhs); + // Emit the RHS. __block variables need the RHS evaluated first. + value = Visit(e->getRHS()); - if (mlir::isa<cir::ComplexType>(op.lhs.getType())) { - mlir::Value real = builder.createComplexReal(op.loc, op.lhs); - mlir::Value imag = builder.createComplexImag(op.loc, op.lhs); - mlir::Value newReal = builder.createAdd(op.loc, real, op.rhs); - return builder.createComplexCreate(op.loc, newReal, imag); - } + // Compute the address to store into. + LValue lhs = cgf.emitLValue(e->getLHS()); - assert(mlir::isa<cir::ComplexType>(op.rhs.getType())); - mlir::Value real = builder.createComplexReal(op.loc, op.rhs); - mlir::Value imag = builder.createComplexImag(op.loc, op.rhs); - mlir::Value newReal = builder.createAdd(op.loc, op.lhs, real); - return builder.createComplexCreate(op.loc, newReal, imag); + // Store the result value into the LHS lvalue. + emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs, + /*isInit*/ false); + return lhs; } -mlir::Value ComplexExprEmitter::emitBinSub(const BinOpInfo &op) { - assert(!cir::MissingFeatures::fastMathFlags()); - assert(!cir::MissingFeatures::cgFPOptionsRAII()); +mlir::Value ComplexExprEmitter::VisitBinAssign(const BinaryOperator *e) { + mlir::Value value; + LValue lv = emitBinAssignLValue(e, value); - if (mlir::isa<cir::ComplexType>(op.lhs.getType()) && - mlir::isa<cir::ComplexType>(op.rhs.getType())) - return builder.create<cir::ComplexSubOp>(op.loc, op.lhs, op.rhs); + // The result of an assignment in C is the assigned r-value. + if (!cgf.getLangOpts().CPlusPlus) + return value; - if (mlir::isa<cir::ComplexType>(op.lhs.getType())) { - mlir::Value real = builder.createComplexReal(op.loc, op.lhs); - mlir::Value imag = builder.createComplexImag(op.loc, op.lhs); - mlir::Value newReal = builder.createSub(op.loc, real, op.rhs); - return builder.createComplexCreate(op.loc, newReal, imag); - } + // If the lvalue is non-volatile, return the computed value of the + // assignment. + if (!lv.isVolatile()) + return value; - assert(mlir::isa<cir::ComplexType>(op.rhs.getType())); - mlir::Value real = builder.createComplexReal(op.loc, op.rhs); - mlir::Value imag = builder.createComplexImag(op.loc, op.rhs); - mlir::Value newReal = builder.createSub(op.loc, op.lhs, real); - return builder.createComplexCreate(op.loc, newReal, imag); + return emitLoadOfLValue(lv, e->getExprLoc()); } -static cir::ComplexRangeKind -getComplexRangeAttr(LangOptions::ComplexRangeKind range) { - switch (range) { - case LangOptions::CX_Full: - return cir::ComplexRangeKind::Full; - case LangOptions::CX_Improved: - return cir::ComplexRangeKind::Improved; - case LangOptions::CX_Promoted: - return cir::ComplexRangeKind::Promoted; - case LangOptions::CX_Basic: - return cir::ComplexRangeKind::Basic; - case LangOptions::CX_None: - // The default value for ComplexRangeKind is Full if no option is selected - return cir::ComplexRangeKind::Full; - } +mlir::Value ComplexExprEmitter::VisitBinComma(const BinaryOperator *e) { + cgf.emitIgnoredExpr(e->getLHS()); + return Visit(e->getRHS()); } -mlir::Value ComplexExprEmitter::emitBinMul(const BinOpInfo &op) { - assert(!cir::MissingFeatures::fastMathFlags()); - assert(!cir::MissingFeatures::cgFPOptionsRAII()); +mlir::Value ComplexExprEmitter::VisitAbstractConditionalOperator( + const AbstractConditionalOperator *e) { + mlir::Value condValue = Visit(e->getCond()); + mlir::Location loc = cgf.getLoc(e->getSourceRange()); - if (mlir::isa<cir::ComplexType>(op.lhs.getType()) && - mlir::isa<cir::ComplexType>(op.rhs.getType())) { - cir::ComplexRangeKind rangeKind = - getComplexRangeAttr(op.fpFeatures.getComplexRange()); - return builder.create<cir::ComplexMulOp>(op.loc, op.lhs, op.rhs, rangeKind); - } + return builder + .create<cir::TernaryOp>( + loc, condValue, + /*thenBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + mlir::Value trueValue = Visit(e->getTrueExpr()); + b.create<cir::YieldOp>(loc, trueValue); + }, + /*elseBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + mlir::Value falseValue = Visit(e->getFalseExpr()); + b.create<cir::YieldOp>(loc, falseValue); + }) + .getResult(); +} - if (mlir::isa<cir::ComplexType>(op.lhs.getType())) { - mlir::Value real = builder.createComplexReal(op.loc, op.lhs); - mlir::Value imag = builder.createComplexImag(op.loc, op.lhs); - mlir::Value newReal = builder.createMul(op.loc, real, op.rhs); - mlir::Value newImag = builder.createMul(op.loc, imag, op.rhs); - return builder.createComplexCreate(op.loc, newReal, newImag); +mlir::Value ComplexExprEmitter::VisitChooseExpr(ChooseExpr *e) { + return Visit(e->getChosenSubExpr()); +} + +mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) { + mlir::Location loc = cgf.getLoc(e->getExprLoc()); + if (e->getNumInits() == 2) { + mlir::Value real = cgf.emitScalarExpr(e->getInit(0)); + mlir::Value imag = cgf.emitScalarExpr(e->getInit(1)); + return builder.createComplexCreate(loc, real, imag); } - assert(mlir::isa<cir::ComplexType>(op.rhs.getType())); - mlir::Value real = builder.createComplexReal(op.loc, op.rhs); - mlir::Value imag = builder.createComplexImag(op.loc, op.rhs); - mlir::Value newReal = builder.createMul(op.loc, op.lhs, real); - mlir::Value newImag = builder.createMul(op.loc, op.lhs, imag); - return builder.createComplexCreate(op.loc, newReal, newImag); + if (e->getNumInits() == 1) + return Visit(e->getInit(0)); + + assert(e->getNumInits() == 0 && "Unexpected number of inits"); + mlir::Type complexTy = cgf.convertType(e->getType()); + return builder.getNullValue(complexTy, loc); } -mlir::Value ComplexExprEmitter::emitBinDiv(const BinOpInfo &op) { - assert(!cir::MissingFeatures::fastMathFlags()); - assert(!cir::MissingFeatures::cgFPOptionsRAII()); +mlir::Value ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *e) { + return cgf.emitVAArg(e); +} - // Handle division between two complex values. In the case of complex integer - // types mixed with scalar integers, the scalar integer type will always be - // promoted to a complex integer value with a zero imaginary component when - // the AST is formed. - if (mlir::isa<cir::ComplexType>(op.lhs.getType()) && - mlir::isa<cir::ComplexType>(op.rhs.getType())) { - cir::ComplexRangeKind rangeKind = - getComplexRangeAttr(op.fpFeatures.getComplexRange()); - return cir::ComplexDivOp::create(builder, op.loc, op.lhs, op.rhs, - rangeKind); - } +//===----------------------------------------------------------------------===// +// Entry Point into this File +//===----------------------------------------------------------------------===// - // The C99 standard (G.5.1) defines division of a complex value by a real - // value in the following simplified form. - if (mlir::isa<cir::ComplexType>(op.lhs.getType())) { - assert(mlir::cast<cir::ComplexType>(op.lhs.getType()).getElementType() == - op.rhs.getType()); - mlir::Value real = builder.createComplexReal(op.loc, op.lhs); - mlir::Value imag = builder.createComplexImag(op.loc, op.lhs); - mlir::Value newReal = builder.createFDiv(op.loc, real, op.rhs); - mlir::Value newImag = builder.createFDiv(op.loc, imag, op.rhs); - return builder.createComplexCreate(op.loc, newReal, newImag); - } +/// EmitComplexExpr - Emit the computation of the specified expression of +/// complex type, ignoring the result. +mlir::Value CIRGenFunction::emitComplexExpr(const Expr *e) { + assert(e && getComplexType(e->getType()) && + "Invalid complex expression to emit"); - assert(mlir::isa<cir::ComplexType>(op.rhs.getType())); - cir::ConstantOp nullValue = builder.getNullValue(op.lhs.getType(), op.loc); - mlir::Value lhs = builder.createComplexCreate(op.loc, op.lhs, nullValue); - cir::ComplexRangeKind rangeKind = - getComplexRangeAttr(op.fpFeatures.getComplexRange()); - return cir::ComplexDivOp::create(builder, op.loc, lhs, op.rhs, rangeKind); + return ComplexExprEmitter(*this).Visit(const_cast<Expr *>(e)); +} + +void CIRGenFunction::emitComplexExprIntoLValue(const Expr *e, LValue dest, + bool isInit) { + assert(e && getComplexType(e->getType()) && + "Invalid complex expression to emit"); + ComplexExprEmitter emitter(*this); + mlir::Value value = emitter.Visit(const_cast<Expr *>(e)); + emitter.emitStoreOfComplex(getLoc(e->getExprLoc()), value, dest, isInit); +} + +/// EmitStoreOfComplex - Store a complex number into the specified l-value. +void CIRGenFunction::emitStoreOfComplex(mlir::Location loc, mlir::Value v, + LValue dest, bool isInit) { + ComplexExprEmitter(*this).emitStoreOfComplex(loc, v, dest, isInit); +} + +mlir::Value CIRGenFunction::emitLoadOfComplex(LValue src, SourceLocation loc) { + return ComplexExprEmitter(*this).emitLoadOfLValue(src, loc); } LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) { @@ -914,13 +1046,6 @@ LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) { return lvalue; } -mlir::Value CIRGenFunction::emitComplexExpr(const Expr *e) { - assert(e && getComplexType(e->getType()) && - "Invalid complex expression to emit"); - - return ComplexExprEmitter(*this).Visit(const_cast<Expr *>(e)); -} - using CompoundFunc = mlir::Value (ComplexExprEmitter::*)(const ComplexExprEmitter::BinOpInfo &); @@ -968,47 +1093,10 @@ mlir::Value CIRGenFunction::emitComplexPrePostIncDec(const UnaryOperator *e, return isPre ? incVal : inVal; } -void CIRGenFunction::emitComplexExprIntoLValue(const Expr *e, LValue dest, - bool isInit) { - assert(e && getComplexType(e->getType()) && - "Invalid complex expression to emit"); - ComplexExprEmitter emitter(*this); - mlir::Value value = emitter.Visit(const_cast<Expr *>(e)); - emitter.emitStoreOfComplex(getLoc(e->getExprLoc()), value, dest, isInit); -} - -mlir::Value CIRGenFunction::emitLoadOfComplex(LValue src, SourceLocation loc) { - return ComplexExprEmitter(*this).emitLoadOfLValue(src, loc); -} - -void CIRGenFunction::emitStoreOfComplex(mlir::Location loc, mlir::Value v, - LValue dest, bool isInit) { - ComplexExprEmitter(*this).emitStoreOfComplex(loc, v, dest, isInit); -} - -mlir::Value CIRGenFunction::emitPromotedComplexExpr(const Expr *e, - QualType promotionType) { - return ComplexExprEmitter(*this).emitPromoted(e, promotionType); -} - -mlir::Value CIRGenFunction::emitPromotedValue(mlir::Value result, - QualType promotionType) { - assert(!mlir::cast<cir::ComplexType>(result.getType()).isIntegerComplex() && - "integral complex will never be promoted"); - return builder.createCast(cir::CastKind::float_complex, result, - convertType(promotionType)); -} - -mlir::Value CIRGenFunction::emitUnPromotedValue(mlir::Value result, - QualType unPromotionType) { - assert(!mlir::cast<cir::ComplexType>(result.getType()).isIntegerComplex() && - "integral complex will never be promoted"); - return builder.createCast(cir::CastKind::float_complex, result, - convertType(unPromotionType)); -} - LValue CIRGenFunction::emitScalarCompoundAssignWithComplex( const CompoundAssignOperator *e, mlir::Value &result) { + // Key Instructions: Don't need to create an atom group here; one will already + // be active through scalar handling code. CompoundFunc op = getComplexOp(e->getOpcode()); RValue value; LValue ret = ComplexExprEmitter(*this).emitCompoundAssignLValue(e, op, value); diff --git a/clang/test/CIR/CodeGen/complex-arithmetic.cpp b/clang/test/CIR/CodeGen/complex-plus-minus.cpp similarity index 100% rename from clang/test/CIR/CodeGen/complex-arithmetic.cpp rename to clang/test/CIR/CodeGen/complex-plus-minus.cpp _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits