clang 20.0.0git
CIRGenTypes.cpp
Go to the documentation of this file.
1#include "CIRGenTypes.h"
2
3#include "CIRGenModule.h"
4
6#include "clang/AST/Type.h"
8
9#include <cassert>
10
11using namespace clang;
12using namespace clang::CIRGen;
13
15 : cgm(genModule), astContext(genModule.getASTContext()),
16 builder(cgm.getBuilder()) {}
17
19
20mlir::MLIRContext &CIRGenTypes::getMLIRContext() const {
21 return *builder.getContext();
22}
23
24/// Return true if the specified type in a function parameter or result position
25/// can be converted to a CIR type at this point. This boils down to being
26/// whether it is complete, as well as whether we've temporarily deferred
27/// expanding the type because we're in a recursive context.
29 // Some ABIs cannot have their member pointers represented in LLVM IR unless
30 // certain circumstances have been reached.
31 assert(!type->getAs<MemberPointerType>() && "NYI");
32
33 // If this isn't a tag type, we can convert it.
34 const TagType *tagType = type->getAs<TagType>();
35 if (!tagType)
36 return true;
37
38 // Function types involving incomplete class types are problematic in MLIR.
39 return !tagType->isIncompleteType();
40}
41
42/// Code to verify a given function type is complete, i.e. the return type and
43/// all of the parameter types are complete. Also check to see if we are in a
44/// RS_StructPointer context, and if so whether any struct types have been
45/// pended. If so, we don't want to ask the ABI lowering code to handle a type
46/// that cannot be converted to a CIR type.
49 return false;
50
51 if (const auto *fpt = dyn_cast<FunctionProtoType>(ft))
52 for (unsigned i = 0, e = fpt->getNumParams(); i != e; i++)
53 if (!isFuncParamTypeConvertible(fpt->getParamType(i)))
54 return false;
55
56 return true;
57}
58
59mlir::Type CIRGenTypes::ConvertFunctionTypeInternal(QualType qft) {
60 assert(qft.isCanonical());
61 const FunctionType *ft = cast<FunctionType>(qft.getTypePtr());
62 // First, check whether we can build the full fucntion type. If the function
63 // type depends on an incomplete type (e.g. a struct or enum), we cannot lower
64 // the function type.
65 if (!isFuncTypeConvertible(ft)) {
66 cgm.errorNYI(SourceLocation(), "function type involving an incomplete type",
67 qft);
68 return cir::FuncType::get(SmallVector<mlir::Type, 1>{}, cgm.VoidTy);
69 }
70
71 // TODO(CIR): This is a stub of what the final code will be. See the
72 // implementation of this function and the implementation of class
73 // CIRGenFunction in the ClangIR incubator project.
74
75 if (const auto *fpt = dyn_cast<FunctionProtoType>(ft)) {
76 SmallVector<mlir::Type> mlirParamTypes;
77 for (unsigned i = 0; i < fpt->getNumParams(); ++i) {
78 mlirParamTypes.push_back(convertType(fpt->getParamType(i)));
79 }
80 return cir::FuncType::get(
81 mlirParamTypes, convertType(fpt->getReturnType().getUnqualifiedType()),
82 fpt->isVariadic());
83 }
84 cgm.errorNYI(SourceLocation(), "non-prototype function type", qft);
85 return cir::FuncType::get(SmallVector<mlir::Type, 1>{}, cgm.VoidTy);
86}
87
89 type = astContext.getCanonicalType(type);
90 const Type *ty = type.getTypePtr();
91
92 // Has the type already been processed?
93 TypeCacheTy::iterator tci = typeCache.find(ty);
94 if (tci != typeCache.end())
95 return tci->second;
96
97 // For types that haven't been implemented yet or are otherwise unsupported,
98 // report an error and return 'int'.
99
100 mlir::Type resultType = nullptr;
101 switch (ty->getTypeClass()) {
102 case Type::Builtin: {
103 switch (cast<BuiltinType>(ty)->getKind()) {
104
105 // void
106 case BuiltinType::Void:
107 resultType = cgm.VoidTy;
108 break;
109
110 // Signed integral types.
111 case BuiltinType::Char_S:
112 case BuiltinType::Int:
113 case BuiltinType::Int128:
114 case BuiltinType::Long:
115 case BuiltinType::LongLong:
116 case BuiltinType::SChar:
117 case BuiltinType::Short:
118 case BuiltinType::WChar_S:
119 resultType =
120 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
121 /*isSigned=*/true);
122 break;
123 // Unsigned integral types.
124 case BuiltinType::Char8:
125 case BuiltinType::Char16:
126 case BuiltinType::Char32:
127 case BuiltinType::Char_U:
128 case BuiltinType::UChar:
129 case BuiltinType::UInt:
130 case BuiltinType::UInt128:
131 case BuiltinType::ULong:
132 case BuiltinType::ULongLong:
133 case BuiltinType::UShort:
134 case BuiltinType::WChar_U:
135 resultType =
136 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
137 /*isSigned=*/false);
138 break;
139
140 // Floating-point types
141 case BuiltinType::Float16:
142 resultType = cgm.FP16Ty;
143 break;
144 case BuiltinType::Half:
145 if (astContext.getLangOpts().NativeHalfType ||
147 resultType = cgm.FP16Ty;
148 } else {
149 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
150 resultType = cgm.SInt32Ty;
151 }
152 break;
153 case BuiltinType::BFloat16:
154 resultType = cgm.BFloat16Ty;
155 break;
156 case BuiltinType::Float:
157 assert(&astContext.getFloatTypeSemantics(type) ==
158 &llvm::APFloat::IEEEsingle() &&
159 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");
160 resultType = cgm.FloatTy;
161 break;
162 case BuiltinType::Double:
163 assert(&astContext.getFloatTypeSemantics(type) ==
164 &llvm::APFloat::IEEEdouble() &&
165 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");
166 resultType = cgm.DoubleTy;
167 break;
168 case BuiltinType::LongDouble:
169 resultType =
170 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(type));
171 break;
172 case BuiltinType::Float128:
173 resultType = cgm.FP128Ty;
174 break;
175 case BuiltinType::Ibm128:
176 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
177 resultType = cgm.SInt32Ty;
178 break;
179
180 default:
181 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
182 resultType = cgm.SInt32Ty;
183 break;
184 }
185 break;
186 }
187
188 case Type::Pointer: {
189 const PointerType *ptrTy = cast<PointerType>(ty);
190 QualType elemTy = ptrTy->getPointeeType();
191 assert(!elemTy->isConstantMatrixType() && "not implemented");
192
193 mlir::Type pointeeType = convertType(elemTy);
194
195 resultType = builder.getPointerTo(pointeeType);
196 break;
197 }
198
199 case Type::FunctionNoProto:
200 case Type::FunctionProto:
201 resultType = ConvertFunctionTypeInternal(type);
202 break;
203
204 case Type::BitInt: {
205 const auto *bitIntTy = cast<BitIntType>(type);
206 if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {
207 cgm.errorNYI(SourceLocation(), "large _BitInt type", type);
208 resultType = cgm.SInt32Ty;
209 } else {
210 resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(),
211 bitIntTy->isSigned());
212 }
213 break;
214 }
215
216 default:
217 cgm.errorNYI(SourceLocation(), "processing of type", type);
218 resultType = cgm.SInt32Ty;
219 break;
220 }
221
222 assert(resultType && "Type conversion not yet implemented");
223
224 typeCache[ty] = resultType;
225 return resultType;
226}
Defines the clang::ASTContext interface.
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:1172
C Language Family Type Representation.
cir::PointerType getPointerTo(mlir::Type ty)
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2716
const LangOptions & getLangOpts() const
Definition: ASTContext.h:834
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2482
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:799
cir::LongDoubleType getLongDoubleTy(const llvm::fltSemantics &format) const
Definition: CIRGenBuilder.h:25
This class organizes the cross-function state that is used while generating CIR code.
Definition: CIRGenModule.h:39
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
bool isFuncTypeConvertible(const clang::FunctionType *ft)
Utility to check whether a function type can be converted to a CIR type (i.e.
Definition: CIRGenTypes.cpp:47
CIRGenTypes(CIRGenModule &cgm)
Definition: CIRGenTypes.cpp:14
mlir::MLIRContext & getMLIRContext() const
Definition: CIRGenTypes.cpp:20
bool isFuncParamTypeConvertible(clang::QualType type)
Return true if the specified type in a function parameter or result position can be converted to a CI...
Definition: CIRGenTypes.cpp:28
mlir::Type convertType(clang::QualType type)
Convert a Clang type into a mlir::Type.
Definition: CIRGenTypes.cpp:88
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: Type.h:4321
QualType getReturnType() const
Definition: Type.h:4643
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition: Type.h:3519
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3198
QualType getPointeeType() const
Definition: Type.h:3208
A (possibly-)qualified type.
Definition: Type.h:929
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:7931
bool isCanonical() const
Definition: Type.h:7988
Encodes a location in the source.
virtual bool useFP16ConversionIntrinsics() const
Check whether llvm intrinsics such as llvm.convert.to.fp16 should be used to convert to and from __fp...
Definition: TargetInfo.h:1002
The base class of the type hierarchy.
Definition: Type.h:1828
bool isConstantMatrixType() const
Definition: Type.h:8320
TypeClass getTypeClass() const
Definition: Type.h:2341
Defines the clang::TargetInfo interface.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< TagType > tagType
Matches tag types (record and enum types).
The JSON file list parser is used to communicate input to InstallAPI.