10#include "mlir/IR/BuiltinAttributes.h"
12#include "llvm/ADT/ArrayRef.h"
13#include "llvm/ADT/TypeSwitch.h"
20 const auto arrayPtrTy = mlir::cast<cir::PointerType>(arrayPtr.getType());
21 const auto arrayTy = mlir::dyn_cast<cir::ArrayType>(arrayPtrTy.getPointee());
24 const cir::PointerType flatPtrTy =
25 getPointerTo(arrayTy.getElementType(), arrayPtrTy.getAddrSpace());
26 return cir::CastOp::create(*
this, loc, flatPtrTy,
27 cir::CastKind::array_to_ptrdecay, arrayPtr);
30 assert(arrayPtrTy.getPointee() == eltTy &&
31 "flat pointee type must match original array element type");
36 mlir::Location arrayLocEnd,
38 mlir::Type eltTy, mlir::Value idx,
40 auto arrayPtrTy = mlir::dyn_cast<cir::PointerType>(arrayPtr.getType());
41 assert(arrayPtrTy &&
"expected pointer type");
43 auto arrayTy = mlir::dyn_cast<cir::ArrayType>(arrayPtrTy.getPointee());
45 assert(mlir::isa<cir::IntType>(idx.getType()) &&
47 mlir::cast<cir::IntType>(idx.getType()).getWidth()));
49 if (shouldDecay && arrayTy && arrayTy == eltTy) {
51 getPointerTo(arrayTy.getElementType(), arrayPtrTy.getAddrSpace());
52 return cir::GetElementOp::create(*
this, arrayLocEnd, eltPtrTy, arrayPtr,
57 mlir::Value basePtr = arrayPtr;
60 const mlir::Type flatPtrTy = basePtr.getType();
61 return cir::PtrStrideOp::create(*
this, arrayLocEnd, flatPtrTy, basePtr, idx);
65 llvm::APSInt intVal) {
66 bool isSigned = intVal.isSigned();
67 unsigned width = intVal.getBitWidth();
70 isSigned ? intVal.getSExtValue() : intVal.getZExtValue());
81 assert(mlir::isa<cir::IntType>(t) &&
"expected cir::IntType");
82 return cir::ConstantOp::create(*
this, loc, cir::IntAttr::get(t, c));
87 llvm::APFloat fpVal) {
88 assert(mlir::isa<cir::FPTypeInterface>(t) &&
"expected floating point type");
89 return cir::ConstantOp::create(*
this, loc, cir::FPAttr::get(t, fpVal));
103 auto getIndexAndNewOffset =
104 [](int64_t offset, int64_t eltSize) -> std::pair<int64_t, int64_t> {
105 int64_t divRet = offset / eltSize;
106 int64_t modRet = offset % eltSize;
111 return {divRet, modRet};
115 llvm::TypeSwitch<mlir::Type, mlir::Type>(ty)
116 .Case<cir::ArrayType>([&](
auto arrayTy) {
118 const auto [
index, newOffset] =
119 getIndexAndNewOffset(offset, eltSize);
120 indices.push_back(
index);
122 return arrayTy.getElementType();
124 .Case<cir::RecordType>([&](
auto recordTy) {
127 for (
size_t i = 0; i < elts.size(); ++i) {
131 if (recordTy.getPacked())
137 if (!recordTy.isUnion())
138 pos = (pos + alignMask) & ~alignMask;
140 if (offset < pos + eltSize) {
141 indices.push_back(i);
146 if (!recordTy.isUnion())
149 llvm_unreachable(
"offset was not found within the record");
151 .Case<cir::IntType>([&](cir::IntType intTy) -> mlir::Type {
158 assert(eltSize > 0 &&
"element size must be positive");
159 const auto [
index, newOffset] =
160 getIndexAndNewOffset(offset, eltSize);
161 indices.push_back(
index);
165 .
Default([](mlir::Type) -> mlir::Type {
166 llvm_unreachable(
"unexpected type");
177 for (int64_t idx : indices) {
178 if (
auto recordTy = dyn_cast<cir::RecordType>(ty)) {
179 offset += recordTy.getElementOffset(layout.
layout, idx);
180 const llvm::Align tyAlign = llvm::Align(
181 recordTy.getPacked() ? 1 : layout.
layout.getTypeABIAlignment(ty));
182 offset = llvm::alignTo(offset, tyAlign);
183 assert(idx < (int64_t)recordTy.getMembers().size());
184 ty = recordTy.getMembers()[idx];
185 }
else if (
auto arrayTy = dyn_cast<cir::ArrayType>(ty)) {
186 ty = arrayTy.getElementType();
188 }
else if (mlir::isa<cir::IntType>(ty)) {
192 llvm_unreachable(
"unexpected type");
199 mlir::ArrayAttr fields,
bool packed,
bool padded, llvm::StringRef name) {
202 members.reserve(fields.size());
203 llvm::transform(fields, std::back_inserter(members),
204 [](mlir::Attribute
attr) {
205 return mlir::cast<mlir::TypedAttr>(
attr).getType();
215 mlir::ArrayAttr arrayAttr,
bool packed,
bool padded, mlir::Type
type) {
216 auto recordTy = mlir::cast_or_null<cir::RecordType>(
type);
224 const bool isZero = llvm::all_of(
225 arrayAttr, [&](mlir::Attribute a) {
return isNullValue(a); });
227 return cir::ZeroAttr::get(recordTy);
228 return cir::ConstRecordAttr::get(recordTy, arrayAttr);
234 mlir::Type elemTy)
const {
static bool isUnsigned(SValBuilder &SVB, NonLoc Value)
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
llvm::TypeSize getTypeAllocSize(mlir::Type ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
llvm::Align getABITypeAlign(mlir::Type ty) const
C++ view class that accepts both !cir.struct and !cir.union types.
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
clang::CharUnits getAlignment() const
mlir::Value getBasePointer() const
cir::RecordType getCompleteNamedRecordType(llvm::ArrayRef< mlir::Type > members, bool packed, bool padded, llvm::StringRef name)
Get a CIR named record type.
cir::IntType getSIntNTy(int n)
mlir::Attribute getConstRecordOrZeroAttr(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type type={})
mlir::Value maybeBuildArrayDecay(mlir::Location loc, mlir::Value arrayPtr, mlir::Type eltTy)
Returns a decayed pointer to the first element of the array pointed to by arrayPtr.
cir::ConstantOp getConstFP(mlir::Location loc, mlir::Type t, llvm::APFloat fpVal)
uint64_t computeOffsetFromGlobalViewIndices(const cir::CIRDataLayout &layout, mlir::Type ty, llvm::ArrayRef< int64_t > indices)
cir::StructType getAnonRecordTy(llvm::ArrayRef< mlir::Type > members, bool packed=false, bool padded=false)
Get a CIR anonymous struct type.
bool isNullValue(mlir::Attribute attr) const
cir::RecordType getCompleteRecordType(mlir::ArrayAttr fields, bool packed=false, bool padded=false, llvm::StringRef name="")
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
void computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)
cir::IntType getUIntNTy(int n)
mlir::Value getArrayElement(mlir::Location arrayLocBegin, mlir::Location arrayLocEnd, mlir::Value arrayPtr, mlir::Type eltTy, mlir::Value idx, bool shouldDecay)
Create a cir.ptr_stride operation to get access to an array element.
bool isValidFundamentalIntWidth(unsigned width)
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
@ Default
Set to the current date and time.
static bool addressPointerAuthInfo()
static bool addressOffset()
static bool astRecordDeclAttr()
static bool addressIsKnownNonNull()