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
