6#include "mlir/IR/BuiltinTypes.h"
22 builder(cgm.
getBuilder()), theCXXABI(cgm.getCXXABI()),
23 theABIInfo(cgm.getTargetCIRGenInfo().
getABIInfo()) {}
26 for (
auto i = functionInfos.begin(), e = functionInfos.end(); i != e;)
31 return *builder.getContext();
51 return !
tagType->isIncompleteType();
63 if (
const auto *fpt = dyn_cast<FunctionProtoType>(ft))
64 for (
unsigned i = 0, e = fpt->getNumParams(); i != e; i++)
71mlir::Type CIRGenTypes::convertFunctionTypeInternal(
QualType qft) {
84 if (
const auto *fpt = dyn_cast<FunctionProtoType>(ft)) {
103 llvm::raw_svector_ostream outStream(typeName);
114 .
print(outStream, policy);
118 outStream << builder.getUniqueAnonRecordName();
123 return builder.getUniqueRecordName(std::string(typeName));
128 const auto it = recordDeclTypes.find(ty);
129 return it != recordDeclTypes.end() && it->second.isComplete();
136 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);
143 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
146 if (!alreadyChecked.insert(rd).second)
150 "Expect RecordDecl to be CompleteDefinition");
171 if (
const CXXRecordDecl *crd = dyn_cast<CXXRecordDecl>(rd)) {
174 ->castAs<RecordType>()
176 ->getDefinitionOrSelf(),
177 cgt, alreadyChecked))
199 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
202 qt = at->getValueType();
235 return astContext.getTypeSize(
type) !=
236 astContext.getTypeSize(
type->getValueType());
243 const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();
251 entry = builder.getIncompleteRecordTy(name, rd);
252 recordDeclTypes[key] = entry;
261 deferredRecords.push_back(rd);
266 bool insertResult = recordsBeingLaidOut.insert(key).second;
268 assert(insertResult &&
"isSafeToCovert() should have caught this.");
271 safeToConvertCache.clear();
274 if (
const auto *
cxxRecordDecl = dyn_cast<CXXRecordDecl>(rd)) {
276 if (base.isVirtual())
284 recordDeclTypes[key] = entry;
285 cirGenRecordLayouts[key] = std::move(layout);
288 bool eraseResult = recordsBeingLaidOut.erase(key);
290 assert(eraseResult &&
"record not in RecordsBeingLaidOut set?");
293 safeToConvertCache.clear();
297 if (recordsBeingLaidOut.empty())
298 while (!deferredRecords.empty())
305 type = astContext.getCanonicalType(
type);
308 if (astContext.getLangOpts().CUDAIsDevice) {
309 if (
type->isCUDADeviceBuiltinSurfaceType()) {
311 cgm.getTargetCIRGenInfo().getCUDADeviceBuiltinSurfaceDeviceType())
313 }
else if (
type->isCUDADeviceBuiltinTextureType()) {
323 TypeCacheTy::iterator tci =
typeCache.find(ty);
330 mlir::Type resultType =
nullptr;
333 llvm_unreachable(
"Should have been handled above");
335 case Type::Builtin: {
338 case BuiltinType::Void:
339 resultType = cgm.voidTy;
343 case BuiltinType::Bool:
348 case BuiltinType::Char_S:
349 case BuiltinType::Int:
350 case BuiltinType::Int128:
351 case BuiltinType::Long:
352 case BuiltinType::LongLong:
353 case BuiltinType::SChar:
354 case BuiltinType::Short:
355 case BuiltinType::WChar_S:
356 case BuiltinType::Accum:
357 case BuiltinType::Fract:
358 case BuiltinType::LongAccum:
359 case BuiltinType::LongFract:
360 case BuiltinType::ShortAccum:
361 case BuiltinType::ShortFract:
363 case BuiltinType::SatAccum:
364 case BuiltinType::SatFract:
365 case BuiltinType::SatLongAccum:
366 case BuiltinType::SatLongFract:
367 case BuiltinType::SatShortAccum:
368 case BuiltinType::SatShortFract:
375 case BuiltinType::SveInt8:
377 cir::VectorType::get(builder.getSInt8Ty(), 16,
true);
379 case BuiltinType::SveUint8:
381 cir::VectorType::get(builder.getUInt8Ty(), 16,
true);
383 case BuiltinType::SveInt16:
385 cir::VectorType::get(builder.getSInt16Ty(), 8,
true);
387 case BuiltinType::SveUint16:
389 cir::VectorType::get(builder.getUInt16Ty(), 8,
true);
391 case BuiltinType::SveFloat16:
392 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
395 case BuiltinType::SveBFloat16:
396 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
399 case BuiltinType::SveInt32:
401 cir::VectorType::get(builder.getSInt32Ty(), 4,
true);
403 case BuiltinType::SveUint32:
405 cir::VectorType::get(builder.getUInt32Ty(), 4,
true);
407 case BuiltinType::SveFloat32:
408 resultType = cir::VectorType::get(builder.getSingleTy(), 4,
411 case BuiltinType::SveInt64:
413 cir::VectorType::get(builder.getSInt64Ty(), 2,
true);
415 case BuiltinType::SveUint64:
417 cir::VectorType::get(builder.getUInt64Ty(), 2,
true);
419 case BuiltinType::SveFloat64:
420 resultType = cir::VectorType::get(builder.getDoubleTy(), 2,
423 case BuiltinType::SveBool:
424 resultType = cir::VectorType::get(builder.getUIntNTy(1), 16,
429 case BuiltinType::Char8:
430 case BuiltinType::Char16:
431 case BuiltinType::Char32:
432 case BuiltinType::Char_U:
433 case BuiltinType::UChar:
434 case BuiltinType::UInt:
435 case BuiltinType::UInt128:
436 case BuiltinType::ULong:
437 case BuiltinType::ULongLong:
438 case BuiltinType::UShort:
439 case BuiltinType::WChar_U:
440 case BuiltinType::UAccum:
441 case BuiltinType::UFract:
442 case BuiltinType::ULongAccum:
443 case BuiltinType::ULongFract:
444 case BuiltinType::UShortAccum:
445 case BuiltinType::UShortFract:
447 case BuiltinType::SatUAccum:
448 case BuiltinType::SatUFract:
449 case BuiltinType::SatULongAccum:
450 case BuiltinType::SatULongFract:
451 case BuiltinType::SatUShortAccum:
452 case BuiltinType::SatUShortFract:
459 case BuiltinType::Float16:
460 resultType = cgm.fP16Ty;
462 case BuiltinType::Half:
463 resultType = cgm.fP16Ty;
465 case BuiltinType::BFloat16:
466 resultType = cgm.bFloat16Ty;
468 case BuiltinType::MFloat8:
469 resultType = cgm.uInt8Ty;
471 case BuiltinType::Float:
472 assert(&astContext.getFloatTypeSemantics(
type) ==
473 &llvm::APFloat::IEEEsingle() &&
474 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");
475 resultType = cgm.floatTy;
477 case BuiltinType::Double:
478 assert(&astContext.getFloatTypeSemantics(
type) ==
479 &llvm::APFloat::IEEEdouble() &&
480 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");
481 resultType = cgm.doubleTy;
483 case BuiltinType::LongDouble:
485 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(
type));
487 case BuiltinType::Float128:
488 resultType = cgm.fP128Ty;
490 case BuiltinType::Ibm128:
492 resultType = cgm.sInt32Ty;
495 case BuiltinType::NullPtr:
500 resultType = builder.getVoidPtrTy();
503#define AMDGPU_OPAQUE_PTR_TYPE(Name, Id, SingletonId, Width, Align, AS) \
504 case BuiltinType::Id: { \
505 if (BuiltinType::Id == BuiltinType::AMDGPUTexture) { \
506 resultType = cir::VectorType::get(builder.getSInt32Ty(), 8); \
508 resultType = builder.getPointerTo( \
510 cir::TargetAddressSpaceAttr::get(&getMLIRContext(), AS)); \
514#define AMDGPU_NAMED_BARRIER_TYPE(Name, Id, SingletonId, Width, Align, Scope) \
515 case BuiltinType::Id: \
516 llvm_unreachable("NYI");
517#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) \
518 case BuiltinType::Id: \
519 llvm_unreachable("NYI");
520#include "clang/Basic/AMDGPUTypes.def"
524 resultType = cgm.sInt32Ty;
530 case Type::Complex: {
532 mlir::Type elementTy =
convertType(ct->getElementType());
533 resultType = cir::ComplexType::get(elementTy);
537 case Type::LValueReference:
538 case Type::RValueReference: {
542 resultType = builder.getPointerTo(pointeeType, elemTy.
getAddressSpace());
543 assert(resultType &&
"Cannot get pointer type?");
547 case Type::Pointer: {
554 resultType = builder.getPointerTo(pointeeType, elemTy.
getAddressSpace());
558 case Type::VariableArray: {
568 case Type::IncompleteArray: {
577 elemTy = cgm.sInt8Ty;
580 resultType = cir::ArrayType::get(elemTy, 0);
584 case Type::ConstantArray: {
592 resultType = cir::ArrayType::get(elemTy, arrTy->
getSize().getZExtValue());
596 case Type::ExtVector:
606 if (
auto integerType = ed->getIntegerType(); !integerType.isNull())
611 resultType = cgm.uInt32Ty;
615 case Type::MemberPointer: {
619 auto clsTy = mlir::cast<cir::RecordType>(
621 if (mpt->isMemberDataPointer()) {
622 mlir::Type memberTy =
convertType(mpt->getPointeeType());
623 resultType = cir::DataMemberType::get(memberTy, clsTy);
625 auto memberFuncTy =
getFunctionType(cgm.getTypes().arrangeCXXMethodType(
629 resultType = cir::MethodType::get(memberFuncTy, clsTy);
634 case Type::FunctionNoProto:
635 case Type::FunctionProto:
636 resultType = convertFunctionTypeInternal(
type);
641 unsigned numBits = bitIntTy->getNumBits();
642 assert(numBits <= cir::IntType::maxBitwidth() &&
643 "_BitInt width exceeds CIR IntType maximum");
645 cir::IntType::get(&
getMLIRContext(), numBits, bitIntTy->isSigned(),
655 uint64_t valueSize = astContext.getTypeSize(valueType);
656 uint64_t atomicSize = astContext.getTypeSize(ty);
657 if (valueSize != atomicSize) {
658 assert(valueSize < atomicSize);
660 cir::ArrayType::get(cgm.sInt8Ty, (atomicSize - valueSize) / 8);
661 mlir::Type elements[] = {resultType, paddingArray};
672 type->getTypeClassName());
673 resultType = cgm.sInt32Ty;
677 assert(resultType &&
"Type conversion not yet implemented");
685 if (
qualType->isConstantMatrixType()) {
686 cgm.errorNYI(
"Matrix type conversion");
692 assert(!forBitField &&
"Bit fields NYI");
696 if (forBitField &&
qualType->isBitIntType())
697 assert(!
qualType->isBitIntType() &&
"Bit field with type _BitInt NYI");
699 return convertedType;
705 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
708 auto it = cirGenRecordLayouts.find(key);
709 if (it != cirGenRecordLayouts.end())
716 it = cirGenRecordLayouts.find(key);
718 assert(it != cirGenRecordLayouts.end() &&
719 "Unable to find record layout information for type");
725 return astContext.getTargetNullPointerValue(t) == 0;
727 if (
const auto *at = astContext.getAsArrayType(t)) {
731 if (
const auto *cat = dyn_cast<ConstantArrayType>(at))
732 if (astContext.getConstantArrayElementCount(cat) == 0)
740 return theCXXABI.isZeroInitializable(mpt);
742 if (t->
getAs<HLSLInlineSpirvType>())
744 "isZeroInitializable for HLSLInlineSpirvType");
757 assert(llvm::all_of(argTypes,
760 llvm::FoldingSetNodeID id;
764 void *insertPos =
nullptr;
772 "Bad match based on CIRGenFunctionInfo folding set id");
781 functionInfos.InsertNode(fi, insertPos);
787 assert(!dyn_cast<ObjCMethodDecl>(gd.
getDecl()) &&
788 "This is reported as a FIXME in LLVM codegen");
804 if ([[maybe_unused]]
const auto *ed = dyn_cast<EnumDecl>(td)) {
812 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
814 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
824 if (rd->isDependentType())
829 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
843 ? cgm.getDataLayout().getProgramAddressSpace()
Defines the clang::ASTContext interface.
static bool isSafeToConvert(QualType qt, CIRGenTypes &cgt, llvm::SmallPtrSetImpl< const RecordDecl * > &alreadyChecked)
Return true if it is safe to convert this field type, which requires the record elements contained by...
static Decl::Kind getKind(const Decl *D)
C Language Family Type Representation.
C++ view class that accepts both !cir.struct and !cir.union types.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
CanQualType getCanonicalTagType(const TagDecl *TD) const
unsigned getTargetAddressSpace(LangAS AS) const
QualType getElementType() const
unsigned getIndexTypeCVRQualifiers() const
CanQualType getReturnType() const
const_arg_iterator argTypesEnd() const
static CIRGenFunctionInfo * create(FunctionType::ExtInfo info, bool instanceMethod, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
static void Profile(llvm::FoldingSetNodeID &id, bool instanceMethod, FunctionType::ExtInfo info, RequiredArgs required, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes)
const_arg_iterator argTypesBegin() const
This class organizes the cross-function state that is used while generating CIR code.
bool isPaddedAtomicType(QualType type)
This class handles record and union layout info while lowering AST types to CIR types.
bool isZeroInitializable() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer.
This class organizes the cross-module state that is used while lowering AST types to CIR types.
const CIRGenFunctionInfo & arrangeGlobalDeclaration(GlobalDecl gd)
unsigned getTargetAddressSpace(QualType ty) const
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, bool isInstanceMethod, llvm::ArrayRef< CanQualType > argTypes, FunctionType::ExtInfo info, RequiredArgs required)
const CIRGenFunctionInfo & arrangeFreeFunctionType(CanQual< FunctionProtoType > fpt)
bool isZeroInitializable(clang::QualType ty)
Return whether a type can be zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
bool isFuncTypeConvertible(const clang::FunctionType *ft)
Utility to check whether a function type can be converted to a CIR type (i.e.
CIRGenTypes(CIRGenModule &cgm)
bool isRecordBeingLaidOut(const clang::Type *ty) const
CIRGenBuilderTy & getBuilder() const
mlir::MLIRContext & getMLIRContext() const
bool isCachedSafeToConvert(const clang::Type *key) const
Check if a record type key is in the safe-to-convert cache.
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
bool isFuncParamTypeConvertible(clang::QualType type)
Return true if the specified type in a function parameter or result position can be converted to a CI...
void updateCompletedType(const clang::TagDecl *td)
UpdateCompletedType - when we find the full definition for a TagDecl, replace the 'opaque' type we pr...
std::string getRecordTypeName(const clang::RecordDecl *, llvm::StringRef suffix)
bool noRecordsBeingLaidOut() const
const ABIInfo & getABIInfo() const
const CIRGenFunctionInfo & arrangeFunctionDeclaration(const clang::FunctionDecl *fd)
Free functions are functions that are compatible with an ordinary C function pointer type.
clang::ASTContext & getASTContext() const
bool isRecordLayoutComplete(const clang::Type *ty) const
Return true if the specified type is already completely laid out.
mlir::Type convertType(clang::QualType type)
Convert a Clang type into a mlir::Type.
const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)
Return record layout info for the given record decl.
std::unique_ptr< CIRGenRecordLayout > computeRecordLayout(const clang::RecordDecl *rd, cir::RecordType *ty)
mlir::Type convertRecordDeclType(const clang::RecordDecl *recordDecl)
Lay out a tagged decl type like struct or union.
void cacheSafeToConvert(const clang::Type *key)
Add a record type key to the safe-to-convert cache.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
A class for recording the number of arguments that a function signature requires.
Represents a base class of a C++ class.
Represents a C++ struct/union/class.
static CanQual< T > CreateUnsafe(QualType Other)
Builds a canonical type from a QualType.
bool isCanonicalAsParam() const
Determines if this canonical type is furthermore canonical as a parameter.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
Represents the canonical version of C arrays with a specified constant size.
llvm::APInt getSize() const
Return the constant array size as an APInt.
Represents a member of a struct/union/class.
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Represents a prototype with parameter type info, e.g.
A class which abstracts out some details necessary for making a call.
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getReturnType() const
GlobalDecl - represents a global declaration.
const Decl * getDecl() const
Represents a C array with an unspecified size.
A pointer to member type per C++ 8.3.3 - Pointers to members.
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
CXXRecordDecl * getAsRecordDecl() const
Retrieve the record declaration stored in this nested name specifier, or null.
const Type * getAsType() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
QualType getPointeeType() const
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
LangAS getAddressSpace() const
Return the address space of this type.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Represents a struct/union/class.
field_range fields() const
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Base for LValueReferenceType and RValueReferenceType.
QualType getPointeeType() const
Encodes a location in the source.
Represents the declaration of a struct/union/class/enum.
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
The base class of the type hierarchy.
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isConstantMatrixType() const
EnumDecl * castAsEnumDecl() const
bool isFunctionType() const
TypeClass getTypeClass() const
const T * getAs() const
Member-template getAs<specific type>'.
Represents a C array with a specified size that is not an integer-constant-expression.
Represents a GCC generic vector type.
unsigned getNumElements() const
QualType getElementType() const
Defines the clang::TargetInfo interface.
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
const internal::VariadicDynCastAllOfMatcher< Decl, TypedefNameDecl > typedefNameDecl
Matches typedef name declarations.
const AstTypeMatcher< TagType > tagType
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< RecordType > recordType
const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl
Matches C++ class declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, RecordDecl > recordDecl
Matches class, struct, and union declarations.
const internal::VariadicAllOfMatcher< QualType > qualType
Matches QualTypes in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
bool isInstanceMethod(const Decl *D)
U cast(CodeGen::Address addr)
static bool opCallCallConv()
static bool cudaTextureType()
static bool generateDebugInfo()
Describes how types, statements, expressions, and declarations should be printed.
unsigned SuppressTagKeyword
Whether type printing should skip printing the tag keyword.
unsigned AlwaysIncludeTypeForTemplateArgument
Whether to use type suffixes (eg: 1U) on integral non-type template parameters.
unsigned SuppressInlineNamespace
Suppress printing parts of scope specifiers that correspond to inline namespaces.
unsigned PrintAsCanonical
Whether to print entities as written or canonically.