[clang] [CIR] Upstream global initialization for ArrayType (PR #131657)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 18 12:23:37 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/2] [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/2] 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);
}
More information about the cfe-commits
mailing list