[clang] [CIR][NFC] Reorder GenExprComplex and add errors for unhandled visitors (PR #156241)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 31 05:55:08 PDT 2025
https://github.com/AmrDeveloper created https://github.com/llvm/llvm-project/pull/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
>From c07585e37e126919d977730dc969f06b059424dd Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Sun, 31 Aug 2025 14:53:06 +0200
Subject: [PATCH] [CIR][NFC] Reorder GenExprComplex and add errors for
unhandled visitors
---
clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp | 950 ++++++++++--------
...-arithmetic.cpp => complex-plus-minus.cpp} | 0
2 files changed, 519 insertions(+), 431 deletions(-)
rename clang/test/CIR/CodeGen/{complex-arithmetic.cpp => complex-plus-minus.cpp} (100%)
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
More information about the cfe-commits
mailing list