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());
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();
103 policy.PrintAsCanonical = true;
104 policy.SuppressTagKeyword = true;
105
106 if (recordDecl->getIdentifier())
107 QualType(astContext.getCanonicalTagType(recordDecl))
108 .print(outStream, policy);
109 else if (auto *typedefNameDecl = recordDecl->getTypedefNameForAnonDecl())
110 typedefNameDecl->printQualifiedName(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/// Return true if the specified type is already completely laid out.
122 const auto it = recordDeclTypes.find(ty);
123 return it != recordDeclTypes.end() && it->second.isComplete();
124}
125
126// We have multiple forms of this function that call each other, so we need to
127// declare one in advance.
128static bool
130 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);
131
132/// Return true if it is safe to convert the specified record decl to CIR and
133/// lay it out, false if doing so would cause us to get into a recursive
134/// compilation mess.
135static bool
137 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
138 // If we have already checked this type (maybe the same type is used by-value
139 // multiple times in multiple record fields, don't check again.
140 if (!alreadyChecked.insert(rd).second)
141 return true;
142
143 assert(rd->isCompleteDefinition() &&
144 "Expect RecordDecl to be CompleteDefinition");
145 const Type *key = cgt.getASTContext().getCanonicalTagType(rd).getTypePtr();
146
147 // If this type is already laid out, converting it is a noop.
148 if (cgt.isRecordLayoutComplete(key))
149 return true;
150
151 // If this type is currently being laid out, we can't recursively compile it.
152 if (cgt.isRecordBeingLaidOut(key))
153 return false;
154
155 // If this type would require laying out bases that are currently being laid
156 // out, don't do it. This includes virtual base classes which get laid out
157 // when a class is translated, even though they aren't embedded by-value into
158 // the class.
159 if (const CXXRecordDecl *crd = dyn_cast<CXXRecordDecl>(rd)) {
160 for (const clang::CXXBaseSpecifier &i : crd->bases())
161 if (!isSafeToConvert(i.getType()
162 ->castAs<RecordType>()
163 ->getDecl()
164 ->getDefinitionOrSelf(),
165 cgt, alreadyChecked))
166 return false;
167 }
168
169 // If this type would require laying out members that are currently being laid
170 // out, don't do it.
171 for (const FieldDecl *field : rd->fields())
172 if (!isSafeToConvert(field->getType(), cgt, alreadyChecked))
173 return false;
174
175 // If there are no problems, lets do it.
176 return true;
177}
178
179/// Return true if it is safe to convert this field type, which requires the
180/// record elements contained by-value to all be recursively safe to convert.
181static bool
183 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
184 // Strip off atomic type sugar.
185 if (const auto *at = qt->getAs<AtomicType>())
186 qt = at->getValueType();
187
188 // If this is a record, check it.
189 if (const auto *rd = qt->getAsRecordDecl())
190 return isSafeToConvert(rd, cgt, alreadyChecked);
191
192 // If this is an array, check the elements, which are embedded inline.
193 if (const auto *at = cgt.getASTContext().getAsArrayType(qt))
194 return isSafeToConvert(at->getElementType(), cgt, alreadyChecked);
195
196 // Otherwise, there is no concern about transforming this. We only care about
197 // things that are contained by-value in a record that can have another
198 // record as a member.
199 return true;
200}
201
202// Return true if it is safe to convert the specified record decl to CIR and lay
203// it out, false if doing so would cause us to get into a recursive compilation
204// mess.
205static bool isSafeToConvert(const RecordDecl *rd, CIRGenTypes &cgt) {
206 // If no records are being laid out, we can certainly do this one.
207 if (cgt.noRecordsBeingLaidOut())
208 return true;
209
211 return isSafeToConvert(rd, cgt, alreadyChecked);
212}
213
214/// Lay out a tagged decl type like struct or union.
216 // TagDecl's are not necessarily unique, instead use the (clang) type
217 // connected to the decl.
218 const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();
219 cir::RecordType entry = recordDeclTypes[key];
220
221 // If we don't have an entry for this record yet, create one.
222 // We create an incomplete type initially. If `rd` is complete, we will
223 // add the members below.
224 if (!entry) {
225 auto name = getRecordTypeName(rd, "");
226 entry = builder.getIncompleteRecordTy(name, rd);
227 recordDeclTypes[key] = entry;
228 }
229
230 rd = rd->getDefinition();
231 if (!rd || !rd->isCompleteDefinition() || entry.isComplete())
232 return entry;
233
234 // If converting this type would cause us to infinitely loop, don't do it!
235 if (!isSafeToConvert(rd, *this)) {
236 deferredRecords.push_back(rd);
237 return entry;
238 }
239
240 // Okay, this is a definition of a type. Compile the implementation now.
241 bool insertResult = recordsBeingLaidOut.insert(key).second;
242 (void)insertResult;
243 assert(insertResult && "isSafeToCovert() should have caught this.");
244
245 // Force conversion of non-virtual base classes recursively.
246 if (const auto *cxxRecordDecl = dyn_cast<CXXRecordDecl>(rd)) {
247 for (const auto &base : cxxRecordDecl->bases()) {
248 if (base.isVirtual())
249 continue;
250 convertRecordDeclType(base.getType()->castAsRecordDecl());
251 }
252 }
253
254 // Layout fields.
255 std::unique_ptr<CIRGenRecordLayout> layout = computeRecordLayout(rd, &entry);
256 recordDeclTypes[key] = entry;
257 cirGenRecordLayouts[key] = std::move(layout);
258
259 // We're done laying out this record.
260 bool eraseResult = recordsBeingLaidOut.erase(key);
261 (void)eraseResult;
262 assert(eraseResult && "record not in RecordsBeingLaidOut set?");
263
264 // If this record blocked a FunctionType conversion, then recompute whatever
265 // was derived from that.
267
268 // If we're done converting the outer-most record, then convert any deferred
269 // records as well.
270 if (recordsBeingLaidOut.empty())
271 while (!deferredRecords.empty())
272 convertRecordDeclType(deferredRecords.pop_back_val());
273
274 return entry;
275}
276
278 type = astContext.getCanonicalType(type);
279 const Type *ty = type.getTypePtr();
280
281 // Process record types before the type cache lookup.
282 if (const auto *recordType = dyn_cast<RecordType>(type))
283 return convertRecordDeclType(recordType->getDecl()->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 ||
346 !astContext.getTargetInfo().useFP16ConversionIntrinsics()) {
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, elemTy.getAddressSpace());
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, elemTy.getAddressSpace());
421 break;
422 }
423
424 case Type::VariableArray: {
426 if (a->getIndexTypeCVRQualifiers() != 0)
427 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
428 // VLAs resolve to the innermost element type; this matches
429 // the return of alloca, and there isn't any obviously better choice.
430 resultType = convertTypeForMem(a->getElementType());
431 break;
432 }
433
434 case Type::IncompleteArray: {
436 if (arrTy->getIndexTypeCVRQualifiers() != 0)
437 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
438
439 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
440 // int X[] -> [0 x int], unless the element type is not sized. If it is
441 // unsized (e.g. an incomplete record) just use [0 x i8].
442 if (!cir::isSized(elemTy)) {
443 elemTy = cgm.sInt8Ty;
444 }
445
446 resultType = cir::ArrayType::get(elemTy, 0);
447 break;
448 }
449
450 case Type::ConstantArray: {
452 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
453
454 // TODO(CIR): In LLVM, "lower arrays of undefined struct type to arrays of
455 // i8 just to have a concrete type"
456 if (!cir::isSized(elemTy)) {
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: {
468 const VectorType *vec = cast<VectorType>(ty);
469 const mlir::Type elemTy = convertType(vec->getElementType());
470 resultType = cir::VectorType::get(elemTy, vec->getNumElements());
471 break;
472 }
473
474 case Type::Enum: {
475 const auto *ed = ty->castAsEnumDecl();
476 if (auto integerType = ed->getIntegerType(); !integerType.isNull())
477 return convertType(integerType);
478 // Return a placeholder 'i32' type. This can be changed later when the
479 // type is defined (see UpdateCompletedType), but is likely to be the
480 // "right" answer.
481 resultType = cgm.uInt32Ty;
482 break;
483 }
484
485 case Type::FunctionNoProto:
486 case Type::FunctionProto:
487 resultType = convertFunctionTypeInternal(type);
488 break;
489
490 case Type::BitInt: {
491 const auto *bitIntTy = cast<BitIntType>(type);
492 if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {
493 cgm.errorNYI(SourceLocation(), "large _BitInt type", type);
494 resultType = cgm.sInt32Ty;
495 } else {
496 resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(),
497 bitIntTy->isSigned());
498 }
499 break;
500 }
501
502 case Type::Atomic: {
503 QualType valueType = cast<AtomicType>(ty)->getValueType();
504 resultType = convertTypeForMem(valueType);
505
506 // Pad out to the inflated size if necessary.
507 uint64_t valueSize = astContext.getTypeSize(valueType);
508 uint64_t atomicSize = astContext.getTypeSize(ty);
509 if (valueSize != atomicSize) {
510 cgm.errorNYI("convertType: atomic type value size != atomic size");
511 }
512
513 break;
514 }
515
516 default:
517 cgm.errorNYI(SourceLocation(), "processing of type",
518 type->getTypeClassName());
519 resultType = cgm.sInt32Ty;
520 break;
521 }
522
523 assert(resultType && "Type conversion not yet implemented");
524
525 typeCache[ty] = resultType;
526 return resultType;
527}
528
530 bool forBitField) {
531 assert(!qualType->isConstantMatrixType() && "Matrix types NYI");
532
533 mlir::Type convertedType = convertType(qualType);
534
535 assert(!forBitField && "Bit fields NYI");
536
537 // If this is a bit-precise integer type in a bitfield representation, map
538 // this integer to the target-specified size.
539 if (forBitField && qualType->isBitIntType())
540 assert(!qualType->isBitIntType() && "Bit field with type _BitInt NYI");
541
542 return convertedType;
543}
544
545/// Return record layout info for the given record decl.
546const CIRGenRecordLayout &
548 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
549
550 // If we have already computed the layout, return it.
551 auto it = cirGenRecordLayouts.find(key);
552 if (it != cirGenRecordLayouts.end())
553 return *it->second;
554
555 // Compute the type information.
557
558 // Now try again.
559 it = cirGenRecordLayouts.find(key);
560
561 assert(it != cirGenRecordLayouts.end() &&
562 "Unable to find record layout information for type");
563 return *it->second;
564}
565
567 if (t->getAs<PointerType>())
568 return astContext.getTargetNullPointerValue(t) == 0;
569
570 if (const auto *at = astContext.getAsArrayType(t)) {
572 return true;
573
574 if (const auto *cat = dyn_cast<ConstantArrayType>(at))
575 if (astContext.getConstantArrayElementCount(cat) == 0)
576 return true;
577 }
578
579 if (const auto *rd = t->getAsRecordDecl())
580 return isZeroInitializable(rd);
581
582 if (t->getAs<MemberPointerType>()) {
583 cgm.errorNYI(SourceLocation(), "isZeroInitializable for MemberPointerType",
584 t);
585 return false;
586 }
587
588 return true;
589}
590
594
595const CIRGenFunctionInfo &
598 RequiredArgs required) {
599 assert(llvm::all_of(argTypes,
600 [](CanQualType t) { return t.isCanonicalAsParam(); }));
601 // Lookup or create unique function info.
602 llvm::FoldingSetNodeID id;
603 CIRGenFunctionInfo::Profile(id, required, returnType, argTypes);
604
605 void *insertPos = nullptr;
606 CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos);
607 if (fi) {
608 // We found a matching function info based on id. These asserts verify that
609 // it really is a match.
610 assert(
611 fi->getReturnType() == returnType &&
612 std::equal(fi->argTypesBegin(), fi->argTypesEnd(), argTypes.begin()) &&
613 "Bad match based on CIRGenFunctionInfo folding set id");
614 return *fi;
615 }
616
618
619 // Construction the function info. We co-allocate the ArgInfos.
620 fi = CIRGenFunctionInfo::create(returnType, argTypes, required);
621 functionInfos.InsertNode(fi, insertPos);
622
623 return *fi;
624}
625
627 assert(!dyn_cast<ObjCMethodDecl>(gd.getDecl()) &&
628 "This is reported as a FIXME in LLVM codegen");
629 const auto *fd = cast<FunctionDecl>(gd.getDecl());
630
634
636}
637
638// When we find the full definition for a TagDecl, replace the 'opaque' type we
639// previously made for it if applicable.
641 // If this is an enum being completed, then we flush all non-struct types
642 // from the cache. This allows function types and other things that may be
643 // derived from the enum to be recomputed.
644 if (const auto *ed = dyn_cast<EnumDecl>(td)) {
645 // Classic codegen clears the type cache if it contains an entry for this
646 // enum type that doesn't use i32 as the underlying type, but I can't find
647 // a test case that meets that condition. C++ doesn't allow forward
648 // declaration of enums, and C doesn't allow an incomplete forward
649 // declaration with a non-default type.
650 assert(
651 !typeCache.count(
652 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
653 (convertType(ed->getIntegerType()) ==
654 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
655 // If necessary, provide the full definition of a type only used with a
656 // declaration so far.
658 return;
659 }
660
661 // If we completed a RecordDecl that we previously used and converted to an
662 // anonymous type, then go ahead and complete it now.
663 const auto *rd = cast<RecordDecl>(td);
664 if (rd->isDependentType())
665 return;
666
667 // Only complete if we converted it already. If we haven't converted it yet,
668 // we'll just do it lazily.
669 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
671
672 // If necessary, provide the full definition of a type only used with a
673 // declaration so far.
675}
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
Definition TypeBase.h:3734
unsigned getIndexTypeCVRQualifiers() const
Definition TypeBase.h:3744
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.
Definition CIRGenTypes.h:48
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
Definition CIRGenTypes.h:81
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.
Definition DeclCXX.h:146
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
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.
Definition TypeBase.h:3760
llvm::APInt getSize() const
Return the constant array size as an APInt.
Definition TypeBase.h:3816
Represents a member of a struct/union/class.
Definition Decl.h:3160
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4450
QualType getReturnType() const
Definition TypeBase.h:4790
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:3909
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3653
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3328
QualType getPointeeType() const
Definition TypeBase.h:3338
A (possibly-)qualified type.
Definition TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8278
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8404
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
bool isCanonical() const
Definition TypeBase.h:8335
Represents a struct/union/class.
Definition Decl.h:4321
field_range fields() const
Definition Decl.h:4524
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition Decl.h:4505
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3573
QualType getPointeeType() const
Definition TypeBase.h:3591
Encodes a location in the source.
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3717
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3812
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:8676
EnumDecl * castAsEnumDecl() const
Definition Type.h:59
TypeClass getTypeClass() const
Definition TypeBase.h:2385
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:3966
Represents a GCC generic vector type.
Definition TypeBase.h:4175
unsigned getNumElements() const
Definition TypeBase.h:4190
QualType getElementType() const
Definition TypeBase.h:4189
Defines the clang::TargetInfo interface.
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
Definition CIRTypes.cpp:30
@ 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)
Definition Address.h:330
U cast(CodeGen::Address addr)
Definition Address.h:327
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.