https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/131657
>From 4ae9c422e786f843f5f019a5d9e55232ec6c8694 Mon Sep 17 00:00:00 2001 From: AmrDeveloper <am...@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 <am...@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); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits