clang: lib/CIR/CodeGen/CIRGenTypes.cpp Source File (original) (raw)
2
5
10
11#include
12
13using namespace clang;
15
17 : cgm(genModule), astContext(genModule.getASTContext()),
18 builder(cgm.getBuilder()), theCXXABI(cgm.getCXXABI()),
19 theABIInfo(cgm.getTargetCIRGenInfo().getABIInfo()) {}
20
22 for (auto i = functionInfos.begin(), e = functionInfos.end(); i != e;)
23 delete &*i++;
24}
25
27 return *builder.getContext();
28}
29
30
31
32
33
35
36
38
39
40 const TagType *tagType = type->getAs();
42 return true;
43
44
45 return ->isIncompleteType();
46}
47
48
49
50
51
52
55 return false;
56
57 if (const auto *fpt = dyn_cast(ft))
58 for (unsigned i = 0, e = fpt->getNumParams(); i != e; i++)
60 return false;
61
62 return true;
63}
64
65mlir::Type CIRGenTypes::convertFunctionTypeInternal(QualType qft) {
68
69
70
73 qft);
75 }
76
78 if (const auto *fpt = dyn_cast(ft)) {
81 } else {
85 }
86
88
89 return resultType;
90}
91
92
93
95 StringRef suffix) {
97 llvm::raw_svector_ostream outStream(typeName);
98
105
108 .print(outStream, policy);
111 else
112 outStream << builder.getUniqueAnonRecordName();
113
114 if (!suffix.empty())
115 outStream << suffix;
116
117 return builder.getUniqueRecordName(std::string(typeName));
118}
119
120
122 const auto it = recordDeclTypes.find(ty);
123 return it != recordDeclTypes.end() && it->second.isComplete();
124}
125
126
127
128static bool
130 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);
131
132
133
134
135static bool
137 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
138
139
140 if (!alreadyChecked.insert(rd).second)
141 return true;
142
144 "Expect RecordDecl to be CompleteDefinition");
146
147
149 return true;
150
151
153 return false;
154
155
156
157
158
159 if (const CXXRecordDecl *crd = dyn_cast(rd)) {
162 ->castAs()
163 ->getDecl()
164 ->getDefinitionOrSelf(),
165 cgt, alreadyChecked))
166 return false;
167 }
168
169
170
172 if ((field->getType(), cgt, alreadyChecked))
173 return false;
174
175
176 return true;
177}
178
179
180
181static bool
183 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
184
186 qt = at->getValueType();
187
188
191
192
194 return isSafeToConvert(at->getElementType(), cgt, alreadyChecked);
195
196
197
198
199 return true;
200}
201
202
203
204
206
208 return true;
209
212}
213
214
216
217
218 const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();
219 cir::RecordType entry = recordDeclTypes[key];
220
221
222
223
224 if (!entry) {
226 entry = builder.getIncompleteRecordTy(name, rd);
227 recordDeclTypes[key] = entry;
228 }
229
232 return entry;
233
234
236 deferredRecords.push_back(rd);
237 return entry;
238 }
239
240
241 bool insertResult = recordsBeingLaidOut.insert(key).second;
242 (void)insertResult;
243 assert(insertResult && "isSafeToCovert() should have caught this.");
244
245
246 if (const auto *cxxRecordDecl = dyn_cast(rd)) {
247 for (const auto &base : cxxRecordDecl->bases()) {
248 if (base.isVirtual())
249 continue;
251 }
252 }
253
254
255 std::unique_ptr layout = computeRecordLayout(rd, &entry);
256 recordDeclTypes[key] = entry;
257 cirGenRecordLayouts[key] = std::move(layout);
258
259
260 bool eraseResult = recordsBeingLaidOut.erase(key);
261 (void)eraseResult;
262 assert(eraseResult && "record not in RecordsBeingLaidOut set?");
263
264
265
267
268
269
270 if (recordsBeingLaidOut.empty())
271 while (!deferredRecords.empty())
273
274 return entry;
275}
276
278 type = astContext.getCanonicalType(type);
279 const Type *ty = type.getTypePtr();
280
281
282 if (const auto *recordType = dyn_cast(type))
284
285
286 TypeCacheTy::iterator tci = typeCache.find(ty);
288 return tci->second;
289
290
291
292
293 mlir::Type resultType = nullptr;
295 case Type::Record:
296 llvm_unreachable("Should have been handled above");
297
298 case Type::Builtin: {
300
301 case BuiltinType::Void:
302 resultType = cgm.voidTy;
303 break;
304
305
306 case BuiltinType::Bool:
308 break;
309
310
311 case BuiltinType::Char_S:
312 case BuiltinType::Int:
313 case BuiltinType::Int128:
314 case BuiltinType::Long:
315 case BuiltinType::LongLong:
316 case BuiltinType::SChar:
317 case BuiltinType::Short:
318 case BuiltinType::WChar_S:
319 resultType =
320 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
321 true);
322 break;
323
324 case BuiltinType::Char8:
325 case BuiltinType::Char16:
326 case BuiltinType::Char32:
327 case BuiltinType::Char_U:
328 case BuiltinType::UChar:
329 case BuiltinType::UInt:
330 case BuiltinType::UInt128:
331 case BuiltinType::ULong:
332 case BuiltinType::ULongLong:
333 case BuiltinType::UShort:
334 case BuiltinType::WChar_U:
335 resultType =
336 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
337 false);
338 break;
339
340
341 case BuiltinType::Float16:
342 resultType = cgm.fP16Ty;
343 break;
344 case BuiltinType::Half:
345 if (astContext.getLangOpts().NativeHalfType ||
346 !astContext.getTargetInfo().useFP16ConversionIntrinsics()) {
347 resultType = cgm.fP16Ty;
348 } else {
350 resultType = cgm.sInt32Ty;
351 }
352 break;
353 case BuiltinType::BFloat16:
354 resultType = cgm.bFloat16Ty;
355 break;
356 case BuiltinType::Float:
357 assert(&astContext.getFloatTypeSemantics(type) ==
358 &llvm::APFloat::IEEEsingle() &&
359 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");
360 resultType = cgm.floatTy;
361 break;
362 case BuiltinType::Double:
363 assert(&astContext.getFloatTypeSemantics(type) ==
364 &llvm::APFloat::IEEEdouble() &&
365 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");
366 resultType = cgm.doubleTy;
367 break;
368 case BuiltinType::LongDouble:
369 resultType =
370 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(type));
371 break;
372 case BuiltinType::Float128:
373 resultType = cgm.fP128Ty;
374 break;
375 case BuiltinType::Ibm128:
377 resultType = cgm.sInt32Ty;
378 break;
379
380 case BuiltinType::NullPtr:
381
382
383
384
385 resultType = builder.getVoidPtrTy();
386 break;
387
388 default:
390 resultType = cgm.sInt32Ty;
391 break;
392 }
393 break;
394 }
395
396 case Type::Complex: {
398 mlir::Type elementTy = convertType(ct->getElementType());
399 resultType = cir::ComplexType::get(elementTy);
400 break;
401 }
402
403 case Type::LValueReference:
404 case Type::RValueReference: {
408 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
409 assert(resultType && "Cannot get pointer type?");
410 break;
411 }
412
413 case Type::Pointer: {
417
418 mlir::Type pointeeType = convertType(elemTy);
419
420 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
421 break;
422 }
423
424 case Type::VariableArray: {
428
429
431 break;
432 }
433
434 case Type::IncompleteArray: {
438
440
441
443 elemTy = cgm.sInt8Ty;
444 }
445
446 resultType = cir::ArrayType::get(elemTy, 0);
447 break;
448 }
449
450 case Type::ConstantArray: {
453
454
455
457 cgm.errorNYI(SourceLocation(), "arrays of undefined struct type", type);
458 resultType = cgm.uInt32Ty;
459 break;
460 }
461
462 resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue());
463 break;
464 }
465
466 case Type::ExtVector:
467 case Type::Vector: {
470 resultType = cir::VectorType::get(elemTy, vec->getNumElements());
471 break;
472 }
473
474 case Type::Enum: {
476 if (auto integerType = ed->getIntegerType(); !integerType.isNull())
478
479
480
481 resultType = cgm.uInt32Ty;
482 break;
483 }
484
485 case Type::MemberPointer: {
487
488 mlir::Type memberTy = convertType(mpt->getPointeeType());
489 auto clsTy = mlir::castcir::RecordType(
491 if (mpt->isMemberDataPointer()) {
492 resultType = cir::DataMemberType::get(memberTy, clsTy);
493 } else {
496 }
497 break;
498 }
499
500 case Type::FunctionNoProto:
501 case Type::FunctionProto:
502 resultType = convertFunctionTypeInternal(type);
503 break;
504
505 case Type::BitInt: {
507 if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {
509 resultType = cgm.sInt32Ty;
510 } else {
511 resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(),
512 bitIntTy->isSigned());
513 }
514 break;
515 }
516
517 case Type::Atomic: {
520
521
522 uint64_t valueSize = astContext.getTypeSize(valueType);
523 uint64_t atomicSize = astContext.getTypeSize(ty);
524 if (valueSize != atomicSize) {
525 cgm.errorNYI("convertType: atomic type value size != atomic size");
526 }
527
528 break;
529 }
530
531 default:
533 type->getTypeClassName());
534 resultType = cgm.sInt32Ty;
535 break;
536 }
537
538 assert(resultType && "Type conversion not yet implemented");
539
541 return resultType;
542}
543
545 bool forBitField) {
546 assert(->isConstantMatrixType() && "Matrix types NYI");
547
549
550 assert(!forBitField && "Bit fields NYI");
551
552
553
554 if (forBitField && qualType->isBitIntType())
555 assert(->isBitIntType() && "Bit field with type _BitInt NYI");
556
557 return convertedType;
558}
559
560
563 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
564
565
566 auto it = cirGenRecordLayouts.find(key);
567 if (it != cirGenRecordLayouts.end())
568 return *it->second;
569
570
572
573
574 it = cirGenRecordLayouts.find(key);
575
576 assert(it != cirGenRecordLayouts.end() &&
577 "Unable to find record layout information for type");
578 return *it->second;
579}
580
583 return astContext.getTargetNullPointerValue(t) == 0;
584
585 if (const auto *at = astContext.getAsArrayType(t)) {
587 return true;
588
589 if (const auto *cat = dyn_cast(at))
590 if (astContext.getConstantArrayElementCount(cat) == 0)
591 return true;
592 }
593
596
598 cgm.errorNYI(SourceLocation(), "isZeroInitializable for MemberPointerType",
599 t);
600 return false;
601 }
602
603 return true;
604}
605
609
614 assert(llvm::all_of(argTypes,
616
617 llvm::FoldingSetNodeID id;
619
620 void *insertPos = nullptr;
621 CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos);
622 if (fi) {
623
624
625 assert(
628 "Bad match based on CIRGenFunctionInfo folding set id");
629 return *fi;
630 }
631
633
634
636 functionInfos.InsertNode(fi, insertPos);
637
638 return *fi;
639}
640
642 assert(!dyn_cast(gd.getDecl()) &&
643 "This is reported as a FIXME in LLVM codegen");
645
649
651}
652
653
654
656
657
658
659 if (const auto *ed = dyn_cast(td)) {
660
661
662
663
664
665 assert(
667 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
669 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
670
671
673 return;
674 }
675
676
677
679 if (rd->isDependentType())
680 return;
681
682
683
684 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
686
687
688
690}
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...
Definition CIRGenTypes.cpp:182
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)
Definition CIRGenTypes.cpp:641
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.
Definition CIRGenTypes.cpp:581
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:53
CIRGenTypes(CIRGenModule &cgm)
Definition CIRGenTypes.cpp:16
bool isRecordBeingLaidOut(const clang::Type *ty) const
CIRGenBuilderTy & getBuilder() const
mlir::MLIRContext & getMLIRContext() const
Definition CIRGenTypes.cpp:26
const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
Definition CIRGenTypes.cpp:611
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...
Definition CIRGenTypes.cpp:34
void updateCompletedType(const clang::TagDecl *td)
UpdateCompletedType - when we find the full definition for a TagDecl, replace the 'opaque' type we pr...
Definition CIRGenTypes.cpp:655
~CIRGenTypes()
Definition CIRGenTypes.cpp:21
std::string getRecordTypeName(const clang::RecordDecl *, llvm::StringRef suffix)
Definition CIRGenTypes.cpp:94
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.
Definition CIRGenTypes.cpp:121
mlir::Type convertType(clang::QualType type)
Convert a Clang type into a mlir::Type.
Definition CIRGenTypes.cpp:277
const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)
Return record layout info for the given record decl.
Definition CIRGenTypes.cpp:562
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.
Definition CIRGenTypes.cpp:215
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
Definition CIRGenTypes.cpp:544
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'.
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.