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"
11
12#include <cassert>
13
14using namespace clang;
15using namespace clang::CIRGen;
16
18 : cgm(genModule), astContext(genModule.getASTContext()),
19 builder(cgm.getBuilder()), theCXXABI(cgm.getCXXABI()),
20 theABIInfo(cgm.getTargetCIRGenInfo().getABIInfo()) {}
21
23 for (auto i = functionInfos.begin(), e = functionInfos.end(); i != e;)
24 delete &*i++;
25}
26
27mlir::MLIRContext &CIRGenTypes::getMLIRContext() const {
28 return *builder.getContext();
29}
30
31/// Return true if the specified type in a function parameter or result position
32/// can be converted to a CIR type at this point. This boils down to being
33/// whether it is complete, as well as whether we've temporarily deferred
34/// expanding the type because we're in a recursive context.
36 // Some ABIs cannot have their member pointers represented in LLVM IR unless
37 // certain circumstances have been reached, but in CIR we represent member
38 // pointer types abstractly at this point so they are always convertible.
39 if (type->getAs<MemberPointerType>())
40 return true;
41
42 // If this isn't a tag type, we can convert it.
43 const TagType *tagType = type->getAs<TagType>();
44 if (!tagType)
45 return true;
46
47 // Function types involving incomplete class types are problematic in MLIR.
48 return !tagType->isIncompleteType();
49}
50
51/// Code to verify a given function type is complete, i.e. the return type and
52/// all of the parameter types are complete. Also check to see if we are in a
53/// RS_StructPointer context, and if so whether any struct types have been
54/// pended. If so, we don't want to ask the ABI lowering code to handle a type
55/// that cannot be converted to a CIR type.
58 return false;
59
60 if (const auto *fpt = dyn_cast<FunctionProtoType>(ft))
61 for (unsigned i = 0, e = fpt->getNumParams(); i != e; i++)
62 if (!isFuncParamTypeConvertible(fpt->getParamType(i)))
63 return false;
64
65 return true;
66}
67
68mlir::Type CIRGenTypes::convertFunctionTypeInternal(QualType qft) {
69 assert(qft.isCanonical());
71 // First, check whether we can build the full function type. If the function
72 // type depends on an incomplete type (e.g. a struct or enum), we cannot lower
73 // the function type.
74 if (!isFuncTypeConvertible(ft)) {
75 cgm.errorNYI(SourceLocation(), "function type involving an incomplete type",
76 qft);
77 return cir::FuncType::get(SmallVector<mlir::Type, 1>{}, cgm.voidTy);
78 }
79
80 const CIRGenFunctionInfo *fi;
81 if (const auto *fpt = dyn_cast<FunctionProtoType>(ft)) {
84 } else {
85 const FunctionNoProtoType *fnpt = cast<FunctionNoProtoType>(ft);
88 }
89
90 mlir::Type resultType = getFunctionType(*fi);
91
92 return resultType;
93}
94
95// This is CIR's version of CodeGenTypes::addRecordTypeName. It isn't shareable
96// because CIR has different uniquing requirements.
98 StringRef suffix) {
100 llvm::raw_svector_ostream outStream(typeName);
101
102 PrintingPolicy policy = recordDecl->getASTContext().getPrintingPolicy();
106 policy.PrintAsCanonical = true;
107 policy.SuppressTagKeyword = true;
108
109 if (recordDecl->getIdentifier())
110 QualType(astContext.getCanonicalTagType(recordDecl))
111 .print(outStream, policy);
112 else if (auto *typedefNameDecl = recordDecl->getTypedefNameForAnonDecl())
113 typedefNameDecl->printQualifiedName(outStream, policy);
114 else
115 outStream << builder.getUniqueAnonRecordName();
116
117 if (!suffix.empty())
118 outStream << suffix;
119
120 return builder.getUniqueRecordName(std::string(typeName));
121}
122
123/// Return true if the specified type is already completely laid out.
125 const auto it = recordDeclTypes.find(ty);
126 return it != recordDeclTypes.end() && it->second.isComplete();
127}
128
129// We have multiple forms of this function that call each other, so we need to
130// declare one in advance.
131static bool
133 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);
134
135/// Return true if it is safe to convert the specified record decl to CIR and
136/// lay it out, false if doing so would cause us to get into a recursive
137/// compilation mess.
138static bool
140 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
141 // If we have already checked this type (maybe the same type is used by-value
142 // multiple times in multiple record fields, don't check again.
143 if (!alreadyChecked.insert(rd).second)
144 return true;
145
146 assert(rd->isCompleteDefinition() &&
147 "Expect RecordDecl to be CompleteDefinition");
148 const Type *key = cgt.getASTContext().getCanonicalTagType(rd).getTypePtr();
149
150 // If this type is already laid out, converting it is a noop.
151 if (cgt.isRecordLayoutComplete(key))
152 return true;
153
154 // If this type is currently being laid out, we can't recursively compile it.
155 if (cgt.isRecordBeingLaidOut(key))
156 return false;
157
158 // If this type would require laying out bases that are currently being laid
159 // out, don't do it. This includes virtual base classes which get laid out
160 // when a class is translated, even though they aren't embedded by-value into
161 // the class.
162 if (const CXXRecordDecl *crd = dyn_cast<CXXRecordDecl>(rd)) {
163 for (const clang::CXXBaseSpecifier &i : crd->bases())
164 if (!isSafeToConvert(i.getType()
165 ->castAs<RecordType>()
166 ->getDecl()
167 ->getDefinitionOrSelf(),
168 cgt, alreadyChecked))
169 return false;
170 }
171
172 // If this type would require laying out members that are currently being laid
173 // out, don't do it.
174 for (const FieldDecl *field : rd->fields())
175 if (!isSafeToConvert(field->getType(), cgt, alreadyChecked))
176 return false;
177
178 // If there are no problems, lets do it.
179 return true;
180}
181
182/// Return true if it is safe to convert this field type, which requires the
183/// record elements contained by-value to all be recursively safe to convert.
184static bool
186 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
187 // Strip off atomic type sugar.
188 if (const auto *at = qt->getAs<AtomicType>())
189 qt = at->getValueType();
190
191 // If this is a record, check it.
192 if (const auto *rd = qt->getAsRecordDecl())
193 return isSafeToConvert(rd, cgt, alreadyChecked);
194
195 // If this is an array, check the elements, which are embedded inline.
196 if (const auto *at = cgt.getASTContext().getAsArrayType(qt))
197 return isSafeToConvert(at->getElementType(), cgt, alreadyChecked);
198
199 // Otherwise, there is no concern about transforming this. We only care about
200 // things that are contained by-value in a record that can have another
201 // record as a member.
202 return true;
203}
204
205// Return true if it is safe to convert the specified record decl to CIR and lay
206// it out, false if doing so would cause us to get into a recursive compilation
207// mess.
208static bool isSafeToConvert(const RecordDecl *rd, CIRGenTypes &cgt) {
209 // If no records are being laid out, we can certainly do this one.
210 if (cgt.noRecordsBeingLaidOut())
211 return true;
212
214 return isSafeToConvert(rd, cgt, alreadyChecked);
215}
216
217/// Lay out a tagged decl type like struct or union.
219 // TagDecl's are not necessarily unique, instead use the (clang) type
220 // connected to the decl.
221 const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();
222 cir::RecordType entry = recordDeclTypes[key];
223
224 // If we don't have an entry for this record yet, create one.
225 // We create an incomplete type initially. If `rd` is complete, we will
226 // add the members below.
227 if (!entry) {
228 auto name = getRecordTypeName(rd, "");
229 entry = builder.getIncompleteRecordTy(name, rd);
230 recordDeclTypes[key] = entry;
231 }
232
233 rd = rd->getDefinition();
234 if (!rd || !rd->isCompleteDefinition() || entry.isComplete())
235 return entry;
236
237 // If converting this type would cause us to infinitely loop, don't do it!
238 if (!isSafeToConvert(rd, *this)) {
239 deferredRecords.push_back(rd);
240 return entry;
241 }
242
243 // Okay, this is a definition of a type. Compile the implementation now.
244 bool insertResult = recordsBeingLaidOut.insert(key).second;
245 (void)insertResult;
246 assert(insertResult && "isSafeToCovert() should have caught this.");
247
248 // Force conversion of non-virtual base classes recursively.
249 if (const auto *cxxRecordDecl = dyn_cast<CXXRecordDecl>(rd)) {
250 for (const auto &base : cxxRecordDecl->bases()) {
251 if (base.isVirtual())
252 continue;
253 convertRecordDeclType(base.getType()->castAsRecordDecl());
254 }
255 }
256
257 // Layout fields.
258 std::unique_ptr<CIRGenRecordLayout> layout = computeRecordLayout(rd, &entry);
259 recordDeclTypes[key] = entry;
260 cirGenRecordLayouts[key] = std::move(layout);
261
262 // We're done laying out this record.
263 bool eraseResult = recordsBeingLaidOut.erase(key);
264 (void)eraseResult;
265 assert(eraseResult && "record not in RecordsBeingLaidOut set?");
266
267 // If this record blocked a FunctionType conversion, then recompute whatever
268 // was derived from that.
270
271 // If we're done converting the outer-most record, then convert any deferred
272 // records as well.
273 if (recordsBeingLaidOut.empty())
274 while (!deferredRecords.empty())
275 convertRecordDeclType(deferredRecords.pop_back_val());
276
277 return entry;
278}
279
281 type = astContext.getCanonicalType(type);
282 const Type *ty = type.getTypePtr();
283
284 // Process record types before the type cache lookup.
285 if (const auto *recordType = dyn_cast<RecordType>(type))
286 return convertRecordDeclType(recordType->getDecl()->getDefinitionOrSelf());
287
288 // Has the type already been processed?
289 TypeCacheTy::iterator tci = typeCache.find(ty);
290 if (tci != typeCache.end())
291 return tci->second;
292
293 // For types that haven't been implemented yet or are otherwise unsupported,
294 // report an error and return 'int'.
295
296 mlir::Type resultType = nullptr;
297 switch (ty->getTypeClass()) {
298 case Type::Record:
299 llvm_unreachable("Should have been handled above");
300
301 case Type::Builtin: {
302 switch (cast<BuiltinType>(ty)->getKind()) {
303 // void
304 case BuiltinType::Void:
305 resultType = cgm.voidTy;
306 break;
307
308 // bool
309 case BuiltinType::Bool:
310 resultType = cir::BoolType::get(&getMLIRContext());
311 break;
312
313 // Signed integral types.
314 case BuiltinType::Char_S:
315 case BuiltinType::Int:
316 case BuiltinType::Int128:
317 case BuiltinType::Long:
318 case BuiltinType::LongLong:
319 case BuiltinType::SChar:
320 case BuiltinType::Short:
321 case BuiltinType::WChar_S:
322 resultType =
323 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
324 /*isSigned=*/true);
325 break;
326
327 // SVE types
328 case BuiltinType::SveInt8:
329 resultType =
330 cir::VectorType::get(builder.getSInt8Ty(), 16, /*is_scalable=*/true);
331 break;
332 case BuiltinType::SveUint8:
333 resultType =
334 cir::VectorType::get(builder.getUInt8Ty(), 16, /*is_scalable=*/true);
335 break;
336 case BuiltinType::SveInt16:
337 resultType =
338 cir::VectorType::get(builder.getSInt16Ty(), 8, /*is_scalable=*/true);
339 break;
340 case BuiltinType::SveUint16:
341 resultType =
342 cir::VectorType::get(builder.getUInt16Ty(), 8, /*is_scalable=*/true);
343 break;
344 case BuiltinType::SveFloat16:
345 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
346 /*is_scalable=*/true);
347 break;
348 case BuiltinType::SveBFloat16:
349 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
350 /*is_scalable=*/true);
351 break;
352 case BuiltinType::SveInt32:
353 resultType =
354 cir::VectorType::get(builder.getSInt32Ty(), 4, /*is_scalable=*/true);
355 break;
356 case BuiltinType::SveUint32:
357 resultType =
358 cir::VectorType::get(builder.getUInt32Ty(), 4, /*is_scalable=*/true);
359 break;
360 case BuiltinType::SveFloat32:
361 resultType = cir::VectorType::get(builder.getSingleTy(), 4,
362 /*is_scalable=*/true);
363 break;
364 case BuiltinType::SveInt64:
365 resultType =
366 cir::VectorType::get(builder.getSInt64Ty(), 2, /*is_scalable=*/true);
367 break;
368 case BuiltinType::SveUint64:
369 resultType =
370 cir::VectorType::get(builder.getUInt64Ty(), 2, /*is_scalable=*/true);
371 break;
372 case BuiltinType::SveFloat64:
373 resultType = cir::VectorType::get(builder.getDoubleTy(), 2,
374 /*is_scalable=*/true);
375 break;
376
377 // Unsigned integral types.
378 case BuiltinType::Char8:
379 case BuiltinType::Char16:
380 case BuiltinType::Char32:
381 case BuiltinType::Char_U:
382 case BuiltinType::UChar:
383 case BuiltinType::UInt:
384 case BuiltinType::UInt128:
385 case BuiltinType::ULong:
386 case BuiltinType::ULongLong:
387 case BuiltinType::UShort:
388 case BuiltinType::WChar_U:
389 resultType =
390 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
391 /*isSigned=*/false);
392 break;
393
394 // Floating-point types
395 case BuiltinType::Float16:
396 resultType = cgm.fP16Ty;
397 break;
398 case BuiltinType::Half:
399 if (astContext.getLangOpts().NativeHalfType ||
400 !astContext.getTargetInfo().useFP16ConversionIntrinsics()) {
401 resultType = cgm.fP16Ty;
402 } else {
403 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
404 resultType = cgm.sInt32Ty;
405 }
406 break;
407 case BuiltinType::BFloat16:
408 resultType = cgm.bFloat16Ty;
409 break;
410 case BuiltinType::Float:
411 assert(&astContext.getFloatTypeSemantics(type) ==
412 &llvm::APFloat::IEEEsingle() &&
413 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");
414 resultType = cgm.floatTy;
415 break;
416 case BuiltinType::Double:
417 assert(&astContext.getFloatTypeSemantics(type) ==
418 &llvm::APFloat::IEEEdouble() &&
419 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");
420 resultType = cgm.doubleTy;
421 break;
422 case BuiltinType::LongDouble:
423 resultType =
424 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(type));
425 break;
426 case BuiltinType::Float128:
427 resultType = cgm.fP128Ty;
428 break;
429 case BuiltinType::Ibm128:
430 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
431 resultType = cgm.sInt32Ty;
432 break;
433
434 case BuiltinType::NullPtr:
435 // Add proper CIR type for it? this looks mostly useful for sema related
436 // things (like for overloads accepting void), for now, given that
437 // `sizeof(std::nullptr_t)` is equal to `sizeof(void *)`, model
438 // std::nullptr_t as !cir.ptr<!void>
439 resultType = builder.getVoidPtrTy();
440 break;
441
442 default:
443 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
444 resultType = cgm.sInt32Ty;
445 break;
446 }
447 break;
448 }
449
450 case Type::Complex: {
451 const auto *ct = cast<clang::ComplexType>(ty);
452 mlir::Type elementTy = convertType(ct->getElementType());
453 resultType = cir::ComplexType::get(elementTy);
454 break;
455 }
456
457 case Type::LValueReference:
458 case Type::RValueReference: {
459 const ReferenceType *refTy = cast<ReferenceType>(ty);
460 QualType elemTy = refTy->getPointeeType();
461 auto pointeeType = convertTypeForMem(elemTy);
462 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
463 assert(resultType && "Cannot get pointer type?");
464 break;
465 }
466
467 case Type::Pointer: {
468 const PointerType *ptrTy = cast<PointerType>(ty);
469 QualType elemTy = ptrTy->getPointeeType();
470 assert(!elemTy->isConstantMatrixType() && "not implemented");
471
472 mlir::Type pointeeType = convertType(elemTy);
473
474 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
475 break;
476 }
477
478 case Type::VariableArray: {
480 if (a->getIndexTypeCVRQualifiers() != 0)
481 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
482 // VLAs resolve to the innermost element type; this matches
483 // the return of alloca, and there isn't any obviously better choice.
484 resultType = convertTypeForMem(a->getElementType());
485 break;
486 }
487
488 case Type::IncompleteArray: {
490 if (arrTy->getIndexTypeCVRQualifiers() != 0)
491 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
492
493 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
494 // int X[] -> [0 x int], unless the element type is not sized. If it is
495 // unsized (e.g. an incomplete record) just use [0 x i8].
496 if (!cir::isSized(elemTy)) {
497 elemTy = cgm.sInt8Ty;
498 }
499
500 resultType = cir::ArrayType::get(elemTy, 0);
501 break;
502 }
503
504 case Type::ConstantArray: {
506 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
507
508 // TODO(CIR): In LLVM, "lower arrays of undefined struct type to arrays of
509 // i8 just to have a concrete type"
510 if (!cir::isSized(elemTy)) {
511 cgm.errorNYI(SourceLocation(), "arrays of undefined struct type", type);
512 resultType = cgm.uInt32Ty;
513 break;
514 }
515
516 resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue());
517 break;
518 }
519
520 case Type::ExtVector:
521 case Type::Vector: {
522 const VectorType *vec = cast<VectorType>(ty);
523 const mlir::Type elemTy = convertType(vec->getElementType());
524 resultType = cir::VectorType::get(elemTy, vec->getNumElements());
525 break;
526 }
527
528 case Type::Enum: {
529 const auto *ed = ty->castAsEnumDecl();
530 if (auto integerType = ed->getIntegerType(); !integerType.isNull())
531 return convertType(integerType);
532 // Return a placeholder 'i32' type. This can be changed later when the
533 // type is defined (see UpdateCompletedType), but is likely to be the
534 // "right" answer.
535 resultType = cgm.uInt32Ty;
536 break;
537 }
538
539 case Type::MemberPointer: {
540 const auto *mpt = cast<MemberPointerType>(ty);
541
542 mlir::Type memberTy = convertType(mpt->getPointeeType());
543 auto clsTy = mlir::cast<cir::RecordType>(
544 convertType(QualType(mpt->getQualifier().getAsType(), 0)));
545 if (mpt->isMemberDataPointer()) {
546 resultType = cir::DataMemberType::get(memberTy, clsTy);
547 } else {
549 cgm.errorNYI(SourceLocation(), "MethodType");
550 }
551 break;
552 }
553
554 case Type::FunctionNoProto:
555 case Type::FunctionProto:
556 resultType = convertFunctionTypeInternal(type);
557 break;
558
559 case Type::BitInt: {
560 const auto *bitIntTy = cast<BitIntType>(type);
561 if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {
562 cgm.errorNYI(SourceLocation(), "large _BitInt type", type);
563 resultType = cgm.sInt32Ty;
564 } else {
565 resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(),
566 bitIntTy->isSigned());
567 }
568 break;
569 }
570
571 case Type::Atomic: {
572 QualType valueType = cast<AtomicType>(ty)->getValueType();
573 resultType = convertTypeForMem(valueType);
574
575 // Pad out to the inflated size if necessary.
576 uint64_t valueSize = astContext.getTypeSize(valueType);
577 uint64_t atomicSize = astContext.getTypeSize(ty);
578 if (valueSize != atomicSize) {
579 cgm.errorNYI("convertType: atomic type value size != atomic size");
580 }
581
582 break;
583 }
584
585 default:
586 cgm.errorNYI(SourceLocation(), "processing of type",
587 type->getTypeClassName());
588 resultType = cgm.sInt32Ty;
589 break;
590 }
591
592 assert(resultType && "Type conversion not yet implemented");
593
594 typeCache[ty] = resultType;
595 return resultType;
596}
597
599 bool forBitField) {
600 assert(!qualType->isConstantMatrixType() && "Matrix types NYI");
601
602 mlir::Type convertedType = convertType(qualType);
603
604 assert(!forBitField && "Bit fields NYI");
605
606 // If this is a bit-precise integer type in a bitfield representation, map
607 // this integer to the target-specified size.
608 if (forBitField && qualType->isBitIntType())
609 assert(!qualType->isBitIntType() && "Bit field with type _BitInt NYI");
610
611 return convertedType;
612}
613
614/// Return record layout info for the given record decl.
615const CIRGenRecordLayout &
617 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
618
619 // If we have already computed the layout, return it.
620 auto it = cirGenRecordLayouts.find(key);
621 if (it != cirGenRecordLayouts.end())
622 return *it->second;
623
624 // Compute the type information.
626
627 // Now try again.
628 it = cirGenRecordLayouts.find(key);
629
630 assert(it != cirGenRecordLayouts.end() &&
631 "Unable to find record layout information for type");
632 return *it->second;
633}
634
636 if (t->getAs<PointerType>())
637 return astContext.getTargetNullPointerValue(t) == 0;
638
639 if (const auto *at = astContext.getAsArrayType(t)) {
641 return true;
642
643 if (const auto *cat = dyn_cast<ConstantArrayType>(at))
644 if (astContext.getConstantArrayElementCount(cat) == 0)
645 return true;
646 }
647
648 if (const auto *rd = t->getAsRecordDecl())
649 return isZeroInitializable(rd);
650
651 if (t->getAs<MemberPointerType>()) {
652 cgm.errorNYI(SourceLocation(), "isZeroInitializable for MemberPointerType",
653 t);
654 return false;
655 }
656
657 return true;
658}
659
663
664const CIRGenFunctionInfo &
667 RequiredArgs required) {
668 assert(llvm::all_of(argTypes,
669 [](CanQualType t) { return t.isCanonicalAsParam(); }));
670 // Lookup or create unique function info.
671 llvm::FoldingSetNodeID id;
672 CIRGenFunctionInfo::Profile(id, required, returnType, argTypes);
673
674 void *insertPos = nullptr;
675 CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos);
676 if (fi) {
677 // We found a matching function info based on id. These asserts verify that
678 // it really is a match.
679 assert(
680 fi->getReturnType() == returnType &&
681 std::equal(fi->argTypesBegin(), fi->argTypesEnd(), argTypes.begin()) &&
682 "Bad match based on CIRGenFunctionInfo folding set id");
683 return *fi;
684 }
685
687
688 // Construction the function info. We co-allocate the ArgInfos.
689 fi = CIRGenFunctionInfo::create(returnType, argTypes, required);
690 functionInfos.InsertNode(fi, insertPos);
691
692 return *fi;
693}
694
696 assert(!dyn_cast<ObjCMethodDecl>(gd.getDecl()) &&
697 "This is reported as a FIXME in LLVM codegen");
698 const auto *fd = cast<FunctionDecl>(gd.getDecl());
699
703
705}
706
707// When we find the full definition for a TagDecl, replace the 'opaque' type we
708// previously made for it if applicable.
710 // If this is an enum being completed, then we flush all non-struct types
711 // from the cache. This allows function types and other things that may be
712 // derived from the enum to be recomputed.
713 if (const auto *ed = dyn_cast<EnumDecl>(td)) {
714 // Classic codegen clears the type cache if it contains an entry for this
715 // enum type that doesn't use i32 as the underlying type, but I can't find
716 // a test case that meets that condition. C++ doesn't allow forward
717 // declaration of enums, and C doesn't allow an incomplete forward
718 // declaration with a non-default type.
719 assert(
720 !typeCache.count(
721 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
722 (convertType(ed->getIntegerType()) ==
723 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
724 // If necessary, provide the full definition of a type only used with a
725 // declaration so far.
727 return;
728 }
729
730 // If we completed a RecordDecl that we previously used and converted to an
731 // anonymous type, then go ahead and complete it now.
732 const auto *rd = cast<RecordDecl>(td);
733 if (rd->isDependentType())
734 return;
735
736 // Only complete if we converted it already. If we haven't converted it yet,
737 // we'll just do it lazily.
738 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
740
741 // If necessary, provide the full definition of a type only used with a
742 // declaration so far.
744}
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:3735
unsigned getIndexTypeCVRQualifiers() const
Definition TypeBase.h:3745
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:3761
llvm::APInt getSize() const
Return the constant array size as an APInt.
Definition TypeBase.h:3817
Represents a member of a struct/union/class.
Definition Decl.h:3160
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4465
QualType getReturnType() const
Definition TypeBase.h:4805
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:3910
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3654
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3329
QualType getPointeeType() const
Definition TypeBase.h:3339
A (possibly-)qualified type.
Definition TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8293
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8419
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
bool isCanonical() const
Definition TypeBase.h:8350
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:3574
QualType getPointeeType() const
Definition TypeBase.h:3592
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:8697
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:9112
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:3967
Represents a GCC generic vector type.
Definition TypeBase.h:4176
unsigned getNumElements() const
Definition TypeBase.h:4191
QualType getElementType() const
Definition TypeBase.h:4190
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.