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

>From 8fc31d0c3e1797fa6887ac8831c2e0eaadfb64fa Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Sat, 12 Jul 2025 00:56:36 +0200
Subject: [PATCH 1/2] [CIR] Upstream ComplexImagPtrOp for ComplexType

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td  | 30 +++++++++++++++++++
 clang/lib/CIR/CodeGen/CIRGenBuilder.h         | 15 ++++++++++
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp          | 10 +++----
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       | 21 +++++++++++--
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 18 +++++++++++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   | 10 +++++++
 clang/test/CIR/CodeGen/complex.cpp            | 14 +++++++++
 7 files changed, 110 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 99fcb322a42d5..aac803247bc22 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2642,6 +2642,36 @@ def ComplexRealPtrOp : CIR_Op<"complex.real_ptr", 
[Pure]> {
   let hasVerifier = 1;
 }
 
+//===----------------------------------------------------------------------===//
+// ComplexImagPtrOp
+//===----------------------------------------------------------------------===//
+
+def ComplexImagPtrOp : CIR_Op<"complex.imag_ptr", [Pure]> {
+  let summary = "Derive a pointer to the imaginary part of a complex value";
+  let description = [{
+    `cir.complex.imag_ptr` operation takes a pointer operand that points to a
+    complex value of type `!cir.complex` and yields a pointer to the imaginary
+    part of the operand.
+
+    Example:
+
+    ```mlir
+    %1 = cir.complex.imag_ptr %0 : !cir.ptr<!cir.complex<!cir.double>>
+      -> !cir.ptr<!cir.double>
+    ```
+  }];
+
+  let results = (outs CIR_PtrToIntOrFloatType:$result);
+  let arguments = (ins CIR_PtrToComplexType:$operand);
+
+  let assemblyFormat = [{
+    $operand `:`
+    qualified(type($operand)) `->` qualified(type($result)) attr-dict
+  }];
+
+  let hasVerifier = 1;
+}
+
 
//===----------------------------------------------------------------------===//
 // ComplexAddOp
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h 
b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index d0b6b6918f0e2..5bd53ebc52ab5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -378,6 +378,21 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
                    addr.getAlignment()};
   }
 
+  /// Create a cir.complex.imag_ptr operation that derives a pointer to the
+  /// imaginary part of the complex value pointed to by the specified pointer
+  /// value.
+  mlir::Value createComplexImagPtr(mlir::Location loc, mlir::Value value) {
+    auto srcPtrTy = mlir::cast<cir::PointerType>(value.getType());
+    auto srcComplexTy = mlir::cast<cir::ComplexType>(srcPtrTy.getPointee());
+    return create<cir::ComplexImagPtrOp>(
+        loc, getPointerTo(srcComplexTy.getElementType()), value);
+  }
+
+  Address createComplexImagPtr(mlir::Location loc, Address addr) {
+    return Address{createComplexImagPtr(loc, addr.getPointer()),
+                   addr.getAlignment()};
+  }
+
   /// Create a cir.ptr_stride operation to get access to an array element.
   /// \p idx is the index of the element to access, \p shouldDecay is true if
   /// the result should decay to a pointer to the element type.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index b1d6b8047a0ab..51da48d330f55 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -637,11 +637,6 @@ LValue CIRGenFunction::emitUnaryOpLValue(const 
UnaryOperator *e) {
   }
   case UO_Real:
   case UO_Imag: {
-    if (op == UO_Imag) {
-      cgm.errorNYI(e->getSourceRange(), "UnaryOp real/imag");
-      return LValue();
-    }
-
     LValue lv = emitLValue(e->getSubExpr());
     assert(lv.isSimple() && "real/imag on non-ordinary l-value");
 
@@ -656,7 +651,10 @@ LValue CIRGenFunction::emitUnaryOpLValue(const 
UnaryOperator *e) {
     QualType exprTy = 
getContext().getCanonicalType(e->getSubExpr()->getType());
     QualType elemTy = exprTy->castAs<clang::ComplexType>()->getElementType();
     mlir::Location loc = getLoc(e->getExprLoc());
-    Address component = builder.createComplexRealPtr(loc, lv.getAddress());
+    Address component =
+        e->getOpcode() == UO_Real
+            ? builder.createComplexRealPtr(loc, lv.getAddress())
+            : builder.createComplexImagPtr(loc, lv.getAddress());
     assert(!cir::MissingFeatures::opTBAA());
     LValue elemLV = makeAddrLValue(component, elemTy);
     elemLV.getQuals().addQualifiers(lv.getQuals());
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 5fe5ac827fff9..f0416b6aba6e4 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -21,6 +21,7 @@
 #include "clang/CIR/Dialect/IR/CIROpsDialect.cpp.inc"
 #include "clang/CIR/Dialect/IR/CIROpsEnums.cpp.inc"
 #include "clang/CIR/MissingFeatures.h"
+#include "llvm/Support/LogicalResult.h"
 
 #include <numeric>
 
@@ -2108,13 +2109,29 @@ LogicalResult cir::ComplexRealPtrOp::verify() {
       mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
 
   if (resultPointeeTy != operandPointeeTy.getElementType()) {
-    emitOpError() << ": result type does not match operand type";
-    return failure();
+    return emitOpError() << ": result type does not match operand type";
   }
 
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// ComplexImagPtrOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult cir::ComplexImagPtrOp::verify() {
+  mlir::Type resultPointeeTy = getType().getPointee();
+  cir::PointerType operandPtrTy = getOperand().getType();
+  auto operandPointeeTy =
+      mlir::cast<cir::ComplexType>(operandPtrTy.getPointee());
+
+  if (resultPointeeTy != operandPointeeTy.getElementType()) {
+    return emitOpError()
+           << "cir.complex.imag_ptr result type does not match operand type";
+  }
+  return success();
+}
+
 
//===----------------------------------------------------------------------===//
 // TableGen'd op method definitions
 
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 3446265769a2c..338dbbcc2be36 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2051,6 +2051,7 @@ void ConvertCIRToLLVMPass::runOnOperation() {
                CIRToLLVMComplexAddOpLowering,
                CIRToLLVMComplexCreateOpLowering,
                CIRToLLVMComplexImagOpLowering,
+               CIRToLLVMComplexImagPtrOpLowering,
                CIRToLLVMComplexRealOpLowering,
                CIRToLLVMComplexRealPtrOpLowering,
                CIRToLLVMConstantOpLowering,
@@ -2527,6 +2528,23 @@ mlir::LogicalResult 
CIRToLLVMSetBitfieldOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMComplexImagPtrOpLowering::matchAndRewrite(
+    cir::ComplexImagPtrOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  cir::PointerType operandTy = op.getOperand().getType();
+  mlir::Type resultLLVMTy = getTypeConverter()->convertType(op.getType());
+  mlir::Type elementLLVMTy =
+      getTypeConverter()->convertType(operandTy.getPointee());
+
+  mlir::LLVM::GEPArg gepIndices[2] = {{0}, {1}};
+  mlir::LLVM::GEPNoWrapFlags inboundsNuw =
+      mlir::LLVM::GEPNoWrapFlags::inbounds | mlir::LLVM::GEPNoWrapFlags::nuw;
+  rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
+      op, resultLLVMTy, elementLLVMTy, adaptor.getOperand(), gepIndices,
+      inboundsNuw);
+  return mlir::success();
+}
+
 mlir::LogicalResult CIRToLLVMComplexRealPtrOpLowering::matchAndRewrite(
     cir::ComplexRealPtrOp op, OpAdaptor adaptor,
     mlir::ConversionPatternRewriter &rewriter) const {
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index ed158eb7289dd..1e461f200942c 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -513,6 +513,16 @@ class CIRToLLVMComplexImagOpLowering
                   mlir::ConversionPatternRewriter &) const override;
 };
 
+class CIRToLLVMComplexImagPtrOpLowering
+    : public mlir::OpConversionPattern<cir::ComplexImagPtrOp> {
+public:
+  using mlir::OpConversionPattern<cir::ComplexImagPtrOp>::OpConversionPattern;
+
+  mlir::LogicalResult
+  matchAndRewrite(cir::ComplexImagPtrOp op, OpAdaptor,
+                  mlir::ConversionPatternRewriter &) const override;
+};
+
 class CIRToLLVMComplexRealPtrOpLowering
     : public mlir::OpConversionPattern<cir::ComplexRealPtrOp> {
 public:
diff --git a/clang/test/CIR/CodeGen/complex.cpp 
b/clang/test/CIR/CodeGen/complex.cpp
index 88df771e6f272..0a7765fcc730d 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -230,6 +230,20 @@ void foo10() {
 // OGCG: %[[COMPLEX:.*]] = alloca { double, double }, align 8
 // OGCG: %[[REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr 
%[[COMPLEX]], i32 0, i32 0
 
+void foo11() {
+  double _Complex c;
+  double *imagPtr = &__imag__ c;
+}
+
+// CIR: %[[COMPLEX:.*]] = cir.alloca !cir.complex<!cir.double>, 
!cir.ptr<!cir.complex<!cir.double>>, ["c"]
+// CIR: %[[IMAG_PTR:.*]] = cir.complex.imag_ptr %[[COMPLEX]] : 
!cir.ptr<!cir.complex<!cir.double>> -> !cir.ptr<!cir.double>
+
+// LLVM: %[[COMPLEX:.*]] = alloca { double, double }, i64 1, align 8
+// LLVM: %[[IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr 
%[[COMPLEX]], i32 0, i32 1
+
+// OGCG: %[[COMPLEX:.*]] = alloca { double, double }, align 8
+// OGCG: %[[IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr 
%[[COMPLEX]], i32 0, i32 1
+
 void foo12() {
   double _Complex c;
   double imag = __imag__ c;

>From 369e212ae9f8c589fb3537f30f0f1215b9d8b8a4 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <am...@programmer.net>
Date: Mon, 14 Jul 2025 18:17:56 +0200
Subject: [PATCH 2/2] Fix the order of operation definitions

---
 clang/include/clang/CIR/Dialect/IR/CIROps.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td 
b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index aac803247bc22..f3f077d12bc37 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -2661,8 +2661,8 @@ def ComplexImagPtrOp : CIR_Op<"complex.imag_ptr", [Pure]> 
{
     ```
   }];
 
-  let results = (outs CIR_PtrToIntOrFloatType:$result);
   let arguments = (ins CIR_PtrToComplexType:$operand);
+  let results = (outs CIR_PtrToIntOrFloatType:$result);
 
   let assemblyFormat = [{
     $operand `:`

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

Reply via email to