[clang] 9781918 - [CIR] Initialization of atomic aggregates with padding (#200668)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 5 21:00:56 PDT 2026
Author: Sirui Mu
Date: 2026-06-06T12:00:51+08:00
New Revision: 978191848cdb929f85c76bbf54b0666971328c59
URL: https://github.com/llvm/llvm-project/commit/978191848cdb929f85c76bbf54b0666971328c59
DIFF: https://github.com/llvm/llvm-project/commit/978191848cdb929f85c76bbf54b0666971328c59.diff
LOG: [CIR] Initialization of atomic aggregates with padding (#200668)
This patch adds support for the initialization of atomic aggregates with
padding. The changes include:
- During CIRGen, the type `_Atomic(T)` is represented by a CIR struct
`{T, sint8[padding_size]}` if the size of `_Atomic(T)` does not match
the size of `T`. `padding_size` is the difference between the size of
`_Atomic(T)` and `T`.
- CIRGen for the initialization process is updated to handle the
initialization of such CIR struct values.
Added:
Modified:
clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
clang/lib/CIR/CodeGen/CIRGenBuilder.h
clang/lib/CIR/CodeGen/CIRGenTypes.cpp
clang/test/CIR/CodeGen/atomic.c
Removed:
################################################################################
diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
index 33ddf8e1539db..758defeed7660 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
@@ -128,9 +128,9 @@ class AtomicInfo {
LValue projectValue() const {
assert(lvalue.isSimple());
Address addr = getAtomicAddress();
- if (hasPadding()) {
- cgf.cgm.errorNYI(loc, "AtomicInfo::projectValue: padding");
- }
+ if (hasPadding())
+ addr = cgf.getBuilder().createGetMember(loc, addr, /*name=*/"value",
+ /*index=*/0);
assert(!cir::MissingFeatures::opTBAA());
return LValue::makeAddr(addr, getValueType(), lvalue.getBaseInfo());
@@ -293,9 +293,14 @@ bool AtomicInfo::emitMemSetZeroIfNecessary() const {
if (!requiresMemSetZero(addr.getElementType()))
return false;
- cgf.cgm.errorNYI(loc,
- "AtomicInfo::emitMemSetZeroIfNecaessary: emit memset zero");
- return false;
+ addr = addr.withElementType(cgf.getBuilder(), cgf.cgm.voidTy);
+ mlir::Value zero = cgf.getBuilder().getConstInt(loc, cgf.cgm.uInt8Ty, 0);
+ mlir::Value memSetSize = cgf.getBuilder().getConstInt(
+ loc, cgf.cgm.uInt64Ty,
+ cgf.getContext().toCharUnitsFromBits(atomicSizeInBits).getQuantity());
+
+ cgf.getBuilder().createMemSet(loc, addr, zero, memSetSize);
+ return true;
}
/// Return true if \param valueTy is a type that should be casted to integer
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index d9fa5e23f40ae..3188b096579be 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -643,6 +643,29 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
addr.getAlignment()};
}
+ using CIRBaseBuilderTy::createGetMember;
+ Address createGetMember(mlir::Location loc, Address base,
+ llvm::StringRef name, unsigned index) {
+ auto recordTy = mlir::cast<cir::RecordType>(base.getElementType());
+
+ assert(index < recordTy.getMembers().size() &&
+ "member index out of bounds");
+ mlir::Type memberTy = recordTy.getMembers()[index];
+ mlir::Type memberPtrTy = getPointerTo(memberTy);
+
+ auto moduleOp =
+ getInsertionBlock()->getParentOp()->getParentOfType<mlir::ModuleOp>();
+ mlir::DataLayout layout(moduleOp);
+ auto memberOffset =
+ CharUnits::fromQuantity(recordTy.getElementOffset(layout, index));
+
+ mlir::Value memberPtr =
+ createGetMember(loc, memberPtrTy, base.getBasePointer(), name, index);
+ return Address(memberPtr, memberTy,
+ base.getAlignment().alignmentAtOffset(memberOffset),
+ base.isKnownNonNull());
+ }
+
cir::GetRuntimeMemberOp createGetIndirectMember(mlir::Location loc,
mlir::Value objectPtr,
mlir::Value memberPtr) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 61e2365bd5255..e6452f8592d22 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -639,7 +639,13 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
uint64_t valueSize = astContext.getTypeSize(valueType);
uint64_t atomicSize = astContext.getTypeSize(ty);
if (valueSize != atomicSize) {
- cgm.errorNYI("convertType: atomic type value size != atomic size");
+ assert(valueSize < atomicSize);
+ auto paddingArray =
+ cir::ArrayType::get(cgm.sInt8Ty, (atomicSize - valueSize) / 8);
+ mlir::Type elements[] = {resultType, paddingArray};
+ resultType = cir::RecordType::get(&getMLIRContext(), /*members=*/elements,
+ /*packed=*/false, /*padded=*/false,
+ /*kind=*/cir::RecordType::Struct);
}
break;
diff --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c
index e4f3fe82310a4..aae9792ba2b76 100644
--- a/clang/test/CIR/CodeGen/atomic.c
+++ b/clang/test/CIR/CodeGen/atomic.c
@@ -5,6 +5,10 @@
// RUN: %clang_cc1 -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 S1 {
+ short x, y, z;
+};
+
_Atomic int g1;
_Atomic int g2 = 42;
// CIR: cir.global external @g2 = #cir.int<42> : !s32i {alignment = 4 : i64}
@@ -83,6 +87,49 @@ void f4(_Atomic(float) *p) {
// OGCG-LABEL: @f4
// OGCG: store atomic float 3.140000e+00, ptr %{{.+}} seq_cst, align 4
+void init_with_padding(_Atomic struct S1 *p) {
+ // CIR-LABEL: @init_with_padding
+ // LLVM-LABEL: @init_with_padding
+ // OGCG-LABEL: @init_with_padding
+
+ __c11_atomic_init(p, (struct S1){1, 2, 3});
+
+ // CIR: %[[PTR_VOID:.+]] = cir.cast bitcast %[[PTR:.+]] : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!void>
+ // CIR-NEXT: %[[MEMSET_VALUE:.+]] = cir.const #cir.int<0> : !u8i
+ // CIR-NEXT: %[[MEMSET_SIZE:.+]] = cir.const #cir.int<8> : !u64i
+ // CIR-NEXT: cir.libc.memset %[[MEMSET_SIZE]] bytes at %[[PTR_VOID]] align(8) to %[[MEMSET_VALUE]] : !cir.ptr<!void>, !u8i, !u64i
+ // CIR-NEXT: %[[VALUE_PTR:.+]] = cir.get_member %[[PTR]][0] {name = "value"} : !cir.ptr<!rec_anon_struct> -> !cir.ptr<!rec_S1>
+ // CIR-NEXT: %[[X_PTR:.+]] = cir.get_member %[[VALUE_PTR]][0] {name = "x"} : !cir.ptr<!rec_S1> -> !cir.ptr<!s16i>
+ // CIR-NEXT: %[[X_INIT:.+]] = cir.const #cir.int<1> : !s16i
+ // CIR-NEXT: cir.store align(8) %[[X_INIT]], %[[X_PTR]] : !s16i, !cir.ptr<!s16i>
+ // CIR-NEXT: %[[Y_PTR:.+]] = cir.get_member %[[VALUE_PTR]][1] {name = "y"} : !cir.ptr<!rec_S1> -> !cir.ptr<!s16i>
+ // CIR-NEXT: %[[Y_INIT:.+]] = cir.const #cir.int<2> : !s16i
+ // CIR-NEXT: cir.store align(2) %[[Y_INIT]], %[[Y_PTR]] : !s16i, !cir.ptr<!s16i>
+ // CIR-NEXT: %[[Z_PTR:.+]] = cir.get_member %[[VALUE_PTR]][2] {name = "z"} : !cir.ptr<!rec_S1> -> !cir.ptr<!s16i>
+ // CIR-NEXT: %[[Z_INIT:.+]] = cir.const #cir.int<3> : !s16i
+ // CIR-NEXT: cir.store align(4) %[[Z_INIT]], %[[Z_PTR]] : !s16i, !cir.ptr<!s16i>
+
+ // LLVM: %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+ // LLVM-NEXT: call void @llvm.memset.p0.i64(ptr align 8 %[[PTR]], i8 0, i64 8, i1 false)
+ // LLVM-NEXT: %[[VALUE_PTR:.+]] = getelementptr inbounds nuw { %struct.S1, [2 x i8] }, ptr %[[PTR]], i32 0, i32 0
+ // LLVM-NEXT: %[[X_PTR:.+]] = getelementptr inbounds nuw %struct.S1, ptr %[[VALUE_PTR]], i32 0, i32 0
+ // LLVM-NEXT: store i16 1, ptr %[[X_PTR]], align 8
+ // LLVM-NEXT: %[[Y_PTR:.+]] = getelementptr inbounds nuw %struct.S1, ptr %[[VALUE_PTR]], i32 0, i32 1
+ // LLVM-NEXT: store i16 2, ptr %[[Y_PTR]], align 2
+ // LLVM-NEXT: %[[Z_PTR:.+]] = getelementptr inbounds nuw %struct.S1, ptr %[[VALUE_PTR]], i32 0, i32 2
+ // LLVM-NEXT: store i16 3, ptr %[[Z_PTR]], align 4
+
+ // OGCG: %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+ // OGCG-NEXT: call void @llvm.memset.p0.i64(ptr align 8 %[[PTR]], i8 0, i64 8, i1 false)
+ // OGCG-NEXT: %[[VALUE_PTR:.+]] = getelementptr inbounds nuw { %struct.S1, [2 x i8] }, ptr %[[PTR]], i32 0, i32 0
+ // OGCG-NEXT: %[[X_PTR:.+]] = getelementptr inbounds nuw %struct.S1, ptr %[[VALUE_PTR]], i32 0, i32 0
+ // OGCG-NEXT: store i16 1, ptr %[[X_PTR]], align 8
+ // OGCG-NEXT: %[[Y_PTR:.+]] = getelementptr inbounds nuw %struct.S1, ptr %[[VALUE_PTR]], i32 0, i32 1
+ // OGCG-NEXT: store i16 2, ptr %[[Y_PTR]], align 2
+ // OGCG-NEXT: %[[Z_PTR:.+]] = getelementptr inbounds nuw %struct.S1, ptr %[[VALUE_PTR]], i32 0, i32 2
+ // OGCG-NEXT: store i16 3, ptr %[[Z_PTR]], align 4
+}
+
void atomic_to_non_atomic(_Atomic int *ptr, _Atomic volatile int *vptr) {
// CIR-LABEL: @atomic_to_non_atomic
// LLVM-LABEL: @atomic_to_non_atomic
More information about the cfe-commits
mailing list