19 builder(cgm.
getBuilder()), theCXXABI(cgm.getCXXABI()),
20 theABIInfo(cgm.getTargetCIRGenInfo().
getABIInfo()) {}
23 for (
auto i = functionInfos.begin(), e = functionInfos.end(); i != e;)
28 return *builder.getContext();
46 return !
tagType->isIncompleteType();
58 if (
const auto *fpt = dyn_cast<FunctionProtoType>(ft))
59 for (
unsigned i = 0, e = fpt->getNumParams(); i != e; i++)
66mlir::Type CIRGenTypes::convertFunctionTypeInternal(
QualType qft) {
79 if (
const auto *fpt = dyn_cast<FunctionProtoType>(ft)) {
98 llvm::raw_svector_ostream outStream(typeName);
109 .
print(outStream, policy);
113 outStream << builder.getUniqueAnonRecordName();
118 return builder.getUniqueRecordName(std::string(typeName));
123 const auto it = recordDeclTypes.find(ty);
124 return it != recordDeclTypes.end() && it->second.isComplete();
131 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);
138 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
141 if (!alreadyChecked.insert(rd).second)
145 "Expect RecordDecl to be CompleteDefinition");
160 if (
const CXXRecordDecl *crd = dyn_cast<CXXRecordDecl>(rd)) {
163 ->castAs<RecordType>()
165 ->getDefinitionOrSelf(),
166 cgt, alreadyChecked))
184 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
187 qt = at->getValueType();
219 const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();
220 cir::RecordType entry = recordDeclTypes[key];
227 entry = builder.getIncompleteRecordTy(name, rd);
228 recordDeclTypes[key] = entry;
237 deferredRecords.push_back(rd);
242 bool insertResult = recordsBeingLaidOut.insert(key).second;
244 assert(insertResult &&
"isSafeToCovert() should have caught this.");
247 if (
const auto *
cxxRecordDecl = dyn_cast<CXXRecordDecl>(rd)) {
249 if (base.isVirtual())
257 recordDeclTypes[key] = entry;
258 cirGenRecordLayouts[key] = std::move(layout);
261 bool eraseResult = recordsBeingLaidOut.erase(key);
263 assert(eraseResult &&
"record not in RecordsBeingLaidOut set?");
271 if (recordsBeingLaidOut.empty())
272 while (!deferredRecords.empty())
279 type = astContext.getCanonicalType(
type);
287 TypeCacheTy::iterator tci =
typeCache.find(ty);
294 mlir::Type resultType =
nullptr;
297 llvm_unreachable(
"Should have been handled above");
299 case Type::Builtin: {
302 case BuiltinType::Void:
303 resultType = cgm.voidTy;
307 case BuiltinType::Bool:
312 case BuiltinType::Char_S:
313 case BuiltinType::Int:
314 case BuiltinType::Int128:
315 case BuiltinType::Long:
316 case BuiltinType::LongLong:
317 case BuiltinType::SChar:
318 case BuiltinType::Short:
319 case BuiltinType::WChar_S:
326 case BuiltinType::SveInt8:
328 cir::VectorType::get(builder.getSInt8Ty(), 16,
true);
330 case BuiltinType::SveUint8:
332 cir::VectorType::get(builder.getUInt8Ty(), 16,
true);
334 case BuiltinType::SveInt16:
336 cir::VectorType::get(builder.getSInt16Ty(), 8,
true);
338 case BuiltinType::SveUint16:
340 cir::VectorType::get(builder.getUInt16Ty(), 8,
true);
342 case BuiltinType::SveFloat16:
343 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
346 case BuiltinType::SveBFloat16:
347 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
350 case BuiltinType::SveInt32:
352 cir::VectorType::get(builder.getSInt32Ty(), 4,
true);
354 case BuiltinType::SveUint32:
356 cir::VectorType::get(builder.getUInt32Ty(), 4,
true);
358 case BuiltinType::SveFloat32:
359 resultType = cir::VectorType::get(builder.getSingleTy(), 4,
362 case BuiltinType::SveInt64:
364 cir::VectorType::get(builder.getSInt64Ty(), 2,
true);
366 case BuiltinType::SveUint64:
368 cir::VectorType::get(builder.getUInt64Ty(), 2,
true);
370 case BuiltinType::SveFloat64:
371 resultType = cir::VectorType::get(builder.getDoubleTy(), 2,
376 case BuiltinType::Char8:
377 case BuiltinType::Char16:
378 case BuiltinType::Char32:
379 case BuiltinType::Char_U:
380 case BuiltinType::UChar:
381 case BuiltinType::UInt:
382 case BuiltinType::UInt128:
383 case BuiltinType::ULong:
384 case BuiltinType::ULongLong:
385 case BuiltinType::UShort:
386 case BuiltinType::WChar_U:
393 case BuiltinType::Float16:
394 resultType = cgm.fP16Ty;
396 case BuiltinType::Half:
397 if (astContext.getLangOpts().NativeHalfType ||
398 !astContext.getTargetInfo().useFP16ConversionIntrinsics()) {
399 resultType = cgm.fP16Ty;
402 resultType = cgm.sInt32Ty;
405 case BuiltinType::BFloat16:
406 resultType = cgm.bFloat16Ty;
408 case BuiltinType::Float:
409 assert(&astContext.getFloatTypeSemantics(
type) ==
410 &llvm::APFloat::IEEEsingle() &&
411 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");
412 resultType = cgm.floatTy;
414 case BuiltinType::Double:
415 assert(&astContext.getFloatTypeSemantics(
type) ==
416 &llvm::APFloat::IEEEdouble() &&
417 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");
418 resultType = cgm.doubleTy;
420 case BuiltinType::LongDouble:
422 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(
type));
424 case BuiltinType::Float128:
425 resultType = cgm.fP128Ty;
427 case BuiltinType::Ibm128:
429 resultType = cgm.sInt32Ty;
432 case BuiltinType::NullPtr:
437 resultType = builder.getVoidPtrTy();
442 resultType = cgm.sInt32Ty;
448 case Type::Complex: {
450 mlir::Type elementTy =
convertType(ct->getElementType());
451 resultType = cir::ComplexType::get(elementTy);
455 case Type::LValueReference:
456 case Type::RValueReference: {
460 resultType = builder.getPointerTo(pointeeType, elemTy.
getAddressSpace());
461 assert(resultType &&
"Cannot get pointer type?");
465 case Type::Pointer: {
472 resultType = builder.getPointerTo(pointeeType, elemTy.
getAddressSpace());
476 case Type::VariableArray: {
486 case Type::IncompleteArray: {
495 elemTy = cgm.sInt8Ty;
498 resultType = cir::ArrayType::get(elemTy, 0);
502 case Type::ConstantArray: {
510 resultType = cgm.uInt32Ty;
514 resultType = cir::ArrayType::get(elemTy, arrTy->
getSize().getZExtValue());
518 case Type::ExtVector:
528 if (
auto integerType = ed->getIntegerType(); !integerType.isNull())
533 resultType = cgm.uInt32Ty;
537 case Type::MemberPointer: {
540 mlir::Type memberTy =
convertType(mpt->getPointeeType());
541 auto clsTy = mlir::cast<cir::RecordType>(
543 if (mpt->isMemberDataPointer()) {
544 resultType = cir::DataMemberType::get(memberTy, clsTy);
552 case Type::FunctionNoProto:
553 case Type::FunctionProto:
554 resultType = convertFunctionTypeInternal(
type);
559 if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {
561 resultType = cgm.sInt32Ty;
563 resultType = cir::IntType::get(&
getMLIRContext(), bitIntTy->getNumBits(),
564 bitIntTy->isSigned());
574 uint64_t valueSize = astContext.getTypeSize(valueType);
575 uint64_t atomicSize = astContext.getTypeSize(ty);
576 if (valueSize != atomicSize) {
577 cgm.errorNYI(
"convertType: atomic type value size != atomic size");
585 type->getTypeClassName());
586 resultType = cgm.sInt32Ty;
590 assert(resultType &&
"Type conversion not yet implemented");
598 assert(!
qualType->isConstantMatrixType() &&
"Matrix types NYI");
602 assert(!forBitField &&
"Bit fields NYI");
606 if (forBitField &&
qualType->isBitIntType())
607 assert(!
qualType->isBitIntType() &&
"Bit field with type _BitInt NYI");
609 return convertedType;
615 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
618 auto it = cirGenRecordLayouts.find(key);
619 if (it != cirGenRecordLayouts.end())
626 it = cirGenRecordLayouts.find(key);
628 assert(it != cirGenRecordLayouts.end() &&
629 "Unable to find record layout information for type");
635 return astContext.getTargetNullPointerValue(t) == 0;
637 if (
const auto *at = astContext.getAsArrayType(t)) {
641 if (
const auto *cat = dyn_cast<ConstantArrayType>(at))
642 if (astContext.getConstantArrayElementCount(cat) == 0)
650 cgm.errorNYI(
SourceLocation(),
"isZeroInitializable for MemberPointerType",
666 assert(llvm::all_of(argTypes,
669 llvm::FoldingSetNodeID id;
672 void *insertPos =
nullptr;
680 "Bad match based on CIRGenFunctionInfo folding set id");
688 functionInfos.InsertNode(fi, insertPos);
694 assert(!dyn_cast<ObjCMethodDecl>(gd.
getDecl()) &&
695 "This is reported as a FIXME in LLVM codegen");
711 if (
const auto *ed = dyn_cast<EnumDecl>(td)) {
719 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
721 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
731 if (rd->isDependentType())
736 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
CanQualType getReturnType() const
const_arg_iterator argTypesEnd() const
static void Profile(llvm::FoldingSetNodeID &id, RequiredArgs required, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes)
const_arg_iterator argTypesBegin() const
static CIRGenFunctionInfo * create(CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
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
const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
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.
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.
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.