https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/220689
>From ab5262b0f5a9db32b228bf490bbaccf719908539 Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Wed, 2 Sep 2026 19:51:14 +0200 Subject: [PATCH] [CIR] Support Aggregate cast from and to atomic type --- clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 39 +++++++++-- clang/test/CIR/CodeGen/agg-atomic-cast.c | 70 +++++++++++++++++++ 2 files changed, 103 insertions(+), 6 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp index 2b3cf598f35a3..16bfdae8cb0f1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp @@ -183,7 +183,13 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> { // If we have an atomic type, evaluate into the destination and then // do an atomic copy. - assert(!cir::MissingFeatures::atomicTypes()); + if (lhs.getType()->isAtomicType() || + cgf.isLValueSuitableForInlineAtomic(lhs)) { + ensureDest(cgf.getLoc(e->getExprLoc()), e->getRHS()->getType()); + Visit(e->getRHS()); + cgf.emitAtomicStore(dest.asRValue(), lhs, /*isInit=*/false); + return; + } // Codegen the RHS so that it stores directly into the LHS. assert(!cir::MissingFeatures::aggValueSlotGC()); @@ -296,18 +302,39 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> { // These two cases are reverses of each other; try to peephole them. CastKind peepholeTarget = (isToAtomic ? CK_AtomicToNonAtomic : CK_NonAtomicToAtomic); + + // These two cases are reverses of each other; try to peephole them. if (Expr *op = findPeephole(e->getSubExpr(), peepholeTarget, cgf.getContext())) { - cgf.cgm.errorNYI(op->getSourceRange(), - "AggExprEmitter: VisitCastExpr peephole"); + assert(cgf.getContext().hasSameUnqualifiedType(op->getType(), + e->getType()) && + "peephole significantly changed types?"); + return Visit(op); } // If we're converting an r-value of non-atomic type to an r-value // of atomic type, just emit directly into the relevant sub-object. if (isToAtomic) { - cgf.cgm.errorNYI(e->getSourceRange(), - "AggExprEmitter: VisitCastExpr r-value of non-atomic " - "type to an r-value of atomic type"); + AggValueSlot valueDest = dest; + if (!valueDest.isIgnored() && cgf.cgm.isPaddedAtomicType(atomicType)) { + // Zero-initialize. (Strictly speaking, we only need to initialize + // the padding at the end, but this is simpler.) + mlir::Location loc = cgf.getLoc(e->getExprLoc()); + if (!dest.isZeroed()) + cgf.emitNullInitialization(loc, dest.getAddress(), atomicType); + + Address valueAddr = cgf.getBuilder().createGetMember( + loc, valueDest.getAddress(), "value_addr", 0); + + assert(!cir::MissingFeatures::aggValueSlotGC()); + valueDest = AggValueSlot::forAddr( + valueAddr, valueDest.getQualifiers(), + valueDest.isExternallyDestructed(), + valueDest.isPotentiallyAliased(), AggValueSlot::DoesNotOverlap, + AggValueSlot::IsZeroed); + } + + cgf.emitAggExpr(e->getSubExpr(), valueDest); return; } diff --git a/clang/test/CIR/CodeGen/agg-atomic-cast.c b/clang/test/CIR/CodeGen/agg-atomic-cast.c index a6c7452ce94d3..ac34d056dccd1 100644 --- a/clang/test/CIR/CodeGen/agg-atomic-cast.c +++ b/clang/test/CIR/CodeGen/agg-atomic-cast.c @@ -101,3 +101,73 @@ struct T load_atomic_struct() { // OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[RET_ADDR]], ptr align 1 %[[RET_VAL_ADDR]], i64 3, i1 false) // OGCG: %[[TMP_RET:.*]] = load i24, ptr %[[RET_ADDR]], align 4 // OGCG: ret i24 %[[TMP_RET]] + +void load_atomic_struct_to_atomic_struct() { + _Atomic(struct T) a; + _Atomic(struct T) b; + b = a; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : !cir.ptr<!rec_anon_struct> +// CIR: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : !cir.ptr<!rec_anon_struct> +// CIR: %[[AGG_TMP_ADDR:.*]] = cir.alloca "agg.tmp.ensured" {{.*}} : !cir.ptr<!rec_anon_struct> +// CIR: %[[A_ADDR_U32:.*]] = cir.cast bitcast %[[A_ADDR]] : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i> +// CIR: %[[TMP_A:.*]] = cir.load {{.*}} atomic(seq_cst) %[[A_ADDR_U32]] : !cir.ptr<!u32i>, !u32i +// CIR: %[[AGG_TMP_ADDR_U32:.*]] = cir.cast bitcast %[[AGG_TMP_ADDR]] : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i> +// CIR: cir.store {{.*}} %[[TMP_A]], %[[AGG_TMP_ADDR_U32]] : !u32i, !cir.ptr<!u32i> +// CIR: %[[AGG_TMP_ADDR_U32:.*]] = cir.cast bitcast %[[AGG_TMP_ADDR]] : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i> +// CIR: %[[AGG_TMP:.*]] = cir.load {{.*}} %[[AGG_TMP_ADDR_U32]] : !cir.ptr<!u32i>, !u32i +// CIR: %[[B_ADDR_U32:.*]] = cir.cast bitcast %[[B_ADDR]] : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i> +// CIR: cir.store {{.*}} atomic(seq_cst) %[[AGG_TMP]], %[[B_ADDR_U32]] : !u32i, !cir.ptr<!u32i> + +// LLVM: %[[A_ADDR:.*]] = alloca { %struct.T, [1 x i8] }, align 4 +// LLVM: %[[B_ADDR:.*]] = alloca { %struct.T, [1 x i8] }, align 4 +// LLVM: %[[AGG_TMP_ADDR:.*]] = alloca { %struct.T, [1 x i8] }, align 4 +// LLVM: %[[TMP_A:.*]] = load atomic i32, ptr %[[A_ADDR]] seq_cst, align 4 +// LLVM: store i32 %[[TMP_A]], ptr %[[AGG_TMP_ADDR]], align 4 +// LLVM: %[[AGG_TMP:.*]] = load i32, ptr %[[AGG_TMP_ADDR]], align 4 +// LLVM: store atomic i32 %[[AGG_TMP]], ptr %[[B_ADDR]] seq_cst, align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { %struct.T, [1 x i8] }, align 4 +// OGCG: %[[B_ADDR:.*]] = alloca { %struct.T, [1 x i8] }, align 4 +// OGCG: %[[AGG_TMP_ADDR:.*]] = alloca { %struct.T, [1 x i8] }, align 4 +// OGCG: %[[TMP_A:.*]] = load atomic i32, ptr %[[A_ADDR]] seq_cst, align 4 +// OGCG: store i32 %[[TMP_A]], ptr %[[AGG_TMP_ADDR]], align 4 +// OGCG: %[[AGG_TMP:.*]] = load i32, ptr %[[AGG_TMP_ADDR]], align 4 +// OGCG: store atomic i32 %[[AGG_TMP]], ptr %[[B_ADDR]] seq_cst, align 4 + +void load_struct_to_atomic_struct() { + struct T a; + _Atomic(struct T) b; + b = a; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : !cir.ptr<!rec_T> +// CIR: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : !cir.ptr<!rec_anon_struct> +// CIR: %[[AGG_TMP_ADDR:.*]] = cir.alloca "agg.tmp.ensured" {{.*}} : !cir.ptr<!rec_anon_struct> +// CIR: %[[AGG_TMP_ZERO:.*]] = cir.get_global @__const.load_struct_to_atomic_struct.agg.tmp.ensured : !cir.ptr<!rec_anon_struct> +// CIR: cir.copy %[[AGG_TMP_ZERO]] to %[[AGG_TMP_ADDR]] : !cir.ptr<!rec_anon_struct> +// CIR: %[[AGG_TMP_PTR:.*]] = cir.get_member %[[AGG_TMP_ADDR]][0] {name = "value_addr"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!rec_T> +// CIR: cir.copy %[[A_ADDR]] {{.*}} to %[[AGG_TMP_PTR]] {{.*}} : !cir.ptr<!rec_T> +// CIR: %[[AGG_TMP_ADDR_U32:.*]] = cir.cast bitcast %[[AGG_TMP_ADDR]] : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i> +// CIR: %[[AGG_TMP:.*]] = cir.load {{.*}} %[[AGG_TMP_ADDR_U32]] : !cir.ptr<!u32i>, !u32i +// CIR: %[[B_ADDR_U32:.*]] = cir.cast bitcast %1 : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!u32i> +// CIR: cir.store {{.*}} atomic(seq_cst) %[[AGG_TMP]], %[[B_ADDR_U32]] : !u32i, !cir.ptr<!u32i> + +// LLVM: %[[A_ADDR:.*]] = alloca %struct.T, align 1 +// LLVM: %[[B_ADDR:.*]] = alloca { %struct.T, [1 x i8] }, align 4 +// LLVM: %[[AGG_TMP_ADDR:.*]] = alloca { %struct.T, [1 x i8] }, align 4 +// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 1 %[[AGG_TMP_ADDR]], ptr align 1 @__const.load_struct_to_atomic_struct.agg.tmp.ensured, i64 4, i1 false) +// LLVM: %[[AGG_TMP_PTR:.*]] = getelementptr inbounds nuw { %struct.T, [1 x i8] }, ptr %[[AGG_TMP_ADDR]], i32 0, i32 0 +// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[AGG_TMP_PTR]], ptr align 1 %[[A_ADDR]], i64 3, i1 false) +// LLVM: %[[AGG_TMP:.*]] = load i32, ptr %[[AGG_TMP_ADDR]], align 4 +// LLVM: store atomic i32 %[[AGG_TMP]], ptr %[[B_ADDR]] seq_cst, align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca %struct.T, align 1 +// OGCG: %[[B_ADDR:.*]] = alloca { %struct.T, [1 x i8] }, align 4 +// OGCG: %[[AGG_TMP_ADDR:.*]] = alloca { %struct.T, [1 x i8] }, align 4 +// OGCG: call void @llvm.memset.p0.i64(ptr align 4 %[[AGG_TMP_ADDR]], i8 0, i64 4, i1 false) +// OGCG: %[[AGG_TMP_PTR:.*]] = getelementptr inbounds nuw { %struct.T, [1 x i8] }, ptr %[[AGG_TMP_ADDR]], i32 0, i32 0 +// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[AGG_TMP_PTR]], ptr align 1 %[[A_ADDR]], i64 3, i1 false) +// OGCG: %[[AGG_TMP:.*]] = load i32, ptr %[[AGG_TMP_ADDR]], align 4 +// OGCG: store atomic i32 %[[AGG_TMP]], ptr %[[B_ADDR]] seq_cst, align 4 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
