14#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
15#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
16#include "mlir/IR/SymbolTable.h"
19 if (
auto intTy = mlir::dyn_cast<cir::IntType>(ty))
20 return intTy.getWidth();
21 assert(mlir::isa<cir::BoolType>(ty) &&
22 "expected CIR integer or bool element type");
26mlir::DenseElementsAttr
29 const auto stringAttr = mlir::cast<mlir::StringAttr>(attr.getElts());
30 const auto arrayTy = mlir::cast<cir::ArrayType>(attr.getType());
31 const unsigned totalSize = arrayTy.getSize();
32 const unsigned trailingZeros = attr.getTrailingZerosNum();
33 assert(stringAttr.size() + trailingZeros == totalSize &&
34 "string const_array size must match explicit elements plus "
39 values.reserve(totalSize);
44 for (
const char element : stringAttr)
45 values.emplace_back(bitWidth,
static_cast<unsigned char>(element));
47 values.insert(values.end(), trailingZeros, mlir::APInt::getZero(bitWidth));
49 return mlir::DenseElementsAttr::get(
50 mlir::RankedTensorType::get({totalSize}, type),
llvm::ArrayRef(values));
54 if (mlir::isa<cir::BoolType>(ty))
55 return mlir::APInt::getZero(1);
56 const auto intTy = mlir::cast<cir::IntType>(ty);
57 return mlir::APInt::getZero(intTy.getWidth());
61 auto fpTy = mlir::cast<cir::FPTypeInterface>(ty);
62 return mlir::APFloat::getZero(fpTy.getFloatSemantics());
70template <
typename AttrTy,
typename StorageTy>
74 int64_t currentIndex) {
75 if (
auto stringAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {
76 if (
auto arrayType = mlir::dyn_cast<cir::ArrayType>(attr.getType())) {
77 for (
auto element : stringAttr) {
78 auto intAttr = cir::IntAttr::get(arrayType.getElementType(), element);
79 values[currentIndex++] = mlir::dyn_cast<AttrTy>(intAttr).getValue();
82 currentIndex += attr.getTrailingZerosNum();
88 std::size_t elementsSizeInCurrentDim = 1;
89 for (std::size_t i = dimIndex; i < currentDims.size(); i++)
90 elementsSizeInCurrentDim *= currentDims[i];
92 auto arrayAttr = mlir::cast<mlir::ArrayAttr>(attr.getElts());
93 for (
auto eltAttr : arrayAttr) {
94 if constexpr (std::is_same_v<StorageTy, mlir::APInt>) {
95 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(eltAttr)) {
96 values[currentIndex++] =
97 llvm::APInt(1,
static_cast<uint64_t
>(boolAttr.getValue()));
101 if (
auto valueAttr = mlir::dyn_cast<AttrTy>(eltAttr)) {
102 values[currentIndex++] = valueAttr.getValue();
106 if (
auto subArrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(eltAttr)) {
108 dimIndex, currentIndex);
109 currentIndex += elementsSizeInCurrentDim;
113 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(eltAttr)) {
114 currentIndex += elementsSizeInCurrentDim;
118 llvm_unreachable(
"unknown element in ConstArrayAttr");
122template <
typename AttrTy,
typename StorageTy>
125 mlir::Type elementType, mlir::Type convertedElementType) {
126 unsigned vectorSize = 1;
127 for (
auto dim : dims)
133 return mlir::DenseElementsAttr::get(
134 mlir::RankedTensorType::get(dims, convertedElementType),
141 mlir::ModuleOp moduleOp,
142 const mlir::TypeConverter *converter) {
143 if (gv.getIndices() || mlir::isa<cir::IntType, cir::VPtrType>(gv.getType()))
146 auto ptrTy = mlir::dyn_cast<cir::PointerType>(gv.getType());
150 unsigned sourceAddrSpace = 0;
151 mlir::Type sourceType;
153 mlir::SymbolTable::lookupSymbolIn(moduleOp, gv.getSymbol());
154 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
155 sourceType = llvmSymbol.getType();
156 sourceAddrSpace = llvmSymbol.getAddrSpace();
157 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(sourceSymbol)) {
158 sourceType = converter->convertType(cirSymbol.getSymType());
159 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
160 cirSymbol.getAddrSpaceAttr()))
161 sourceAddrSpace = targetAS.getValue();
168 auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
169 if (llvmDstTy.getAddressSpace() != sourceAddrSpace)
172 mlir::Type llvmEltTy = converter->convertType(ptrTy.getPointee());
173 if (llvmEltTy == sourceType)
175 if (
auto arrTy = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(sourceType))
176 return llvmEltTy == arrTy.getElementType();
184static std::optional<mlir::Attribute>
186 mlir::ModuleOp moduleOp,
187 const mlir::TypeConverter *converter) {
188 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(elt)) {
191 return gv.getSymbol();
193 if (
auto nullPtr = mlir::dyn_cast<cir::ConstPtrAttr>(elt)) {
194 if (nullPtr.isNullValue())
195 return mlir::LLVM::ZeroAttr::get(ctx);
202 if (mlir::isa<cir::PoisonAttr>(attr))
204 if (
auto elts = mlir::dyn_cast<mlir::ArrayAttr>(attr))
206 if (
auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(attr)) {
207 if (mlir::isa<mlir::StringAttr>(constArr.getElts()))
209 if (
auto elts = mlir::dyn_cast<mlir::ArrayAttr>(constArr.getElts()))
215std::optional<mlir::Attribute>
217 const mlir::TypeConverter *converter,
218 mlir::ModuleOp moduleOp) {
220 const auto typedConstArr = mlir::cast<mlir::TypedAttr>(constArr);
223 const auto cirArrayType = mlir::cast<cir::ArrayType>(typedConstArr.getType());
226 mlir::Type type = cirArrayType;
228 while (
auto arrayType = mlir::dyn_cast<cir::ArrayType>(type)) {
229 dims.push_back(arrayType.getSize());
230 type = arrayType.getElementType();
236 if (mlir::isa<mlir::StringAttr>(constArr.getElts()))
238 converter->convertType(type));
239 if (mlir::isa<cir::IntType>(type))
241 constArr, dims, type, converter->convertType(type));
243 if (mlir::isa<cir::BoolType>(type))
245 constArr, dims, type, converter->convertType(type));
247 if (mlir::isa<cir::FPTypeInterface>(type))
249 constArr, dims, type, converter->convertType(type));
251 if (mlir::isa<cir::PointerType>(type)) {
254 if (constArr.getTrailingZerosNum() > 0)
256 auto eltsArr = mlir::dyn_cast<mlir::ArrayAttr>(constArr.getElts());
260 lowered.reserve(eltsArr.size());
261 mlir::MLIRContext *ctx = constArr.getContext();
262 for (mlir::Attribute elt : eltsArr) {
263 std::optional<mlir::Attribute> llvmElt =
267 lowered.push_back(*llvmElt);
269 return mlir::ArrayAttr::get(ctx, lowered);
282static std::optional<mlir::Attribute>
284 const mlir::TypeConverter *converter,
285 mlir::ModuleOp moduleOp) {
286 mlir::MLIRContext *ctx = attr.getContext();
288 if (
auto arrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(attr))
291 if (
auto recordAttr = mlir::dyn_cast<cir::ConstRecordAttr>(attr))
294 if (mlir::isa<cir::ZeroAttr>(attr))
295 return mlir::LLVM::ZeroAttr::get(ctx);
297 if (mlir::isa<cir::UndefAttr>(attr))
298 return mlir::LLVM::UndefAttr::get(ctx);
300 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr))
301 return mlir::IntegerAttr::get(converter->convertType(intAttr.getType()),
304 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr))
305 return mlir::IntegerAttr::get(converter->convertType(boolAttr.getType()),
306 boolAttr.getValue() ? 1 : 0);
308 if (
auto fpAttr = mlir::dyn_cast<cir::FPAttr>(attr))
309 return mlir::FloatAttr::get(converter->convertType(fpAttr.getType()),
317std::optional<mlir::Attribute>
319 const mlir::TypeConverter *converter,
320 mlir::ModuleOp moduleOp) {
325 mlir::ArrayAttr memberAttrs = constRecord.getMembers();
327 loweredMembers.reserve(memberAttrs.size());
328 for (mlir::Attribute member : memberAttrs) {
329 std::optional<mlir::Attribute> lowered =
333 loweredMembers.push_back(*lowered);
339 if (
auto unionTy = mlir::dyn_cast<cir::UnionType>(constRecord.getType());
340 unionTy && unionTy.getPadded()) {
341 assert(loweredMembers.size() == 1);
342 loweredMembers.push_back(
343 mlir::LLVM::UndefAttr::get(constRecord.getContext()));
346 return mlir::ArrayAttr::get(constRecord.getContext(), loweredMembers);
350 mlir::Type typ,
const llvm::APInt &val) {
351 return mlir::LLVM::ConstantOp::create(bld, loc, typ, val);
354mlir::Value
getConst(mlir::OpBuilder &bld, mlir::Location loc, mlir::Type typ,
356 return mlir::LLVM::ConstantOp::create(bld, loc, typ, val);
359mlir::Value
createShL(mlir::OpBuilder &bld, mlir::Value lhs,
unsigned rhs) {
362 mlir::Value rhsVal =
getConst(bld, lhs.getLoc(), lhs.getType(), rhs);
363 return mlir::LLVM::ShlOp::create(bld, lhs.getLoc(), lhs, rhsVal);
366mlir::Value
createAShR(mlir::OpBuilder &bld, mlir::Value lhs,
unsigned rhs) {
369 mlir::Value rhsVal =
getConst(bld, lhs.getLoc(), lhs.getType(), rhs);
370 return mlir::LLVM::AShrOp::create(bld, lhs.getLoc(), lhs, rhsVal);
373mlir::Value
createAnd(mlir::OpBuilder &bld, mlir::Value lhs,
374 const llvm::APInt &rhs) {
375 mlir::Value rhsVal =
getConstAPInt(bld, lhs.getLoc(), lhs.getType(), rhs);
376 return mlir::LLVM::AndOp::create(bld, lhs.getLoc(), lhs, rhsVal);
379mlir::Value
createLShR(mlir::OpBuilder &bld, mlir::Value lhs,
unsigned rhs) {
382 mlir::Value rhsVal =
getConst(bld, lhs.getLoc(), lhs.getType(), rhs);
383 return mlir::LLVM::LShrOp::create(bld, lhs.getLoc(), lhs, rhsVal);
mlir::DenseElementsAttr convertStringAttrToDenseElementsAttr(cir::ConstArrayAttr attr, mlir::Type type)
std::optional< mlir::Attribute > lowerConstArrayAttr(cir::ConstArrayAttr constArr, const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp)
mlir::Value createLShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createShL(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value getConst(mlir::OpBuilder &bld, mlir::Location loc, mlir::Type typ, unsigned val)
mlir::Value getConstAPInt(mlir::OpBuilder &bld, mlir::Location loc, mlir::Type typ, const llvm::APInt &val)
std::optional< mlir::Attribute > lowerConstRecordAttr(cir::ConstRecordAttr constRecord, const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp)
void convertToDenseElementsAttrImpl(cir::ConstArrayAttr attr, llvm::SmallVectorImpl< StorageTy > &values, const llvm::SmallVectorImpl< int64_t > ¤tDims, int64_t dimIndex, int64_t currentIndex)
static bool containsPoison(mlir::Attribute attr)
static std::optional< mlir::Attribute > lowerConstRecordMemberAttr(mlir::Attribute attr, const mlir::TypeConverter *converter, mlir::ModuleOp moduleOp)
Lower a constant attribute that initializes a single member of a record (or a leaf of a nested aggreg...
static bool globalViewMatchesPointerLeaf(cir::GlobalViewAttr gv, mlir::ModuleOp moduleOp, const mlir::TypeConverter *converter)
Return true when gv can be lowered to a FlatSymbolRefAttr leaf without addrspacecast or bitcast (mirr...
static std::optional< mlir::Attribute > lowerPointerElementAttr(mlir::Attribute elt, mlir::MLIRContext *ctx, mlir::ModuleOp moduleOp, const mlir::TypeConverter *converter)
Lower a single pointer-element of a cir.const_array to an LLVM-dialect constant leaf suitable for a b...
mlir::Value createAShR(mlir::OpBuilder &bld, mlir::Value lhs, unsigned rhs)
mlir::Value createAnd(mlir::OpBuilder &bld, mlir::Value lhs, const llvm::APInt &rhs)
mlir::DenseElementsAttr convertToDenseElementsAttr(cir::ConstArrayAttr attr, const llvm::SmallVectorImpl< int64_t > &dims, mlir::Type elementType, mlir::Type convertedElementType)
mlir::APInt getZeroInitFromType(mlir::Type ty)
static unsigned getIntOrBoolBitWidth(mlir::Type ty)
StorageTy getZeroInitFromType(mlir::Type ty)