https://github.com/AmrDeveloper updated 
https://github.com/llvm/llvm-project/pull/144868

>From 8fd8deef461d0a818be9b0d4de66b686dc88a9ed Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Thu, 19 Jun 2025 12:28:29 +0200
Subject: [PATCH 1/2] [CIR] Upstream BinAssign for ComplexType

---
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp        |   5 +-
 clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp | 100 +++++++++++++++++++-
 clang/lib/CIR/CodeGen/CIRGenFunction.h      |   2 +
 clang/lib/CIR/CodeGen/CIRGenValue.h         |   4 +-
 clang/test/CIR/CodeGen/complex.cpp          |  26 +++++
 5 files changed, 126 insertions(+), 11 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 4f2046ad26d72..c31754dc11d69 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -997,10 +997,9 @@ LValue CIRGenFunction::emitBinaryOperatorLValue(const 
BinaryOperator *e) {
   }
 
   case cir::TEK_Complex: {
-    assert(!cir::MissingFeatures::complexType());
-    cgm.errorNYI(e->getSourceRange(), "complex l-values");
-    return {};
+    return emitComplexAssignmentLValue(e);
   }
+
   case cir::TEK_Aggregate:
     cgm.errorNYI(e->getSourceRange(), "aggregate lvalues");
     return {};
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index 12e8e27948cf7..bcfe2e3768e7a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -19,6 +19,13 @@ 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.
@@ -27,18 +34,18 @@ class ComplexExprEmitter : public 
StmtVisitor<ComplexExprEmitter, mlir::Value> {
   }
 
   mlir::Value emitLoadOfLValue(LValue lv, SourceLocation loc);
-
   /// Store the specified real/imag parts into the
   /// specified value pointer.
   void emitStoreOfComplex(mlir::Location loc, mlir::Value val, LValue lv,
                           bool isInit);
 
+  mlir::Value VisitBinAssign(const BinaryOperator *e);
   mlir::Value VisitCallExpr(const CallExpr *e);
-  mlir::Value VisitInitListExpr(InitListExpr *e);
-
+  mlir::Value VisitDeclRefExpr(DeclRefExpr *e);
+  mlir::Value VisitImplicitCastExpr(ImplicitCastExpr *e);
+  mlir::Value VisitInitListExpr(const InitListExpr *e);
   mlir::Value VisitImaginaryLiteral(const ImaginaryLiteral *il);
 };
-
 } // namespace
 
 static const ComplexType *getComplexType(QualType type) {
@@ -48,6 +55,48 @@ static const ComplexType *getComplexType(QualType type) {
   return cast<ComplexType>(cast<AtomicType>(type)->getValueType());
 }
 
+LValue ComplexExprEmitter::emitBinAssignLValue(const BinaryOperator *e,
+                                               mlir::Value &value) {
+  assert(cgf.getContext().hasSameUnqualifiedType(e->getLHS()->getType(),
+                                                 e->getRHS()->getType()) &&
+         "Invalid assignment");
+
+  // Emit the RHS.  __block variables need the RHS evaluated first.
+  value = Visit(e->getRHS());
+
+  // Compute the address to store into.
+  LValue lhs = cgf.emitLValue(e->getLHS());
+
+  // Store the result value into the LHS lvalue.
+  emitStoreOfComplex(cgf.getLoc(e->getExprLoc()), value, lhs, /*isInit*/ 
false);
+  return lhs;
+}
+
+mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
+                                         QualType destTy) {
+  switch (ck) {
+  case CK_LValueToRValue: {
+    return Visit(op);
+  }
+  default:
+    cgf.cgm.errorNYI("ComplexType Cast");
+    break;
+  }
+
+  return {};
+}
+
+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::emitLoadOfLValue(LValue lv,
                                                  SourceLocation loc) {
   assert(lv.isSimple() && "non-simple complex l-value?");
@@ -70,6 +119,22 @@ void ComplexExprEmitter::emitStoreOfComplex(mlir::Location 
loc, mlir::Value val,
   builder.createStore(loc, val, destAddr);
 }
 
+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());
+}
+
 mlir::Value ComplexExprEmitter::VisitCallExpr(const CallExpr *e) {
   if (e->getCallReturnType(cgf.getContext())->isReferenceType())
     return emitLoadOfLValue(e);
@@ -77,7 +142,21 @@ mlir::Value ComplexExprEmitter::VisitCallExpr(const 
CallExpr *e) {
   return cgf.emitCallExpr(e).getValue();
 }
 
-mlir::Value ComplexExprEmitter::VisitInitListExpr(InitListExpr *e) {
+mlir::Value ComplexExprEmitter::VisitDeclRefExpr(DeclRefExpr *e) {
+  if (CIRGenFunction::ConstantEmission constant = cgf.tryEmitAsConstant(e))
+    return emitConstant(constant, e);
+  return emitLoadOfLValue(e);
+}
+
+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());
+}
+
+mlir::Value ComplexExprEmitter::VisitInitListExpr(const InitListExpr *e) {
   mlir::Location loc = cgf.getLoc(e->getExprLoc());
   if (e->getNumInits() == 2) {
     mlir::Value real = cgf.emitScalarExpr(e->getInit(0));
@@ -127,6 +206,17 @@ ComplexExprEmitter::VisitImaginaryLiteral(const 
ImaginaryLiteral *il) {
   return builder.create<cir::ConstantOp>(loc, complexAttr);
 }
 
+LValue CIRGenFunction::emitComplexAssignmentLValue(const BinaryOperator *e) {
+  assert(e->getOpcode() == BO_Assign && "Expected assign op");
+
+  mlir::Value value; // ignored
+  LValue lvalue = ComplexExprEmitter(*this).emitBinAssignLValue(e, value);
+  if (getLangOpts().OpenMP)
+    cgm.errorNYI("emitComplexAssignmentLValue OpenMP");
+
+  return lvalue;
+}
+
 mlir::Value CIRGenFunction::emitComplexExpr(const Expr *e) {
   assert(e && getComplexType(e->getType()) &&
          "Invalid complex expression to emit");
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 6c490a72b2e93..82aa7ec9cb220 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -870,6 +870,8 @@ class CIRGenFunction : public CIRGenTypeCache {
   /// returning the result.
   mlir::Value emitComplexExpr(const Expr *e);
 
+  LValue emitComplexAssignmentLValue(const BinaryOperator *e);
+
   void emitCompoundStmt(const clang::CompoundStmt &s);
 
   void emitCompoundStmtWithoutScope(const clang::CompoundStmt &s);
diff --git a/clang/lib/CIR/CodeGen/CIRGenValue.h 
b/clang/lib/CIR/CodeGen/CIRGenValue.h
index 7180d92f8c314..a5a457ddafa9c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenValue.h
+++ b/clang/lib/CIR/CodeGen/CIRGenValue.h
@@ -182,9 +182,7 @@ class LValue {
   bool isSimple() const { return lvType == Simple; }
   bool isVectorElt() const { return lvType == VectorElt; }
   bool isBitField() const { return lvType == BitField; }
-
-  // TODO: Add support for volatile
-  bool isVolatile() const { return false; }
+  bool isVolatile() const { return quals.hasVolatile(); }
 
   unsigned getVRQualifiers() const {
     return quals.getCVRQualifiers() & ~clang::Qualifiers::Const;
diff --git a/clang/test/CIR/CodeGen/complex.cpp 
b/clang/test/CIR/CodeGen/complex.cpp
index 721db235b37de..cfeed345b4f11 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -230,3 +230,29 @@ void foo14() {
 // OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[COMPLEX]], i32 0, i32 1
 // OGCG: store i32 0, ptr %[[C_REAL_PTR]], align 4
 // OGCG: store i32 2, ptr %[[C_IMAG_PTR]], align 4
+
+void foo15() {
+  int _Complex a;
+  int _Complex b = a;
+}
+
+// CIR: %[[COMPLEX_A:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["a"]
+// CIR: %[[COMPLEX_B:.*]] = cir.alloca !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>, ["b", init]
+// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[COMPLEX_A]] : 
!cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CIR: cir.store{{.*}} %[[TMP_A]], %[[COMPLEX_B]] : !cir.complex<!s32i>, 
!cir.ptr<!cir.complex<!s32i>>
+
+// LLVM: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[TMP_A:.*]] = load { i32, i32 }, ptr %[[COMPLEX_A]], align 4
+// LLVM: store { i32, i32 } %[[TMP_A]], ptr %[[COMPLEX_B]], align 4
+
+// OGCG: %[[COMPLEX_A:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[COMPLEX_B:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[COMPLEX_A]], i32 0, i32 0
+// OGCG: %[[A_REAL:.*]] = load i32, ptr %[[A_REAL_PTR]], align 4
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[COMPLEX_A]], i32 0, i32 1
+// OGCG: %[[A_IMAG:.*]] = load i32, ptr %[[A_IMAG_PTR]], align 4
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[COMPLEX_B]], i32 0, i32 0
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr 
%[[COMPLEX_B]], i32 0, i32 1
+// OGCG: store i32 %[[A_REAL]], ptr %[[B_REAL_PTR]], align 4
+// OGCG: store i32 %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 4

>From 3369ee7c58fb7cc3c22ed1f383ef42f74faf3daf Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Fri, 20 Jun 2025 23:59:20 +0200
Subject: [PATCH 2/2] Address code review comment

---
 clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
index bcfe2e3768e7a..eaa199abc1657 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp
@@ -75,14 +75,12 @@ LValue ComplexExprEmitter::emitBinAssignLValue(const 
BinaryOperator *e,
 mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op,
                                          QualType destTy) {
   switch (ck) {
-  case CK_LValueToRValue: {
+  case CK_LValueToRValue:
     return Visit(op);
-  }
   default:
     cgf.cgm.errorNYI("ComplexType Cast");
     break;
   }
-
   return {};
 }
 

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

Reply via email to