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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
