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
509 // TODO(CIR): In LLVM, "lower arrays of undefined struct type to arrays of
510 // i8 just to have a concrete type"
511 if (!cir::isSized(elemTy)) {
512 cgm.errorNYI(SourceLocation(), "arrays of undefined struct type", type);
513 resultType = cgm.uInt32Ty;
514 break;
515 }
516
517 resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue());
518 break;
519 }
520
521 case Type::ExtVector:
522 case Type::Vector: {
523 const VectorType *vec = cast<VectorType>(ty);
524 const mlir::Type elemTy = convertType(vec->getElementType());
525 resultType = cir::VectorType::get(elemTy, vec->getNumElements());
526 break;
527 }
528
529 case Type::Enum: {
530 const auto *ed = ty->castAsEnumDecl();
531 if (auto integerType = ed->getIntegerType(); !integerType.isNull())
532 return convertType(integerType);
533 // Return a placeholder 'i32' type. This can be changed later when the
534 // type is defined (see UpdateCompletedType), but is likely to be the
535 // "right" answer.
536 resultType = cgm.uInt32Ty;
537 break;
538 }
539
540 case Type::MemberPointer: {
541 const auto *mpt = cast<MemberPointerType>(ty);
542
543 mlir::Type memberTy = convertType(mpt->getPointeeType());
544 auto clsTy = mlir::cast<cir::RecordType>(
545 convertType(QualType(mpt->getQualifier().getAsType(), 0)));
546 if (mpt->isMemberDataPointer()) {
547 resultType = cir::DataMemberType::get(memberTy, clsTy);
548 } else {
549 auto memberFuncTy = mlir::cast<cir::FuncType>(memberTy);
550 resultType = cir::MethodType::get(memberFuncTy, clsTy);
551 }
552 break;
553 }
554
555 case Type::FunctionNoProto:
556 case Type::FunctionProto:
557 resultType = convertFunctionTypeInternal(type);
558 break;
559
560 case Type::BitInt: {
561 const auto *bitIntTy = cast<BitIntType>(type);
562 if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {
563 cgm.errorNYI(SourceLocation(), "large _BitInt type", type);
564 resultType = cgm.sInt32Ty;
565 } else {
566 resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(),
567 bitIntTy->isSigned());
568 }
569 break;
570 }
571
572 case Type::Atomic: {
573 QualType valueType = cast<AtomicType>(ty)->getValueType();
574 resultType = convertTypeForMem(valueType);
575
576 // Pad out to the inflated size if necessary.
577 uint64_t valueSize = astContext.getTypeSize(valueType);
578 uint64_t atomicSize = astContext.getTypeSize(ty);
579 if (valueSize != atomicSize) {
580 cgm.errorNYI("convertType: atomic type value size != atomic size");
581 }
582
583 break;
584 }
585
586 default:
587 cgm.errorNYI(SourceLocation(), "processing of type",
588 type->getTypeClassName());
589 resultType = cgm.sInt32Ty;
590 break;
591 }
592
593 assert(resultType && "Type conversion not yet implemented");
594
595 typeCache[ty] = resultType;
596 return resultType;
597}
598
600 bool forBitField) {
601 assert(!qualType->isConstantMatrixType() && "Matrix types NYI");
602
603 mlir::Type convertedType = convertType(qualType);
604
605 assert(!forBitField && "Bit fields NYI");
606
607 // If this is a bit-precise integer type in a bitfield representation, map
608 // this integer to the target-specified size.
609 if (forBitField && qualType->isBitIntType())
610 assert(!qualType->isBitIntType() && "Bit field with type _BitInt NYI");
611
612 return convertedType;
613}
614
615/// Return record layout info for the given record decl.
616const CIRGenRecordLayout &
618 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
619
620 // If we have already computed the layout, return it.
621 auto it = cirGenRecordLayouts.find(key);
622 if (it != cirGenRecordLayouts.end())
623 return *it->second;
624
625 // Compute the type information.
627
628 // Now try again.
629 it = cirGenRecordLayouts.find(key);
630
631 assert(it != cirGenRecordLayouts.end() &&
632 "Unable to find record layout information for type");
633 return *it->second;
634}
635
637 if (t->getAs<PointerType>())
638 return astContext.getTargetNullPointerValue(t) == 0;
639
640 if (const auto *at = astContext.getAsArrayType(t)) {
642 return true;
643
644 if (const auto *cat = dyn_cast<ConstantArrayType>(at))
645 if (astContext.getConstantArrayElementCount(cat) == 0)
646 return true;
647 }
648
649 if (const auto *rd = t->getAsRecordDecl())
650 return isZeroInitializable(rd);
651
652 if (t->getAs<MemberPointerType>()) {
653 cgm.errorNYI(SourceLocation(), "isZeroInitializable for MemberPointerType",
654 t);
655 return false;
656 }
657
658 return true;
659}
660
664
665const CIRGenFunctionInfo &
668 RequiredArgs required) {
669 assert(llvm::all_of(argTypes,
670 [](CanQualType t) { return t.isCanonicalAsParam(); }));
671 // Lookup or create unique function info.
672 llvm::FoldingSetNodeID id;
673 CIRGenFunctionInfo::Profile(id, required, returnType, argTypes);
674
675 void *insertPos = nullptr;
676 CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos);
677 if (fi) {
678 // We found a matching function info based on id. These asserts verify that
679 // it really is a match.
680 assert(
681 fi->getReturnType() == returnType &&
682 std::equal(fi->argTypesBegin(), fi->argTypesEnd(), argTypes.begin()) &&
683 "Bad match based on CIRGenFunctionInfo folding set id");
684 return *fi;
685 }
686
688
689 // Construction the function info. We co-allocate the ArgInfos.
690 fi = CIRGenFunctionInfo::create(returnType, argTypes, required);
691 functionInfos.InsertNode(fi, insertPos);
692
693 return *fi;
694}
695
697 assert(!dyn_cast<ObjCMethodDecl>(gd.getDecl()) &&
698 "This is reported as a FIXME in LLVM codegen");
699 const auto *fd = cast<FunctionDecl>(gd.getDecl());
700
704
706}
707
708// When we find the full definition for a TagDecl, replace the 'opaque' type we
709// previously made for it if applicable.
711 // If this is an enum being completed, then we flush all non-struct types
712 // from the cache. This allows function types and other things that may be
713 // derived from the enum to be recomputed.
714 if ([[maybe_unused]] const auto *ed = dyn_cast<EnumDecl>(td)) {
715 // Classic codegen clears the type cache if it contains an entry for this
716 // enum type that doesn't use i32 as the underlying type, but I can't find
717 // a test case that meets that condition. C++ doesn't allow forward
718 // declaration of enums, and C doesn't allow an incomplete forward
719 // declaration with a non-default type.
720 assert(
721 !typeCache.count(
722 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
723 (convertType(ed->getIntegerType()) ==
724 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
725 // If necessary, provide the full definition of a type only used with a
726 // declaration so far.
728 return;
729 }
730
731 // If we completed a RecordDecl that we previously used and converted to an
732 // anonymous type, then go ahead and complete it now.
733 const auto *rd = cast<RecordDecl>(td);
734 if (rd->isDependentType())
735 return;
736
737 // Only complete if we converted it already. If we haven't converted it yet,
738 // we'll just do it lazily.
739 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
741
742 // If necessary, provide the full definition of a type only used with a
743 // declaration so far.
745}
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: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.