6#include "mlir/IR/BuiltinTypes.h"
21 builder(cgm.
getBuilder()), theCXXABI(cgm.getCXXABI()),
22 theABIInfo(cgm.getTargetCIRGenInfo().
getABIInfo()) {}
25 for (
auto i = functionInfos.begin(), e = functionInfos.end(); i != e;)
30 return *builder.getContext();
50 return !
tagType->isIncompleteType();
62 if (
const auto *fpt = dyn_cast<FunctionProtoType>(ft))
63 for (
unsigned i = 0, e = fpt->getNumParams(); i != e; i++)
70mlir::Type CIRGenTypes::convertFunctionTypeInternal(
QualType qft) {
83 if (
const auto *fpt = dyn_cast<FunctionProtoType>(ft)) {
102 llvm::raw_svector_ostream outStream(typeName);
113 .
print(outStream, policy);
117 outStream << builder.getUniqueAnonRecordName();
122 return builder.getUniqueRecordName(std::string(typeName));
127 const auto it = recordDeclTypes.find(ty);
128 return it != recordDeclTypes.end() && it->second.isComplete();
135 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);
142 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
145 if (!alreadyChecked.insert(rd).second)
149 "Expect RecordDecl to be CompleteDefinition");
170 if (
const CXXRecordDecl *crd = dyn_cast<CXXRecordDecl>(rd)) {
173 ->castAs<RecordType>()
175 ->getDefinitionOrSelf(),
176 cgt, alreadyChecked))
198 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
201 qt = at->getValueType();
233 const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();
234 cir::RecordType entry = recordDeclTypes[key];
241 entry = builder.getIncompleteRecordTy(name, rd);
242 recordDeclTypes[key] = entry;
251 deferredRecords.push_back(rd);
256 bool insertResult = recordsBeingLaidOut.insert(key).second;
258 assert(insertResult &&
"isSafeToCovert() should have caught this.");
261 safeToConvertCache.clear();
264 if (
const auto *
cxxRecordDecl = dyn_cast<CXXRecordDecl>(rd)) {
266 if (base.isVirtual())
274 recordDeclTypes[key] = entry;
275 cirGenRecordLayouts[key] = std::move(layout);
278 bool eraseResult = recordsBeingLaidOut.erase(key);
280 assert(eraseResult &&
"record not in RecordsBeingLaidOut set?");
283 safeToConvertCache.clear();
287 if (recordsBeingLaidOut.empty())
288 while (!deferredRecords.empty())
295 type = astContext.getCanonicalType(
type);
303 TypeCacheTy::iterator tci =
typeCache.find(ty);
310 mlir::Type resultType =
nullptr;
313 llvm_unreachable(
"Should have been handled above");
315 case Type::Builtin: {
318 case BuiltinType::Void:
319 resultType = cgm.voidTy;
323 case BuiltinType::Bool:
328 case BuiltinType::Char_S:
329 case BuiltinType::Int:
330 case BuiltinType::Int128:
331 case BuiltinType::Long:
332 case BuiltinType::LongLong:
333 case BuiltinType::SChar:
334 case BuiltinType::Short:
335 case BuiltinType::WChar_S:
336 case BuiltinType::Accum:
337 case BuiltinType::Fract:
338 case BuiltinType::LongAccum:
339 case BuiltinType::LongFract:
340 case BuiltinType::ShortAccum:
341 case BuiltinType::ShortFract:
343 case BuiltinType::SatAccum:
344 case BuiltinType::SatFract:
345 case BuiltinType::SatLongAccum:
346 case BuiltinType::SatLongFract:
347 case BuiltinType::SatShortAccum:
348 case BuiltinType::SatShortFract:
355 case BuiltinType::SveInt8:
357 cir::VectorType::get(builder.getSInt8Ty(), 16,
true);
359 case BuiltinType::SveUint8:
361 cir::VectorType::get(builder.getUInt8Ty(), 16,
true);
363 case BuiltinType::SveInt16:
365 cir::VectorType::get(builder.getSInt16Ty(), 8,
true);
367 case BuiltinType::SveUint16:
369 cir::VectorType::get(builder.getUInt16Ty(), 8,
true);
371 case BuiltinType::SveFloat16:
372 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
375 case BuiltinType::SveBFloat16:
376 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
379 case BuiltinType::SveInt32:
381 cir::VectorType::get(builder.getSInt32Ty(), 4,
true);
383 case BuiltinType::SveUint32:
385 cir::VectorType::get(builder.getUInt32Ty(), 4,
true);
387 case BuiltinType::SveFloat32:
388 resultType = cir::VectorType::get(builder.getSingleTy(), 4,
391 case BuiltinType::SveInt64:
393 cir::VectorType::get(builder.getSInt64Ty(), 2,
true);
395 case BuiltinType::SveUint64:
397 cir::VectorType::get(builder.getUInt64Ty(), 2,
true);
399 case BuiltinType::SveFloat64:
400 resultType = cir::VectorType::get(builder.getDoubleTy(), 2,
403 case BuiltinType::SveBool:
404 resultType = cir::VectorType::get(builder.getUIntNTy(1), 16,
409 case BuiltinType::Char8:
410 case BuiltinType::Char16:
411 case BuiltinType::Char32:
412 case BuiltinType::Char_U:
413 case BuiltinType::UChar:
414 case BuiltinType::UInt:
415 case BuiltinType::UInt128:
416 case BuiltinType::ULong:
417 case BuiltinType::ULongLong:
418 case BuiltinType::UShort:
419 case BuiltinType::WChar_U:
420 case BuiltinType::UAccum:
421 case BuiltinType::UFract:
422 case BuiltinType::ULongAccum:
423 case BuiltinType::ULongFract:
424 case BuiltinType::UShortAccum:
425 case BuiltinType::UShortFract:
427 case BuiltinType::SatUAccum:
428 case BuiltinType::SatUFract:
429 case BuiltinType::SatULongAccum:
430 case BuiltinType::SatULongFract:
431 case BuiltinType::SatUShortAccum:
432 case BuiltinType::SatUShortFract:
439 case BuiltinType::Float16:
440 resultType = cgm.fP16Ty;
442 case BuiltinType::Half:
443 if (astContext.getLangOpts().NativeHalfType ||
444 !astContext.getTargetInfo().useFP16ConversionIntrinsics()) {
445 resultType = cgm.fP16Ty;
448 resultType = cgm.sInt32Ty;
451 case BuiltinType::BFloat16:
452 resultType = cgm.bFloat16Ty;
454 case BuiltinType::MFloat8:
455 resultType = cgm.uInt8Ty;
457 case BuiltinType::Float:
458 assert(&astContext.getFloatTypeSemantics(
type) ==
459 &llvm::APFloat::IEEEsingle() &&
460 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");
461 resultType = cgm.floatTy;
463 case BuiltinType::Double:
464 assert(&astContext.getFloatTypeSemantics(
type) ==
465 &llvm::APFloat::IEEEdouble() &&
466 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");
467 resultType = cgm.doubleTy;
469 case BuiltinType::LongDouble:
471 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(
type));
473 case BuiltinType::Float128:
474 resultType = cgm.fP128Ty;
476 case BuiltinType::Ibm128:
478 resultType = cgm.sInt32Ty;
481 case BuiltinType::NullPtr:
486 resultType = builder.getVoidPtrTy();
491 resultType = cgm.sInt32Ty;
497 case Type::Complex: {
499 mlir::Type elementTy =
convertType(ct->getElementType());
500 resultType = cir::ComplexType::get(elementTy);
504 case Type::LValueReference:
505 case Type::RValueReference: {
509 resultType = builder.getPointerTo(pointeeType, elemTy.
getAddressSpace());
510 assert(resultType &&
"Cannot get pointer type?");
514 case Type::Pointer: {
521 resultType = builder.getPointerTo(pointeeType, elemTy.
getAddressSpace());
525 case Type::VariableArray: {
535 case Type::IncompleteArray: {
544 elemTy = cgm.sInt8Ty;
547 resultType = cir::ArrayType::get(elemTy, 0);
551 case Type::ConstantArray: {
559 resultType = cir::ArrayType::get(elemTy, arrTy->
getSize().getZExtValue());
563 case Type::ExtVector:
573 if (
auto integerType = ed->getIntegerType(); !integerType.isNull())
578 resultType = cgm.uInt32Ty;
582 case Type::MemberPointer: {
586 auto clsTy = mlir::cast<cir::RecordType>(
588 if (mpt->isMemberDataPointer()) {
589 mlir::Type memberTy =
convertType(mpt->getPointeeType());
590 resultType = cir::DataMemberType::get(memberTy, clsTy);
592 auto memberFuncTy =
getFunctionType(cgm.getTypes().arrangeCXXMethodType(
596 resultType = cir::MethodType::get(memberFuncTy, clsTy);
601 case Type::FunctionNoProto:
602 case Type::FunctionProto:
603 resultType = convertFunctionTypeInternal(
type);
608 unsigned numBits = bitIntTy->getNumBits();
609 assert(numBits <= cir::IntType::maxBitwidth() &&
610 "_BitInt width exceeds CIR IntType maximum");
612 cir::IntType::get(&
getMLIRContext(), numBits, bitIntTy->isSigned(),
622 uint64_t valueSize = astContext.getTypeSize(valueType);
623 uint64_t atomicSize = astContext.getTypeSize(ty);
624 if (valueSize != atomicSize) {
625 cgm.errorNYI(
"convertType: atomic type value size != atomic size");
633 type->getTypeClassName());
634 resultType = cgm.sInt32Ty;
638 assert(resultType &&
"Type conversion not yet implemented");
646 if (
qualType->isConstantMatrixType()) {
647 cgm.errorNYI(
"Matrix type conversion");
653 assert(!forBitField &&
"Bit fields NYI");
657 if (forBitField &&
qualType->isBitIntType())
658 assert(!
qualType->isBitIntType() &&
"Bit field with type _BitInt NYI");
660 return convertedType;
666 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
669 auto it = cirGenRecordLayouts.find(key);
670 if (it != cirGenRecordLayouts.end())
677 it = cirGenRecordLayouts.find(key);
679 assert(it != cirGenRecordLayouts.end() &&
680 "Unable to find record layout information for type");
686 return astContext.getTargetNullPointerValue(t) == 0;
688 if (
const auto *at = astContext.getAsArrayType(t)) {
692 if (
const auto *cat = dyn_cast<ConstantArrayType>(at))
693 if (astContext.getConstantArrayElementCount(cat) == 0)
701 return theCXXABI.isZeroInitializable(mpt);
703 if (t->
getAs<HLSLInlineSpirvType>())
705 "isZeroInitializable for HLSLInlineSpirvType");
718 assert(llvm::all_of(argTypes,
721 llvm::FoldingSetNodeID id;
725 void *insertPos =
nullptr;
733 "Bad match based on CIRGenFunctionInfo folding set id");
742 functionInfos.InsertNode(fi, insertPos);
748 assert(!dyn_cast<ObjCMethodDecl>(gd.
getDecl()) &&
749 "This is reported as a FIXME in LLVM codegen");
765 if ([[maybe_unused]]
const auto *ed = dyn_cast<EnumDecl>(td)) {
773 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
775 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
785 if (rd->isDependentType())
790 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
804 ? 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.
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.
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 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.