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 <am...@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

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to