[clang] [CIR] Upstream global initialization for ArrayType (PR #131657)

Amr Hesham via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 18 13:15:38 PDT 2025


https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/131657

>From 4ae9c422e786f843f5f019a5d9e55232ec6c8694 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Fri, 14 Mar 2025 21:46:57 +0100
Subject: [PATCH 1/3] [CIR] Upstream global initialization for ArrayType

---
 .../include/clang/CIR/Dialect/IR/CIRAttrs.td  |  42 ++++++
 clang/lib/CIR/CodeGen/CIRGenBuilder.h         |  34 +++++
 clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h |   6 +-
 clang/lib/CIR/CodeGen/CIRGenDecl.cpp          |   1 -
 clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp  | 122 ++++++++++++++++--
 clang/lib/CIR/CodeGen/CIRGenModule.cpp        |  38 +-----
 clang/lib/CIR/Dialect/IR/CIRAttrs.cpp         | 109 ++++++++++++++++
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       |   9 ++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  75 ++++++++++-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h   |   6 +
 clang/test/CIR/CodeGen/array.cpp              |  25 +++-
 clang/test/CIR/IR/array.cir                   |  24 +++-
 clang/test/CIR/Lowering/array.cpp             |  29 ++++-
 13 files changed, 453 insertions(+), 67 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
index 7b3741de29075..3680ded4afafe 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRAttrs.td
@@ -154,6 +154,48 @@ def FPAttr : CIR_Attr<"FP", "fp", [TypedAttrInterface]> {
   }];
 }
 
+
+//===----------------------------------------------------------------------===//
+// ConstArrayAttr
+//===----------------------------------------------------------------------===//
+
+def ConstArrayAttr : CIR_Attr<"ConstArray", "const_array", [TypedAttrInterface]> {
+  let summary = "A constant array from ArrayAttr or StringRefAttr";
+  let description = [{
+    An CIR array attribute is an array of literals of the specified attr types.
+  }];
+
+  let parameters = (ins AttributeSelfTypeParameter<"">:$type,
+                        "mlir::Attribute":$elts,
+                        "int":$trailingZerosNum);
+
+  // Define a custom builder for the type; that removes the need to pass
+  // in an MLIRContext instance, as it can be infered from the `type`.
+  let builders = [
+    AttrBuilderWithInferredContext<(ins "cir::ArrayType":$type,
+                                        "mlir::Attribute":$elts), [{
+      int zeros = 0;
+      auto typeSize = mlir::cast<cir::ArrayType>(type).getSize();
+      if (auto str = mlir::dyn_cast<mlir::StringAttr>(elts))
+        zeros = typeSize - str.size();
+      else
+        zeros = typeSize - mlir::cast<mlir::ArrayAttr>(elts).size();
+
+      return $_get(type.getContext(), type, elts, zeros);
+    }]>
+  ];
+
+  // Printing and parsing available in CIRDialect.cpp
+  let hasCustomAssemblyFormat = 1;
+
+  // Enable verifier.
+  let genVerifyDecl = 1;
+
+  let extraClassDeclaration = [{
+    bool hasTrailingZeros() const { return getTrailingZerosNum() != 0; };
+  }];
+}
+
 //===----------------------------------------------------------------------===//
 // ConstPtrAttr
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 260ee25719be1..a2a75148ee884 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -43,6 +43,40 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
     assert(!cir::MissingFeatures::unsizedTypes());
     return false;
   }
+
+  bool isNullValue(mlir::Attribute attr) const {
+    if (mlir::isa<cir::ZeroAttr>(attr))
+      return true;
+
+    if (const auto ptrVal = mlir::dyn_cast<cir::ConstPtrAttr>(attr))
+      return ptrVal.isNullValue();
+
+    if (const auto intVal = mlir::dyn_cast<cir::IntAttr>(attr))
+      return intVal.isNullValue();
+
+    if (const auto boolVal = mlir::dyn_cast<cir::BoolAttr>(attr))
+      return !boolVal.getValue();
+
+    if (auto fpAttr = mlir::dyn_cast<cir::FPAttr>(attr)) {
+      auto fpVal = fpAttr.getValue();
+      bool ignored;
+      llvm::APFloat fv(+0.0);
+      fv.convert(fpVal.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
+                 &ignored);
+      return fv.bitwiseIsEqual(fpVal);
+    }
+
+    if (const auto arrayVal = mlir::dyn_cast<cir::ConstArrayAttr>(attr)) {
+      if (mlir::isa<mlir::StringAttr>(arrayVal.getElts()))
+        return false;
+      for (const auto elt : mlir::cast<mlir::ArrayAttr>(arrayVal.getElts())) {
+        if (!isNullValue(elt))
+          return false;
+      }
+      return true;
+    }
+    return false;
+  }
 };
 
 } // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h b/clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h
index 5b22a8e59908d..ca4e607992bbc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h
+++ b/clang/lib/CIR/CodeGen/CIRGenConstantEmitter.h
@@ -20,7 +20,6 @@
 
 #include "CIRGenFunction.h"
 #include "CIRGenModule.h"
-#include "llvm/ADT/SmallVector.h"
 
 namespace clang::CIRGen {
 
@@ -41,6 +40,9 @@ class ConstantEmitter {
   /// block addresses or PredefinedExprs.
   ConstantEmitter(CIRGenFunction &cgf) : cgm(cgf.cgm), cgf(&cgf) {}
 
+  ConstantEmitter(CIRGenModule &cgm, CIRGenFunction *cgf = nullptr)
+      : cgm(cgm), cgf(cgf) {}
+
   ConstantEmitter(const ConstantEmitter &other) = delete;
   ConstantEmitter &operator=(const ConstantEmitter &other) = delete;
 
@@ -66,7 +68,7 @@ class ConstantEmitter {
   mlir::Attribute emitAbstract(SourceLocation loc, const APValue &value,
                                QualType t);
 
-  mlir::Attribute tryEmitConstantExpr(const ConstantExpr *CE);
+  mlir::Attribute tryEmitConstantExpr(const ConstantExpr *ce);
 
   // These are private helper routines of the constant emitter that
   // can't actually be private because things are split out into helper
diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
index 27ed0113a4f55..a93e8dbcb42de 100644
--- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp
@@ -225,7 +225,6 @@ void CIRGenFunction::emitScalarInit(const Expr *init, mlir::Location loc,
   }
   assert(!cir::MissingFeatures::emitNullabilityCheck());
   emitStoreThroughLValue(RValue::get(value), lvalue, true);
-  return;
 }
 
 void CIRGenFunction::emitExprAsInit(const Expr *init, const ValueDecl *d,
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 1ea7f6212766c..d3c22f54127c5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -158,13 +158,56 @@ class ConstExprEmitter
 
 // TODO(cir): this can be shared with LLVM's codegen
 static QualType getNonMemoryType(CIRGenModule &cgm, QualType type) {
-  if (auto at = type->getAs<AtomicType>()) {
+  if (const auto *at = type->getAs<AtomicType>()) {
     return cgm.getASTContext().getQualifiedType(at->getValueType(),
                                                 type.getQualifiers());
   }
   return type;
 }
 
+static mlir::Attribute
+emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
+                  mlir::Type commonElementType, unsigned arrayBound,
+                  SmallVectorImpl<mlir::TypedAttr> &elements,
+                  mlir::TypedAttr filter) {
+  const auto &builder = cgm.getBuilder();
+
+  unsigned nonzeroLength = arrayBound;
+  if (elements.size() < nonzeroLength && builder.isNullValue(filter))
+    nonzeroLength = elements.size();
+
+  if (nonzeroLength == elements.size()) {
+    while (nonzeroLength > 0 &&
+           builder.isNullValue(elements[nonzeroLength - 1]))
+      --nonzeroLength;
+  }
+
+  if (nonzeroLength == 0)
+    return cir::ZeroAttr::get(builder.getContext(), desiredType);
+
+  const unsigned trailingZeroes = arrayBound - nonzeroLength;
+  if (trailingZeroes >= 8) {
+    if (elements.size() < nonzeroLength)
+      cgm.errorNYI("missing initializer for non-zero element");
+  } else if (elements.size() != arrayBound) {
+    elements.resize(arrayBound, filter);
+
+    if (filter.getType() != commonElementType)
+      cgm.errorNYI(
+          "array filter type should always be the same as element type");
+  }
+
+  SmallVector<mlir::Attribute, 4> eles;
+  eles.reserve(elements.size());
+
+  for (const auto &element : elements)
+    eles.push_back(element);
+
+  return cir::ConstArrayAttr::get(
+      cir::ArrayType::get(builder.getContext(), commonElementType, arrayBound),
+      mlir::ArrayAttr::get(builder.getContext(), eles));
+}
+
 //===----------------------------------------------------------------------===//
 //                             ConstantEmitter
 //===----------------------------------------------------------------------===//
@@ -271,16 +314,61 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
         cgm.getASTContext().getTargetInfo().useFP16ConversionIntrinsics()) {
       cgm.errorNYI("ConstExprEmitter::tryEmitPrivate half");
       return {};
-    } else {
-      mlir::Type ty = cgm.convertType(destType);
-      assert(mlir::isa<cir::CIRFPTypeInterface>(ty) &&
-             "expected floating-point type");
-      return cgm.getBuilder().getAttr<cir::FPAttr>(ty, init);
     }
+
+    mlir::Type ty = cgm.convertType(destType);
+    assert(mlir::isa<cir::CIRFPTypeInterface>(ty) &&
+           "expected floating-point type");
+    return cgm.getBuilder().getAttr<cir::FPAttr>(ty, init);
   }
   case APValue::Array: {
-    cgm.errorNYI("ConstExprEmitter::tryEmitPrivate array");
-    return {};
+    const ArrayType *arrayTy = cgm.getASTContext().getAsArrayType(destType);
+    const QualType arrayElementTy = arrayTy->getElementType();
+    const unsigned numElements = value.getArraySize();
+    const unsigned numInitElts = value.getArrayInitializedElts();
+
+    mlir::Attribute filter;
+    if (value.hasArrayFiller()) {
+      filter =
+          tryEmitPrivate(value.getArrayFiller(), arrayTy->getElementType());
+      if (!filter)
+        return {};
+    }
+
+    SmallVector<mlir::TypedAttr, 16> elements;
+    if (filter && builder.isNullValue(filter))
+      elements.reserve(numInitElts + 1);
+    else
+      elements.reserve(numInitElts);
+
+    mlir::Type commonElementType;
+    for (unsigned i = 0; i < numInitElts; ++i) {
+      const APValue &arrayElement = value.getArrayInitializedElt(i);
+      const mlir::Attribute element =
+          tryEmitPrivateForMemory(arrayElement, arrayElementTy);
+      if (!element)
+        return {};
+
+      const mlir::TypedAttr elementTyped = mlir::cast<mlir::TypedAttr>(element);
+      if (i == 0)
+        commonElementType = elementTyped.getType();
+      else if (elementTyped.getType() != commonElementType) {
+        cgm.errorNYI("ConstExprEmitter::tryEmitPrivate Array without common "
+                     "element type");
+        return {};
+      }
+
+      elements.push_back(elementTyped);
+    }
+
+    mlir::TypedAttr typedFilter =
+        llvm::dyn_cast_or_null<mlir::TypedAttr>(filter);
+    if (filter && !typedFilter)
+      cgm.errorNYI("array filter should always be typed");
+
+    mlir::Type desiredType = cgm.convertType(destType);
+    return emitArrayConstant(cgm, desiredType, commonElementType, numElements,
+                             elements, typedFilter);
   }
   case APValue::Vector: {
     cgm.errorNYI("ConstExprEmitter::tryEmitPrivate vector");
@@ -290,9 +378,23 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
     cgm.errorNYI("ConstExprEmitter::tryEmitPrivate member pointer");
     return {};
   }
-  case APValue::LValue:
-    cgm.errorNYI("ConstExprEmitter::tryEmitPrivate lvalue");
+  case APValue::LValue: {
+
+    if (value.getLValueBase()) {
+      cgm.errorNYI("non-null pointer initialization");
+    } else {
+
+      mlir::Type desiredType = cgm.convertType(destType);
+      if (const cir::PointerType ptrType =
+              mlir::dyn_cast<cir::PointerType>(desiredType)) {
+        return builder.getConstPtrAttr(ptrType,
+                                       value.getLValueOffset().getQuantity());
+      } else {
+        llvm_unreachable("non-pointer variable initialized with a pointer");
+      }
+    }
     return {};
+  }
   case APValue::Struct:
   case APValue::Union:
     cgm.errorNYI("ConstExprEmitter::tryEmitPrivate struct or union");
diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
index 0e3e15ca2cadc..c7620a8355b2f 100644
--- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "CIRGenModule.h"
+#include "CIRGenConstantEmitter.h"
 #include "CIRGenFunction.h"
 
 #include "clang/AST/ASTContext.h"
@@ -127,7 +128,8 @@ void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
 
 void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
                                            bool isTentative) {
-  mlir::Type type = convertType(vd->getType());
+  const QualType astTy = vd->getType();
+  const mlir::Type type = convertType(vd->getType());
   if (clang::IdentifierInfo *identifier = vd->getIdentifier()) {
     auto varOp = builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()),
                                                identifier->getName(), type);
@@ -140,38 +142,8 @@ void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
     if (initExpr) {
       mlir::Attribute initializer;
       if (APValue *value = initDecl->evaluateValue()) {
-        switch (value->getKind()) {
-        case APValue::Int: {
-          if (mlir::isa<cir::BoolType>(type))
-            initializer =
-                builder.getCIRBoolAttr(value->getInt().getZExtValue());
-          else
-            initializer = builder.getAttr<cir::IntAttr>(type, value->getInt());
-          break;
-        }
-        case APValue::Float: {
-          initializer = builder.getAttr<cir::FPAttr>(type, value->getFloat());
-          break;
-        }
-        case APValue::LValue: {
-          if (value->getLValueBase()) {
-            errorNYI(initExpr->getSourceRange(),
-                     "non-null pointer initialization");
-          } else {
-            if (auto ptrType = mlir::dyn_cast<cir::PointerType>(type)) {
-              initializer = builder.getConstPtrAttr(
-                  ptrType, value->getLValueOffset().getQuantity());
-            } else {
-              llvm_unreachable(
-                  "non-pointer variable initialized with a pointer");
-            }
-          }
-          break;
-        }
-        default:
-          errorNYI(initExpr->getSourceRange(), "unsupported initializer kind");
-          break;
-        }
+        ConstantEmitter emitter(*this);
+        initializer = emitter.tryEmitPrivateForMemory(*value, astTy);
       } else {
         errorNYI(initExpr->getSourceRange(), "non-constant initializer");
       }
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 8e8f7d5b7d7cb..8dfe56b75a47b 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -190,6 +190,115 @@ LogicalResult FPAttr::verify(function_ref<InFlightDiagnostic()> emitError,
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// CIR ConstArrayAttr
+//===----------------------------------------------------------------------===//
+
+LogicalResult
+ConstArrayAttr::verify(function_ref<::mlir::InFlightDiagnostic()> emitError,
+                       Type type, Attribute elts, int trailingZerosNum) {
+
+  if (!(mlir::isa<ArrayAttr>(elts) || mlir::isa<StringAttr>(elts)))
+    return emitError() << "constant array expects ArrayAttr or StringAttr";
+
+  if (StringAttr strAttr = mlir::dyn_cast<StringAttr>(elts)) {
+    ArrayType arrayTy = mlir::cast<ArrayType>(type);
+    IntType intTy = mlir::dyn_cast<IntType>(arrayTy.getEltType());
+
+    // TODO: add CIR type for char.
+    if (!intTy || intTy.getWidth() != 8) {
+      emitError() << "constant array element for string literals expects "
+                     "!cir.int<u, 8> element type";
+      return failure();
+    }
+    return success();
+  }
+
+  assert(mlir::isa<ArrayAttr>(elts));
+  ArrayAttr arrayAttr = mlir::cast<mlir::ArrayAttr>(elts);
+  ArrayType arrayTy = mlir::cast<ArrayType>(type);
+
+  // Make sure both number of elements and subelement types match type.
+  if (arrayTy.getSize() != arrayAttr.size() + trailingZerosNum)
+    return emitError() << "constant array size should match type size";
+  return success();
+}
+
+Attribute ConstArrayAttr::parse(AsmParser &parser, Type type) {
+  ::mlir::FailureOr<Type> resultTy;
+  ::mlir::FailureOr<Attribute> resultVal;
+  ::llvm::SMLoc loc = parser.getCurrentLocation();
+  (void)loc;
+  // Parse literal '<'
+  if (parser.parseLess())
+    return {};
+
+  // Parse variable 'value'
+  resultVal = FieldParser<Attribute>::parse(parser);
+  if (failed(resultVal)) {
+    parser.emitError(
+        parser.getCurrentLocation(),
+        "failed to parse ConstArrayAttr parameter 'value' which is "
+        "to be a `Attribute`");
+    return {};
+  }
+
+  // ArrayAttrrs have per-element type, not the type of the array...
+  if (mlir::dyn_cast<ArrayAttr>(*resultVal)) {
+    // Array has implicit type: infer from const array type.
+    if (parser.parseOptionalColon().failed()) {
+      resultTy = type;
+    } else { // Array has explicit type: parse it.
+      resultTy = FieldParser<Type>::parse(parser);
+      if (failed(resultTy)) {
+        parser.emitError(
+            parser.getCurrentLocation(),
+            "failed to parse ConstArrayAttr parameter 'type' which is "
+            "to be a `::mlir::Type`");
+        return {};
+      }
+    }
+  } else {
+    assert(mlir::isa<TypedAttr>(*resultVal) && "IDK");
+    auto ta = mlir::cast<TypedAttr>(*resultVal);
+    resultTy = ta.getType();
+    if (mlir::isa<mlir::NoneType>(*resultTy)) {
+      parser.emitError(parser.getCurrentLocation(),
+                       "expected type declaration for string literal");
+      return {};
+    }
+  }
+
+  auto zeros = 0;
+  if (parser.parseOptionalComma().succeeded()) {
+    if (parser.parseOptionalKeyword("trailing_zeros").succeeded()) {
+      auto typeSize = mlir::cast<cir::ArrayType>(resultTy.value()).getSize();
+      auto elts = resultVal.value();
+      if (auto str = mlir::dyn_cast<mlir::StringAttr>(elts))
+        zeros = typeSize - str.size();
+      else
+        zeros = typeSize - mlir::cast<mlir::ArrayAttr>(elts).size();
+    } else {
+      return {};
+    }
+  }
+
+  // Parse literal '>'
+  if (parser.parseGreater())
+    return {};
+
+  return parser.getChecked<ConstArrayAttr>(
+      loc, parser.getContext(), resultTy.value(), resultVal.value(), zeros);
+}
+
+void ConstArrayAttr::print(AsmPrinter &printer) const {
+  printer << "<";
+  printer.printStrippedAttrOrType(getElts());
+  if (getTrailingZerosNum())
+    printer << ", trailing_zeros";
+  printer << ">";
+}
+
 //===----------------------------------------------------------------------===//
 // CIR Dialect
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index d041791770d82..467e6237ef01a 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -149,6 +149,12 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
     return success();
   }
 
+  if (isa<cir::ZeroAttr>(attrType)) {
+    if (::mlir::isa<cir::ArrayType>(opType))
+      return success();
+    return op->emitOpError("zero expects struct or array type");
+  }
+
   if (mlir::isa<cir::BoolAttr>(attrType)) {
     if (!mlir::isa<cir::BoolType>(opType))
       return op->emitOpError("result type (")
@@ -166,6 +172,9 @@ static LogicalResult checkConstantTypes(mlir::Operation *op, mlir::Type opType,
     return success();
   }
 
+  if (mlir::isa<cir::ConstArrayAttr>(attrType))
+    return success();
+
   assert(isa<TypedAttr>(attrType) && "What else could we be looking at here?");
   return op->emitOpError("global with type ")
          << cast<TypedAttr>(attrType).getType() << " not yet supported";
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 0cd27ecf1a3bd..f0b9986a9efaf 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -113,6 +113,21 @@ static mlir::Value emitToMemory(mlir::ConversionPatternRewriter &rewriter,
   return value;
 }
 
+static mlir::Value
+emitCirAttrToMemory(mlir::Operation *parentOp, mlir::Attribute attr,
+                    mlir::ConversionPatternRewriter &rewriter,
+                    const mlir::TypeConverter *converter,
+                    mlir::DataLayout const &dataLayout) {
+
+  mlir::Value loweredValue =
+      lowerCirAttrAsValue(parentOp, attr, rewriter, converter);
+  if (auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr)) {
+    return emitToMemory(rewriter, dataLayout, boolAttr.getType(), loweredValue);
+  }
+
+  return loweredValue;
+}
+
 mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage) {
   using CIR = cir::GlobalLinkageKind;
   using LLVM = mlir::LLVM::Linkage;
@@ -151,14 +166,16 @@ class CIRAttrToValue {
 
   mlir::Value visit(mlir::Attribute attr) {
     return llvm::TypeSwitch<mlir::Attribute, mlir::Value>(attr)
-        .Case<cir::IntAttr, cir::FPAttr, cir::ConstPtrAttr>(
-            [&](auto attrT) { return visitCirAttr(attrT); })
+        .Case<cir::IntAttr, cir::FPAttr, cir::ConstArrayAttr, cir::ConstPtrAttr,
+              cir::ZeroAttr>([&](auto attrT) { return visitCirAttr(attrT); })
         .Default([&](auto attrT) { return mlir::Value(); });
   }
 
   mlir::Value visitCirAttr(cir::IntAttr intAttr);
   mlir::Value visitCirAttr(cir::FPAttr fltAttr);
   mlir::Value visitCirAttr(cir::ConstPtrAttr ptrAttr);
+  mlir::Value visitCirAttr(cir::ConstArrayAttr attr);
+  mlir::Value visitCirAttr(cir::ZeroAttr attr);
 
 private:
   mlir::Operation *parentOp;
@@ -166,6 +183,18 @@ class CIRAttrToValue {
   const mlir::TypeConverter *converter;
 };
 
+/// Switches on the type of attribute and calls the appropriate conversion.
+mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp,
+                                const mlir::Attribute attr,
+                                mlir::ConversionPatternRewriter &rewriter,
+                                const mlir::TypeConverter *converter) {
+  CIRAttrToValue valueConverter(parentOp, rewriter, converter);
+  auto value = valueConverter.visit(attr);
+  if (!value)
+    llvm_unreachable("unhandled attribute type");
+  return value;
+}
+
 /// IntAttr visitor.
 mlir::Value CIRAttrToValue::visitCirAttr(cir::IntAttr intAttr) {
   mlir::Location loc = parentOp->getLoc();
@@ -195,6 +224,43 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::FPAttr fltAttr) {
       loc, converter->convertType(fltAttr.getType()), fltAttr.getValue());
 }
 
+// ConstArrayAttr visitor
+mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
+  auto llvmTy = converter->convertType(attr.getType());
+  auto loc = parentOp->getLoc();
+  mlir::Value result;
+
+  if (auto zeros = attr.getTrailingZerosNum()) {
+    auto arrayTy = attr.getType();
+    result = rewriter.create<mlir::LLVM::ZeroOp>(
+        loc, converter->convertType(arrayTy));
+  } else {
+    result = rewriter.create<mlir::LLVM::UndefOp>(loc, llvmTy);
+  }
+
+  // Iteratively lower each constant element of the array.
+  if (auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
+    for (auto [idx, elt] : llvm::enumerate(arrayAttr)) {
+      mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
+      mlir::Value init =
+          emitCirAttrToMemory(parentOp, elt, rewriter, converter, dataLayout);
+      result =
+          rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
+    }
+  } else {
+    llvm_unreachable("unexpected ConstArrayAttr elements");
+  }
+
+  return result;
+}
+
+/// ZeroAttr visitor.
+mlir::Value CIRAttrToValue::visitCirAttr(cir::ZeroAttr attr) {
+  auto loc = parentOp->getLoc();
+  return rewriter.create<mlir::LLVM::ZeroOp>(
+      loc, converter->convertType(attr.getType()));
+}
+
 // This class handles rewriting initializer attributes for types that do not
 // require region initialization.
 class GlobalInitAttrRewriter {
@@ -493,7 +559,7 @@ CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal(
     cir::GlobalOp op, mlir::Attribute init,
     mlir::ConversionPatternRewriter &rewriter) const {
   // TODO: Generalize this handling when more types are needed here.
-  assert(isa<cir::ConstPtrAttr>(init));
+  assert((isa<cir::ConstArrayAttr, cir::ConstPtrAttr, cir::ZeroAttr>(init)));
 
   // TODO(cir): once LLVM's dialect has proper equivalent attributes this
   // should be updated. For now, we use a custom op to initialize globals
@@ -546,7 +612,8 @@ mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewrite(
         op.emitError() << "unsupported initializer '" << init.value() << "'";
         return mlir::failure();
       }
-    } else if (mlir::isa<cir::ConstPtrAttr>(init.value())) {
+    } else if (mlir::isa<cir::ConstArrayAttr, cir::ConstPtrAttr, cir::ZeroAttr>(
+                   init.value())) {
       // TODO(cir): once LLVM's dialect has proper equivalent attributes this
       // should be updated. For now, we use a custom op to initialize globals
       // to the appropriate value.
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
index d090bbe4f2e10..544d7d331b75f 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
@@ -20,6 +20,12 @@ namespace cir {
 
 namespace direct {
 
+/// Convert a CIR attribute to an LLVM attribute. May use the datalayout for
+/// lowering attributes to-be-stored in memory.
+mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp, mlir::Attribute attr,
+                                mlir::ConversionPatternRewriter &rewriter,
+                                const mlir::TypeConverter *converter);
+
 mlir::LLVM::Linkage convertLinkage(cir::GlobalLinkageKind linkage);
 
 class CIRToLLVMReturnOpLowering
diff --git a/clang/test/CIR/CodeGen/array.cpp b/clang/test/CIR/CodeGen/array.cpp
index 02ecdc11e1d94..294c4af822c44 100644
--- a/clang/test/CIR/CodeGen/array.cpp
+++ b/clang/test/CIR/CodeGen/array.cpp
@@ -12,15 +12,30 @@ extern int b[10];
 extern int bb[10][5];
 // CHECK: cir.global external @bb : !cir.array<!cir.array<!cir.int<s, 32> x 5> x 10>
 
-void f() {
+int c[10] = {};
+// CHECK: cir.global external @c = #cir.zero : !cir.array<!cir.int<s, 32> x 10>
+
+int d[3] = {1, 2, 3};
+// CHECK: cir.global external @d = #cir.const_array<[#cir.int<1> : !cir.int<s, 32>, #cir.int<2> : !cir.int<s, 32>, #cir.int<3> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 3>
+
+int dd[3][2] = {{1, 2}, {3, 4}, {5, 6}};
+// CHECK: cir.global external @dd = #cir.const_array<[#cir.const_array<[#cir.int<1> : !cir.int<s, 32>, #cir.int<2> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 2>, #cir.const_array<[#cir.int<3> : !cir.int<s, 32>, #cir.int<4> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 2>, #cir.const_array<[#cir.int<5> : !cir.int<s, 32>, #cir.int<6> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 2>]> : !cir.array<!cir.array<!cir.int<s, 32> x 2> x 3>
+
+int e[10] = {1, 2};
+// CHECK: cir.global external @e = #cir.const_array<[#cir.int<1> : !cir.int<s, 32>, #cir.int<2> : !cir.int<s, 32>], trailing_zeros> : !cir.array<!cir.int<s, 32> x 10>
+
+int f[5] = {1, 2};
+// CHECK: cir.global external @f = #cir.const_array<[#cir.int<1> : !cir.int<s, 32>, #cir.int<2> : !cir.int<s, 32>, #cir.int<0> : !cir.int<s, 32>, #cir.int<0> : !cir.int<s, 32>, #cir.int<0> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 5>
+
+void func() {
   int l[10];
   // CHECK: %[[ARR:.*]] = cir.alloca !cir.array<!cir.int<s, 32> x 10>, !cir.ptr<!cir.array<!cir.int<s, 32> x 10>>, ["l"]
 }
 
-void f2(int p[10]) {}
-// CHECK: cir.func @f2(%arg0: !cir.ptr<!cir.int<s, 32>>
+void func2(int p[10]) {}
+// CHECK: cir.func @func2(%arg0: !cir.ptr<!cir.int<s, 32>>
 // CHECK: cir.alloca !cir.ptr<!cir.int<s, 32>>, !cir.ptr<!cir.ptr<!cir.int<s, 32>>>, ["p", init]
 
-void f3(int pp[10][5]) {}
-// CHECK: cir.func @f3(%arg0: !cir.ptr<!cir.array<!cir.int<s, 32> x 5>>
+void func3(int pp[10][5]) {}
+// CHECK: cir.func @func3(%arg0: !cir.ptr<!cir.array<!cir.int<s, 32> x 5>>
 // CHECK: cir.alloca !cir.ptr<!cir.array<!cir.int<s, 32> x 5>>, !cir.ptr<!cir.ptr<!cir.array<!cir.int<s, 32> x 5>>>
diff --git a/clang/test/CIR/IR/array.cir b/clang/test/CIR/IR/array.cir
index 293a202d18a92..790a988d9b9d8 100644
--- a/clang/test/CIR/IR/array.cir
+++ b/clang/test/CIR/IR/array.cir
@@ -14,35 +14,47 @@ cir.global external @b : !cir.array<!cir.int<s, 32> x 10>
 cir.global external @bb : !cir.array<!cir.array<!cir.int<s, 32> x 10> x 10>
 // CHECK: cir.global external @bb : !cir.array<!cir.array<!cir.int<s, 32> x 10> x 10>
 
-cir.func @f() {
+cir.global external @c = #cir.zero : !cir.array<!cir.int<s, 32> x 10>
+// CHECK: cir.global external @c = #cir.zero : !cir.array<!cir.int<s, 32> x 10>
+
+cir.global external @d = #cir.const_array<[#cir.int<1> : !cir.int<s, 32>, #cir.int<2> : !cir.int<s, 32>, #cir.int<3> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 3>
+// CHECK: cir.global external @d = #cir.const_array<[#cir.int<1> : !cir.int<s, 32>, #cir.int<2> : !cir.int<s, 32>, #cir.int<3> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 3>
+
+cir.global external @dd = #cir.const_array<[#cir.const_array<[#cir.int<1> : !cir.int<s, 32>, #cir.int<2> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 2>, #cir.const_array<[#cir.int<3> : !cir.int<s, 32>, #cir.int<4> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 2>, #cir.const_array<[#cir.int<5> : !cir.int<s, 32>, #cir.int<6> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 2>]> : !cir.array<!cir.array<!cir.int<s, 32> x 2> x 3>
+// CHECK: cir.global external @dd = #cir.const_array<[#cir.const_array<[#cir.int<1> : !cir.int<s, 32>, #cir.int<2> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 2>, #cir.const_array<[#cir.int<3> : !cir.int<s, 32>, #cir.int<4> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 2>, #cir.const_array<[#cir.int<5> : !cir.int<s, 32>, #cir.int<6> : !cir.int<s, 32>]> : !cir.array<!cir.int<s, 32> x 2>]> : !cir.array<!cir.array<!cir.int<s, 32> x 2> x 3>
+
+cir.global external @e = #cir.const_array<[#cir.int<1> : !cir.int<s, 32>, #cir.int<2> : !cir.int<s, 32>], trailing_zeros> : !cir.array<!cir.int<s, 32> x 10>
+// CHECK: cir.global external @e = #cir.const_array<[#cir.int<1> : !cir.int<s, 32>, #cir.int<2> : !cir.int<s, 32>], trailing_zeros> : !cir.array<!cir.int<s, 32> x 10>
+
+cir.func @func() {
   %0 = cir.alloca !cir.array<!cir.int<s, 32> x 10>, !cir.ptr<!cir.array<!cir.int<s, 32> x 10>>, ["l"] {alignment = 4 : i64}
   cir.return
 }
 
-// CHECK: cir.func @f() {
+// CHECK: cir.func @func() {
 // CHECK:   %0 = cir.alloca !cir.array<!cir.int<s, 32> x 10>, !cir.ptr<!cir.array<!cir.int<s, 32> x 10>>, ["l"] {alignment = 4 : i64}
 // CHECK:   cir.return
 // CHECK: }
 
-cir.func @f2(%arg0: !cir.ptr<!cir.int<s, 32>>) {
+cir.func @func2(%arg0: !cir.ptr<!cir.int<s, 32>>) {
   %0 = cir.alloca !cir.ptr<!cir.int<s, 32>>, !cir.ptr<!cir.ptr<!cir.int<s, 32>>>, ["p", init] {alignment = 8 : i64}
   cir.store %arg0, %0 : !cir.ptr<!cir.int<s, 32>>, !cir.ptr<!cir.ptr<!cir.int<s, 32>>>
   cir.return
 }
 
-// CHECK: cir.func @f2(%arg0: !cir.ptr<!cir.int<s, 32>>) {
+// CHECK: cir.func @func2(%arg0: !cir.ptr<!cir.int<s, 32>>) {
 // CHECK:   %0 = cir.alloca !cir.ptr<!cir.int<s, 32>>, !cir.ptr<!cir.ptr<!cir.int<s, 32>>>, ["p", init] {alignment = 8 : i64}
 // CHECK:   cir.store %arg0, %0 : !cir.ptr<!cir.int<s, 32>>, !cir.ptr<!cir.ptr<!cir.int<s, 32>>>
 // CHECK:   cir.return
 // CHECK: }
 
-cir.func @f3(%arg0: !cir.ptr<!cir.array<!cir.int<s, 32> x 10>>) {
+cir.func @func3(%arg0: !cir.ptr<!cir.array<!cir.int<s, 32> x 10>>) {
   %0 = cir.alloca !cir.ptr<!cir.array<!cir.int<s, 32> x 10>>, !cir.ptr<!cir.ptr<!cir.array<!cir.int<s, 32> x 10>>>, ["pp", init] {alignment = 8 : i64}
   cir.store %arg0, %0 : !cir.ptr<!cir.array<!cir.int<s, 32> x 10>>, !cir.ptr<!cir.ptr<!cir.array<!cir.int<s, 32> x 10>>>
   cir.return
 }
 
-// CHECK: cir.func @f3(%arg0: !cir.ptr<!cir.array<!cir.int<s, 32> x 10>>) {
+// CHECK: cir.func @func3(%arg0: !cir.ptr<!cir.array<!cir.int<s, 32> x 10>>) {
 // CHECK:   %0 = cir.alloca !cir.ptr<!cir.array<!cir.int<s, 32> x 10>>, !cir.ptr<!cir.ptr<!cir.array<!cir.int<s, 32> x 10>>>, ["pp", init] {alignment = 8 : i64}
 // CHECK:   cir.store %arg0, %0 : !cir.ptr<!cir.array<!cir.int<s, 32> x 10>>, !cir.ptr<!cir.ptr<!cir.array<!cir.int<s, 32> x 10>>>
 // CHECK:   cir.return
diff --git a/clang/test/CIR/Lowering/array.cpp b/clang/test/CIR/Lowering/array.cpp
index 42208a81caea2..763980b9124a3 100644
--- a/clang/test/CIR/Lowering/array.cpp
+++ b/clang/test/CIR/Lowering/array.cpp
@@ -12,16 +12,33 @@ extern int b[10];
 extern int bb[10][5];
 // CHECK: @bb = external dso_local global [10 x [5 x i32]]
 
-void f() {
+int c[10] = {};
+// CHECK: @c = dso_local global [10 x i32] zeroinitializer
+
+int d[3] = {1, 2, 3};
+// CHECK: @d = dso_local global [3 x i32] [i32 1, i32 2, i32 3]
+
+int dd[3][2] = {{1, 2}, {3, 4}, {5, 6}};
+// CHECK: @dd = dso_local global [3 x [2 x i32]] [
+// CHECK: [2 x i32] [i32 1, i32 2], [2 x i32]
+// CHECK: [i32 3, i32 4], [2 x i32] [i32 5, i32 6]]
+
+int e[10] = {1, 2};
+// CHECK: @e = dso_local global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0]
+
+int f[5] = {1, 2};
+// CHECK: @f = dso_local global [5 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0]
+
+void func() {
   int l[10];
 }
-// CHECK: define void @f()
+// CHECK: define void @func()
 // CHECK-NEXT: alloca [10 x i32], i64 1, align 16
 
-void f2(int p[10]) {}
-// CHECK: define void @f2(ptr {{%.*}})
+void func2(int p[10]) {}
+// CHECK: define void @func2(ptr {{%.*}})
 // CHECK-NEXT: alloca ptr, i64 1, align 8
 
-void f3(int pp[10][5]) {}
-// CHECK: define void @f3(ptr {{%.*}})
+void func3(int pp[10][5]) {}
+// CHECK: define void @func3(ptr {{%.*}})
 // CHECK-NEXT: alloca ptr, i64 1, align 8

>From ea0aee496a9d3191eb46af5ad89365f2cc89c22d Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Tue, 18 Mar 2025 18:56:14 +0100
Subject: [PATCH 2/3] Address code review comments

---
 clang/lib/CIR/CodeGen/CIRGenBuilder.h         |  1 +
 clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp  | 36 ++++++++++---------
 clang/lib/CIR/Dialect/IR/CIRAttrs.cpp         | 28 +++++++--------
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp |  5 ++-
 4 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index a2a75148ee884..d052b321e9bb4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -44,6 +44,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
     return false;
   }
 
+  // Return true if this is the null value
   bool isNullValue(mlir::Attribute attr) const {
     if (mlir::isa<cir::ZeroAttr>(attr))
       return true;
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index d3c22f54127c5..898f26d3bafcd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -169,11 +169,11 @@ static mlir::Attribute
 emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
                   mlir::Type commonElementType, unsigned arrayBound,
                   SmallVectorImpl<mlir::TypedAttr> &elements,
-                  mlir::TypedAttr filter) {
-  const auto &builder = cgm.getBuilder();
+                  mlir::TypedAttr filler) {
+  const CIRGenBuilderTy &builder = cgm.getBuilder();
 
   unsigned nonzeroLength = arrayBound;
-  if (elements.size() < nonzeroLength && builder.isNullValue(filter))
+  if (elements.size() < nonzeroLength && builder.isNullValue(filler))
     nonzeroLength = elements.size();
 
   if (nonzeroLength == elements.size()) {
@@ -186,13 +186,15 @@ emitArrayConstant(CIRGenModule &cgm, mlir::Type desiredType,
     return cir::ZeroAttr::get(builder.getContext(), desiredType);
 
   const unsigned trailingZeroes = arrayBound - nonzeroLength;
+
+  // Add a zeroinitializer array filler if we have lots of trailing zeroes.
   if (trailingZeroes >= 8) {
-    if (elements.size() < nonzeroLength)
-      cgm.errorNYI("missing initializer for non-zero element");
+    assert(elements.size() >= nonzeroLength &&
+           "missing initializer for non-zero element");
   } else if (elements.size() != arrayBound) {
-    elements.resize(arrayBound, filter);
+    elements.resize(arrayBound, filler);
 
-    if (filter.getType() != commonElementType)
+    if (filler.getType() != commonElementType)
       cgm.errorNYI(
           "array filter type should always be the same as element type");
   }
@@ -327,16 +329,16 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
     const unsigned numElements = value.getArraySize();
     const unsigned numInitElts = value.getArrayInitializedElts();
 
-    mlir::Attribute filter;
+    mlir::Attribute filler;
     if (value.hasArrayFiller()) {
-      filter =
-          tryEmitPrivate(value.getArrayFiller(), arrayTy->getElementType());
-      if (!filter)
+      filler =
+          tryEmitPrivate(value.getArrayFiller(), arrayElementTy);
+      if (!filler)
         return {};
     }
 
     SmallVector<mlir::TypedAttr, 16> elements;
-    if (filter && builder.isNullValue(filter))
+    if (filler && builder.isNullValue(filler))
       elements.reserve(numInitElts + 1);
     else
       elements.reserve(numInitElts);
@@ -361,14 +363,14 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
       elements.push_back(elementTyped);
     }
 
-    mlir::TypedAttr typedFilter =
-        llvm::dyn_cast_or_null<mlir::TypedAttr>(filter);
-    if (filter && !typedFilter)
-      cgm.errorNYI("array filter should always be typed");
+    mlir::TypedAttr typedFiller =
+        llvm::cast_or_null<mlir::TypedAttr>(filler);
+    if (filler && !typedFiller)
+      cgm.errorNYI("array filler should always be typed");
 
     mlir::Type desiredType = cgm.convertType(destType);
     return emitArrayConstant(cgm, desiredType, commonElementType, numElements,
-                             elements, typedFilter);
+                             elements, typedFiller);
   }
   case APValue::Vector: {
     cgm.errorNYI("ConstExprEmitter::tryEmitPrivate vector");
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 8dfe56b75a47b..1fe200a116bc8 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -201,9 +201,9 @@ ConstArrayAttr::verify(function_ref<::mlir::InFlightDiagnostic()> emitError,
   if (!(mlir::isa<ArrayAttr>(elts) || mlir::isa<StringAttr>(elts)))
     return emitError() << "constant array expects ArrayAttr or StringAttr";
 
-  if (StringAttr strAttr = mlir::dyn_cast<StringAttr>(elts)) {
-    ArrayType arrayTy = mlir::cast<ArrayType>(type);
-    IntType intTy = mlir::dyn_cast<IntType>(arrayTy.getEltType());
+  if (auto strAttr = mlir::dyn_cast<StringAttr>(elts)) {
+    const auto arrayTy = mlir::cast<ArrayType>(type);
+    const auto intTy = mlir::dyn_cast<IntType>(arrayTy.getEltType());
 
     // TODO: add CIR type for char.
     if (!intTy || intTy.getWidth() != 8) {
@@ -215,8 +215,8 @@ ConstArrayAttr::verify(function_ref<::mlir::InFlightDiagnostic()> emitError,
   }
 
   assert(mlir::isa<ArrayAttr>(elts));
-  ArrayAttr arrayAttr = mlir::cast<mlir::ArrayAttr>(elts);
-  ArrayType arrayTy = mlir::cast<ArrayType>(type);
+  const auto arrayAttr = mlir::cast<mlir::ArrayAttr>(elts);
+  const auto arrayTy = mlir::cast<ArrayType>(type);
 
   // Make sure both number of elements and subelement types match type.
   if (arrayTy.getSize() != arrayAttr.size() + trailingZerosNum)
@@ -225,10 +225,9 @@ ConstArrayAttr::verify(function_ref<::mlir::InFlightDiagnostic()> emitError,
 }
 
 Attribute ConstArrayAttr::parse(AsmParser &parser, Type type) {
-  ::mlir::FailureOr<Type> resultTy;
-  ::mlir::FailureOr<Attribute> resultVal;
-  ::llvm::SMLoc loc = parser.getCurrentLocation();
-  (void)loc;
+  mlir::FailureOr<Type> resultTy;
+  mlir::FailureOr<Attribute> resultVal;
+
   // Parse literal '<'
   if (parser.parseLess())
     return {};
@@ -244,7 +243,7 @@ Attribute ConstArrayAttr::parse(AsmParser &parser, Type type) {
   }
 
   // ArrayAttrrs have per-element type, not the type of the array...
-  if (mlir::dyn_cast<ArrayAttr>(*resultVal)) {
+  if (mlir::isa<ArrayAttr>(*resultVal)) {
     // Array has implicit type: infer from const array type.
     if (parser.parseOptionalColon().failed()) {
       resultTy = type;
@@ -259,7 +258,6 @@ Attribute ConstArrayAttr::parse(AsmParser &parser, Type type) {
       }
     }
   } else {
-    assert(mlir::isa<TypedAttr>(*resultVal) && "IDK");
     auto ta = mlir::cast<TypedAttr>(*resultVal);
     resultTy = ta.getType();
     if (mlir::isa<mlir::NoneType>(*resultTy)) {
@@ -269,11 +267,11 @@ Attribute ConstArrayAttr::parse(AsmParser &parser, Type type) {
     }
   }
 
-  auto zeros = 0;
+  unsigned zeros = 0;
   if (parser.parseOptionalComma().succeeded()) {
     if (parser.parseOptionalKeyword("trailing_zeros").succeeded()) {
-      auto typeSize = mlir::cast<cir::ArrayType>(resultTy.value()).getSize();
-      auto elts = resultVal.value();
+      unsigned typeSize = mlir::cast<cir::ArrayType>(resultTy.value()).getSize();
+      mlir::Attribute elts = resultVal.value();
       if (auto str = mlir::dyn_cast<mlir::StringAttr>(elts))
         zeros = typeSize - str.size();
       else
@@ -288,7 +286,7 @@ Attribute ConstArrayAttr::parse(AsmParser &parser, Type type) {
     return {};
 
   return parser.getChecked<ConstArrayAttr>(
-      loc, parser.getContext(), resultTy.value(), resultVal.value(), zeros);
+      parser.getCurrentLocation(), parser.getContext(), resultTy.value(), resultVal.value(), zeros);
 }
 
 void ConstArrayAttr::print(AsmPrinter &printer) const {
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index f0b9986a9efaf..a5cb987e4d5f3 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -189,7 +189,7 @@ mlir::Value lowerCirAttrAsValue(mlir::Operation *parentOp,
                                 mlir::ConversionPatternRewriter &rewriter,
                                 const mlir::TypeConverter *converter) {
   CIRAttrToValue valueConverter(parentOp, rewriter, converter);
-  auto value = valueConverter.visit(attr);
+  mlir::Value value = valueConverter.visit(attr);
   if (!value)
     llvm_unreachable("unhandled attribute type");
   return value;
@@ -242,8 +242,7 @@ mlir::Value CIRAttrToValue::visitCirAttr(cir::ConstArrayAttr attr) {
   if (auto arrayAttr = mlir::dyn_cast<mlir::ArrayAttr>(attr.getElts())) {
     for (auto [idx, elt] : llvm::enumerate(arrayAttr)) {
       mlir::DataLayout dataLayout(parentOp->getParentOfType<mlir::ModuleOp>());
-      mlir::Value init =
-          emitCirAttrToMemory(parentOp, elt, rewriter, converter, dataLayout);
+      mlir::Value init = visit(elt);
       result =
           rewriter.create<mlir::LLVM::InsertValueOp>(loc, result, init, idx);
     }

>From 4c97120292cac6a4aa959f1a1431d0cb6005ad03 Mon Sep 17 00:00:00 2001
From: AmrDeveloper <amr96 at programmer.net>
Date: Tue, 18 Mar 2025 21:05:21 +0100
Subject: [PATCH 3/3] Format the code

---
 clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp | 6 ++----
 clang/lib/CIR/Dialect/IR/CIRAttrs.cpp        | 6 ++++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
index 898f26d3bafcd..af3823c827e54 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprConstant.cpp
@@ -331,8 +331,7 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
 
     mlir::Attribute filler;
     if (value.hasArrayFiller()) {
-      filler =
-          tryEmitPrivate(value.getArrayFiller(), arrayElementTy);
+      filler = tryEmitPrivate(value.getArrayFiller(), arrayElementTy);
       if (!filler)
         return {};
     }
@@ -363,8 +362,7 @@ mlir::Attribute ConstantEmitter::tryEmitPrivate(const APValue &value,
       elements.push_back(elementTyped);
     }
 
-    mlir::TypedAttr typedFiller =
-        llvm::cast_or_null<mlir::TypedAttr>(filler);
+    mlir::TypedAttr typedFiller = llvm::cast_or_null<mlir::TypedAttr>(filler);
     if (filler && !typedFiller)
       cgm.errorNYI("array filler should always be typed");
 
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 1fe200a116bc8..a8d9f6a0e6e9b 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -270,7 +270,8 @@ Attribute ConstArrayAttr::parse(AsmParser &parser, Type type) {
   unsigned zeros = 0;
   if (parser.parseOptionalComma().succeeded()) {
     if (parser.parseOptionalKeyword("trailing_zeros").succeeded()) {
-      unsigned typeSize = mlir::cast<cir::ArrayType>(resultTy.value()).getSize();
+      unsigned typeSize =
+          mlir::cast<cir::ArrayType>(resultTy.value()).getSize();
       mlir::Attribute elts = resultVal.value();
       if (auto str = mlir::dyn_cast<mlir::StringAttr>(elts))
         zeros = typeSize - str.size();
@@ -286,7 +287,8 @@ Attribute ConstArrayAttr::parse(AsmParser &parser, Type type) {
     return {};
 
   return parser.getChecked<ConstArrayAttr>(
-      parser.getCurrentLocation(), parser.getContext(), resultTy.value(), resultVal.value(), zeros);
+      parser.getCurrentLocation(), parser.getContext(), resultTy.value(),
+      resultVal.value(), zeros);
 }
 
 void ConstArrayAttr::print(AsmPrinter &printer) const {



More information about the cfe-commits mailing list