14#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
15#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
16#include "mlir/IR/BuiltinTypes.h"
17#include "mlir/IR/SymbolTable.h"
18#include "mlir/Interfaces/DataLayoutInterfaces.h"
21 if (
auto intTy = mlir::dyn_cast<cir::IntType>(ty))
22 return intTy.getWidth();
23 assert(mlir::isa<cir::BoolType>(ty) &&
24 "expected CIR integer or bool element type");
28mlir::DenseElementsAttr
31 const auto stringAttr = mlir::cast<mlir::StringAttr>(attr.getElts());
32 const auto arrayTy = mlir::cast<cir::ArrayType>(attr.getType());
33 const unsigned totalSize = arrayTy.getSize();
34 const unsigned trailingZeros = attr.getTrailingZerosNum();
35 assert(stringAttr.size() + trailingZeros == totalSize &&
36 "string const_array size must match explicit elements plus "
41 values.reserve(totalSize);
46 for (
const char element : stringAttr)
47 values.emplace_back(bitWidth,
static_cast<unsigned char>(element));
49 values.insert(values.end(), trailingZeros, mlir::APInt::getZero(bitWidth));
51 return mlir::DenseElementsAttr::get(
52 mlir::RankedTensorType::get({totalSize}, type),
llvm::ArrayRef(values));
56 if (mlir::isa<cir::BoolType>(ty))
57 return mlir::APInt::getZero(1);
58 const auto intTy = mlir::cast<cir::IntType>(ty);
59 return mlir::APInt::getZero(intTy.getWidth());
63 auto fpTy = mlir::cast<cir::FPTypeInterface>(ty);
64 return mlir::APFloat::getZero(fpTy.getFloatSemantics());
72template <
typename AttrTy,
typename StorageTy>
76 int64_t currentIndex) {
77 if (
auto stringAttr = mlir::dyn_cast<mlir::StringAttr>(attr.getElts())) {
78 if (
auto arrayType = mlir::dyn_cast<cir::ArrayType>(attr.getType())) {
79 for (
auto element : stringAttr) {
80 auto intAttr = cir::IntAttr::get(arrayType.getElementType(), element);
81 values[currentIndex++] = mlir::dyn_cast<AttrTy>(intAttr).getValue();
84 currentIndex += attr.getTrailingZerosNum();
90 std::size_t elementsSizeInCurrentDim = 1;
91 for (std::size_t i = dimIndex; i < currentDims.size(); i++)
92 elementsSizeInCurrentDim *= currentDims[i];
94 auto arrayAttr = mlir::cast<mlir::ArrayAttr>(attr.getElts());
95 for (
auto eltAttr : arrayAttr) {
96 if constexpr (std::is_same_v<StorageTy, mlir::APInt>) {
97 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(eltAttr)) {
98 values[currentIndex++] =
99 llvm::APInt(1,
static_cast<uint64_t
>(boolAttr.getValue()));
103 if (
auto valueAttr = mlir::dyn_cast<AttrTy>(eltAttr)) {
104 values[currentIndex++] = valueAttr.getValue();
108 if (
auto subArrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(eltAttr)) {
110 dimIndex, currentIndex);
111 currentIndex += elementsSizeInCurrentDim;
115 if (mlir::isa<cir::ZeroAttr, cir::UndefAttr>(eltAttr)) {
116 currentIndex += elementsSizeInCurrentDim;
120 llvm_unreachable(
"unknown element in ConstArrayAttr");
124template <
typename AttrTy,
typename StorageTy>
127 mlir::Type elementType, mlir::Type convertedElementType) {
128 unsigned vectorSize = 1;
129 for (
auto dim : dims)
135 return mlir::DenseElementsAttr::get(
136 mlir::RankedTensorType::get(dims, convertedElementType),
143 mlir::ModuleOp moduleOp,
144 const mlir::TypeConverter *converter) {
145 if (gv.getIndices() || mlir::isa<cir::IntType, cir::VPtrType>(gv.getType()))
148 auto ptrTy = mlir::dyn_cast<cir::PointerType>(gv.getType());
152 unsigned sourceAddrSpace = 0;
153 mlir::Type sourceType;
155 mlir::SymbolTable::lookupSymbolIn(moduleOp, gv.getSymbol());
156 if (
auto llvmSymbol = mlir::dyn_cast<mlir::LLVM::GlobalOp>(sourceSymbol)) {
157 sourceType = llvmSymbol.getType();
158 sourceAddrSpace = llvmSymbol.getAddrSpace();
159 }
else if (
auto cirSymbol = mlir::dyn_cast<cir::GlobalOp>(sourceSymbol)) {
160 sourceType = converter->convertType(cirSymbol.getSymType());
161 if (
auto targetAS = mlir::dyn_cast_if_present<cir::TargetAddressSpaceAttr>(
162 cirSymbol.getAddrSpaceAttr()))
163 sourceAddrSpace = targetAS.getValue();
170 auto llvmDstTy = converter->convertType<mlir::LLVM::LLVMPointerType>(ptrTy);
171 if (llvmDstTy.getAddressSpace() != sourceAddrSpace)
174 mlir::Type llvmEltTy = converter->convertType(ptrTy.getPointee());
175 if (llvmEltTy == sourceType)
177 if (
auto arrTy = mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(sourceType))
178 return llvmEltTy == arrTy.getElementType();
186static std::optional<mlir::Attribute>
188 mlir::ModuleOp moduleOp,
189 const mlir::TypeConverter *converter) {
190 if (
auto gv = mlir::dyn_cast<cir::GlobalViewAttr>(elt)) {
193 return gv.getSymbol();
195 if (
auto nullPtr = mlir::dyn_cast<cir::ConstPtrAttr>(elt)) {
196 if (nullPtr.isNullValue())
197 return mlir::LLVM::ZeroAttr::get(ctx);
204 if (mlir::isa<cir::PoisonAttr>(attr))
206 if (
auto elts = mlir::dyn_cast<mlir::ArrayAttr>(attr))
208 if (
auto constArr = mlir::dyn_cast<cir::ConstArrayAttr>(attr)) {
209 if (mlir::isa<mlir::StringAttr>(constArr.getElts()))
211 if (
auto elts = mlir::dyn_cast<mlir::ArrayAttr>(constArr.getElts()))
217std::optional<mlir::Attribute>
219 const mlir::TypeConverter *converter,
220 mlir::ModuleOp moduleOp) {
222 const auto typedConstArr = mlir::cast<mlir::TypedAttr>(constArr);
225 const auto cirArrayType = mlir::cast<cir::ArrayType>(typedConstArr.getType());
228 mlir::Type type = cirArrayType;
230 while (
auto arrayType = mlir::dyn_cast<cir::ArrayType>(type)) {
231 dims.push_back(arrayType.getSize());
232 type = arrayType.getElementType();
238 if (mlir::isa<mlir::StringAttr>(constArr.getElts()))
240 converter->convertType(type));
241 if (mlir::isa<cir::IntType>(type)) {
245 if (mlir::cast<cir::IntType>(type).isBitInt())
248 constArr, dims, type, converter->convertType(type));
251 if (mlir::isa<cir::BoolType>(type))
253 constArr, dims, type, converter->convertType(type));
255 if (mlir::isa<cir::FPTypeInterface>(type))
257 constArr, dims, type, converter->convertType(type));
259 if (mlir::isa<cir::PointerType>(type)) {
262 if (constArr.getTrailingZerosNum() > 0)
264 auto eltsArr = mlir::dyn_cast<mlir::ArrayAttr>(constArr.getElts());
268 lowered.reserve(eltsArr.size());
269 mlir::MLIRContext *ctx = constArr.getContext();
270 for (mlir::Attribute elt : eltsArr) {
271 std::optional<mlir::Attribute> llvmElt =
275 lowered.push_back(*llvmElt);
277 return mlir::ArrayAttr::get(ctx, lowered);
290static std::optional<mlir::Attribute>
292 const mlir::TypeConverter *converter,
293 mlir::ModuleOp moduleOp) {
294 mlir::MLIRContext *ctx = attr.getContext();
296 if (
auto arrayAttr = mlir::dyn_cast<cir::ConstArrayAttr>(attr))
299 if (
auto recordAttr = mlir::dyn_cast<cir::ConstRecordAttr>(attr))
302 if (mlir::isa<cir::ZeroAttr>(attr))
303 return mlir::LLVM::ZeroAttr::get(ctx);
305 if (mlir::isa<cir::UndefAttr>(attr))
306 return mlir::LLVM::UndefAttr::get(ctx);
308 if (
auto intAttr = mlir::dyn_cast<cir::IntAttr>(attr)) {
311 if (mlir::cast<cir::IntType>(intAttr.getType()).isBitInt())
313 return mlir::IntegerAttr::get(converter->convertType(intAttr.getType()),
317 if (
auto boolAttr = mlir::dyn_cast<cir::BoolAttr>(attr))
318 return mlir::IntegerAttr::get(converter->convertType(boolAttr.getType()),
319 boolAttr.getValue() ? 1 : 0);
321 if (
auto fpAttr = mlir::dyn_cast<cir::FPAttr>(attr))
322 return mlir::FloatAttr::get(converter->convertType(fpAttr.getType()),
341 uint64_t maxAlign = 1;
342 uint64_t totalSize = 0;
343 for (mlir::Type member : members) {
344 uint64_t align = dataLayout.getTypeABIAlignment(member);
345 maxAlign = std::max(maxAlign, align);
346 uint64_t size = dataLayout.getTypeSize(member).getFixedValue();
348 if (llvm::alignTo(totalSize, align) != totalSize)
353 return llvm::alignTo(totalSize, maxAlign) != totalSize;
367 mlir::LLVM::LLVMStructType structTy, cir::ConstRecordAttr constRecord,
368 const mlir::TypeConverter &converter,
const mlir::DataLayout &dataLayout) {
371 constRecord.getMembers().getValue();
373 bool changed =
false;
379 for (
auto [idx, member] : llvm::enumerate(initMembers)) {
380 if (idx >= newBody.size())
382 mlir::Type adjusted =
384 if (adjusted != newBody[idx]) {
385 newBody[idx] = adjusted;
396 bool packed = structTy.isPacked();
398 mlir::dyn_cast<mlir::LLVM::LLVMArrayType>(structTy.getBody().back());
399 fam && fam.getNumElements() == 0) {
400 mlir::Type lastInitType =
401 mlir::cast<mlir::TypedAttr>(initMembers.back()).getType();
402 if (mlir::cast<cir::ArrayType>(lastInitType).getSize() != 0) {
403 newBody.back() = converter.convertType(lastInitType);
412 return mlir::LLVM::LLVMStructType::getLiteral(structTy.getContext(), newBody,
425 mlir::LLVM::LLVMStructType structTy, cir::ConstRecordAttr constRecord,
426 const mlir::TypeConverter &converter,
const mlir::DataLayout &dataLayout) {
428 auto unionTy = mlir::cast<cir::UnionType>(constRecord.getType());
431 assert(constRecord.getMembers().size() == 1);
432 mlir::Attribute member = constRecord.getMembers()[0];
433 mlir::Type memberTy =
434 converter.convertType(mlir::cast<mlir::TypedAttr>(member).
getType());
444 if (memberTy == structTy.getBody().front())
447 uint64_t unionSize = dataLayout.getTypeSize(unionTy).getFixedValue();
448 uint64_t initSize = dataLayout.getTypeSize(memberTy).getFixedValue();
449 assert(initSize <= unionSize &&
"union initializer larger than the union");
452 newBody.push_back(memberTy);
455 if (initSize < unionSize)
456 newBody.push_back(mlir::LLVM::LLVMArrayType::get(
457 mlir::IntegerType::get(structTy.getContext(), 8),
458 unionSize - initSize));
460 return mlir::LLVM::LLVMStructType::getLiteral(structTy.getContext(), newBody,
461 unionTy.getPacked());
466 const mlir::TypeConverter &converter,
467 const mlir::DataLayout &dataLayout) {
469 auto constRecord = mlir::dyn_cast_if_present<cir::ConstRecordAttr>(init);
475 auto structTy = mlir::dyn_cast<mlir::LLVM::LLVMStructType>(llvmType);
476 if (!structTy || structTy.getBody().empty())
480 if (mlir::isa<cir::StructType>(constRecord.getType()))
483 if (mlir::isa<cir::UnionType>(constRecord.getType()))
489std::optional<mlir::Attribute>
491 const mlir::TypeConverter *converter,
492 mlir::ModuleOp moduleOp) {
497 mlir::ArrayAttr memberAttrs = constRecord.getMembers();
499 loweredMembers.reserve(memberAttrs.size());
500 for (mlir::Attribute member : memberAttrs) {
501 std::optional<mlir::Attribute> lowered =
505 loweredMembers.push_back(*lowered);
515 converter->convertType(constRecord.getType()), constRecord, *converter,
516 mlir::DataLayout(moduleOp));
517 if (
auto structTy = mlir::dyn_cast<mlir::LLVM::LLVMStructType>(adjustedTy))
518 while (loweredMembers.size() < structTy.getBody().size())
519 loweredMembers.push_back(
520 mlir::LLVM::UndefAttr::get(constRecord.getContext()));
522 return mlir::ArrayAttr::get(constRecord.getContext(), loweredMembers);
526 mlir::Type typ,
const llvm::APInt &val) {
527 return mlir::LLVM::ConstantOp::create(bld, loc, typ, val);
530mlir::Value
getConst(mlir::OpBuilder &bld, mlir::Location loc, mlir::Type typ,
532 return mlir::LLVM::ConstantOp::create(bld, loc, typ, val);
535mlir::Value
createShL(mlir::OpBuilder &bld, mlir::Value lhs,
unsigned rhs) {
538 mlir::Value rhsVal =
getConst(bld, lhs.getLoc(), lhs.getType(), rhs);
539 return mlir::LLVM::ShlOp::create(bld, lhs.getLoc(), lhs, rhsVal);
542mlir::Value
createAShR(mlir::OpBuilder &bld, mlir::Value lhs,
unsigned rhs) {
545 mlir::Value rhsVal =
getConst(bld, lhs.getLoc(), lhs.getType(), rhs);
546 return mlir::LLVM::AShrOp::create(bld, lhs.getLoc(), lhs, rhsVal);
549mlir::Value
createAnd(mlir::OpBuilder &bld, mlir::Value lhs,
550 const llvm::APInt &rhs) {
551 mlir::Value rhsVal =
getConstAPInt(bld, lhs.getLoc(), lhs.getType(), rhs);
552 return mlir::LLVM::AndOp::create(bld, lhs.getLoc(), lhs, rhsVal);
555mlir::Value
createLShR(mlir::OpBuilder &bld, mlir::Value lhs,
unsigned rhs) {
558 mlir::Value rhsVal =
getConst(bld, lhs.getLoc(), lhs.getType(), rhs);
559 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)
mlir::Type adjustGlobalTypeForInit(mlir::Type llvmType, mlir::Attribute init, const mlir::TypeConverter &converter, const mlir::DataLayout &dataLayout)
Adjust llvmType (the converted type of init) to the concrete LLVM type a global constant initialized ...
static mlir::Type adjustGlobalStructTypeForInit(mlir::LLVM::LLVMStructType structTy, cir::ConstRecordAttr constRecord, const mlir::TypeConverter &converter, const mlir::DataLayout &dataLayout)
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)
static bool shouldPackFAMStruct(const mlir::DataLayout &dataLayout, llvm::ArrayRef< mlir::Type > members)
mlir::DenseElementsAttr convertToDenseElementsAttr(cir::ConstArrayAttr attr, const llvm::SmallVectorImpl< int64_t > &dims, mlir::Type elementType, mlir::Type convertedElementType)
static mlir::Type adjustGlobalUnionTypeForInit(mlir::LLVM::LLVMStructType structTy, cir::ConstRecordAttr constRecord, const mlir::TypeConverter &converter, const mlir::DataLayout &dataLayout)
mlir::APInt getZeroInitFromType(mlir::Type ty)
static unsigned getIntOrBoolBitWidth(mlir::Type ty)
StorageTy getZeroInitFromType(mlir::Type ty)