[clang] [CIR] Implement AtomicExpr for Aggregate expr (PR #173775)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 7 10:49:07 PST 2026
https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/173775
>From c25e12c605021e4bf8f6fc8b2f1bbf0add83baab Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Sat, 27 Dec 2025 22:15:28 +0100
Subject: [PATCH 1/2] [CIR] Implement AtomicExpr for Aggregate expr
---
clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 3 +--
clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 11 +++++++-
clang/lib/CIR/CodeGen/CIRGenValue.h | 4 +++
clang/test/CIR/CodeGen/atomic.c | 27 +++++++++++++++++++
4 files changed, 42 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 1d386f43fc8f4..cd13498e3702f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -2145,8 +2145,7 @@ RValue CIRGenFunction::convertTempToRValue(Address addr, clang::QualType type,
case cir::TEK_Complex:
return RValue::getComplex(emitLoadOfComplex(lvalue, loc));
case cir::TEK_Aggregate:
- cgm.errorNYI(loc, "convertTempToRValue: aggregate type");
- return RValue::get(nullptr);
+ return lvalue.asAggregateRValue();
case cir::TEK_Scalar:
return RValue::get(emitLoadOfScalar(lvalue, loc));
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index 3eef284405ad0..b6b369cfcb7ea 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -130,6 +130,7 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
Expr *exprToVisit, ArrayRef<Expr *> args,
Expr *arrayFiller);
+ void emitFinalDestCopy(QualType type, RValue src);
/// Perform the final copy to DestPtr, if desired.
void emitFinalDestCopy(QualType type, const LValue &src);
@@ -397,7 +398,8 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitCXXThrowExpr");
}
void VisitAtomicExpr(AtomicExpr *e) {
- cgf.cgm.errorNYI(e->getSourceRange(), "AggExprEmitter: VisitAtomicExpr");
+ RValue result = cgf.emitAtomicExpr(e);
+ emitFinalDestCopy(e->getType(), result);
}
};
@@ -587,6 +589,13 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
}
}
+/// EmitFinalDestCopy - Perform the final copy to DestPtr, if desired.
+void AggExprEmitter::emitFinalDestCopy(QualType type, RValue src) {
+ assert(src.isAggregate() && "value must be aggregate value!");
+ LValue srcLV = cgf.makeAddrLValue(src.getAggregateAddress(), type);
+ emitFinalDestCopy(type, srcLV);
+}
+
/// Perform the final copy to destPtr, if desired.
void AggExprEmitter::emitFinalDestCopy(QualType type, const LValue &src) {
// If dest is ignored, then we're evaluating an aggregate expression
diff --git a/clang/lib/CIR/CodeGen/CIRGenValue.h b/clang/lib/CIR/CodeGen/CIRGenValue.h
index 2002bd7e7c488..e5b925f82a635 100644
--- a/clang/lib/CIR/CodeGen/CIRGenValue.h
+++ b/clang/lib/CIR/CodeGen/CIRGenValue.h
@@ -328,6 +328,10 @@ class LValue {
r.initialize(type, type.getQualifiers(), addr.getAlignment(), baseInfo);
return r;
}
+
+ RValue asAggregateRValue() const {
+ return RValue::getAggregate(getAddress(), isVolatileQualified());
+ }
};
/// An aggregate value slot.
diff --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c
index 4baac3bab7bce..483dc6d26dccd 100644
--- a/clang/test/CIR/CodeGen/atomic.c
+++ b/clang/test/CIR/CodeGen/atomic.c
@@ -158,6 +158,33 @@ void c11_load(_Atomic(int) *ptr) {
// OGCG: %{{.+}} = load atomic i32, ptr %{{.+}} seq_cst, align 4
// OGCG: }
+struct Pair {
+ int x;
+ int y;
+};
+
+void c11_load_aggregate() {
+ _Atomic(struct Pair) a;
+ __c11_atomic_load(&a, __ATOMIC_RELAXED);
+ __c11_atomic_load(&a, __ATOMIC_ACQUIRE);
+ __c11_atomic_load(&a, __ATOMIC_SEQ_CST);
+}
+
+// CIR-LABEL: @c11_load_aggregate
+// CIR: %{{.*}} = cir.load {{.*}} syncscope(system) atomic(relaxed) %{{.*}} : !cir.ptr<!u64i>, !u64i
+// CIR: %{{.*}} = cir.load {{.*}} syncscope(system) atomic(acquire) %{{.*}} : !cir.ptr<!u64i>, !u64i
+// CIR: %{{.*}} = cir.load {{.*}} syncscope(system) atomic(seq_cst) %{{.*}} : !cir.ptr<!u64i>, !u64i
+
+// LLVM-LABEL: @c11_load_aggregate
+// LLVM: %{{.*}} = load atomic i64, ptr %{{.*}} monotonic, align 8
+// LLVM: %{{.*}} = load atomic i64, ptr %{{.*}} acquire, align 8
+// LLVM: %{{.*}} = load atomic i64, ptr %{{.*}} seq_cst, align 8
+
+// OGCG-LABEL: @c11_load_aggregate
+// OGCG: %{{.*}} = load atomic i64, ptr %{{.*}} monotonic, align 8
+// OGCG: %{{.*}} = load atomic i64, ptr %{{.*}} acquire, align 8
+// OGCG: %{{.*}} = load atomic i64, ptr %{{.*}} seq_cst, align 8
+
void store(int *ptr, int x) {
__atomic_store(ptr, &x, __ATOMIC_RELAXED);
__atomic_store(ptr, &x, __ATOMIC_RELEASE);
>From 12f140bdb6330e484d459a07bf02e7c3f37cee52 Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Wed, 7 Jan 2026 19:48:38 +0100
Subject: [PATCH 2/2] Add NYI for ExprValueKind in emitFinalDestCopy
---
clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp | 21 ++++++++++++++++---
clang/lib/CIR/CodeGen/CIRGenFunction.h | 2 ++
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index b6b369cfcb7ea..8fcff6d0f9b84 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -131,8 +131,11 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
Expr *arrayFiller);
void emitFinalDestCopy(QualType type, RValue src);
+
/// Perform the final copy to DestPtr, if desired.
- void emitFinalDestCopy(QualType type, const LValue &src);
+ void emitFinalDestCopy(QualType type, const LValue &src,
+ CIRGenFunction::ExprValueKind srcValueKind =
+ CIRGenFunction::EVK_NonRValue);
void emitCopy(QualType type, const AggValueSlot &dest,
const AggValueSlot &src);
@@ -593,11 +596,13 @@ void AggExprEmitter::emitArrayInit(Address destPtr, cir::ArrayType arrayTy,
void AggExprEmitter::emitFinalDestCopy(QualType type, RValue src) {
assert(src.isAggregate() && "value must be aggregate value!");
LValue srcLV = cgf.makeAddrLValue(src.getAggregateAddress(), type);
- emitFinalDestCopy(type, srcLV);
+ emitFinalDestCopy(type, srcLV, CIRGenFunction::EVK_RValue);
}
/// Perform the final copy to destPtr, if desired.
-void AggExprEmitter::emitFinalDestCopy(QualType type, const LValue &src) {
+void AggExprEmitter::emitFinalDestCopy(
+ QualType type, const LValue &src,
+ CIRGenFunction::ExprValueKind srcValueKind) {
// If dest is ignored, then we're evaluating an aggregate expression
// in a context that doesn't care about the result. Note that loads
// from volatile l-values force the existence of a non-ignored
@@ -605,6 +610,16 @@ void AggExprEmitter::emitFinalDestCopy(QualType type, const LValue &src) {
if (dest.isIgnored())
return;
+ if (srcValueKind == CIRGenFunction::EVK_RValue) {
+ if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct) {
+ cgf.cgm.errorNYI("emitFinalDestCopy: EVK_RValue & PCK_Struct");
+ }
+ } else {
+ if (type.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) {
+ cgf.cgm.errorNYI("emitFinalDestCopy: !EVK_RValue & PCK_Struct");
+ }
+ }
+
assert(!cir::MissingFeatures::aggValueSlotVolatile());
assert(!cir::MissingFeatures::aggEmitFinalDestCopyRValue());
assert(!cir::MissingFeatures::aggValueSlotGC());
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 49ebccc221950..3101fc6cd228c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1309,6 +1309,8 @@ class CIRGenFunction : public CIRGenTypeCache {
void emitAggExpr(const clang::Expr *e, AggValueSlot slot);
+ enum ExprValueKind { EVK_RValue, EVK_NonRValue };
+
LValue emitAggExprToLValue(const Expr *e);
/// Emit an aggregate copy.
More information about the cfe-commits
mailing list