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();
100 policy.SuppressInlineNamespace = false;
102 policy.PrintAsCanonical = true;
103 policy.SuppressTagKeyword = true;
104
105 if (recordDecl->getIdentifier())
106 QualType(astContext.getCanonicalTagType(recordDecl))
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>()
162 ->getDecl()
163 ->getDefinitionOrSelf(),
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))
282 return convertRecordDeclType(recordType->getDecl()->getDefinitionOrSelf());
283
284 // Has the type already been processed?
285 TypeCacheTy::iterator tci = typeCache.find(ty);
286 if (tci != typeCache.end())
287 return tci->second;
288
289 // For types that haven't been implemented yet or are otherwise unsupported,
290 // report an error and return 'int'.
291
292 mlir::Type resultType = nullptr;
293 switch (ty->getTypeClass()) {
294 case Type::Record:
295 llvm_unreachable("Should have been handled above");
296
297 case Type::Builtin: {
298 switch (cast<BuiltinType>(ty)->getKind()) {
299 // void
300 case BuiltinType::Void:
301 resultType = cgm.voidTy;
302 break;
303
304 // bool
305 case BuiltinType::Bool:
306 resultType = cir::BoolType::get(&getMLIRContext());
307 break;
308
309 // Signed integral types.
310 case BuiltinType::Char_S:
311 case BuiltinType::Int:
312 case BuiltinType::Int128:
313 case BuiltinType::Long:
314 case BuiltinType::LongLong:
315 case BuiltinType::SChar:
316 case BuiltinType::Short:
317 case BuiltinType::WChar_S:
318 resultType =
319 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
320 /*isSigned=*/true);
321 break;
322 // Unsigned integral types.
323 case BuiltinType::Char8:
324 case BuiltinType::Char16:
325 case BuiltinType::Char32:
326 case BuiltinType::Char_U:
327 case BuiltinType::UChar:
328 case BuiltinType::UInt:
329 case BuiltinType::UInt128:
330 case BuiltinType::ULong:
331 case BuiltinType::ULongLong:
332 case BuiltinType::UShort:
333 case BuiltinType::WChar_U:
334 resultType =
335 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
336 /*isSigned=*/false);
337 break;
338
339 // Floating-point types
340 case BuiltinType::Float16:
341 resultType = cgm.fP16Ty;
342 break;
343 case BuiltinType::Half:
344 if (astContext.getLangOpts().NativeHalfType ||
345 !astContext.getTargetInfo().useFP16ConversionIntrinsics()) {
346 resultType = cgm.fP16Ty;
347 } else {
348 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
349 resultType = cgm.sInt32Ty;
350 }
351 break;
352 case BuiltinType::BFloat16:
353 resultType = cgm.bFloat16Ty;
354 break;
355 case BuiltinType::Float:
356 assert(&astContext.getFloatTypeSemantics(type) ==
357 &llvm::APFloat::IEEEsingle() &&
358 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");
359 resultType = cgm.floatTy;
360 break;
361 case BuiltinType::Double:
362 assert(&astContext.getFloatTypeSemantics(type) ==
363 &llvm::APFloat::IEEEdouble() &&
364 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");
365 resultType = cgm.doubleTy;
366 break;
367 case BuiltinType::LongDouble:
368 resultType =
369 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(type));
370 break;
371 case BuiltinType::Float128:
372 resultType = cgm.fP128Ty;
373 break;
374 case BuiltinType::Ibm128:
375 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
376 resultType = cgm.sInt32Ty;
377 break;
378
379 case BuiltinType::NullPtr:
380 // Add proper CIR type for it? this looks mostly useful for sema related
381 // things (like for overloads accepting void), for now, given that
382 // `sizeof(std::nullptr_t)` is equal to `sizeof(void *)`, model
383 // std::nullptr_t as !cir.ptr<!void>
384 resultType = builder.getVoidPtrTy();
385 break;
386
387 default:
388 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
389 resultType = cgm.sInt32Ty;
390 break;
391 }
392 break;
393 }
394
395 case Type::Complex: {
396 const auto *ct = cast<clang::ComplexType>(ty);
397 mlir::Type elementTy = convertType(ct->getElementType());
398 resultType = cir::ComplexType::get(elementTy);
399 break;
400 }
401
402 case Type::LValueReference:
403 case Type::RValueReference: {
404 const ReferenceType *refTy = cast<ReferenceType>(ty);
405 QualType elemTy = refTy->getPointeeType();
406 auto pointeeType = convertTypeForMem(elemTy);
407 resultType = builder.getPointerTo(pointeeType);
408 assert(resultType && "Cannot get pointer type?");
409 break;
410 }
411
412 case Type::Pointer: {
413 const PointerType *ptrTy = cast<PointerType>(ty);
414 QualType elemTy = ptrTy->getPointeeType();
415 assert(!elemTy->isConstantMatrixType() && "not implemented");
416
417 mlir::Type pointeeType = convertType(elemTy);
418
419 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
420 break;
421 }
422
423 case Type::VariableArray: {
425 if (a->getIndexTypeCVRQualifiers() != 0)
426 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
427 // VLAs resolve to the innermost element type; this matches
428 // the return of alloca, and there isn't any obviously better choice.
429 resultType = convertTypeForMem(a->getElementType());
430 break;
431 }
432
433 case Type::IncompleteArray: {
435 if (arrTy->getIndexTypeCVRQualifiers() != 0)
436 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
437
438 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
439 // int X[] -> [0 x int], unless the element type is not sized. If it is
440 // unsized (e.g. an incomplete record) just use [0 x i8].
441 if (!cir::isSized(elemTy)) {
442 elemTy = cgm.sInt8Ty;
443 }
444
445 resultType = cir::ArrayType::get(elemTy, 0);
446 break;
447 }
448
449 case Type::ConstantArray: {
451 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
452
453 // TODO(CIR): In LLVM, "lower arrays of undefined struct type to arrays of
454 // i8 just to have a concrete type"
455 if (!cir::isSized(elemTy)) {
456 cgm.errorNYI(SourceLocation(), "arrays of undefined struct type", type);
457 resultType = cgm.uInt32Ty;
458 break;
459 }
460
461 resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue());
462 break;
463 }
464
465 case Type::ExtVector:
466 case Type::Vector: {
467 const VectorType *vec = cast<VectorType>(ty);
468 const mlir::Type elemTy = convertType(vec->getElementType());
469 resultType = cir::VectorType::get(elemTy, vec->getNumElements());
470 break;
471 }
472
473 case Type::Enum: {
474 const auto *ed = ty->castAsEnumDecl();
475 if (auto integerType = ed->getIntegerType(); !integerType.isNull())
476 return convertType(integerType);
477 // Return a placeholder 'i32' type. This can be changed later when the
478 // type is defined (see UpdateCompletedType), but is likely to be the
479 // "right" answer.
480 resultType = cgm.uInt32Ty;
481 break;
482 }
483
484 case Type::FunctionNoProto:
485 case Type::FunctionProto:
486 resultType = convertFunctionTypeInternal(type);
487 break;
488
489 case Type::BitInt: {
490 const auto *bitIntTy = cast<BitIntType>(type);
491 if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {
492 cgm.errorNYI(SourceLocation(), "large _BitInt type", type);
493 resultType = cgm.sInt32Ty;
494 } else {
495 resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(),
496 bitIntTy->isSigned());
497 }
498 break;
499 }
500
501 case Type::Atomic: {
502 QualType valueType = cast<AtomicType>(ty)->getValueType();
503 resultType = convertTypeForMem(valueType);
504
505 // Pad out to the inflated size if necessary.
506 uint64_t valueSize = astContext.getTypeSize(valueType);
507 uint64_t atomicSize = astContext.getTypeSize(ty);
508 if (valueSize != atomicSize) {
509 cgm.errorNYI("convertType: atomic type value size != atomic size");
510 }
511
512 break;
513 }
514
515 default:
516 cgm.errorNYI(SourceLocation(), "processing of type",
517 type->getTypeClassName());
518 resultType = cgm.sInt32Ty;
519 break;
520 }
521
522 assert(resultType && "Type conversion not yet implemented");
523
524 typeCache[ty] = resultType;
525 return resultType;
526}
527
529 bool forBitField) {
530 assert(!qualType->isConstantMatrixType() && "Matrix types NYI");
531
532 mlir::Type convertedType = convertType(qualType);
533
534 assert(!forBitField && "Bit fields NYI");
535
536 // If this is a bit-precise integer type in a bitfield representation, map
537 // this integer to the target-specified size.
538 if (forBitField && qualType->isBitIntType())
539 assert(!qualType->isBitIntType() && "Bit field with type _BitInt NYI");
540
541 return convertedType;
542}
543
544/// Return record layout info for the given record decl.
545const CIRGenRecordLayout &
547 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
548
549 // If we have already computed the layout, return it.
550 auto it = cirGenRecordLayouts.find(key);
551 if (it != cirGenRecordLayouts.end())
552 return *it->second;
553
554 // Compute the type information.
556
557 // Now try again.
558 it = cirGenRecordLayouts.find(key);
559
560 assert(it != cirGenRecordLayouts.end() &&
561 "Unable to find record layout information for type");
562 return *it->second;
563}
564
566 if (t->getAs<PointerType>())
567 return astContext.getTargetNullPointerValue(t) == 0;
568
569 if (const auto *at = astContext.getAsArrayType(t)) {
571 return true;
572
573 if (const auto *cat = dyn_cast<ConstantArrayType>(at))
574 if (astContext.getConstantArrayElementCount(cat) == 0)
575 return true;
576 }
577
578 if (const auto *rd = t->getAsRecordDecl())
579 return isZeroInitializable(rd);
580
581 if (t->getAs<MemberPointerType>()) {
582 cgm.errorNYI(SourceLocation(), "isZeroInitializable for MemberPointerType",
583 t);
584 return false;
585 }
586
587 return true;
588}
589
593
594const CIRGenFunctionInfo &
597 RequiredArgs required) {
598 assert(llvm::all_of(argTypes,
599 [](CanQualType t) { return t.isCanonicalAsParam(); }));
600 // Lookup or create unique function info.
601 llvm::FoldingSetNodeID id;
602 CIRGenFunctionInfo::Profile(id, required, returnType, argTypes);
603
604 void *insertPos = nullptr;
605 CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos);
606 if (fi) {
607 // We found a matching function info based on id. These asserts verify that
608 // it really is a match.
609 assert(
610 fi->getReturnType() == returnType &&
611 std::equal(fi->argTypesBegin(), fi->argTypesEnd(), argTypes.begin()) &&
612 "Bad match based on CIRGenFunctionInfo folding set id");
613 return *fi;
614 }
615
617
618 // Construction the function info. We co-allocate the ArgInfos.
619 fi = CIRGenFunctionInfo::create(returnType, argTypes, required);
620 functionInfos.InsertNode(fi, insertPos);
621
622 return *fi;
623}
624
626 assert(!dyn_cast<ObjCMethodDecl>(gd.getDecl()) &&
627 "This is reported as a FIXME in LLVM codegen");
628 const auto *fd = cast<FunctionDecl>(gd.getDecl());
629
633
635}
636
637// When we find the full definition for a TagDecl, replace the 'opaque' type we
638// previously made for it if applicable.
640 // If this is an enum being completed, then we flush all non-struct types
641 // from the cache. This allows function types and other things that may be
642 // derived from the enum to be recomputed.
643 if (const auto *ed = dyn_cast<EnumDecl>(td)) {
644 // Classic codegen clears the type cache if it contains an entry for this
645 // enum type that doesn't use i32 as the underlying type, but I can't find
646 // a test case that meets that condition. C++ doesn't allow forward
647 // declaration of enums, and C doesn't allow an incomplete forward
648 // declaration with a non-default type.
649 assert(
650 !typeCache.count(
651 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
652 (convertType(ed->getIntegerType()) ==
653 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
654 // If necessary, provide the full definition of a type only used with a
655 // declaration so far.
657 return;
658 }
659
660 // If we completed a RecordDecl that we previously used and converted to an
661 // anonymous type, then go ahead and complete it now.
662 const auto *rd = cast<RecordDecl>(td);
663 if (rd->isDependentType())
664 return;
665
666 // Only complete if we converted it already. If we haven't converted it yet,
667 // we'll just do it lazily.
668 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
670
671 // If necessary, provide the full definition of a type only used with a
672 // declaration so far.
674}
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:4312
field_range fields() const
Definition Decl.h:4515
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition Decl.h:4496
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:25
@ 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.