================
@@ -374,6 +374,202 @@ mlir::Attribute buildRecord(ConstantEmitter &emitter, 
const APValue &val,
 }
 } // namespace ConstRecordBuilder
 
+//===----------------------------------------------------------------------===//
+//                         DesignatedInitUpdateExpr
+//===----------------------------------------------------------------------===//
+
+// Forward declaration.
+static bool emitDesignatedInitUpdater(ConstantEmitter &emitter,
+                                      CIRGenModule &cgm, QualType type,
+                                      mlir::Attribute &base,
+                                      const InitListExpr *updater);
+
+/// Apply a DesignatedInitUpdateExpr's updater InitListExpr to an existing
+/// record constant. The record's fields are decomposed, modified according to
+/// the updater, and reassembled.
+static bool updateRecord(ConstantEmitter &emitter, CIRGenModule &cgm,
+                         const RecordDecl *rd, mlir::Attribute &base,
+                         const InitListExpr *updater) {
+  CIRGenBuilderTy &builder = cgm.getBuilder();
+  const CIRGenRecordLayout &cirLayout =
+      cgm.getTypes().getCIRGenRecordLayout(rd);
+  cir::RecordType recordTy = cirLayout.getCIRType();
+
+  // Decompose the base record into mutable elements.
+  llvm::SmallVector<mlir::Attribute> elements;
+  if (auto recAttr = mlir::dyn_cast<cir::ConstRecordAttr>(base)) {
+    for (mlir::Attribute m : recAttr.getMembers())
+      elements.push_back(m);
+  } else if (mlir::isa<cir::ZeroAttr>(base)) {
+    // Zero-initialized base: fill with per-field zero attrs.
+    elements.resize(recordTy.getNumElements());
+    for (unsigned i = 0; i < recordTy.getNumElements(); ++i)
+      elements[i] = builder.getZeroInitAttr(recordTy.getElementType(i));
+  } else if (mlir::isa<cir::ConstVectorAttr>(base) ||
+             mlir::isa<cir::PoisonAttr>(base)) {
+    cgm.errorNYI("updateRecord: ConstVectorAttr or PoisonAttr base");
+    return false;
+  } else {
+    cgm.errorNYI("updateRecord: unsupported base attribute kind");
+    return false;
+  }
+
+  unsigned fieldNo = 0;
+  for (const FieldDecl *field : rd->fields()) {
+    if (field->isUnnamedBitField()) {
+      ++fieldNo;
+      continue;
+    }
+    if (fieldNo >= updater->getNumInits())
+      break;
+
+    const Expr *init = updater->getInit(fieldNo);
+    ++fieldNo;
+
+    if (isa<NoInitExpr>(init))
+      continue;
+
+    if (!cirLayout.hasCIRField(field))
+      continue;
+
+    unsigned fieldIdx = cirLayout.getCIRFieldNo(field);
+
+    // When the updater contains a nested InitListExpr for a sub-aggregate,
+    // it represents additional overwriting of the current value (not a new
+    // independent constant).
+    if ((field->getType()->isArrayType() || field->getType()->isRecordType())) 
{
+      if (auto *subILE = dyn_cast<InitListExpr>(init)) {
+        if (!emitDesignatedInitUpdater(emitter, cgm, field->getType(),
+                                       elements[fieldIdx], subILE))
+          return false;
+        continue;
+      }
+      // For non-InitListExpr aggregate inits (e.g. compound literals),
+      // fall through to the regular emission below.
+    }
+
+    mlir::Attribute eltAttr =
+        emitter.tryEmitPrivateForMemory(init, field->getType());
+    if (!eltAttr)
+      return false;
+
+    if (field->isBitField()) {
+      elements[fieldIdx] = ConstRecordBuilder::setBitfieldInit(
+          cgm, cirLayout, builder, field, elements[fieldIdx], eltAttr);
+    } else {
+      elements[fieldIdx] = eltAttr;
+    }
+  }
+
+  base = builder.getConstRecordOrZeroAttr(builder.getArrayAttr(elements),
+                                          recordTy.getPacked(),
+                                          recordTy.getPadded(), recordTy);
+  return true;
+}
+
+/// Apply a DesignatedInitUpdateExpr's updater InitListExpr to an existing
+/// array constant. Individual array elements are modified according to
+/// the updater.
+static bool updateArray(ConstantEmitter &emitter, CIRGenModule &cgm,
+                        QualType type, mlir::Attribute &base,
+                        const InitListExpr *updater) {
+  CIRGenBuilderTy &builder = cgm.getBuilder();
+  auto cat = cgm.getASTContext().getAsConstantArrayType(type);
+  if (!cat)
+    return false;
+
+  QualType elemType = cat->getElementType();
+  uint64_t numElements = cat->getZExtSize();
+
+  // Decompose the base array into mutable elements.
+  llvm::SmallVector<mlir::Attribute> elements;
+  elements.resize(numElements);
+
+  if (auto arrAttr = mlir::dyn_cast<cir::ConstArrayAttr>(base)) {
+    auto eltsAttr = mlir::dyn_cast<mlir::ArrayAttr>(arrAttr.getElts());
+    if (!eltsAttr) {
+      cgm.errorNYI("updateArray: string literal array base");
+      return false;
+    }
+    for (unsigned i = 0; i < eltsAttr.size(); ++i)
+      elements[i] = eltsAttr[i];
----------------
erichkeane wrote:

if you take my above, we can just do:
```
  elements.insert(elements.begin(), eltsAttr.begin(), eltsAttr.end());
```

https://github.com/llvm/llvm-project/pull/194238
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to