28#include "llvm/IR/DataLayout.h"
29#include "llvm/IR/DerivedTypes.h"
30#include "llvm/IR/Module.h"
36 : CGM(cgm), Context(cgm.
getContext()), TheModule(cgm.getModule()),
38 SkippedLayout =
false;
39 LongDoubleReferenced =
false;
43 for (llvm::FoldingSet<CGFunctionInfo>::iterator
44 I = FunctionInfos.begin(), E = FunctionInfos.end(); I != E; )
51 return CGM.getCodeGenOpts();
58 llvm::raw_svector_ostream OS(
TypeName);
80 if (TDD->getDeclContext())
81 TDD->printQualifiedName(OS, Policy);
90 Ty->setName(OS.str());
105 if (T->isConstantMatrixType()) {
106 const Type *Ty = Context.getCanonicalType(T).getTypePtr();
109 if (Context.getLangOpts().HLSL) {
110 if (T->isConstantMatrixBoolType())
116 unsigned VecLen = IsRowMajor ? NumCols : NumRows;
117 unsigned ArrayLen = IsRowMajor ? NumRows : NumCols;
118 llvm::Type *VecTy = llvm::FixedVectorType::get(IRElemTy, VecLen);
119 return llvm::ArrayType::get(VecTy, ArrayLen);
127 if (T->isExtVectorBoolType()) {
130 if (Context.getLangOpts().HLSL) {
132 return llvm::FixedVectorType::get(IRElemTy, FixedVT->getNumElements());
136 uint64_t BytePadded = std::max<uint64_t>(FixedVT->getNumElements(), 8);
137 return llvm::IntegerType::get(FixedVT->getContext(), BytePadded);
153 if (T->isBitIntType()) {
155 return llvm::ArrayType::get(CGM.Int8Ty,
156 Context.getTypeSizeInChars(T).getQuantity());
158 (
unsigned)Context.getTypeSize(T));
161 if (R->isIntegerTy(1))
163 (
unsigned)Context.getTypeSize(T));
170 llvm::Type *LLVMTy) {
174 CharUnits ASTSize = Context.getTypeSizeInChars(ASTTy);
177 return ASTSize != LLVMSize;
181 llvm::Type *LLVMTy) {
185 if (T->isBitIntType())
186 return llvm::Type::getIntNTy(
187 getLLVMContext(), Context.getTypeSizeInChars(T).getQuantity() * 8);
189 if (LLVMTy->isIntegerTy(1))
191 (
unsigned)Context.getTypeSize(T));
193 if (T->isConstantMatrixBoolType()) {
197 const Type *Ty = Context.getCanonicalType(T).getTypePtr();
203 if (T->isExtVectorBoolType())
212 llvm::DenseMap<const Type*, llvm::StructType *>::const_iterator I =
213 RecordDeclTypes.find(Ty);
214 return I != RecordDeclTypes.end() && !I->second->isOpaque();
227 const TagType *TT = Ty->
getAs<TagType>();
228 if (!TT)
return true;
231 return !TT->isIncompleteType();
245 for (
unsigned i = 0, e = FPT->getNumParams(); i != e; i++)
255 CanQualType T = CGM.getContext().getCanonicalTagType(TD);
259 if (
const EnumDecl *ED = dyn_cast<EnumDecl>(TD)) {
261 if (TypeCache.count(T->getTypePtr())) {
265 if (!
ConvertType(ED->getIntegerType())->isIntegerTy(32))
271 DI->completeType(ED);
282 if (RecordDeclTypes.count(T.getTypePtr()))
288 DI->completeType(RD);
293 T = Context.getCanonicalType(T);
295 const Type *Ty = T.getTypePtr();
296 if (RecordsWithOpaqueMemberPointers.count(Ty)) {
298 RecordsWithOpaqueMemberPointers.clear();
302llvm::Type *CodeGenTypes::ConvertFunctionTypeInternal(
QualType QFT) {
316 for (
unsigned i = 0, e = FPT->getNumParams(); i != e; i++)
317 if (
const auto *RD = FPT->getParamType(i)->getAsRecordDecl())
320 SkippedLayout =
true;
338 llvm::Type *ResultType =
nullptr;
341 if (FunctionsBeingProcessed.count(FI)) {
344 SkippedLayout =
true;
356 T = Context.getCanonicalType(T);
358 const Type *Ty = T.getTypePtr();
362 if (Context.getLangOpts().CUDAIsDevice) {
363 if (T->isCUDADeviceBuiltinSurfaceType()) {
364 if (
auto *Ty = CGM.getTargetCodeGenInfo()
365 .getCUDADeviceBuiltinSurfaceDeviceType())
367 }
else if (T->isCUDADeviceBuiltinTextureType()) {
368 if (
auto *Ty = CGM.getTargetCodeGenInfo()
369 .getCUDADeviceBuiltinTextureDeviceType())
375 if (
const auto *RT = dyn_cast<RecordType>(Ty))
378 llvm::Type *CachedType =
nullptr;
379 auto TCI = TypeCache.find(Ty);
380 if (TCI != TypeCache.end())
381 CachedType = TCI->second;
384#ifndef EXPENSIVE_CHECKS
390 llvm::Type *ResultType =
nullptr;
393#define TYPE(Class, Base)
394#define ABSTRACT_TYPE(Class, Base)
395#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
396#define DEPENDENT_TYPE(Class, Base) case Type::Class:
397#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
398#include "clang/AST/TypeNodes.inc"
399 llvm_unreachable(
"Non-canonical or dependent types aren't possible.");
401 case Type::Builtin: {
403 case BuiltinType::Void:
404 case BuiltinType::ObjCId:
405 case BuiltinType::ObjCClass:
406 case BuiltinType::ObjCSel:
412 case BuiltinType::Bool:
417 case BuiltinType::Char_S:
418 case BuiltinType::Char_U:
419 case BuiltinType::SChar:
420 case BuiltinType::UChar:
421 case BuiltinType::Short:
422 case BuiltinType::UShort:
423 case BuiltinType::Int:
424 case BuiltinType::UInt:
425 case BuiltinType::Long:
426 case BuiltinType::ULong:
427 case BuiltinType::LongLong:
428 case BuiltinType::ULongLong:
429 case BuiltinType::WChar_S:
430 case BuiltinType::WChar_U:
431 case BuiltinType::Char8:
432 case BuiltinType::Char16:
433 case BuiltinType::Char32:
434 case BuiltinType::ShortAccum:
435 case BuiltinType::Accum:
436 case BuiltinType::LongAccum:
437 case BuiltinType::UShortAccum:
438 case BuiltinType::UAccum:
439 case BuiltinType::ULongAccum:
440 case BuiltinType::ShortFract:
441 case BuiltinType::Fract:
442 case BuiltinType::LongFract:
443 case BuiltinType::UShortFract:
444 case BuiltinType::UFract:
445 case BuiltinType::ULongFract:
446 case BuiltinType::SatShortAccum:
447 case BuiltinType::SatAccum:
448 case BuiltinType::SatLongAccum:
449 case BuiltinType::SatUShortAccum:
450 case BuiltinType::SatUAccum:
451 case BuiltinType::SatULongAccum:
452 case BuiltinType::SatShortFract:
453 case BuiltinType::SatFract:
454 case BuiltinType::SatLongFract:
455 case BuiltinType::SatUShortFract:
456 case BuiltinType::SatUFract:
457 case BuiltinType::SatULongFract:
459 static_cast<unsigned>(Context.getTypeSize(T)));
462 case BuiltinType::Float16:
463 ResultType = llvm::Type::getFloatingPointTy(
467 case BuiltinType::Half:
470 ResultType = llvm::Type::getFloatingPointTy(
473 case BuiltinType::LongDouble:
474 LongDoubleReferenced =
true;
476 case BuiltinType::BFloat16:
477 case BuiltinType::Float:
478 case BuiltinType::Double:
479 case BuiltinType::Float128:
480 case BuiltinType::Ibm128:
481 ResultType = llvm::Type::getFloatingPointTy(
485 case BuiltinType::NullPtr:
490 case BuiltinType::UInt128:
491 case BuiltinType::Int128:
495#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
496 case BuiltinType::Id:
497#include "clang/Basic/OpenCLImageTypes.def"
498#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
499 case BuiltinType::Id:
500#include "clang/Basic/OpenCLExtensionTypes.def"
501 case BuiltinType::OCLSampler:
502 case BuiltinType::OCLEvent:
503 case BuiltinType::OCLClkEvent:
504 case BuiltinType::OCLQueue:
505 case BuiltinType::OCLReserveID:
506 ResultType = CGM.getOpenCLRuntime().convertOpenCLSpecificType(Ty);
508#define SVE_VECTOR_TYPE(Name, MangledName, Id, SingletonId) \
509 case BuiltinType::Id:
510#define SVE_PREDICATE_TYPE(Name, MangledName, Id, SingletonId) \
511 case BuiltinType::Id:
512#include "clang/Basic/AArch64ACLETypes.def"
522 auto *VTy = llvm::VectorType::get(EltTy, Info.
EC);
525 llvm_unreachable(
"Expected 1, 2, 3 or 4 vectors!");
529 return llvm::StructType::get(VTy, VTy);
531 return llvm::StructType::get(VTy, VTy, VTy);
533 return llvm::StructType::get(VTy, VTy, VTy, VTy);
536 case BuiltinType::SveCount:
537 return llvm::TargetExtType::get(
getLLVMContext(),
"aarch64.svcount");
538 case BuiltinType::MFloat8:
539 return llvm::VectorType::get(llvm::Type::getInt8Ty(
getLLVMContext()), 1,
541#define PPC_VECTOR_TYPE(Name, Id, Size) \
542 case BuiltinType::Id: \
544 llvm::FixedVectorType::get(ConvertType(Context.BoolTy), Size); \
546#include "clang/Basic/PPCTypes.def"
547#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
548#include "clang/Basic/RISCVVTypes.def"
553 unsigned I8EltCount =
554 Info.
EC.getKnownMinValue() *
556 return llvm::TargetExtType::get(
558 llvm::ScalableVectorType::get(
563 Info.
EC.getKnownMinValue());
565#define WASM_REF_TYPE(Name, MangledName, Id, SingletonId, AS) \
566 case BuiltinType::Id: { \
567 if (BuiltinType::Id == BuiltinType::WasmExternRef) \
568 ResultType = CGM.getTargetCodeGenInfo().getWasmExternrefReferenceType(); \
570 llvm_unreachable("Unexpected wasm reference builtin type!"); \
572#include "clang/Basic/WebAssemblyReferenceTypes.def"
573#define AMDGPU_OPAQUE_PTR_TYPE(Name, Id, SingletonId, Width, Align, AS) \
574 case BuiltinType::Id: { \
575 if (BuiltinType::Id == BuiltinType::AMDGPUTexture) { \
576 return llvm::FixedVectorType::get( \
577 llvm::Type::getInt32Ty(getLLVMContext()), 8); \
579 return llvm::PointerType::get(getLLVMContext(), AS); \
581#define AMDGPU_NAMED_BARRIER_TYPE(Name, Id, SingletonId, Width, Align, Scope) \
582 case BuiltinType::Id: \
583 return llvm::TargetExtType::get(getLLVMContext(), "amdgcn.named.barrier", \
585#define AMDGPU_FEATURE_PREDICATE_TYPE(Name, Id, SingletonId, Width, Align) \
586 case BuiltinType::Id: \
587 return ConvertType(getContext().getLogicalOperationType());
588#include "clang/Basic/AMDGPUTypes.def"
589#define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
590#include "clang/Basic/HLSLIntangibleTypes.def"
591 ResultType = CGM.getHLSLRuntime().convertHLSLSpecificType(Ty);
593 case BuiltinType::Dependent:
594#define BUILTIN_TYPE(Id, SingletonId)
595#define PLACEHOLDER_TYPE(Id, SingletonId) \
596 case BuiltinType::Id:
597#include "clang/AST/BuiltinTypes.def"
598 llvm_unreachable(
"Unexpected placeholder builtin type!");
603 case Type::DeducedTemplateSpecialization:
604 llvm_unreachable(
"Unexpected undeduced type!");
605 case Type::Complex: {
607 ResultType = llvm::StructType::get(EltTy, EltTy);
610 case Type::LValueReference:
611 case Type::RValueReference: {
618 case Type::Pointer: {
622 ResultType = CGM.getTargetCodeGenInfo().getWasmFuncrefReferenceType();
630 case Type::VariableArray: {
633 "FIXME: We only handle trivial array types so far!");
639 case Type::IncompleteArray: {
642 "FIXME: We only handle trivial array types so far!");
646 if (!ResultType->isSized()) {
647 SkippedLayout =
true;
650 ResultType = llvm::ArrayType::get(ResultType, 0);
653 case Type::ArrayParameter:
654 case Type::ConstantArray: {
660 if (!EltTy->isSized()) {
661 SkippedLayout =
true;
665 ResultType = llvm::ArrayType::get(EltTy, A->
getZExtSize());
668 case Type::ExtVector:
672 llvm::Type *IRElemTy = VT->isPackedVectorBoolType(Context)
674 : VT->getElementType()->isMFloat8Type()
677 ResultType = llvm::FixedVectorType::get(IRElemTy, VT->getNumElements());
680 case Type::ConstantMatrix: {
687 case Type::FunctionNoProto:
688 case Type::FunctionProto:
689 ResultType = ConvertFunctionTypeInternal(T);
691 case Type::ObjCObject:
695 case Type::ObjCInterface: {
706 case Type::ObjCObjectPointer:
712 if (ED->isCompleteDefinition() || ED->isFixed())
721 case Type::BlockPointer: {
734 case Type::MemberPointer: {
736 if (!
getCXXABI().isMemberPointerConvertible(MPTy)) {
737 CanQualType T = CGM.getContext().getCanonicalTagType(
738 MPTy->getMostRecentCXXRecordDecl());
740 RecordsWithOpaqueMemberPointers.try_emplace(T.getTypePtr());
741 if (Insertion.second)
742 Insertion.first->second = llvm::StructType::create(
getLLVMContext());
743 ResultType = Insertion.first->second;
755 uint64_t valueSize = Context.getTypeSize(valueType);
756 uint64_t atomicSize = Context.getTypeSize(Ty);
757 if (valueSize != atomicSize) {
758 assert(valueSize < atomicSize);
759 llvm::Type *elts[] = {
761 llvm::ArrayType::get(CGM.Int8Ty, (atomicSize - valueSize) / 8)
769 ResultType = CGM.getOpenCLRuntime().getPipeType(
cast<PipeType>(Ty));
774 ResultType = llvm::Type::getIntNTy(
getLLVMContext(), EIT->getNumBits());
777 case Type::HLSLAttributedResource:
778 case Type::HLSLInlineSpirv:
779 ResultType = CGM.getHLSLRuntime().convertHLSLSpecificType(Ty);
781 case Type::OverflowBehavior:
787 assert(ResultType &&
"Didn't convert a type?");
788 assert((!CachedType || CachedType == ResultType) &&
789 "Cached type doesn't match computed type");
791 TypeCache[Ty] = ResultType;
800 return Context.getTypeSize(
type) != Context.getTypeSize(
type->getValueType());
807 const Type *Key = Context.getCanonicalTagType(RD).getTypePtr();
809 llvm::StructType *&Entry = RecordDeclTypes[Key];
816 llvm::StructType *Ty = Entry;
825 if (
const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD)) {
826 for (
const auto &I : CRD->bases()) {
827 if (I.isVirtual())
continue;
834 CGRecordLayouts[Key] = std::move(Layout);
848 const Type *Key = Context.getCanonicalTagType(RD).getTypePtr();
850 auto I = CGRecordLayouts.find(Key);
851 if (I != CGRecordLayouts.end())
857 I = CGRecordLayouts.find(Key);
859 assert(I != CGRecordLayouts.end() &&
860 "Unable to find record layout information for type");
865 assert((T->isAnyPointerType() || T->isBlockPointerType() ||
866 T->isNullPtrType()) &&
873 return Context.getTargetNullPointerValue(T) == 0;
875 if (
const auto *AT = Context.getAsArrayType(T)) {
878 if (
const auto *CAT = dyn_cast<ConstantArrayType>(AT))
879 if (Context.getConstantArrayElementCount(CAT) == 0)
881 T = Context.getBaseElementType(T);
886 if (
const auto *RD = T->getAsRecordDecl())
894 if (T->getAs<HLSLInlineSpirvType>())
910 return T->isFunctionType() && !T.hasAddressSpace()
Defines the clang::ASTContext interface.
static Decl::Kind getKind(const Decl *D)
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines AST-level helper utilities for matrix types.
static QualType getUnderlyingType(const SubRegion *R)
static CharUnits getTypeAllocSize(CodeGenModule &CGM, llvm::Type *type)
const clang::PrintingPolicy & getPrintingPolicy() const
unsigned getTargetAddressSpace(LangAS AS) const
QualType getElementType() const
unsigned getIndexTypeCVRQualifiers() const
Represents a C++ struct/union/class.
static CanQual< T > CreateUnsafe(QualType Other)
Builds a canonical type from a QualType.
CharUnits - This is an opaque type for sizes expressed in character units.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
Implements C++ ABI-specific code generation functions.
virtual bool isMemberPointerConvertible(const MemberPointerType *MPT) const
Return whether or not a member pointers type is convertible to an IR type.
virtual llvm::Type * ConvertMemberPointerType(const MemberPointerType *MPT)
Find the LLVM type used to represent the given member pointer type.
virtual bool isZeroInitializable(const MemberPointerType *MPT)
Return true if the given member pointer can be zero-initialized (in the C++ sense) with an LLVM zeroi...
This class gathers all debug information during compilation and is responsible for emitting to llvm g...
CGFunctionInfo - Class to encapsulate the information about a function definition.
CGRecordLayout - This class handles struct and union layout info while lowering AST types to LLVM typ...
bool isZeroInitializable() const
Check whether this struct can be C++ zero-initialized with a zeroinitializer.
This class organizes the cross-function state that is used while generating LLVM code.
bool isPaddedAtomicType(QualType type)
CGCXXABI & getCXXABI() const
CodeGenTypes(CodeGenModule &cgm)
llvm::Type * ConvertType(QualType T)
ConvertType - Convert type T into a llvm::Type.
CGCXXABI & getCXXABI() const
bool isPointerZeroInitializable(QualType T)
Check if the pointer type can be zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
const CodeGenOptions & getCodeGenOpts() const
ASTContext & getContext() const
const CGFunctionInfo & arrangeFreeFunctionType(CanQual< FunctionProtoType > Ty)
Arrange the argument and result information for a value of the given freestanding function type.
llvm::FunctionType * GetFunctionType(const CGFunctionInfo &Info)
GetFunctionType - Get the LLVM function type for.
bool isFuncTypeConvertible(const FunctionType *FT)
isFuncTypeConvertible - Utility to check whether a function type can be converted to an LLVM type (i....
const TargetInfo & getTarget() const
std::unique_ptr< CGRecordLayout > ComputeRecordLayout(const RecordDecl *D, llvm::StructType *Ty)
Compute a new LLVM record layout object for the given record.
llvm::Type * convertTypeForLoadStore(QualType T, llvm::Type *LLVMTy=nullptr)
Given that T is a scalar type, return the IR type that should be used for load and store operations.
const CGRecordLayout & getCGRecordLayout(const RecordDecl *)
getCGRecordLayout - Return record layout info for the given record decl.
unsigned getTargetAddressSpace(QualType T) const
llvm::StructType * ConvertRecordDeclType(const RecordDecl *TD)
ConvertRecordDeclType - Lay out a tagged decl type like struct or union.
void RefreshTypeCacheForClass(const CXXRecordDecl *RD)
Remove stale types from the type cache when an inheritance model gets assigned to a class.
bool isRecordLayoutComplete(const Type *Ty) const
isRecordLayoutComplete - Return true if the specified type is already completely laid out.
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
CodeGenModule & getCGM() const
void UpdateCompletedType(const TagDecl *TD)
UpdateCompletedType - When we find the full definition for a TagDecl, replace the 'opaque' type we pr...
llvm::LLVMContext & getLLVMContext()
bool typeRequiresSplitIntoByteArray(QualType ASTTy, llvm::Type *LLVMTy=nullptr)
Check whether the given type needs to be laid out in memory using an opaque byte-array type because i...
const llvm::DataLayout & getDataLayout() const
bool isFuncParamTypeConvertible(QualType Ty)
isFuncParamTypeConvertible - Return true if the specified type in a function parameter or result posi...
bool isZeroInitializable(QualType T)
IsZeroInitializable - Return whether a type can be zero-initialized (in the C++ sense) with an LLVM z...
void addRecordTypeName(const RecordDecl *RD, llvm::StructType *Ty, StringRef suffix)
addRecordTypeName - Compute a name from the given record decl with an optional suffix and name the gi...
Represents the canonical version of C arrays with a specified constant size.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
Represents a concrete matrix type with constant number of rows and columns.
unsigned getNumColumns() const
Returns the number of columns in the matrix.
unsigned getNumRows() const
Returns the number of rows in the matrix.
unsigned getNumElementsFlattened() const
Returns the number of elements required to embed the matrix into a vector.
ASTContext & getASTContext() const LLVM_READONLY
DeclContext * getDeclContext()
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.
FunctionType - C99 6.7.5.3 - Function Declarators.
QualType getReturnType() const
Represents a C array with an unspecified size.
QualType getElementType() const
Returns type of the elements being stored in the matrix.
A pointer to member type per C++ 8.3.3 - Pointers to members.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
void printQualifiedName(raw_ostream &OS) const
Returns a human-readable qualified name for this declaration, like A::B::i, for i being member of nam...
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.
Represents a struct/union/class.
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Base for LValueReferenceType and RValueReferenceType.
QualType getPointeeType() const
Represents the declaration of a struct/union/class/enum.
StringRef getKindName() const
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
TypedefNameDecl * getTypedefNameForAnonDecl() const
void printName(raw_ostream &OS, const PrintingPolicy &Policy) const override
Pretty-print the unqualified name of this declaration.
bool isDependentType() const
Whether this declaration declares a type that is dependent, i.e., a type that somehow depends on temp...
bool isMFloat8Type() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
EnumDecl * castAsEnumDecl() const
TypeClass getTypeClass() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
Base class for declarations which introduce a typedef-name.
Represents a C array with a specified size that is not an integer-constant-expression.
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
const internal::VariadicAllOfMatcher< Type > type
Matches Types 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 isMatrixRowMajor(const LangOptions &LangOpts, QualType T)
Returns true if matrices of T should be laid out in row-major order.
U cast(CodeGen::Address addr)
Describes how types, statements, expressions, and declarations should be printed.
unsigned SuppressInlineNamespace
Suppress printing parts of scope specifiers that correspond to inline namespaces.