https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/199260
>From 3480548421290a83b62f333b9244ef847940bd3c Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Fri, 22 May 2026 21:14:24 +0200 Subject: [PATCH 1/2] [CIR] Implement Atomic Complex to Complex cast --- clang/lib/CIR/CodeGen/CIRGenAtomic.cpp | 46 +++++++++++++++++++- clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp | 8 +--- clang/test/CIR/CodeGen/complex-atomic-cast.c | 37 ++++++++++++++++ 3 files changed, 83 insertions(+), 8 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp index 3df0cd23d570e..95280242618a2 100644 --- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp @@ -110,6 +110,10 @@ class AtomicInfo { /// copy the value across. Address convertToAtomicIntPointer(Address addr) const; + /// Turn an atomic-layout object into an r-value. + RValue convertAtomicTempToRValue(Address addr, SourceLocation loc, + bool asValue) const; + /// Converts a rvalue to integer value. mlir::Value convertRValueToInt(RValue rvalue, bool cmpxchg = false) const; @@ -202,6 +206,33 @@ Address AtomicInfo::convertToAtomicIntPointer(Address addr) const { return castToAtomicIntPointer(addr); } +RValue AtomicInfo::convertAtomicTempToRValue(Address addr, SourceLocation loc, + bool asValue) const { + if (lvalue.isSimple()) { + if (evaluationKind == TEK_Aggregate) { + cgf.cgm.errorNYI( + loc, + "AtomicInfo::convertAtomicTempToRValue: evaluationKind is aggregate"); + return RValue::get(nullptr); + } + + // Drill into the padding structure if we have one. + if (hasPadding()) { + cgf.cgm.errorNYI(loc, + "AtomicInfo::convertAtomicTempToRValue: hasPadding"); + return RValue::get(nullptr); + } + + // Otherwise, just convert the temporary to an r-value using the + // normal conversion routine. + return cgf.convertTempToRValue(addr, getValueType(), loc); + } + + cgf.cgm.errorNYI( + loc, "AtomicInfo::convertAtomicTempToRValue: lvalue is not simple"); + return RValue::get(nullptr); +} + RValue AtomicInfo::emitAtomicLoad(AggValueSlot resultSlot, SourceLocation loc, bool asValue, cir::MemOrder order, bool isVolatile) { @@ -334,8 +365,19 @@ RValue AtomicInfo::convertToValueOrAtomic(mlir::Value intVal, return RValue::get(nullptr); } - cgf.cgm.errorNYI("convertToValueOrAtomic: convert through temp"); - return RValue::get(nullptr); + // Create a temporary. This needs to be big enough to hold the + // atomic integer. + if (asValue && getEvaluationKind() == TEK_Aggregate) { + cgf.cgm.errorNYI("convertToValueOrAtomic: temporary aggregate"); + return RValue::get(nullptr); + } + + Address temp = createTempAlloca(); + + // Slam the integer into the temporary. + Address castTemp = castToAtomicIntPointer(temp); + cgf.getBuilder().createStore(cgf.getLoc(loc), intVal, castTemp); + return convertAtomicTempToRValue(temp, loc, asValue); } /// Copy an r-value into memory as part of storing to an atomic type. diff --git a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp index 53a3e6e6f2cc7..c576cb9159f36 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprComplex.cpp @@ -333,7 +333,7 @@ mlir::Value ComplexExprEmitter::emitLoadOfLValue(LValue lv, SourceLocation loc) { assert(lv.isSimple() && "non-simple complex l-value?"); if (lv.getType()->isAtomicType()) - cgf.cgm.errorNYI(loc, "emitLoadOfLValue with Atomic LV"); + return cgf.emitAtomicLoad(lv, loc).getComplexValue(); const Address srcAddr = lv.getAddress(); return builder.createLoad(cgf.getLoc(loc), srcAddr, lv.isVolatileQualified()); @@ -459,16 +459,12 @@ mlir::Value ComplexExprEmitter::emitCast(CastKind ck, Expr *op, // Atomic to non-atomic casts may be more than a no-op for some platforms // and for some types. case CK_NonAtomicToAtomic: + case CK_AtomicToNonAtomic: case CK_NoOp: case CK_LValueToRValue: case CK_UserDefinedConversion: return Visit(op); - case CK_AtomicToNonAtomic: { - cgf.cgm.errorNYI("ComplexExprEmitter::emitCast AtomicToNonAtomic"); - return {}; - } - case CK_LValueBitCast: { LValue origLV = cgf.emitLValue(op); Address addr = diff --git a/clang/test/CIR/CodeGen/complex-atomic-cast.c b/clang/test/CIR/CodeGen/complex-atomic-cast.c index 9500db594ea85..a15858fcf9711 100644 --- a/clang/test/CIR/CodeGen/complex-atomic-cast.c +++ b/clang/test/CIR/CodeGen/complex-atomic-cast.c @@ -30,3 +30,40 @@ void complex_to_atomic_complex() { // OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[B_ADDR]], i32 0, i32 1 // OGCG: store i32 %[[A_REAL]], ptr %[[B_REAL_PTR]], align 8 // OGCG: store i32 %[[A_IMAG]], ptr %[[B_IMAG_PTR]], align 4 + +void atomic_complex_to_complex() { + _Atomic _Complex int a; + _Complex int b = a; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a"] +// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b", init] +// CIR: %[[ATOMIC_TMP_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["atomic-temp"] +// CIR: %[[A_U64I:.*]] = cir.cast bitcast %[[A_ADDR]] : !cir.ptr<!cir.complex<!s32i>> -> !cir.ptr<!u64i> +// CIR: %[[TMP_A:.*]] = cir.load {{.*}} atomic(seq_cst) %[[A_U64I]] : !cir.ptr<!u64i>, !u64i +// CIR: %[[ATOMIC_TMP_U64I:.*]] = cir.cast bitcast %[[ATOMIC_TMP_ADDR]] : !cir.ptr<!cir.complex<!s32i>> -> !cir.ptr<!u64i> +// CIR: cir.store {{.*}} %[[TMP_A]], %[[ATOMIC_TMP_U64I]] : !u64i, !cir.ptr<!u64i> +// CIR: %[[TMP_ATOMIC:.*]] = cir.load {{.*}} %[[ATOMIC_TMP_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> +// CIR: cir.store {{.*}} %[[TMP_ATOMIC]], %[[B_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>> + +// LLVM: %[[A_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 8 +// LLVM: %[[B_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4 +// LLVM: %[[ATOMIC_TMP_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 8 +// LLVM: %[[TMP_A:.*]] = load atomic i64, ptr %[[A_ADDR]] seq_cst, align 8 +// LLVM: store i64 %[[TMP_A]], ptr %[[ATOMIC_TMP_ADDR]], align 8 +// LLVM: %[[TMP_ATOMIC:.*]] = load { i32, i32 }, ptr %[[ATOMIC_TMP_ADDR]], align 8 +// LLVM: store { i32, i32 } %[[TMP_ATOMIC]], ptr %[[B_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca { i32, i32 }, align 8 +// OGCG: %[[B_ADDR:.*]] = alloca { i32, i32 }, align 4 +// OGCG: %[[ATOMIC_TMP_ADDR:.*]] = alloca { i32, i32 }, align 8 +// OGCG: %[[TMP_A:.*]] = load atomic i64, ptr %[[A_ADDR]] seq_cst, align 8 +// OGCG: store i64 %[[TMP_A]], ptr %[[ATOMIC_TMP_ADDR]], align 8 +// OGCG: %[[ATOMIC_TMP_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[ATOMIC_TMP_ADDR]], i32 0, i32 0 +// OGCG: %[[ATOMIC_TMP_REAL:.*]] = load i32, ptr %[[ATOMIC_TMP_REAL_PTR]], align 8 +// OGCG: %[[ATOMIC_TMP_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[ATOMIC_TMP_ADDR]], i32 0, i32 1 +// OGCG: %[[ATOMIC_TMP_IMAG:.*]] = load i32, ptr %[[ATOMIC_TMP_IMAG_PTR]], align 4 +// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[B_ADDR]], i32 0, i32 0 +// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[B_ADDR]], i32 0, i32 1 +// OGCG: store i32 %[[ATOMIC_TMP_REAL]], ptr %[[B_REAL_PTR]], align 4 +// OGCG: store i32 %[[ATOMIC_TMP_IMAG]], ptr %[[B_IMAG_PTR]], align 4 >From 60bbfad7143a665a8c739f4a851f2e8b21cdf181 Mon Sep 17 00:00:00 2001 From: Amr Hesham <[email protected]> Date: Sun, 31 May 2026 13:06:32 +0200 Subject: [PATCH 2/2] Address code review comments --- clang/lib/CIR/CodeGen/CIRGenAtomic.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp index 95280242618a2..33ddf8e1539db 100644 --- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp @@ -367,13 +367,14 @@ RValue AtomicInfo::convertToValueOrAtomic(mlir::Value intVal, // Create a temporary. This needs to be big enough to hold the // atomic integer. + Address temp = Address::invalid(); if (asValue && getEvaluationKind() == TEK_Aggregate) { cgf.cgm.errorNYI("convertToValueOrAtomic: temporary aggregate"); return RValue::get(nullptr); + } else { + temp = createTempAlloca(); } - Address temp = createTempAlloca(); - // Slam the integer into the temporary. Address castTemp = castToAtomicIntPointer(temp); cgf.getBuilder().createStore(cgf.getLoc(loc), intVal, castTemp); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
