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