https://github.com/andykaylor updated https://github.com/llvm/llvm-project/pull/164508
>From 08353a39097576500fa3516b121c87e7711d30b7 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Tue, 21 Oct 2025 15:17:45 -0700 Subject: [PATCH 1/2] [CIR] Handle overlapping values in constant init expressions This adds handling for generating constant initializers in the case where a value we are emitting overlaps with a previous constant, such as can happen when initializing a structure with bitfields. --- clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 19 +++++++++++++++++-- clang/test/CIR/CodeGen/struct-init.cpp | 15 +++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp index 800262aac8fa4..8f05014811a1f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp @@ -179,8 +179,23 @@ bool ConstantAggregateBuilder::add(mlir::TypedAttr typedAttr, CharUnits offset, } // Uncommon case: constant overlaps what we've already created. - cgm.errorNYI("overlapping constants"); - return false; + std::optional<size_t> firstElemToReplace = splitAt(offset); + if (!firstElemToReplace) + return false; + + CharUnits cSize = getSize(typedAttr); + std::optional<size_t> lastElemToReplace = splitAt(offset + cSize); + if (!lastElemToReplace) + return false; + + assert((firstElemToReplace == lastElemToReplace || allowOverwrite) && + "unexpectedly overwriting field"); + + Element newElt(typedAttr, offset); + replace(elements, *firstElemToReplace, *lastElemToReplace, {newElt}); + size = std::max(size, offset + cSize); + naturalLayout = false; + return true; } bool ConstantAggregateBuilder::addBits(llvm::APInt bits, uint64_t offsetInBits, diff --git a/clang/test/CIR/CodeGen/struct-init.cpp b/clang/test/CIR/CodeGen/struct-init.cpp index cb509994d1cbf..9d6389f5ad977 100644 --- a/clang/test/CIR/CodeGen/struct-init.cpp +++ b/clang/test/CIR/CodeGen/struct-init.cpp @@ -5,6 +5,21 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll // RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s +struct O { + unsigned int a:4; + unsigned int b:14; + unsigned int c:14; +}; + +O overlapping_init = { 3, 2, 1 }; + +// This is unintuitive. The bitfields are initialized using a struct of constants +// that maps to the bitfields but splits the value into bytes. + +// CIR: cir.global external @overlapping_init = #cir.const_record<{#cir.int<35> : !u8i, #cir.int<0> : !u8i, #cir.int<4> : !u8i, #cir.int<0> : !u8i}> : !rec_anon_struct +// LLVM: @overlapping_init = global { i8, i8, i8, i8 } { i8 35, i8 0, i8 4, i8 0 } +// OGCG: @overlapping_init = global { i8, i8, i8, i8 } { i8 35, i8 0, i8 4, i8 0 } + struct S { int a, b, c; }; >From f4a6bb74a767df0dd51177d75d214d8b7e0fdf28 Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Wed, 22 Oct 2025 14:02:25 -0700 Subject: [PATCH 2/2] Rename test struct --- clang/test/CIR/CodeGen/struct-init.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/CIR/CodeGen/struct-init.cpp b/clang/test/CIR/CodeGen/struct-init.cpp index 9d6389f5ad977..63e13dd708392 100644 --- a/clang/test/CIR/CodeGen/struct-init.cpp +++ b/clang/test/CIR/CodeGen/struct-init.cpp @@ -5,13 +5,13 @@ // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll // RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s -struct O { +struct BitfieldStruct { unsigned int a:4; unsigned int b:14; unsigned int c:14; }; -O overlapping_init = { 3, 2, 1 }; +BitfieldStruct overlapping_init = { 3, 2, 1 }; // This is unintuitive. The bitfields are initialized using a struct of constants // that maps to the bitfields but splits the value into bytes. _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
