clang 23.0.0git
CIRGenTypes.cpp
Go to the documentation of this file.
1#include "CIRGenTypes.h"
2
3#include "CIRGenCXXABI.h"
5#include "CIRGenModule.h"
6#include "mlir/IR/BuiltinTypes.h"
7
10#include "clang/AST/Type.h"
13
14#include <cassert>
15
16using namespace clang;
17using namespace clang::CIRGen;
18
20 : cgm(genModule), astContext(genModule.getASTContext()),
21 builder(cgm.getBuilder()), theCXXABI(cgm.getCXXABI()),
22 theABIInfo(cgm.getTargetCIRGenInfo().getABIInfo()) {}
23
25 for (auto i = functionInfos.begin(), e = functionInfos.end(); i != e;)
26 delete &*i++;
27}
28
29mlir::MLIRContext &CIRGenTypes::getMLIRContext() const {
30 return *builder.getContext();
31}
32
33/// Return true if the specified type in a function parameter or result position
34/// can be converted to a CIR type at this point. This boils down to being
35/// whether it is complete, as well as whether we've temporarily deferred
36/// expanding the type because we're in a recursive context.
38 // Some ABIs cannot have their member pointers represented in LLVM IR unless
39 // certain circumstances have been reached, but in CIR we represent member
40 // pointer types abstractly at this point so they are always convertible.
41 if (type->getAs<MemberPointerType>())
42 return true;
43
44 // If this isn't a tag type, we can convert it.
45 const TagType *tagType = type->getAs<TagType>();
46 if (!tagType)
47 return true;
48
49 // Function types involving incomplete class types are problematic in MLIR.
50 return !tagType->isIncompleteType();
51}
52
53/// Code to verify a given function type is complete, i.e. the return type and
54/// all of the parameter types are complete. Also check to see if we are in a
55/// RS_StructPointer context, and if so whether any struct types have been
56/// pended. If so, we don't want to ask the ABI lowering code to handle a type
57/// that cannot be converted to a CIR type.
60 return false;
61
62 if (const auto *fpt = dyn_cast<FunctionProtoType>(ft))
63 for (unsigned i = 0, e = fpt->getNumParams(); i != e; i++)
64 if (!isFuncParamTypeConvertible(fpt->getParamType(i)))
65 return false;
66
67 return true;
68}
69
70mlir::Type CIRGenTypes::convertFunctionTypeInternal(QualType qft) {
71 assert(qft.isCanonical());
73
74 // In classic codegen, if the function type depends on an incomplete type
75 // (e.g. a struct or enum), it cannot lower the function type due to ABI
76 // handling requirements and returns a placeholder. In CIR, ABI handling is
77 // deferred until after codegen, and record types are identified by name, so
78 // incomplete record type references in the function type will automatically
79 // see the complete type once the record is defined. We can always produce a
80 // proper function type here.
81
82 const CIRGenFunctionInfo *fi;
83 if (const auto *fpt = dyn_cast<FunctionProtoType>(ft)) {
86 } else {
90 }
91
92 mlir::Type resultType = getFunctionType(*fi);
93
94 return resultType;
95}
96
97// This is CIR's version of CodeGenTypes::addRecordTypeName. It isn't shareable
98// because CIR has different uniquing requirements.
100 StringRef suffix) {
101 llvm::SmallString<256> typeName;
102 llvm::raw_svector_ostream outStream(typeName);
103
104 PrintingPolicy policy = recordDecl->getASTContext().getPrintingPolicy();
108 policy.PrintAsCanonical = true;
109 policy.SuppressTagKeyword = true;
110
111 if (recordDecl->getIdentifier())
112 QualType(astContext.getCanonicalTagType(recordDecl))
113 .print(outStream, policy);
114 else if (auto *typedefNameDecl = recordDecl->getTypedefNameForAnonDecl())
115 typedefNameDecl->printQualifiedName(outStream, policy);
116 else
117 outStream << builder.getUniqueAnonRecordName();
118
119 if (!suffix.empty())
120 outStream << suffix;
121
122 return builder.getUniqueRecordName(std::string(typeName));
123}
124
125/// Return true if the specified type is already completely laid out.
127 const auto it = recordDeclTypes.find(ty);
128 return it != recordDeclTypes.end() && it->second.isComplete();
129}
130
131// We have multiple forms of this function that call each other, so we need to
132// declare one in advance.
133static bool
135 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);
136
137/// Return true if it is safe to convert the specified record decl to CIR and
138/// lay it out, false if doing so would cause us to get into a recursive
139/// compilation mess.
140static bool
142 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
143 // If we have already checked this type (maybe the same type is used by-value
144 // multiple times in multiple record fields, don't check again.
145 if (!alreadyChecked.insert(rd).second)
146 return true;
147
148 assert(rd->isCompleteDefinition() &&
149 "Expect RecordDecl to be CompleteDefinition");
150 const Type *key = cgt.getASTContext().getCanonicalTagType(rd).getTypePtr();
151
152 // If this type is already laid out, converting it is a noop.
153 if (cgt.isRecordLayoutComplete(key))
154 return true;
155
156 // Check the cross-call cache. This avoids redundant recursive field walks
157 // for the same record types across different convertRecordDeclType calls
158 // during a single layout phase.
159 if (cgt.isCachedSafeToConvert(key))
160 return true;
161
162 // If this type is currently being laid out, we can't recursively compile it.
163 if (cgt.isRecordBeingLaidOut(key))
164 return false;
165
166 // If this type would require laying out bases that are currently being laid
167 // out, don't do it. This includes virtual base classes which get laid out
168 // when a class is translated, even though they aren't embedded by-value into
169 // the class.
170 if (const CXXRecordDecl *crd = dyn_cast<CXXRecordDecl>(rd)) {
171 for (const clang::CXXBaseSpecifier &i : crd->bases())
172 if (!isSafeToConvert(i.getType()
173 ->castAs<RecordType>()
174 ->getDecl()
175 ->getDefinitionOrSelf(),
176 cgt, alreadyChecked))
177 return false;
178 }
179
180 // If this type would require laying out members that are currently being laid
181 // out, don't do it.
182 for (const FieldDecl *field : rd->fields())
183 if (!isSafeToConvert(field->getType(), cgt, alreadyChecked))
184 return false;
185
186 // Cache the positive result. This will be cleared when recordsBeingLaidOut
187 // changes.
188 cgt.cacheSafeToConvert(key);
189
190 // If there are no problems, lets do it.
191 return true;
192}
193
194/// Return true if it is safe to convert this field type, which requires the
195/// record elements contained by-value to all be recursively safe to convert.
196static bool
198 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
199 // Strip off atomic type sugar.
200 if (const auto *at = qt->getAs<AtomicType>())
201 qt = at->getValueType();
202
203 // If this is a record, check it.
204 if (const auto *rd = qt->getAsRecordDecl())
205 return isSafeToConvert(rd, cgt, alreadyChecked);
206
207 // If this is an array, check the elements, which are embedded inline.
208 if (const auto *at = cgt.getASTContext().getAsArrayType(qt))
209 return isSafeToConvert(at->getElementType(), cgt, alreadyChecked);
210
211 // Otherwise, there is no concern about transforming this. We only care about
212 // things that are contained by-value in a record that can have another
213 // record as a member.
214 return true;
215}
216
217// Return true if it is safe to convert the specified record decl to CIR and lay
218// it out, false if doing so would cause us to get into a recursive compilation
219// mess.
220static bool isSafeToConvert(const RecordDecl *rd, CIRGenTypes &cgt) {
221 // If no records are being laid out, we can certainly do this one.
222 if (cgt.noRecordsBeingLaidOut())
223 return true;
224
226 return isSafeToConvert(rd, cgt, alreadyChecked);
227}
228
232
234 return astContext.getTypeSize(type) !=
235 astContext.getTypeSize(type->getValueType());
236}
237
238/// Lay out a tagged decl type like struct or union.
240 // TagDecl's are not necessarily unique, instead use the (clang) type
241 // connected to the decl.
242 const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();
243 cir::RecordType entry = recordDeclTypes[key];
244
245 // If we don't have an entry for this record yet, create one.
246 // We create an incomplete type initially. If `rd` is complete, we will
247 // add the members below.
248 if (!entry) {
249 auto name = getRecordTypeName(rd, "");
250 entry = builder.getIncompleteRecordTy(name, rd);
251 recordDeclTypes[key] = entry;
252 }
253
254 rd = rd->getDefinition();
255 if (!rd || !rd->isCompleteDefinition() || entry.isComplete())
256 return entry;
257
258 // If converting this type would cause us to infinitely loop, don't do it!
259 if (!isSafeToConvert(rd, *this)) {
260 deferredRecords.push_back(rd);
261 return entry;
262 }
263
264 // Okay, this is a definition of a type. Compile the implementation now.
265 bool insertResult = recordsBeingLaidOut.insert(key).second;
266 (void)insertResult;
267 assert(insertResult && "isSafeToCovert() should have caught this.");
268
269 // Invalidate the safety cache since recordsBeingLaidOut changed.
270 safeToConvertCache.clear();
271
272 // Force conversion of non-virtual base classes recursively.
273 if (const auto *cxxRecordDecl = dyn_cast<CXXRecordDecl>(rd)) {
274 for (const auto &base : cxxRecordDecl->bases()) {
275 if (base.isVirtual())
276 continue;
277 convertRecordDeclType(base.getType()->castAsRecordDecl());
278 }
279 }
280
281 // Layout fields.
282 std::unique_ptr<CIRGenRecordLayout> layout = computeRecordLayout(rd, &entry);
283 recordDeclTypes[key] = entry;
284 cirGenRecordLayouts[key] = std::move(layout);
285
286 // We're done laying out this record.
287 bool eraseResult = recordsBeingLaidOut.erase(key);
288 (void)eraseResult;
289 assert(eraseResult && "record not in RecordsBeingLaidOut set?");
290
291 // Invalidate the safety cache since recordsBeingLaidOut changed.
292 safeToConvertCache.clear();
293
294 // If we're done converting the outer-most record, then convert any deferred
295 // records as well.
296 if (recordsBeingLaidOut.empty())
297 while (!deferredRecords.empty())
298 convertRecordDeclType(deferredRecords.pop_back_val());
299
300 return entry;
301}
302
304 type = astContext.getCanonicalType(type);
305 const Type *ty = type.getTypePtr();
306
307 // Process record types before the type cache lookup.
308 if (const auto *recordType = dyn_cast<RecordType>(type))
309 return convertRecordDeclType(recordType->getDecl()->getDefinitionOrSelf());
310
311 // Has the type already been processed?
312 TypeCacheTy::iterator tci = typeCache.find(ty);
313 if (tci != typeCache.end())
314 return tci->second;
315
316 // For types that haven't been implemented yet or are otherwise unsupported,
317 // report an error and return 'int'.
318
319 mlir::Type resultType = nullptr;
320 switch (ty->getTypeClass()) {
321 case Type::Record:
322 llvm_unreachable("Should have been handled above");
323
324 case Type::Builtin: {
325 switch (cast<BuiltinType>(ty)->getKind()) {
326 // void
327 case BuiltinType::Void:
328 resultType = cgm.voidTy;
329 break;
330
331 // bool
332 case BuiltinType::Bool:
333 resultType = cir::BoolType::get(&getMLIRContext());
334 break;
335
336 // Signed integral types.
337 case BuiltinType::Char_S:
338 case BuiltinType::Int:
339 case BuiltinType::Int128:
340 case BuiltinType::Long:
341 case BuiltinType::LongLong:
342 case BuiltinType::SChar:
343 case BuiltinType::Short:
344 case BuiltinType::WChar_S:
345 case BuiltinType::Accum:
346 case BuiltinType::Fract:
347 case BuiltinType::LongAccum:
348 case BuiltinType::LongFract:
349 case BuiltinType::ShortAccum:
350 case BuiltinType::ShortFract:
351 // Saturated signed types.
352 case BuiltinType::SatAccum:
353 case BuiltinType::SatFract:
354 case BuiltinType::SatLongAccum:
355 case BuiltinType::SatLongFract:
356 case BuiltinType::SatShortAccum:
357 case BuiltinType::SatShortFract:
358 resultType =
359 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
360 /*isSigned=*/true);
361 break;
362
363 // SVE types
364 case BuiltinType::SveInt8:
365 resultType =
366 cir::VectorType::get(builder.getSInt8Ty(), 16, /*is_scalable=*/true);
367 break;
368 case BuiltinType::SveUint8:
369 resultType =
370 cir::VectorType::get(builder.getUInt8Ty(), 16, /*is_scalable=*/true);
371 break;
372 case BuiltinType::SveInt16:
373 resultType =
374 cir::VectorType::get(builder.getSInt16Ty(), 8, /*is_scalable=*/true);
375 break;
376 case BuiltinType::SveUint16:
377 resultType =
378 cir::VectorType::get(builder.getUInt16Ty(), 8, /*is_scalable=*/true);
379 break;
380 case BuiltinType::SveFloat16:
381 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
382 /*is_scalable=*/true);
383 break;
384 case BuiltinType::SveBFloat16:
385 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
386 /*is_scalable=*/true);
387 break;
388 case BuiltinType::SveInt32:
389 resultType =
390 cir::VectorType::get(builder.getSInt32Ty(), 4, /*is_scalable=*/true);
391 break;
392 case BuiltinType::SveUint32:
393 resultType =
394 cir::VectorType::get(builder.getUInt32Ty(), 4, /*is_scalable=*/true);
395 break;
396 case BuiltinType::SveFloat32:
397 resultType = cir::VectorType::get(builder.getSingleTy(), 4,
398 /*is_scalable=*/true);
399 break;
400 case BuiltinType::SveInt64:
401 resultType =
402 cir::VectorType::get(builder.getSInt64Ty(), 2, /*is_scalable=*/true);
403 break;
404 case BuiltinType::SveUint64:
405 resultType =
406 cir::VectorType::get(builder.getUInt64Ty(), 2, /*is_scalable=*/true);
407 break;
408 case BuiltinType::SveFloat64:
409 resultType = cir::VectorType::get(builder.getDoubleTy(), 2,
410 /*is_scalable=*/true);
411 break;
412 case BuiltinType::SveBool:
413 resultType = cir::VectorType::get(builder.getUIntNTy(1), 16,
414 /*is_scalable=*/true);
415 break;
416
417 // Unsigned integral types.
418 case BuiltinType::Char8:
419 case BuiltinType::Char16:
420 case BuiltinType::Char32:
421 case BuiltinType::Char_U:
422 case BuiltinType::UChar:
423 case BuiltinType::UInt:
424 case BuiltinType::UInt128:
425 case BuiltinType::ULong:
426 case BuiltinType::ULongLong:
427 case BuiltinType::UShort:
428 case BuiltinType::WChar_U:
429 case BuiltinType::UAccum:
430 case BuiltinType::UFract:
431 case BuiltinType::ULongAccum:
432 case BuiltinType::ULongFract:
433 case BuiltinType::UShortAccum:
434 case BuiltinType::UShortFract:
435 // Saturated unsigned types.
436 case BuiltinType::SatUAccum:
437 case BuiltinType::SatUFract:
438 case BuiltinType::SatULongAccum:
439 case BuiltinType::SatULongFract:
440 case BuiltinType::SatUShortAccum:
441 case BuiltinType::SatUShortFract:
442 resultType =
443 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
444 /*isSigned=*/false);
445 break;
446
447 // Floating-point types
448 case BuiltinType::Float16:
449 resultType = cgm.fP16Ty;
450 break;
451 case BuiltinType::Half:
452 if (astContext.getLangOpts().NativeHalfType ||
453 !astContext.getTargetInfo().useFP16ConversionIntrinsics()) {
454 resultType = cgm.fP16Ty;
455 } else {
456 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
457 resultType = cgm.sInt32Ty;
458 }
459 break;
460 case BuiltinType::BFloat16:
461 resultType = cgm.bFloat16Ty;
462 break;
463 case BuiltinType::MFloat8:
464 resultType = cgm.uInt8Ty;
465 break;
466 case BuiltinType::Float:
467 assert(&astContext.getFloatTypeSemantics(type) ==
468 &llvm::APFloat::IEEEsingle() &&
469 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");
470 resultType = cgm.floatTy;
471 break;
472 case BuiltinType::Double:
473 assert(&astContext.getFloatTypeSemantics(type) ==
474 &llvm::APFloat::IEEEdouble() &&
475 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");
476 resultType = cgm.doubleTy;
477 break;
478 case BuiltinType::LongDouble:
479 resultType =
480 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(type));
481 break;
482 case BuiltinType::Float128:
483 resultType = cgm.fP128Ty;
484 break;
485 case BuiltinType::Ibm128:
486 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
487 resultType = cgm.sInt32Ty;
488 break;
489
490 case BuiltinType::NullPtr:
491 // Add proper CIR type for it? this looks mostly useful for sema related
492 // things (like for overloads accepting void), for now, given that
493 // `sizeof(std::nullptr_t)` is equal to `sizeof(void *)`, model
494 // std::nullptr_t as !cir.ptr<!void>
495 resultType = builder.getVoidPtrTy();
496 break;
497
498#define AMDGPU_OPAQUE_PTR_TYPE(Name, Id, SingletonId, Width, Align, AS) \
499 case BuiltinType::Id: { \
500 if (BuiltinType::Id == BuiltinType::AMDGPUTexture) { \
501 resultType = cir::VectorType::get(builder.getSInt32Ty(), 8); \
502 } else { \
503 resultType = builder.getPointerTo(cgm.voidTy); \
504 } \
505 break; \
506 }
507#define AMDGPU_NAMED_BARRIER_TYPE(Name, Id, SingletonId, Width, Align, Scope) \
508 case BuiltinType::Id: \
509 llvm_unreachable("NYI");
510#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) \
511 case BuiltinType::Id: \
512 llvm_unreachable("NYI");
513#include "clang/Basic/AMDGPUTypes.def"
514
515 default:
516 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
517 resultType = cgm.sInt32Ty;
518 break;
519 }
520 break;
521 }
522
523 case Type::Complex: {
524 const auto *ct = cast<clang::ComplexType>(ty);
525 mlir::Type elementTy = convertType(ct->getElementType());
526 resultType = cir::ComplexType::get(elementTy);
527 break;
528 }
529
530 case Type::LValueReference:
531 case Type::RValueReference: {
532 const ReferenceType *refTy = cast<ReferenceType>(ty);
533 QualType elemTy = refTy->getPointeeType();
534 auto pointeeType = convertTypeForMem(elemTy);
535 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
536 assert(resultType && "Cannot get pointer type?");
537 break;
538 }
539
540 case Type::Pointer: {
541 const PointerType *ptrTy = cast<PointerType>(ty);
542 QualType elemTy = ptrTy->getPointeeType();
543 assert(!elemTy->isConstantMatrixType() && "not implemented");
544
545 mlir::Type pointeeType = convertType(elemTy);
546
547 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
548 break;
549 }
550
551 case Type::VariableArray: {
553 if (a->getIndexTypeCVRQualifiers() != 0)
554 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
555 // VLAs resolve to the innermost element type; this matches
556 // the return of alloca, and there isn't any obviously better choice.
557 resultType = convertTypeForMem(a->getElementType());
558 break;
559 }
560
561 case Type::IncompleteArray: {
563 if (arrTy->getIndexTypeCVRQualifiers() != 0)
564 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
565
566 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
567 // int X[] -> [0 x int], unless the element type is not sized. If it is
568 // unsized (e.g. an incomplete record) just use [0 x i8].
569 if (!cir::isSized(elemTy)) {
570 elemTy = cgm.sInt8Ty;
571 }
572
573 resultType = cir::ArrayType::get(elemTy, 0);
574 break;
575 }
576
577 case Type::ConstantArray: {
579 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
580 // In classic codegen, arrays of unsized types which it assumes are "arrays
581 // of undefined struct type" are lowered to arrays of i8 "just to have a
582 // concrete type", but in CIR, we can get here with abstract types like
583 // !cir.method and !cir.data_member, so we just create an array of the type
584 // and handle it during lowering if we still don't have a sized type.
585 resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue());
586 break;
587 }
588
589 case Type::ExtVector:
590 case Type::Vector: {
591 const VectorType *vec = cast<VectorType>(ty);
592 const mlir::Type elemTy = convertType(vec->getElementType());
593 resultType = cir::VectorType::get(elemTy, vec->getNumElements());
594 break;
595 }
596
597 case Type::Enum: {
598 const auto *ed = ty->castAsEnumDecl();
599 if (auto integerType = ed->getIntegerType(); !integerType.isNull())
600 return convertType(integerType);
601 // Return a placeholder 'i32' type. This can be changed later when the
602 // type is defined (see UpdateCompletedType), but is likely to be the
603 // "right" answer.
604 resultType = cgm.uInt32Ty;
605 break;
606 }
607
608 case Type::MemberPointer: {
609 const auto *mpt = cast<MemberPointerType>(ty);
610
611 NestedNameSpecifier mptNNS = mpt->getQualifier();
612 auto clsTy = mlir::cast<cir::RecordType>(
613 convertType(QualType(mptNNS.getAsType(), 0)));
614 if (mpt->isMemberDataPointer()) {
615 mlir::Type memberTy = convertType(mpt->getPointeeType());
616 resultType = cir::DataMemberType::get(memberTy, clsTy);
617 } else {
618 auto memberFuncTy = getFunctionType(cgm.getTypes().arrangeCXXMethodType(
619 mptNNS.getAsRecordDecl(),
620 mpt->getPointeeType()->getAs<clang::FunctionProtoType>(),
621 /*methodDecl=*/nullptr));
622 resultType = cir::MethodType::get(memberFuncTy, clsTy);
623 }
624 break;
625 }
626
627 case Type::FunctionNoProto:
628 case Type::FunctionProto:
629 resultType = convertFunctionTypeInternal(type);
630 break;
631
632 case Type::BitInt: {
633 const auto *bitIntTy = cast<BitIntType>(type);
634 unsigned numBits = bitIntTy->getNumBits();
635 assert(numBits <= cir::IntType::maxBitwidth() &&
636 "_BitInt width exceeds CIR IntType maximum");
637 resultType =
638 cir::IntType::get(&getMLIRContext(), numBits, bitIntTy->isSigned(),
639 /*isBitInt=*/true);
640 break;
641 }
642
643 case Type::Atomic: {
644 QualType valueType = cast<AtomicType>(ty)->getValueType();
645 resultType = convertTypeForMem(valueType);
646
647 // Pad out to the inflated size if necessary.
648 uint64_t valueSize = astContext.getTypeSize(valueType);
649 uint64_t atomicSize = astContext.getTypeSize(ty);
650 if (valueSize != atomicSize) {
651 assert(valueSize < atomicSize);
652 auto paddingArray =
653 cir::ArrayType::get(cgm.sInt8Ty, (atomicSize - valueSize) / 8);
654 mlir::Type elements[] = {resultType, paddingArray};
655 resultType = cir::StructType::get(&getMLIRContext(), /*members=*/elements,
656 /*packed=*/false, /*padded=*/false,
657 /*is_class=*/false);
658 }
659
660 break;
661 }
662
663 default:
664 cgm.errorNYI(SourceLocation(), "processing of type",
665 type->getTypeClassName());
666 resultType = cgm.sInt32Ty;
667 break;
668 }
669
670 assert(resultType && "Type conversion not yet implemented");
671
672 typeCache[ty] = resultType;
673 return resultType;
674}
675
677 bool forBitField) {
678 if (qualType->isConstantMatrixType()) {
679 cgm.errorNYI("Matrix type conversion");
680 return cgm.sInt32Ty;
681 }
682
683 mlir::Type convertedType = convertType(qualType);
684
685 assert(!forBitField && "Bit fields NYI");
686
687 // If this is a bit-precise integer type in a bitfield representation, map
688 // this integer to the target-specified size.
689 if (forBitField && qualType->isBitIntType())
690 assert(!qualType->isBitIntType() && "Bit field with type _BitInt NYI");
691
692 return convertedType;
693}
694
695/// Return record layout info for the given record decl.
696const CIRGenRecordLayout &
698 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
699
700 // If we have already computed the layout, return it.
701 auto it = cirGenRecordLayouts.find(key);
702 if (it != cirGenRecordLayouts.end())
703 return *it->second;
704
705 // Compute the type information.
707
708 // Now try again.
709 it = cirGenRecordLayouts.find(key);
710
711 assert(it != cirGenRecordLayouts.end() &&
712 "Unable to find record layout information for type");
713 return *it->second;
714}
715
717 if (t->getAs<PointerType>())
718 return astContext.getTargetNullPointerValue(t) == 0;
719
720 if (const auto *at = astContext.getAsArrayType(t)) {
722 return true;
723
724 if (const auto *cat = dyn_cast<ConstantArrayType>(at))
725 if (astContext.getConstantArrayElementCount(cat) == 0)
726 return true;
727 }
728
729 if (const auto *rd = t->getAsRecordDecl())
730 return isZeroInitializable(rd);
731
732 if (const auto *mpt = t->getAs<MemberPointerType>())
733 return theCXXABI.isZeroInitializable(mpt);
734
735 if (t->getAs<HLSLInlineSpirvType>())
736 cgm.errorNYI(SourceLocation(),
737 "isZeroInitializable for HLSLInlineSpirvType");
738
739 return true;
740}
741
745
747 CanQualType returnType, bool isInstanceMethod,
749 RequiredArgs required) {
750 assert(llvm::all_of(argTypes,
751 [](CanQualType t) { return t.isCanonicalAsParam(); }));
752 // Lookup or create unique function info.
753 llvm::FoldingSetNodeID id;
754 CIRGenFunctionInfo::Profile(id, isInstanceMethod, info, required, returnType,
755 argTypes);
756
757 void *insertPos = nullptr;
758 CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos);
759 if (fi) {
760 // We found a matching function info based on id. These asserts verify that
761 // it really is a match.
762 assert(
763 fi->getReturnType() == returnType &&
764 std::equal(fi->argTypesBegin(), fi->argTypesEnd(), argTypes.begin()) &&
765 "Bad match based on CIRGenFunctionInfo folding set id");
766 return *fi;
767 }
768
770
771 // Construction the function info. We co-allocate the ArgInfos.
772 fi = CIRGenFunctionInfo::create(info, isInstanceMethod, returnType, argTypes,
773 required);
774 functionInfos.InsertNode(fi, insertPos);
775
776 return *fi;
777}
778
780 assert(!dyn_cast<ObjCMethodDecl>(gd.getDecl()) &&
781 "This is reported as a FIXME in LLVM codegen");
782 const auto *fd = cast<FunctionDecl>(gd.getDecl());
783
787
789}
790
791// When we find the full definition for a TagDecl, replace the 'opaque' type we
792// previously made for it if applicable.
794 // If this is an enum being completed, then we flush all non-struct types
795 // from the cache. This allows function types and other things that may be
796 // derived from the enum to be recomputed.
797 if ([[maybe_unused]] const auto *ed = dyn_cast<EnumDecl>(td)) {
798 // Classic codegen clears the type cache if it contains an entry for this
799 // enum type that doesn't use i32 as the underlying type, but I can't find
800 // a test case that meets that condition. C++ doesn't allow forward
801 // declaration of enums, and C doesn't allow an incomplete forward
802 // declaration with a non-default type.
803 assert(
804 !typeCache.count(
805 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
806 (convertType(ed->getIntegerType()) ==
807 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
808 // If necessary, provide the full definition of a type only used with a
809 // declaration so far.
811 return;
812 }
813
814 // If we completed a RecordDecl that we previously used and converted to an
815 // anonymous type, then go ahead and complete it now.
816 const auto *rd = cast<RecordDecl>(td);
817 if (rd->isDependentType())
818 return;
819
820 // Only complete if we converted it already. If we haven't converted it yet,
821 // we'll just do it lazily.
822 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
824
825 // If necessary, provide the full definition of a type only used with a
826 // declaration so far.
828}
829
831 // Return the address space for the type. If the type is a
832 // function type without an address space qualifier, the
833 // program address space is used. Otherwise, the target picks
834 // the best address space based on the type information
835 return ty->isFunctionType() && !ty.hasAddressSpace()
836 ? cgm.getDataLayout().getProgramAddressSpace()
838}
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.
C++ view class that accepts both !cir.struct and !cir.union types.
Definition CIRTypes.h:93
bool isComplete() const
Definition CIRTypes.h:112
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
CanQualType getCanonicalTagType(const TagDecl *TD) const
unsigned getTargetAddressSpace(LangAS AS) const
QualType getElementType() const
Definition TypeBase.h:3798
unsigned getIndexTypeCVRQualifiers() const
Definition TypeBase.h:3808
const_arg_iterator argTypesEnd() const
static CIRGenFunctionInfo * create(FunctionType::ExtInfo info, bool instanceMethod, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
static void Profile(llvm::FoldingSetNodeID &id, bool instanceMethod, FunctionType::ExtInfo info, RequiredArgs required, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes)
const_arg_iterator argTypesBegin() const
This class organizes the cross-function state that is used while generating CIR code.
bool isPaddedAtomicType(QualType type)
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:50
const CIRGenFunctionInfo & arrangeGlobalDeclaration(GlobalDecl gd)
unsigned getTargetAddressSpace(QualType ty) const
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, bool isInstanceMethod, llvm::ArrayRef< CanQualType > argTypes, FunctionType::ExtInfo info, RequiredArgs required)
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:89
mlir::MLIRContext & getMLIRContext() const
bool isCachedSafeToConvert(const clang::Type *key) const
Check if a record type key is in the safe-to-convert cache.
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.
void cacheSafeToConvert(const clang::Type *key)
Add a record type key to the safe-to-convert cache.
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:3824
llvm::APInt getSize() const
Return the constant array size as an APInt.
Definition TypeBase.h:3880
Represents a member of a struct/union/class.
Definition Decl.h:3190
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4949
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5371
A class which abstracts out some details necessary for making a call.
Definition TypeBase.h:4678
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4567
QualType getReturnType() const
Definition TypeBase.h:4907
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:3973
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3717
Represents a C++ nested name specifier, such as "\::std::vector<int>::".
CXXRecordDecl * getAsRecordDecl() const
Retrieve the record declaration stored in this nested name specifier, or null.
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3392
QualType getPointeeType() const
Definition TypeBase.h:3402
A (possibly-)qualified type.
Definition TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8447
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8573
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Definition TypeBase.h:8568
bool isCanonical() const
Definition TypeBase.h:8504
Represents a struct/union/class.
Definition Decl.h:4355
field_range fields() const
Definition Decl.h:4558
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition Decl.h:4539
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3637
QualType getPointeeType() const
Definition TypeBase.h:3655
Encodes a location in the source.
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3747
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3848
The base class of the type hierarchy.
Definition TypeBase.h:1875
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isConstantMatrixType() const
Definition TypeBase.h:8851
EnumDecl * castAsEnumDecl() const
Definition Type.h:59
bool isFunctionType() const
Definition TypeBase.h:8680
TypeClass getTypeClass() const
Definition TypeBase.h:2445
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9277
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4030
Represents a GCC generic vector type.
Definition TypeBase.h:4239
unsigned getNumElements() const
Definition TypeBase.h:4254
QualType getElementType() const
Definition TypeBase.h:4253
Defines the clang::TargetInfo interface.
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
Definition CIRTypes.cpp:34
@ 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
bool isInstanceMethod(const Decl *D)
Definition Attr.h:120
U cast(CodeGen::Address addr)
Definition Address.h:327
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.