5#include "mlir/IR/BuiltinTypes.h"
20 builder(cgm.
getBuilder()), theCXXABI(cgm.getCXXABI()),
21 theABIInfo(cgm.getTargetCIRGenInfo().
getABIInfo()) {}
24 for (
auto i = functionInfos.begin(), e = functionInfos.end(); i != e;)
29 return *builder.getContext();
49 return !
tagType->isIncompleteType();
61 if (
const auto *fpt = dyn_cast<FunctionProtoType>(ft))
62 for (
unsigned i = 0, e = fpt->getNumParams(); i != e; i++)
69mlir::Type CIRGenTypes::convertFunctionTypeInternal(
QualType qft) {
82 if (
const auto *fpt = dyn_cast<FunctionProtoType>(ft)) {
101 llvm::raw_svector_ostream outStream(typeName);
112 .
print(outStream, policy);
116 outStream << builder.getUniqueAnonRecordName();
121 return builder.getUniqueRecordName(std::string(typeName));
126 const auto it = recordDeclTypes.find(ty);
127 return it != recordDeclTypes.end() && it->second.isComplete();
134 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);
141 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
144 if (!alreadyChecked.insert(rd).second)
148 "Expect RecordDecl to be CompleteDefinition");
163 if (
const CXXRecordDecl *crd = dyn_cast<CXXRecordDecl>(rd)) {
166 ->castAs<RecordType>()
168 ->getDefinitionOrSelf(),
169 cgt, alreadyChecked))
187 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
190 qt = at->getValueType();
222 const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();
223 cir::RecordType entry = recordDeclTypes[key];
230 entry = builder.getIncompleteRecordTy(name, rd);
231 recordDeclTypes[key] = entry;
240 deferredRecords.push_back(rd);
245 bool insertResult = recordsBeingLaidOut.insert(key).second;
247 assert(insertResult &&
"isSafeToCovert() should have caught this.");
250 if (
const auto *
cxxRecordDecl = dyn_cast<CXXRecordDecl>(rd)) {
252 if (base.isVirtual())
260 recordDeclTypes[key] = entry;
261 cirGenRecordLayouts[key] = std::move(layout);
264 bool eraseResult = recordsBeingLaidOut.erase(key);
266 assert(eraseResult &&
"record not in RecordsBeingLaidOut set?");
274 if (recordsBeingLaidOut.empty())
275 while (!deferredRecords.empty())
282 type = astContext.getCanonicalType(
type);
290 TypeCacheTy::iterator tci =
typeCache.find(ty);
297 mlir::Type resultType =
nullptr;
300 llvm_unreachable(
"Should have been handled above");
302 case Type::Builtin: {
305 case BuiltinType::Void:
306 resultType = cgm.voidTy;
310 case BuiltinType::Bool:
315 case BuiltinType::Char_S:
316 case BuiltinType::Int:
317 case BuiltinType::Int128:
318 case BuiltinType::Long:
319 case BuiltinType::LongLong:
320 case BuiltinType::SChar:
321 case BuiltinType::Short:
322 case BuiltinType::WChar_S:
329 case BuiltinType::SveInt8:
331 cir::VectorType::get(builder.getSInt8Ty(), 16,
true);
333 case BuiltinType::SveUint8:
335 cir::VectorType::get(builder.getUInt8Ty(), 16,
true);
337 case BuiltinType::SveInt16:
339 cir::VectorType::get(builder.getSInt16Ty(), 8,
true);
341 case BuiltinType::SveUint16:
343 cir::VectorType::get(builder.getUInt16Ty(), 8,
true);
345 case BuiltinType::SveFloat16:
346 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
349 case BuiltinType::SveBFloat16:
350 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
353 case BuiltinType::SveInt32:
355 cir::VectorType::get(builder.getSInt32Ty(), 4,
true);
357 case BuiltinType::SveUint32:
359 cir::VectorType::get(builder.getUInt32Ty(), 4,
true);
361 case BuiltinType::SveFloat32:
362 resultType = cir::VectorType::get(builder.getSingleTy(), 4,
365 case BuiltinType::SveInt64:
367 cir::VectorType::get(builder.getSInt64Ty(), 2,
true);
369 case BuiltinType::SveUint64:
371 cir::VectorType::get(builder.getUInt64Ty(), 2,
true);
373 case BuiltinType::SveFloat64:
374 resultType = cir::VectorType::get(builder.getDoubleTy(), 2,
379 case BuiltinType::Char8:
380 case BuiltinType::Char16:
381 case BuiltinType::Char32:
382 case BuiltinType::Char_U:
383 case BuiltinType::UChar:
384 case BuiltinType::UInt:
385 case BuiltinType::UInt128:
386 case BuiltinType::ULong:
387 case BuiltinType::ULongLong:
388 case BuiltinType::UShort:
389 case BuiltinType::WChar_U:
396 case BuiltinType::Float16:
397 resultType = cgm.fP16Ty;
399 case BuiltinType::Half:
400 if (astContext.getLangOpts().NativeHalfType ||
401 !astContext.getTargetInfo().useFP16ConversionIntrinsics()) {
402 resultType = cgm.fP16Ty;
405 resultType = cgm.sInt32Ty;
408 case BuiltinType::BFloat16:
409 resultType = cgm.bFloat16Ty;
411 case BuiltinType::Float:
412 assert(&astContext.getFloatTypeSemantics(
type) ==
413 &llvm::APFloat::IEEEsingle() &&
414 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");
415 resultType = cgm.floatTy;
417 case BuiltinType::Double:
418 assert(&astContext.getFloatTypeSemantics(
type) ==
419 &llvm::APFloat::IEEEdouble() &&
420 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");
421 resultType = cgm.doubleTy;
423 case BuiltinType::LongDouble:
425 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(
type));
427 case BuiltinType::Float128:
428 resultType = cgm.fP128Ty;
430 case BuiltinType::Ibm128:
432 resultType = cgm.sInt32Ty;
435 case BuiltinType::NullPtr:
440 resultType = builder.getVoidPtrTy();
445 resultType = cgm.sInt32Ty;
451 case Type::Complex: {
453 mlir::Type elementTy =
convertType(ct->getElementType());
454 resultType = cir::ComplexType::get(elementTy);
458 case Type::LValueReference:
459 case Type::RValueReference: {
463 resultType = builder.getPointerTo(pointeeType, elemTy.
getAddressSpace());
464 assert(resultType &&
"Cannot get pointer type?");
468 case Type::Pointer: {
475 resultType = builder.getPointerTo(pointeeType, elemTy.
getAddressSpace());
479 case Type::VariableArray: {
489 case Type::IncompleteArray: {
498 elemTy = cgm.sInt8Ty;
501 resultType = cir::ArrayType::get(elemTy, 0);
505 case Type::ConstantArray: {
513 resultType = cir::ArrayType::get(elemTy, arrTy->
getSize().getZExtValue());
517 case Type::ExtVector:
527 if (
auto integerType = ed->getIntegerType(); !integerType.isNull())
532 resultType = cgm.uInt32Ty;
536 case Type::MemberPointer: {
539 mlir::Type memberTy =
convertType(mpt->getPointeeType());
540 auto clsTy = mlir::cast<cir::RecordType>(
542 if (mpt->isMemberDataPointer()) {
543 resultType = cir::DataMemberType::get(memberTy, clsTy);
545 auto memberFuncTy = mlir::cast<cir::FuncType>(memberTy);
546 resultType = cir::MethodType::get(memberFuncTy, clsTy);
551 case Type::FunctionNoProto:
552 case Type::FunctionProto:
553 resultType = convertFunctionTypeInternal(
type);
558 if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {
560 resultType = cgm.sInt32Ty;
562 resultType = cir::IntType::get(&
getMLIRContext(), bitIntTy->getNumBits(),
563 bitIntTy->isSigned());
573 uint64_t valueSize = astContext.getTypeSize(valueType);
574 uint64_t atomicSize = astContext.getTypeSize(ty);
575 if (valueSize != atomicSize) {
576 cgm.errorNYI(
"convertType: atomic type value size != atomic size");
584 type->getTypeClassName());
585 resultType = cgm.sInt32Ty;
589 assert(resultType &&
"Type conversion not yet implemented");
597 assert(!
qualType->isConstantMatrixType() &&
"Matrix types NYI");
601 assert(!forBitField &&
"Bit fields NYI");
605 if (forBitField &&
qualType->isBitIntType())
606 assert(!
qualType->isBitIntType() &&
"Bit field with type _BitInt NYI");
608 return convertedType;
614 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
617 auto it = cirGenRecordLayouts.find(key);
618 if (it != cirGenRecordLayouts.end())
625 it = cirGenRecordLayouts.find(key);
627 assert(it != cirGenRecordLayouts.end() &&
628 "Unable to find record layout information for type");
634 return astContext.getTargetNullPointerValue(t) == 0;
636 if (
const auto *at = astContext.getAsArrayType(t)) {
640 if (
const auto *cat = dyn_cast<ConstantArrayType>(at))
641 if (astContext.getConstantArrayElementCount(cat) == 0)
649 cgm.errorNYI(
SourceLocation(),
"isZeroInitializable for MemberPointerType",
664 assert(llvm::all_of(argTypes,
667 llvm::FoldingSetNodeID id;
670 void *insertPos =
nullptr;
678 "Bad match based on CIRGenFunctionInfo folding set id");
686 functionInfos.InsertNode(fi, insertPos);
692 assert(!dyn_cast<ObjCMethodDecl>(gd.
getDecl()) &&
693 "This is reported as a FIXME in LLVM codegen");
709 if ([[maybe_unused]]
const auto *ed = dyn_cast<EnumDecl>(td)) {
717 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
719 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
729 if (rd->isDependentType())
734 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
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
QualType getElementType() const
unsigned getIndexTypeCVRQualifiers() const
static void Profile(llvm::FoldingSetNodeID &id, FunctionType::ExtInfo info, RequiredArgs required, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes)
CanQualType getReturnType() const
const_arg_iterator argTypesEnd() const
static CIRGenFunctionInfo * create(FunctionType::ExtInfo info, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
const_arg_iterator argTypesBegin() const
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
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)
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
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
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 CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, llvm::ArrayRef< CanQualType > argTypes, FunctionType::ExtInfo info, RequiredArgs required)
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.
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.
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.
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
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
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)
U cast(CodeGen::Address addr)
static bool skippedLayout()
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.