9#ifndef LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENBUILDER_H
10#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENBUILDER_H
21#include "llvm/ADT/APFloat.h"
22#include "llvm/ADT/STLExtras.h"
28 llvm::StringMap<unsigned> recordNames;
29 llvm::StringMap<unsigned> globalsVersioning;
38 mlir::Attribute
getString(llvm::StringRef str, mlir::Type eltTy,
39 std::optional<size_t> size) {
40 size_t finalSize = size.value_or(str.size());
42 size_t lastNonZeroPos = str.find_last_not_of(
'\0');
45 if (lastNonZeroPos == llvm::StringRef::npos) {
46 auto arrayTy = cir::ArrayType::get(eltTy, finalSize);
47 return cir::ZeroAttr::get(arrayTy);
50 size_t trailingZerosNum = 0;
51 if (finalSize > lastNonZeroPos + 2)
52 trailingZerosNum = finalSize - lastNonZeroPos - 1;
53 auto truncatedArrayTy =
54 cir::ArrayType::get(eltTy, finalSize - trailingZerosNum);
55 auto fullArrayTy = cir::ArrayType::get(eltTy, finalSize);
56 return cir::ConstArrayAttr::get(
58 mlir::StringAttr::get(str.drop_back(trailingZerosNum),
68 for (
auto &f : arrayAttr) {
69 auto ta = mlir::cast<mlir::TypedAttr>(f);
70 members.push_back(ta.getType());
76 auto sTy = mlir::cast<cir::RecordType>(ty);
77 return cir::ConstRecordAttr::get(sTy, arrayAttr);
83 auto it = recordNames.find(baseName);
84 if (it == recordNames.end()) {
85 recordNames[baseName] = 0;
89 return baseName +
"." + std::to_string(recordNames[baseName]++);
93 if (&format == &llvm::APFloat::IEEEdouble())
94 return cir::LongDoubleType::get(getContext(), typeCache.
DoubleTy);
95 if (&format == &llvm::APFloat::x87DoubleExtended())
96 return cir::LongDoubleType::get(getContext(), typeCache.
FP80Ty);
97 if (&format == &llvm::APFloat::IEEEquad())
98 return cir::LongDoubleType::get(getContext(), typeCache.
FP128Ty);
99 if (&format == &llvm::APFloat::PPCDoubleDouble())
100 llvm_unreachable(
"NYI: PPC double-double format for long double");
101 llvm_unreachable(
"Unsupported format for long double");
112 return cir::RecordType::Class;
114 return cir::RecordType::Struct;
116 return cir::RecordType::Union;
118 llvm_unreachable(
"interface records are NYI");
120 llvm_unreachable(
"enums are not records");
122 llvm_unreachable(
"Unsupported record kind");
130 llvm::StringRef name,
bool packed,
132 const auto nameAttr = getStringAttr(name);
133 auto kind = cir::RecordType::RecordKind::Struct;
138 getType<cir::RecordType>(members, nameAttr, packed, padded, kind);
142 assert(!
type.isIncomplete() ||
143 (
type.getMembers() == members &&
type.getPacked() == packed &&
144 type.getPadded() == padded));
148 type.complete(members, packed, padded);
158 const mlir::StringAttr nameAttr = getStringAttr(name);
159 cir::RecordType::RecordKind kind = cir::RecordType::RecordKind::Struct;
162 return getType<cir::RecordType>(nameAttr, kind);
168 if (mlir::isa<cir::ZeroAttr>(
attr))
171 if (
const auto ptrVal = mlir::dyn_cast<cir::ConstPtrAttr>(
attr))
172 return ptrVal.isNullValue();
174 if (
const auto intVal = mlir::dyn_cast<cir::IntAttr>(
attr))
175 return intVal.isNullValue();
177 if (
const auto boolVal = mlir::dyn_cast<cir::BoolAttr>(
attr))
178 return !boolVal.getValue();
180 if (
auto fpAttr = mlir::dyn_cast<cir::FPAttr>(
attr)) {
181 auto fpVal = fpAttr.getValue();
183 llvm::APFloat fv(+0.0);
184 fv.convert(fpVal.getSemantics(), llvm::APFloat::rmNearestTiesToEven,
186 return fv.bitwiseIsEqual(fpVal);
189 if (
const auto arrayVal = mlir::dyn_cast<cir::ConstArrayAttr>(
attr)) {
190 if (mlir::isa<mlir::StringAttr>(arrayVal.getElts()))
194 mlir::cast<mlir::ArrayAttr>(arrayVal.getElts()),
195 [&](
const mlir::Attribute &elt) { return isNullValue(elt); });
215 return cir::IntType::get(getContext(), n,
false);
230 return cir::IntType::get(getContext(), n,
true);
246 cir::ConstantOp
getConstInt(mlir::Location loc, llvm::APSInt intVal);
248 cir::ConstantOp
getConstInt(mlir::Location loc, llvm::APInt intVal);
250 cir::ConstantOp
getConstInt(mlir::Location loc, mlir::Type t, uint64_t
c);
252 cir::ConstantOp
getConstFP(mlir::Location loc, mlir::Type t,
253 llvm::APFloat fpVal);
267 bool isInt(mlir::Type i) {
return mlir::isa<cir::IntType>(i); }
274 bool packed =
false,
bool padded =
false) {
276 auto kind = cir::RecordType::RecordKind::Struct;
277 return getType<cir::RecordType>(members, packed, padded, kind);
292 cir::ConstantOp
getNullPtr(mlir::Type ty, mlir::Location loc) {
299 if (
auto intTy = mlir::dyn_cast<cir::IntType>(value.getType())) {
301 if (intTy.isUnsigned())
303 return cir::UnaryOp::create(*
this, value.getLoc(), value.getType(),
304 cir::UnaryOpKind::Minus, value);
307 llvm_unreachable(
"negation for the given type is NYI");
315 return cir::CastOp::create(*
this, v.getLoc(), destType,
316 cir::CastKind::floating, v);
319 mlir::Value
createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
324 return cir::BinOp::create(*
this, loc, cir::BinOpKind::Sub, lhs, rhs);
327 mlir::Value
createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
332 return cir::BinOp::create(*
this, loc, cir::BinOpKind::Add, lhs, rhs);
334 mlir::Value
createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
339 return cir::BinOp::create(*
this, loc, cir::BinOpKind::Mul, lhs, rhs);
341 mlir::Value
createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
346 return cir::BinOp::create(*
this, loc, cir::BinOpKind::Div, lhs, rhs);
350 mlir::Type destType,
unsigned offset,
351 bool assumeNotNull) {
357 cir::BaseClassAddrOp::create(*
this, loc, ptrTy, addr.
getPointer(),
358 mlir::APInt(64, offset), assumeNotNull);
365 mlir::Type destType) {
375 bool isVolatile =
false) {
377 return cir::LoadOp::create(*
this, loc, addr.
getPointer(),
false,
379 cir::MemOrderAttr{});
383 bool isVolatile =
false,
384 mlir::IntegerAttr align = {},
385 cir::MemOrderAttr order = {}) {
388 return CIRBaseBuilderTy::createStore(loc, val, dst.getPointer(), isVolatile,
395 auto srcPtrTy = mlir::cast<cir::PointerType>(value.getType());
396 auto srcComplexTy = mlir::cast<cir::ComplexType>(srcPtrTy.getPointee());
397 return cir::ComplexRealPtrOp::create(
398 *
this, loc,
getPointerTo(srcComplexTy.getElementType()), value);
410 auto srcPtrTy = mlir::cast<cir::PointerType>(value.getType());
411 auto srcComplexTy = mlir::cast<cir::ComplexType>(srcPtrTy.getPointee());
412 return cir::ComplexImagPtrOp::create(
413 *
this, loc,
getPointerTo(srcComplexTy.getElementType()), value);
425 mlir::Location arrayLocEnd, mlir::Value arrayPtr,
426 mlir::Type eltTy, mlir::Value idx,
445 [[nodiscard]] cir::GlobalOp
447 mlir::StringRef name, mlir::Type
type,
bool isConstant,
448 cir::GlobalLinkageKind linkage) {
450 std::string uniqueName;
451 if (
unsigned version = globalsVersioning[name.str()]++)
452 uniqueName = name.str() +
"." + std::to_string(version);
454 uniqueName = name.str();
460 Address dstAddr, mlir::Type storageType,
462 bool isLvalueVolatile,
bool useVolatile) {
468 useVolatile ? cir::IntType::get(storageType.getContext(),
471 return cir::SetBitfieldOp::create(
472 *
this, loc, resultType, dstAddr.
getPointer(), storageType, src,
478 Address addr, mlir::Type storageType,
480 bool isLvalueVolatile,
bool useVolatile) {
486 useVolatile ? cir::IntType::get(storageType.getContext(),
489 return cir::GetBitfieldOp::create(*
this, loc, resultType, addr.
getPointer(),
490 storageType, info.
name, info.
size, offset,
__device__ __2f16 float c
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createIntCast(mlir::Value src, mlir::Type newTy)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
CIRBaseBuilderTy(mlir::MLIRContext &mlirContext)
cir::GlobalOp createGlobal(mlir::ModuleOp mlirModule, mlir::Location loc, mlir::StringRef name, mlir::Type type, bool isConstant, cir::GlobalLinkageKind linkage)
mlir::IntegerAttr getAlignmentAttr(clang::CharUnits alignment)
cir::ConstantOp getConstantInt(mlir::Location loc, mlir::Type ty, int64_t value)
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)
mlir::Value getPointer() const
mlir::Type getElementType() const
clang::CharUnits getAlignment() const
cir::IntType getUInt64Ty()
cir::IntType getUInt8Ty()
mlir::Value createComplexRealPtr(mlir::Location loc, mlir::Value value)
Create a cir.complex.real_ptr operation that derives a pointer to the real part of the complex value ...
cir::RecordType::RecordKind getRecordKind(const clang::TagTypeKind kind)
Get a CIR record kind from a AST declaration tag.
cir::IntType getSIntNTy(int n)
cir::ConstRecordAttr getAnonConstRecord(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type ty={})
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
cir::RecordType getIncompleteRecordTy(llvm::StringRef name, const clang::RecordDecl *rd)
Get an incomplete CIR struct type.
cir::ConstantOp getUInt32(uint32_t c, mlir::Location loc)
cir::GlobalOp createVersionedGlobal(mlir::ModuleOp module, mlir::Location loc, mlir::StringRef name, mlir::Type type, bool isConstant, cir::GlobalLinkageKind linkage)
Creates a versioned global variable.
cir::PointerType getUInt8PtrTy()
std::string getUniqueRecordName(const std::string &baseName)
cir::RecordType getAnonRecordTy(llvm::ArrayRef< mlir::Type > members, bool packed=false, bool padded=false)
Get a CIR anonymous record type.
Address createBaseClassAddr(mlir::Location loc, Address addr, mlir::Type destType, unsigned offset, bool assumeNotNull)
mlir::Value createComplexImagPtr(mlir::Location loc, mlir::Value value)
Create a cir.complex.imag_ptr operation that derives a pointer to the imaginary part of the complex v...
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.
mlir::Attribute getString(llvm::StringRef str, mlir::Type eltTy, std::optional< size_t > size)
Get a cir::ConstArrayAttr for a string literal.
cir::ConstantOp getConstFP(mlir::Location loc, mlir::Type t, llvm::APFloat fpVal)
mlir::Value createFloatingCast(mlir::Value v, mlir::Type destType)
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::RecordType getCompleteRecordTy(llvm::ArrayRef< mlir::Type > members, llvm::StringRef name, bool packed, bool padded)
Get a CIR named record type.
std::string getUniqueAnonRecordName()
Address createElementBitCast(mlir::Location loc, Address addr, mlir::Type destType)
Cast the element type of the given address to a different type, preserving information like the align...
cir::IntType getSInt8Ty()
bool isInt16Ty(mlir::Type i)
bool isInt32Ty(mlir::Type i)
cir::IntType getUInt16Ty()
mlir::Value createGetBitfield(mlir::Location loc, mlir::Type resultType, Address addr, mlir::Type storageType, const CIRGenBitFieldInfo &info, bool isLvalueVolatile, bool useVolatile)
bool isNullValue(mlir::Attribute attr) const
bool isInt64Ty(mlir::Type i)
mlir::Value createSetBitfield(mlir::Location loc, mlir::Type resultType, Address dstAddr, mlir::Type storageType, mlir::Value src, const CIRGenBitFieldInfo &info, bool isLvalueVolatile, bool useVolatile)
Address createComplexRealPtr(mlir::Location loc, Address addr)
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
CIRGenBuilderTy(mlir::MLIRContext &mlirContext, const CIRGenTypeCache &tc)
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
cir::VoidType getVoidTy()
void computeGlobalViewIndicesFromFlatOffset(int64_t offset, mlir::Type ty, cir::CIRDataLayout layout, llvm::SmallVectorImpl< int64_t > &indices)
cir::IntType getUInt32Ty()
mlir::Type getPtrToVPtrType()
cir::IntType getSInt32Ty()
Address createComplexImagPtr(mlir::Location loc, Address addr)
mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
cir::IntType getSInt64Ty()
cir::ConstantOp getSInt32(int32_t c, mlir::Location loc)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)
cir::LongDoubleType getLongDoubleTy(const llvm::fltSemantics &format) const
cir::IntType getSInt16Ty()
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs)
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.
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::MemOrderAttr order={})
bool isInt8Ty(mlir::Type i)
mlir::Value createNeg(mlir::Value value)
llvm::Align getAsAlign() const
getAsAlign - Returns Quantity as a valid llvm::Align, Beware llvm::Align assumes power of two 8-bit b...
Represents a struct/union/class.
TagKind getTagKind() const
const internal::VariadicAllOfMatcher< Attr > attr
Matches attributes.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
TagTypeKind
The kind of a tag type.
@ Interface
The "__interface" keyword.
@ Struct
The "struct" keyword.
@ Class
The "class" keyword.
@ Union
The "union" keyword.
@ Enum
The "enum" keyword.
static bool metaDataNode()
static bool targetCodeGenInfoGetNullPointer()
static bool fpConstraints()
static bool astRecordDeclAttr()
static bool fastMathFlags()
Record with information about how a bitfield should be accessed.
unsigned offset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
unsigned volatileStorageSize
The storage size in bits which should be used when accessing this bitfield.
unsigned size
The total size of the bit-field, in bits.
unsigned isSigned
Whether the bit-field is signed.
unsigned volatileOffset
The offset within a contiguous run of bitfields that are represented as a single "field" within the c...
llvm::StringRef name
The name of a bitfield.
This structure provides a set of types that are commonly used during IR emission.
cir::PointerType UInt8PtrTy