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