[clang] [CIR][CodeGen] Support DesignatedInitUpdateExpr in constant emission (PR #194238)

Andy Kaylor via cfe-commits cfe-commits at lists.llvm.org
Fri May 1 12:37:58 PDT 2026


================
@@ -347,7 +347,80 @@ std::optional<size_t> ConstantAggregateBuilder::splitAt(CharUnits pos) {
 /// Hint indicates the location at which we'd like to split, but may be
 /// ignored.
 bool ConstantAggregateBuilder::split(size_t index, CharUnits hint) {
-  cgm.errorNYI("split constant at index");
+  naturalLayout = false;
+  mlir::TypedAttr c = elements[index].element;
+  CharUnits offset = elements[index].offset;
+
+  if (auto constRecord = mlir::dyn_cast<cir::ConstRecordAttr>(c)) {
+    // Expand the record into its contained member elements.
+    auto recordTy = mlir::cast<cir::RecordType>(constRecord.getType());
+    mlir::ArrayAttr members = constRecord.getMembers();
+    unsigned numMembers = members.size();
+
+    SmallVector<Element> newElems;
+    newElems.reserve(numMembers);
+    for (unsigned i = 0; i < numMembers; ++i) {
+      auto memberAttr = mlir::cast<mlir::TypedAttr>(members[i]);
+      CharUnits memberOffset =
+          offset + CharUnits::fromQuantity(
+                       recordTy.getElementOffset(dataLayout.layout, i));
+      newElems.emplace_back(memberAttr, memberOffset);
+    }
+    replace(elements, index, index + 1, newElems);
+    return true;
+  }
+
+  if (auto constArray = mlir::dyn_cast<cir::ConstArrayAttr>(c)) {
+    // Expand the array into its contained elements.
+    auto arrayTy = mlir::cast<cir::ArrayType>(constArray.getType());
+    CharUnits elemSize = getSize(arrayTy.getElementType());
+
+    if (auto arrayAttr =
+            mlir::dyn_cast<mlir::ArrayAttr>(constArray.getElts())) {
+      // Array with explicit elements (plus possible trailing zeros).
+      SmallVector<Element> newElems;
+      unsigned numExplicit = arrayAttr.size();
+      unsigned trailingZeros = constArray.getTrailingZerosNum();
+      newElems.reserve(numExplicit + trailingZeros);
+
+      for (unsigned i = 0; i < numExplicit; ++i) {
+        auto eltAttr = mlir::cast<mlir::TypedAttr>(arrayAttr[i]);
+        newElems.emplace_back(eltAttr, offset + i * elemSize);
+      }
+      // Expand trailing zeros as individual zero elements.
+      for (unsigned i = 0; i < trailingZeros; ++i) {
+        auto zeroAttr = mlir::cast<mlir::TypedAttr>(
+            cir::ZeroAttr::get(arrayTy.getElementType()));
+        newElems.emplace_back(zeroAttr, offset + (numExplicit + i) * elemSize);
+      }
+      replace(elements, index, index + 1, newElems);
+      return true;
+    }
+    // TODO: Handle StringAttr elements (char arrays) if needed.
+    return false;
+  }
+
+  if (mlir::isa<cir::ZeroAttr>(c)) {
+    // Split into two zeros at the hinted offset.
+    CharUnits elemSize = getSize(c);
+    assert(hint > offset && hint < offset + elemSize && "nothing to split");
+    // Create two byte-array padding elements to represent the two halves.
+    mlir::TypedAttr firstZero = getPadding(hint - offset);
+    mlir::TypedAttr secondZero = getPadding(offset + elemSize - hint);
+    SmallVector<Element> newElems;
+    newElems.emplace_back(firstZero, offset);
+    newElems.emplace_back(secondZero, hint);
+    replace(elements, index, index + 1, newElems);
+    return true;
+  }
+
+  if (mlir::isa<cir::UndefAttr>(c)) {
+    // Drop undef; it doesn't contribute to the final layout.
+    replace(elements, index, index + 1, SmallVector<Element>{});
+    return true;
+  }
+
+  // FIXME: We could split a cir::IntAttr if the need ever arose.
----------------
andykaylor wrote:

Can you add an errorNYI diagnostic if `c` is `cir::ConstVectorAttr` or `cir::PoisonAttr`? That won't happen with designated init expressions, but we could run into it in future uses of this function.

https://github.com/llvm/llvm-project/pull/194238


More information about the cfe-commits mailing list