clang 22.0.0git
CIRGenTypes.cpp
Go to the documentation of this file.
1#include "CIRGenTypes.h"
2
4#include "CIRGenModule.h"
5
8#include "clang/AST/Type.h"
10
11#include <cassert>
12
13using namespace clang;
14using namespace clang::CIRGen;
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
26mlir::MLIRContext &CIRGenTypes::getMLIRContext() const {
27 return *builder.getContext();
28}
29
30/// Return true if the specified type in a function parameter or result position
31/// can be converted to a CIR type at this point. This boils down to being
32/// whether it is complete, as well as whether we've temporarily deferred
33/// expanding the type because we're in a recursive context.
35 // Some ABIs cannot have their member pointers represented in LLVM IR unless
36 // certain circumstances have been reached.
37 assert(!type->getAs<MemberPointerType>() && "NYI");
38
39 // If this isn't a tag type, we can convert it.
40 const TagType *tagType = type->getAs<TagType>();
41 if (!tagType)
42 return true;
43
44 // Function types involving incomplete class types are problematic in MLIR.
45 return !tagType->isIncompleteType();
46}
47
48/// Code to verify a given function type is complete, i.e. the return type and
49/// all of the parameter types are complete. Also check to see if we are in a
50/// RS_StructPointer context, and if so whether any struct types have been
51/// pended. If so, we don't want to ask the ABI lowering code to handle a type
52/// that cannot be converted to a CIR type.
55 return false;
56
57 if (const auto *fpt = dyn_cast<FunctionProtoType>(ft))
58 for (unsigned i = 0, e = fpt->getNumParams(); i != e; i++)
59 if (!isFuncParamTypeConvertible(fpt->getParamType(i)))
60 return false;
61
62 return true;
63}
64
65mlir::Type CIRGenTypes::convertFunctionTypeInternal(QualType qft) {
66 assert(qft.isCanonical());
67 const FunctionType *ft = cast<FunctionType>(qft.getTypePtr());
68 // First, check whether we can build the full function type. If the function
69 // type depends on an incomplete type (e.g. a struct or enum), we cannot lower
70 // the function type.
71 if (!isFuncTypeConvertible(ft)) {
72 cgm.errorNYI(SourceLocation(), "function type involving an incomplete type",
73 qft);
74 return cir::FuncType::get(SmallVector<mlir::Type, 1>{}, cgm.VoidTy);
75 }
76
77 const CIRGenFunctionInfo *fi;
78 if (const auto *fpt = dyn_cast<FunctionProtoType>(ft)) {
81 } else {
82 const FunctionNoProtoType *fnpt = cast<FunctionNoProtoType>(ft);
85 }
86
87 mlir::Type resultType = getFunctionType(*fi);
88
89 return resultType;
90}
91
92// This is CIR's version of CodeGenTypes::addRecordTypeName. It isn't shareable
93// because CIR has different uniquing requirements.
95 StringRef suffix) {
97 llvm::raw_svector_ostream outStream(typeName);
98
99 PrintingPolicy policy = recordDecl->getASTContext().getPrintingPolicy();
100 policy.SuppressInlineNamespace = false;
102 policy.PrintAsCanonical = true;
103 policy.SuppressTagKeyword = true;
104
105 if (recordDecl->getIdentifier())
107 .print(outStream, policy);
108 else if (auto *typedefNameDecl = recordDecl->getTypedefNameForAnonDecl())
109 typedefNameDecl->printQualifiedName(outStream, policy);
110 else
111 outStream << builder.getUniqueAnonRecordName();
112
113 if (!suffix.empty())
114 outStream << suffix;
115
116 return builder.getUniqueRecordName(std::string(typeName));
117}
118
119/// Return true if the specified type is already completely laid out.
121 const auto it = recordDeclTypes.find(ty);
122 return it != recordDeclTypes.end() && it->second.isComplete();
123}
124
125// We have multiple forms of this function that call each other, so we need to
126// declare one in advance.
127static bool
129 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);
130
131/// Return true if it is safe to convert the specified record decl to CIR and
132/// lay it out, false if doing so would cause us to get into a recursive
133/// compilation mess.
134static bool
136 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
137 // If we have already checked this type (maybe the same type is used by-value
138 // multiple times in multiple record fields, don't check again.
139 if (!alreadyChecked.insert(rd).second)
140 return true;
141
142 assert(rd->isCompleteDefinition() &&
143 "Expect RecordDecl to be CompleteDefinition");
144 const Type *key = cgt.getASTContext().getCanonicalTagType(rd).getTypePtr();
145
146 // If this type is already laid out, converting it is a noop.
147 if (cgt.isRecordLayoutComplete(key))
148 return true;
149
150 // If this type is currently being laid out, we can't recursively compile it.
151 if (cgt.isRecordBeingLaidOut(key))
152 return false;
153
154 // If this type would require laying out bases that are currently being laid
155 // out, don't do it. This includes virtual base classes which get laid out
156 // when a class is translated, even though they aren't embedded by-value into
157 // the class.
158 if (const CXXRecordDecl *crd = dyn_cast<CXXRecordDecl>(rd)) {
159 for (const clang::CXXBaseSpecifier &i : crd->bases())
160 if (!isSafeToConvert(i.getType()
161 ->castAs<RecordType>()
164 cgt, alreadyChecked))
165 return false;
166 }
167
168 // If this type would require laying out members that are currently being laid
169 // out, don't do it.
170 for (const FieldDecl *field : rd->fields())
171 if (!isSafeToConvert(field->getType(), cgt, alreadyChecked))
172 return false;
173
174 // If there are no problems, lets do it.
175 return true;
176}
177
178/// Return true if it is safe to convert this field type, which requires the
179/// record elements contained by-value to all be recursively safe to convert.
180static bool
182 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
183 // Strip off atomic type sugar.
184 if (const auto *at = qt->getAs<AtomicType>())
185 qt = at->getValueType();
186
187 // If this is a record, check it.
188 if (const auto *rd = qt->getAsRecordDecl())
189 return isSafeToConvert(rd, cgt, alreadyChecked);
190
191 // If this is an array, check the elements, which are embedded inline.
192 if (const auto *at = cgt.getASTContext().getAsArrayType(qt))
193 return isSafeToConvert(at->getElementType(), cgt, alreadyChecked);
194
195 // Otherwise, there is no concern about transforming this. We only care about
196 // things that are contained by-value in a record that can have another
197 // record as a member.
198 return true;
199}
200
201// Return true if it is safe to convert the specified record decl to CIR and lay
202// it out, false if doing so would cause us to get into a recursive compilation
203// mess.
204static bool isSafeToConvert(const RecordDecl *rd, CIRGenTypes &cgt) {
205 // If no records are being laid out, we can certainly do this one.
206 if (cgt.noRecordsBeingLaidOut())
207 return true;
208
210 return isSafeToConvert(rd, cgt, alreadyChecked);
211}
212
213/// Lay out a tagged decl type like struct or union.
215 // TagDecl's are not necessarily unique, instead use the (clang) type
216 // connected to the decl.
217 const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();
218 cir::RecordType entry = recordDeclTypes[key];
219
220 // If we don't have an entry for this record yet, create one.
221 // We create an incomplete type initially. If `rd` is complete, we will
222 // add the members below.
223 if (!entry) {
224 auto name = getRecordTypeName(rd, "");
225 entry = builder.getIncompleteRecordTy(name, rd);
226 recordDeclTypes[key] = entry;
227 }
228
229 rd = rd->getDefinition();
230 if (!rd || !rd->isCompleteDefinition() || entry.isComplete())
231 return entry;
232
233 // If converting this type would cause us to infinitely loop, don't do it!
234 if (!isSafeToConvert(rd, *this)) {
235 deferredRecords.push_back(rd);
236 return entry;
237 }
238
239 // Okay, this is a definition of a type. Compile the implementation now.
240 bool insertResult = recordsBeingLaidOut.insert(key).second;
241 (void)insertResult;
242 assert(insertResult && "isSafeToCovert() should have caught this.");
243
244 // Force conversion of non-virtual base classes recursively.
245 if (const auto *cxxRecordDecl = dyn_cast<CXXRecordDecl>(rd)) {
246 for (const auto &base : cxxRecordDecl->bases()) {
247 if (base.isVirtual())
248 continue;
249 convertRecordDeclType(base.getType()->castAsRecordDecl());
250 }
251 }
252
253 // Layout fields.
254 std::unique_ptr<CIRGenRecordLayout> layout = computeRecordLayout(rd, &entry);
255 recordDeclTypes[key] = entry;
256 cirGenRecordLayouts[key] = std::move(layout);
257
258 // We're done laying out this record.
259 bool eraseResult = recordsBeingLaidOut.erase(key);
260 (void)eraseResult;
261 assert(eraseResult && "record not in RecordsBeingLaidOut set?");
262
263 // If this record blocked a FunctionType conversion, then recompute whatever
264 // was derived from that.
266
267 // If we're done converting the outer-most record, then convert any deferred
268 // records as well.
269 if (recordsBeingLaidOut.empty())
270 while (!deferredRecords.empty())
271 convertRecordDeclType(deferredRecords.pop_back_val());
272
273 return entry;
274}
275
277 type = astContext.getCanonicalType(type);
278 const Type *ty = type.getTypePtr();
279
280 // Process record types before the type cache lookup.
281 if (const auto *recordType = dyn_cast<RecordType>(type))
283 recordType->getOriginalDecl()->getDefinitionOrSelf());
284
285 // Has the type already been processed?
286 TypeCacheTy::iterator tci = typeCache.find(ty);
287 if (tci != typeCache.end())
288 return tci->second;
289
290 // For types that haven't been implemented yet or are otherwise unsupported,
291 // report an error and return 'int'.
292
293 mlir::Type resultType = nullptr;
294 switch (ty->getTypeClass()) {
295 case Type::Record:
296 llvm_unreachable("Should have been handled above");
297
298 case Type::Builtin: {
299 switch (cast<BuiltinType>(ty)->getKind()) {
300 // void
301 case BuiltinType::Void:
302 resultType = cgm.VoidTy;
303 break;
304
305 // bool
306 case BuiltinType::Bool:
307 resultType = cir::BoolType::get(&getMLIRContext());
308 break;
309
310 // Signed integral types.
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 /*isSigned=*/true);
322 break;
323 // Unsigned integral types.
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 /*isSigned=*/false);
338 break;
339
340 // Floating-point types
341 case BuiltinType::Float16:
342 resultType = cgm.FP16Ty;
343 break;
344 case BuiltinType::Half:
345 if (astContext.getLangOpts().NativeHalfType ||
347 resultType = cgm.FP16Ty;
348 } else {
349 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
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:
376 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
377 resultType = cgm.SInt32Ty;
378 break;
379
380 case BuiltinType::NullPtr:
381 // Add proper CIR type for it? this looks mostly useful for sema related
382 // things (like for overloads accepting void), for now, given that
383 // `sizeof(std::nullptr_t)` is equal to `sizeof(void *)`, model
384 // std::nullptr_t as !cir.ptr<!void>
385 resultType = builder.getVoidPtrTy();
386 break;
387
388 default:
389 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
390 resultType = cgm.SInt32Ty;
391 break;
392 }
393 break;
394 }
395
396 case Type::Complex: {
397 const auto *ct = cast<clang::ComplexType>(ty);
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: {
405 const ReferenceType *refTy = cast<ReferenceType>(ty);
406 QualType elemTy = refTy->getPointeeType();
407 auto pointeeType = convertTypeForMem(elemTy);
408 resultType = builder.getPointerTo(pointeeType);
409 assert(resultType && "Cannot get pointer type?");
410 break;
411 }
412
413 case Type::Pointer: {
414 const PointerType *ptrTy = cast<PointerType>(ty);
415 QualType elemTy = ptrTy->getPointeeType();
416 assert(!elemTy->isConstantMatrixType() && "not implemented");
417
418 mlir::Type pointeeType = convertType(elemTy);
419
420 resultType = builder.getPointerTo(pointeeType);
421 break;
422 }
423
424 case Type::IncompleteArray: {
425 const IncompleteArrayType *arrTy = cast<IncompleteArrayType>(ty);
426 if (arrTy->getIndexTypeCVRQualifiers() != 0)
427 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
428
429 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
430 // int X[] -> [0 x int], unless the element type is not sized. If it is
431 // unsized (e.g. an incomplete record) just use [0 x i8].
432 if (!cir::isSized(elemTy)) {
433 elemTy = cgm.SInt8Ty;
434 }
435
436 resultType = cir::ArrayType::get(elemTy, 0);
437 break;
438 }
439
440 case Type::ConstantArray: {
441 const ConstantArrayType *arrTy = cast<ConstantArrayType>(ty);
442 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
443
444 // TODO(CIR): In LLVM, "lower arrays of undefined struct type to arrays of
445 // i8 just to have a concrete type"
446 if (!cir::isSized(elemTy)) {
447 cgm.errorNYI(SourceLocation(), "arrays of undefined struct type", type);
448 resultType = cgm.UInt32Ty;
449 break;
450 }
451
452 resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue());
453 break;
454 }
455
456 case Type::ExtVector:
457 case Type::Vector: {
458 const VectorType *vec = cast<VectorType>(ty);
459 const mlir::Type elemTy = convertType(vec->getElementType());
460 resultType = cir::VectorType::get(elemTy, vec->getNumElements());
461 break;
462 }
463
464 case Type::Enum: {
465 const auto *ed = ty->castAsEnumDecl();
466 if (auto integerType = ed->getIntegerType(); !integerType.isNull())
467 return convertType(integerType);
468 // Return a placeholder 'i32' type. This can be changed later when the
469 // type is defined (see UpdateCompletedType), but is likely to be the
470 // "right" answer.
471 resultType = cgm.UInt32Ty;
472 break;
473 }
474
475 case Type::FunctionNoProto:
476 case Type::FunctionProto:
477 resultType = convertFunctionTypeInternal(type);
478 break;
479
480 case Type::BitInt: {
481 const auto *bitIntTy = cast<BitIntType>(type);
482 if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {
483 cgm.errorNYI(SourceLocation(), "large _BitInt type", type);
484 resultType = cgm.SInt32Ty;
485 } else {
486 resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(),
487 bitIntTy->isSigned());
488 }
489 break;
490 }
491
492 case Type::Atomic: {
493 QualType valueType = cast<AtomicType>(ty)->getValueType();
494 resultType = convertTypeForMem(valueType);
495
496 // Pad out to the inflated size if necessary.
497 uint64_t valueSize = astContext.getTypeSize(valueType);
498 uint64_t atomicSize = astContext.getTypeSize(ty);
499 if (valueSize != atomicSize) {
500 cgm.errorNYI("convertType: atomic type value size != atomic size");
501 }
502
503 break;
504 }
505
506 default:
507 cgm.errorNYI(SourceLocation(), "processing of type",
508 type->getTypeClassName());
509 resultType = cgm.SInt32Ty;
510 break;
511 }
512
513 assert(resultType && "Type conversion not yet implemented");
514
515 typeCache[ty] = resultType;
516 return resultType;
517}
518
520 bool forBitField) {
521 assert(!qualType->isConstantMatrixType() && "Matrix types NYI");
522
523 mlir::Type convertedType = convertType(qualType);
524
525 assert(!forBitField && "Bit fields NYI");
526
527 // If this is a bit-precise integer type in a bitfield representation, map
528 // this integer to the target-specified size.
529 if (forBitField && qualType->isBitIntType())
530 assert(!qualType->isBitIntType() && "Bit field with type _BitInt NYI");
531
532 return convertedType;
533}
534
535/// Return record layout info for the given record decl.
536const CIRGenRecordLayout &
538 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
539
540 // If we have already computed the layout, return it.
541 auto it = cirGenRecordLayouts.find(key);
542 if (it != cirGenRecordLayouts.end())
543 return *it->second;
544
545 // Compute the type information.
547
548 // Now try again.
549 it = cirGenRecordLayouts.find(key);
550
551 assert(it != cirGenRecordLayouts.end() &&
552 "Unable to find record layout information for type");
553 return *it->second;
554}
555
557 if (t->getAs<PointerType>())
558 return astContext.getTargetNullPointerValue(t) == 0;
559
560 if (const auto *at = astContext.getAsArrayType(t)) {
561 if (isa<IncompleteArrayType>(at))
562 return true;
563
564 if (const auto *cat = dyn_cast<ConstantArrayType>(at))
565 if (astContext.getConstantArrayElementCount(cat) == 0)
566 return true;
567 }
568
569 if (const auto *rd = t->getAsRecordDecl())
570 return isZeroInitializable(rd);
571
572 if (t->getAs<MemberPointerType>()) {
573 cgm.errorNYI(SourceLocation(), "isZeroInitializable for MemberPointerType",
574 t);
575 return false;
576 }
577
578 return true;
579}
580
583}
584
585const CIRGenFunctionInfo &
588 RequiredArgs required) {
589 assert(llvm::all_of(argTypes,
590 [](CanQualType t) { return t.isCanonicalAsParam(); }));
591 // Lookup or create unique function info.
592 llvm::FoldingSetNodeID id;
593 CIRGenFunctionInfo::Profile(id, required, returnType, argTypes);
594
595 void *insertPos = nullptr;
596 CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos);
597 if (fi) {
598 // We found a matching function info based on id. These asserts verify that
599 // it really is a match.
600 assert(
601 fi->getReturnType() == returnType &&
602 std::equal(fi->argTypesBegin(), fi->argTypesEnd(), argTypes.begin()) &&
603 "Bad match based on CIRGenFunctionInfo folding set id");
604 return *fi;
605 }
606
608
609 // Construction the function info. We co-allocate the ArgInfos.
610 fi = CIRGenFunctionInfo::create(returnType, argTypes, required);
611 functionInfos.InsertNode(fi, insertPos);
612
613 return *fi;
614}
615
617 assert(!dyn_cast<ObjCMethodDecl>(gd.getDecl()) &&
618 "This is reported as a FIXME in LLVM codegen");
619 const auto *fd = cast<FunctionDecl>(gd.getDecl());
620
621 if (isa<CXXConstructorDecl>(gd.getDecl()) ||
622 isa<CXXDestructorDecl>(gd.getDecl())) {
624 "arrangeGlobalDeclaration for C++ constructor or destructor");
625 }
626
628}
629
630// When we find the full definition for a TagDecl, replace the 'opaque' type we
631// previously made for it if applicable.
633 // If this is an enum being completed, then we flush all non-struct types
634 // from the cache. This allows function types and other things that may be
635 // derived from the enum to be recomputed.
636 if (const auto *ed = dyn_cast<EnumDecl>(td)) {
637 // Classic codegen clears the type cache if it contains an entry for this
638 // enum type that doesn't use i32 as the underlying type, but I can't find
639 // a test case that meets that condition. C++ doesn't allow forward
640 // declaration of enums, and C doesn't allow an incomplete forward
641 // declaration with a non-default type.
642 assert(
643 !typeCache.count(
644 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
645 (convertType(ed->getIntegerType()) ==
646 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
647 // If necessary, provide the full definition of a type only used with a
648 // declaration so far.
650 return;
651 }
652
653 // If we completed a RecordDecl that we previously used and converted to an
654 // anonymous type, then go ahead and complete it now.
655 const auto *rd = cast<RecordDecl>(td);
656 if (rd->isDependentType())
657 return;
658
659 // Only complete if we converted it already. If we haven't converted it yet,
660 // we'll just do it lazily.
661 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
663
664 // If necessary, provide the full definition of a type only used with a
665 // declaration so far.
667}
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)
Definition: DeclBase.cpp:1192
C Language Family Type Representation.
cir::PointerType getPointerTo(mlir::Type ty)
cir::PointerType getVoidPtrTy()
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
uint64_t getTargetNullPointerValue(QualType QT) const
Get target-dependent integer value for null pointer which is used for constant folding.
CanQualType getCanonicalType(QualType T) const
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
Definition: ASTContext.h:2851
const LangOptions & getLangOpts() const
Definition: ASTContext.h:894
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
Definition: ASTContext.h:2625
const TargetInfo & getTargetInfo() const
Definition: ASTContext.h:859
uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const
Return number of constant array elements.
CanQualType getCanonicalTagType(const TagDecl *TD) const
QualType getElementType() const
Definition: TypeBase.h:3750
unsigned getIndexTypeCVRQualifiers() const
Definition: TypeBase.h:3760
cir::RecordType getIncompleteRecordTy(llvm::StringRef name, const clang::RecordDecl *rd)
Get an incomplete CIR struct type.
std::string getUniqueRecordName(const std::string &baseName)
Definition: CIRGenBuilder.h:82
std::string getUniqueAnonRecordName()
Definition: CIRGenBuilder.h:80
cir::LongDoubleType getLongDoubleTy(const llvm::fltSemantics &format) const
Definition: CIRGenBuilder.h:92
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)
Definition: CIRGenCall.cpp:24
This class organizes the cross-function state that is used while generating CIR code.
Definition: CIRGenModule.h:56
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.
Definition: CIRGenTypes.h:48
const CIRGenFunctionInfo & arrangeGlobalDeclaration(GlobalDecl gd)
const CIRGenFunctionInfo & arrangeFreeFunctionType(CanQual< FunctionProtoType > fpt)
Definition: CIRGenCall.cpp:487
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.
Definition: CIRGenTypes.cpp:53
CIRGenTypes(CIRGenModule &cgm)
Definition: CIRGenTypes.cpp:16
bool isRecordBeingLaidOut(const clang::Type *ty) const
Definition: CIRGenTypes.h:104
mlir::MLIRContext & getMLIRContext() const
Definition: CIRGenTypes.cpp:26
const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
Definition: CIRGenCall.cpp:50
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...
std::string getRecordTypeName(const clang::RecordDecl *, llvm::StringRef suffix)
Definition: CIRGenTypes.cpp:94
bool noRecordsBeingLaidOut() const
Definition: CIRGenTypes.h:103
const CIRGenFunctionInfo & arrangeFunctionDeclaration(const clang::FunctionDecl *fd)
Free functions are functions that are compatible with an ordinary C function pointer type.
Definition: CIRGenCall.cpp:436
clang::ASTContext & getASTContext() const
Definition: CIRGenTypes.h:100
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.
Definition: DeclCXX.h:146
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
Represents a canonical, potentially-qualified type.
Definition: CanonicalType.h:66
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.
Definition: CanonicalType.h:84
Represents the canonical version of C arrays with a specified constant size.
Definition: TypeBase.h:3776
llvm::APInt getSize() const
Return the constant array size as an APInt.
Definition: TypeBase.h:3832
Represents a member of a struct/union/class.
Definition: Decl.h:3157
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition: TypeBase.h:4860
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: TypeBase.h:4478
QualType getReturnType() const
Definition: TypeBase.h:4818
GlobalDecl - represents a global declaration.
Definition: GlobalDecl.h:57
const Decl * getDecl() const
Definition: GlobalDecl.h:106
Represents a C array with an unspecified size.
Definition: TypeBase.h:3925
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition: TypeBase.h:3669
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: TypeBase.h:3346
QualType getPointeeType() const
Definition: TypeBase.h:3356
A (possibly-)qualified type.
Definition: TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: TypeBase.h:8343
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
bool isCanonical() const
Definition: TypeBase.h:8400
Represents a struct/union/class.
Definition: Decl.h:4309
field_range fields() const
Definition: Decl.h:4512
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition: Decl.h:4493
RecordDecl * getDefinitionOrSelf() const
Definition: Decl.h:4497
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: TypeBase.h:6502
RecordDecl * getOriginalDecl() const
Definition: TypeBase.h:6509
Base for LValueReferenceType and RValueReferenceType.
Definition: TypeBase.h:3589
QualType getPointeeType() const
Definition: TypeBase.h:3607
Encodes a location in the source.
Represents the declaration of a struct/union/class/enum.
Definition: Decl.h:3714
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition: Decl.h:3809
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:1015
The base class of the type hierarchy.
Definition: TypeBase.h:1833
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.h:41
bool isConstantMatrixType() const
Definition: TypeBase.h:8741
EnumDecl * castAsEnumDecl() const
Definition: Type.h:59
TypeClass getTypeClass() const
Definition: TypeBase.h:2403
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
Represents a GCC generic vector type.
Definition: TypeBase.h:4191
unsigned getNumElements() const
Definition: TypeBase.h:4206
QualType getElementType() const
Definition: TypeBase.h:4205
Defines the clang::TargetInfo interface.
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
Definition: CIRTypes.cpp:24
const internal::VariadicDynCastAllOfMatcher< Decl, TypedefNameDecl > typedefNameDecl
Matches typedef name declarations.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< TagType > tagType
Matches tag types (record and enum types).
const AstTypeMatcher< RecordType > recordType
Matches record types (e.g.
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.
static bool skippedLayout()
static bool opCallCallConv()
static bool generateDebugInfo()
Describes how types, statements, expressions, and declarations should be printed.
Definition: PrettyPrinter.h:57
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.