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