https://github.com/andykaylor created https://github.com/llvm/llvm-project/pull/184933
If an array is explicitly initialized with more than eight non-zero values followed by a number of explicit zero initializers, CIR generates a constant record initializer with a constant array that is declared as the size of the non-zero initializers but with the explicit zero initializers included in the array initialization attribute. This resulted in an error when we tried to lower that attribute to LLVM IR. This patch fixes that problem and adds a verifier to ConstantArrayAttr to check for that condition. >From ea1b1d53aa728199d32f2509f3dc7b0a0ab3624a Mon Sep 17 00:00:00 2001 From: Andy Kaylor <[email protected]> Date: Thu, 5 Mar 2026 17:33:02 -0800 Subject: [PATCH] [CIR] Fix array constant initialization with trailing zeros If an array is explicitly initialized with more than eight non-zero values followed by a number of explicit zero initializers, CIR generates a constant record initializer with a constant array that is declared as the size of the non-zero initializers but with the explicit zero initializers included in the array initialization attribute. This resulted in an error when we tried to lower that attribute to LLVM IR. This patch fixes that problem and adds a verifier to ConstantArrayAttr to check for that condition. --- clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 4 ++-- clang/lib/CIR/Dialect/IR/CIRAttrs.cpp | 4 ++++ clang/test/CIR/CodeGen/array.cpp | 23 ++++++++++++++++++++ clang/test/CIR/IR/invalid-const-array.cir | 6 +++++ 4 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 clang/test/CIR/IR/invalid-const-array.cir diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp index 9d17c8937aac9..b697ca5cd3f6d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp @@ -1167,8 +1167,8 @@ emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType, // (the nonzero data and the zeroinitializer). SmallVector<mlir::Attribute> eles; eles.reserve(nonzeroLength); - for (const auto &element : elements) - eles.push_back(element); + for (unsigned i = 0; i < nonzeroLength; ++i) + eles.push_back(elements[i]); auto initial = cir::ConstArrayAttr::get( cir::ArrayType::get(commonElementType, nonzeroLength), mlir::ArrayAttr::get(builder.getContext(), eles)); diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp index 67509f3cf452a..4cd2073bf49aa 100644 --- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp @@ -501,6 +501,10 @@ ConstArrayAttr::verify(function_ref<InFlightDiagnostic()> emitError, Type type, const auto arrayTy = mlir::cast<ArrayType>(type); // Make sure both number of elements and subelement types match type. + if (arrayAttr.size() > arrayTy.getSize()) + return emitError() << "constant array has " << arrayAttr.size() + << " values but array type has size " + << arrayTy.getSize(); if (arrayTy.getSize() != arrayAttr.size() + trailingZerosNum) return emitError() << "constant array size should match type size"; return success(); diff --git a/clang/test/CIR/CodeGen/array.cpp b/clang/test/CIR/CodeGen/array.cpp index 4808abbc3200d..8edcde82c4dbf 100644 --- a/clang/test/CIR/CodeGen/array.cpp +++ b/clang/test/CIR/CodeGen/array.cpp @@ -86,6 +86,29 @@ int g[16] = {1, 2, 3, 4, 5, 6, 7, 8}; // OGCG-SAME: i32 5, i32 6, i32 7, i32 8], // OGCG-SAME: [8 x i32] zeroinitializer }> +// If we have explicit trailing zeros, those should still be combined into +// a zero initializer array. +int h[16] = {1, 2, 3, 4, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0}; + +// CIR: cir.global external @h = #cir.const_record<{ +// CIR-SAME: #cir.const_array<[#cir.int<1> : !s32i, #cir.int<2> : !s32i, +// CIR-SAME: #cir.int<3> : !s32i, #cir.int<4> : !s32i, +// CIR-SAME: #cir.int<5> : !s32i, #cir.int<6> : !s32i, +// CIR-SAME: #cir.int<7> : !s32i, #cir.int<8> : !s32i]> +// CIR-SAME: : !cir.array<!s32i x 8>, +// CIR-SAME: #cir.zero : !cir.array<!s32i x 8>}> : !rec_anon_struct1 + +// LLVM: @h = global <{ [8 x i32], [8 x i32] }> +// LLVM-SAME: <{ [8 x i32] +// LLVM-SAME: [i32 1, i32 2, i32 3, i32 4, +// LLVM-SAME: i32 5, i32 6, i32 7, i32 8], +// LLVM-SAME: [8 x i32] zeroinitializer }> + +// OGCG: @h = global <{ [8 x i32], [8 x i32] }> +// OGCG-SAME: <{ [8 x i32] +// OGCG-SAME: [i32 1, i32 2, i32 3, i32 4, +// OGCG-SAME: i32 5, i32 6, i32 7, i32 8], +// OGCG-SAME: [8 x i32] zeroinitializer }> extern int b[10]; // CIR: cir.global "private" external @b : !cir.array<!s32i x 10> diff --git a/clang/test/CIR/IR/invalid-const-array.cir b/clang/test/CIR/IR/invalid-const-array.cir new file mode 100644 index 0000000000000..e2de226e5533e --- /dev/null +++ b/clang/test/CIR/IR/invalid-const-array.cir @@ -0,0 +1,6 @@ +// RUN: cir-opt %s -verify-diagnostics + +!s32i = !cir.int<s, 32> + +// expected-error @below {{constant array has 4 values but array type has size 2}} +cir.global external @a = #cir.const_array<[#cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<0> : !s32i, #cir.int<0> : !s32i]> : !cir.array<!s32i x 2> _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
