Author: Amr Hesham
Date: 2026-06-19T20:26:00+02:00
New Revision: d1c306c5ef9fc687df3630145b256f0d67a767b2

URL: 
https://github.com/llvm/llvm-project/commit/d1c306c5ef9fc687df3630145b256f0d67a767b2
DIFF: 
https://github.com/llvm/llvm-project/commit/d1c306c5ef9fc687df3630145b256f0d67a767b2.diff

LOG: [CIR] Implement Aggregate non-atomic to atomic cast (#204653)

Implement support for Aggregate non-atomic to atomic cast

Added: 
    clang/test/CIR/CodeGen/agg-atomic-cast.cpp

Modified: 
    clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
    clang/lib/CIR/CodeGen/CIRGenModule.h
    clang/lib/CIR/CodeGen/CIRGenTypes.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 44f481508cd7e..c53453bd3e88b 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -258,6 +258,36 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
 
       break;
     }
+
+    case CK_NonAtomicToAtomic:
+    case CK_AtomicToNonAtomic: {
+      bool isToAtomic = (e->getCastKind() == CK_NonAtomicToAtomic);
+      if (!isToAtomic) {
+        cgf.cgm.errorNYI(e->getSourceRange(),
+                         "AggExprEmitter: CK_AtomicToNonAtomic");
+        return;
+      }
+
+      // Determine the atomic and value types.
+      QualType atomicType = e->getSubExpr()->getType();
+      QualType valueType = e->getType();
+      if (isToAtomic)
+        std::swap(atomicType, valueType);
+
+      assert(atomicType->isAtomicType());
+      assert(cgf.getContext().hasSameUnqualifiedType(
+          valueType, atomicType->castAs<AtomicType>()->getValueType()));
+
+      // Just recurse normally if we're ignoring the result or the
+      // atomic type doesn't change representation.
+      if (dest.isIgnored() || !cgf.cgm.isPaddedAtomicType(atomicType))
+        return Visit(e->getSubExpr());
+
+      cgf.cgm.errorNYI(
+          e->getSourceRange(),
+          "AggExprEmitter: AtomicCast not ignored and has padded atomic type");
+      return;
+    }
     case CK_LValueToRValue:
       // If we're loading from a volatile type, force the destination
       // into existence.

diff  --git a/clang/lib/CIR/CodeGen/CIRGenModule.h 
b/clang/lib/CIR/CodeGen/CIRGenModule.h
index fa166c1f39b69..0883a6b891c61 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.h
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.h
@@ -823,6 +823,9 @@ class CIRGenModule : public CIRGenTypeCache {
     return *openMPRuntime;
   }
 
+  bool isPaddedAtomicType(QualType type);
+  bool isPaddedAtomicType(const AtomicType *type);
+
   mlir::IntegerAttr getSize(CharUnits size) {
     return builder.getSizeFromCharUnits(size);
   }

diff  --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp 
b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index ea37d82c82d79..3170666304a06 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -226,6 +226,15 @@ static bool isSafeToConvert(const RecordDecl *rd, 
CIRGenTypes &cgt) {
   return isSafeToConvert(rd, cgt, alreadyChecked);
 }
 
+bool CIRGenModule::isPaddedAtomicType(QualType type) {
+  return isPaddedAtomicType(type->castAs<AtomicType>());
+}
+
+bool CIRGenModule::isPaddedAtomicType(const AtomicType *type) {
+  return astContext.getTypeSize(type) !=
+         astContext.getTypeSize(type->getValueType());
+}
+
 /// Lay out a tagged decl type like struct or union.
 mlir::Type CIRGenTypes::convertRecordDeclType(const clang::RecordDecl *rd) {
   // TagDecl's are not necessarily unique, instead use the (clang) type

diff  --git a/clang/test/CIR/CodeGen/agg-atomic-cast.cpp 
b/clang/test/CIR/CodeGen/agg-atomic-cast.cpp
new file mode 100644
index 0000000000000..12ed04f14edf2
--- /dev/null
+++ b/clang/test/CIR/CodeGen/agg-atomic-cast.cpp
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu 
-Wno-unused-value -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu 
-Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu 
-Wno-unused-value -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+struct S {
+  int data[4];
+};
+
+void non_atomic_to_atomic_cast() {
+  S s;
+  _Atomic(S) as =  s;
+}
+
+// CIR: %[[S_ADDR:.*]] = cir.alloca "s" {{.*}} : !cir.ptr<!rec_S>
+// CIR: %[[SA_ADDR:.*]] = cir.alloca "as" {{.*}} init : !cir.ptr<!rec_S>
+// CIR: cir.copy %[[S_ADDR]] to %[[SA_ADDR]] : !cir.ptr<!rec_S>
+
+// LLVM:  %[[S_ADDR:.*]] = alloca %struct.S, i64 1, align 4
+// LLVM: %[[SA_ADDR:.*]] = alloca %struct.S, i64 1, align 16
+// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %[[SA_ADDR]], ptr %[[S_ADDR]], 
i64 16, i1 false)
+
+// OGCG: %[[S_ADDR:.*]] = alloca %struct.S, align 4
+// OGCG: %[[SA_ADDR:.*]] = alloca %struct.S, align 16
+// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[SA_ADDR]], ptr align 
4 %[[S_ADDR]], i64 16, i1 false)


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to