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"
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(cgm.voidTy); \
509 } \
510 break; \
511 }
512#define AMDGPU_NAMED_BARRIER_TYPE(Name, Id, SingletonId, Width, Align, Scope) \
513 case BuiltinType::Id: \
514 llvm_unreachable("NYI");
515#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) \
516 case BuiltinType::Id: \
517 llvm_unreachable("NYI");
518#include "clang/Basic/AMDGPUTypes.def"
519
520 default:
521 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
522 resultType = cgm.sInt32Ty;
523 break;
524 }
525 break;
526 }
527
528 case Type::Complex: {
529 const auto *ct = cast<clang::ComplexType>(ty);
530 mlir::Type elementTy = convertType(ct->getElementType());
531 resultType = cir::ComplexType::get(elementTy);
532 break;
533 }
534
535 case Type::LValueReference:
536 case Type::RValueReference: {
537 const ReferenceType *refTy = cast<ReferenceType>(ty);
538 QualType elemTy = refTy->getPointeeType();
539 auto pointeeType = convertTypeForMem(elemTy);
540 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
541 assert(resultType && "Cannot get pointer type?");
542 break;
543 }
544
545 case Type::Pointer: {
546 const PointerType *ptrTy = cast<PointerType>(ty);
547 QualType elemTy = ptrTy->getPointeeType();
548 assert(!elemTy->isConstantMatrixType() && "not implemented");
549
550 mlir::Type pointeeType = convertType(elemTy);
551
552 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
553 break;
554 }
555
556 case Type::VariableArray: {
558 if (a->getIndexTypeCVRQualifiers() != 0)
559 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
560 // VLAs resolve to the innermost element type; this matches
561 // the return of alloca, and there isn't any obviously better choice.
562 resultType = convertTypeForMem(a->getElementType());
563 break;
564 }
565
566 case Type::IncompleteArray: {
568 if (arrTy->getIndexTypeCVRQualifiers() != 0)
569 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
570
571 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
572 // int X[] -> [0 x int], unless the element type is not sized. If it is
573 // unsized (e.g. an incomplete record) just use [0 x i8].
574 if (!cir::isSized(elemTy)) {
575 elemTy = cgm.sInt8Ty;
576 }
577
578 resultType = cir::ArrayType::get(elemTy, 0);
579 break;
580 }
581
582 case Type::ConstantArray: {
584 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
585 // In classic codegen, arrays of unsized types which it assumes are "arrays
586 // of undefined struct type" are lowered to arrays of i8 "just to have a
587 // concrete type", but in CIR, we can get here with abstract types like
588 // !cir.method and !cir.data_member, so we just create an array of the type
589 // and handle it during lowering if we still don't have a sized type.
590 resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue());
591 break;
592 }
593
594 case Type::ExtVector:
595 case Type::Vector: {
596 const VectorType *vec = cast<VectorType>(ty);
597 const mlir::Type elemTy = convertType(vec->getElementType());
598 resultType = cir::VectorType::get(elemTy, vec->getNumElements());
599 break;
600 }
601
602 case Type::Enum: {
603 const auto *ed = ty->castAsEnumDecl();
604 if (auto integerType = ed->getIntegerType(); !integerType.isNull())
605 return convertType(integerType);
606 // Return a placeholder 'i32' type. This can be changed later when the
607 // type is defined (see UpdateCompletedType), but is likely to be the
608 // "right" answer.
609 resultType = cgm.uInt32Ty;
610 break;
611 }
612
613 case Type::MemberPointer: {
614 const auto *mpt = cast<MemberPointerType>(ty);
615
616 NestedNameSpecifier mptNNS = mpt->getQualifier();
617 auto clsTy = mlir::cast<cir::RecordType>(
618 convertType(QualType(mptNNS.getAsType(), 0)));
619 if (mpt->isMemberDataPointer()) {
620 mlir::Type memberTy = convertType(mpt->getPointeeType());
621 resultType = cir::DataMemberType::get(memberTy, clsTy);
622 } else {
623 auto memberFuncTy = getFunctionType(cgm.getTypes().arrangeCXXMethodType(
624 mptNNS.getAsRecordDecl(),
625 mpt->getPointeeType()->getAs<clang::FunctionProtoType>(),
626 /*methodDecl=*/nullptr));
627 resultType = cir::MethodType::get(memberFuncTy, clsTy);
628 }
629 break;
630 }
631
632 case Type::FunctionNoProto:
633 case Type::FunctionProto:
634 resultType = convertFunctionTypeInternal(type);
635 break;
636
637 case Type::BitInt: {
638 const auto *bitIntTy = cast<BitIntType>(type);
639 unsigned numBits = bitIntTy->getNumBits();
640 assert(numBits <= cir::IntType::maxBitwidth() &&
641 "_BitInt width exceeds CIR IntType maximum");
642 resultType =
643 cir::IntType::get(&getMLIRContext(), numBits, bitIntTy->isSigned(),
644 /*isBitInt=*/true);
645 break;
646 }
647
648 case Type::Atomic: {
649 QualType valueType = cast<AtomicType>(ty)->getValueType();
650 resultType = convertTypeForMem(valueType);
651
652 // Pad out to the inflated size if necessary.
653 uint64_t valueSize = astContext.getTypeSize(valueType);
654 uint64_t atomicSize = astContext.getTypeSize(ty);
655 if (valueSize != atomicSize) {
656 assert(valueSize < atomicSize);
657 auto paddingArray =
658 cir::ArrayType::get(cgm.sInt8Ty, (atomicSize - valueSize) / 8);
659 mlir::Type elements[] = {resultType, paddingArray};
660 resultType = cir::StructType::get(&getMLIRContext(), /*members=*/elements,
661 /*packed=*/false, /*padded=*/false,
662 /*is_class=*/false);
663 }
664
665 break;
666 }
667
668 default:
669 cgm.errorNYI(SourceLocation(), "processing of type",
670 type->getTypeClassName());
671 resultType = cgm.sInt32Ty;
672 break;
673 }
674
675 assert(resultType && "Type conversion not yet implemented");
676
677 typeCache[ty] = resultType;
678 return resultType;
679}
680
682 bool forBitField) {
683 if (qualType->isConstantMatrixType()) {
684 cgm.errorNYI("Matrix type conversion");
685 return cgm.sInt32Ty;
686 }
687
688 mlir::Type convertedType = convertType(qualType);
689
690 assert(!forBitField && "Bit fields NYI");
691
692 // If this is a bit-precise integer type in a bitfield representation, map
693 // this integer to the target-specified size.
694 if (forBitField && qualType->isBitIntType())
695 assert(!qualType->isBitIntType() && "Bit field with type _BitInt NYI");
696
697 return convertedType;
698}
699
700/// Return record layout info for the given record decl.
701const CIRGenRecordLayout &
703 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
704
705 // If we have already computed the layout, return it.
706 auto it = cirGenRecordLayouts.find(key);
707 if (it != cirGenRecordLayouts.end())
708 return *it->second;
709
710 // Compute the type information.
712
713 // Now try again.
714 it = cirGenRecordLayouts.find(key);
715
716 assert(it != cirGenRecordLayouts.end() &&
717 "Unable to find record layout information for type");
718 return *it->second;
719}
720
722 if (t->getAs<PointerType>())
723 return astContext.getTargetNullPointerValue(t) == 0;
724
725 if (const auto *at = astContext.getAsArrayType(t)) {
727 return true;
728
729 if (const auto *cat = dyn_cast<ConstantArrayType>(at))
730 if (astContext.getConstantArrayElementCount(cat) == 0)
731 return true;
732 }
733
734 if (const auto *rd = t->getAsRecordDecl())
735 return isZeroInitializable(rd);
736
737 if (const auto *mpt = t->getAs<MemberPointerType>())
738 return theCXXABI.isZeroInitializable(mpt);
739
740 if (t->getAs<HLSLInlineSpirvType>())
741 cgm.errorNYI(SourceLocation(),
742 "isZeroInitializable for HLSLInlineSpirvType");
743
744 return true;
745}
746
750
752 CanQualType returnType, bool isInstanceMethod,
754 RequiredArgs required) {
755 assert(llvm::all_of(argTypes,
756 [](CanQualType t) { return t.isCanonicalAsParam(); }));
757 // Lookup or create unique function info.
758 llvm::FoldingSetNodeID id;
759 CIRGenFunctionInfo::Profile(id, isInstanceMethod, info, required, returnType,
760 argTypes);
761
762 void *insertPos = nullptr;
763 CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos);
764 if (fi) {
765 // We found a matching function info based on id. These asserts verify that
766 // it really is a match.
767 assert(
768 fi->getReturnType() == returnType &&
769 std::equal(fi->argTypesBegin(), fi->argTypesEnd(), argTypes.begin()) &&
770 "Bad match based on CIRGenFunctionInfo folding set id");
771 return *fi;
772 }
773
775
776 // Construction the function info. We co-allocate the ArgInfos.
777 fi = CIRGenFunctionInfo::create(info, isInstanceMethod, returnType, argTypes,
778 required);
779 functionInfos.InsertNode(fi, insertPos);
780
781 return *fi;
782}
783
785 assert(!dyn_cast<ObjCMethodDecl>(gd.getDecl()) &&
786 "This is reported as a FIXME in LLVM codegen");
787 const auto *fd = cast<FunctionDecl>(gd.getDecl());
788
792
794}
795
796// When we find the full definition for a TagDecl, replace the 'opaque' type we
797// previously made for it if applicable.
799 // If this is an enum being completed, then we flush all non-struct types
800 // from the cache. This allows function types and other things that may be
801 // derived from the enum to be recomputed.
802 if ([[maybe_unused]] const auto *ed = dyn_cast<EnumDecl>(td)) {
803 // Classic codegen clears the type cache if it contains an entry for this
804 // enum type that doesn't use i32 as the underlying type, but I can't find
805 // a test case that meets that condition. C++ doesn't allow forward
806 // declaration of enums, and C doesn't allow an incomplete forward
807 // declaration with a non-default type.
808 assert(
809 !typeCache.count(
810 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
811 (convertType(ed->getIntegerType()) ==
812 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
813 // If necessary, provide the full definition of a type only used with a
814 // declaration so far.
816 return;
817 }
818
819 // If we completed a RecordDecl that we previously used and converted to an
820 // anonymous type, then go ahead and complete it now.
821 const auto *rd = cast<RecordDecl>(td);
822 if (rd->isDependentType())
823 return;
824
825 // Only complete if we converted it already. If we haven't converted it yet,
826 // we'll just do it lazily.
827 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
829
830 // If necessary, provide the full definition of a type only used with a
831 // declaration so far.
833}
834
836 // Return the address space for the type. If the type is a
837 // function type without an address space qualifier, the
838 // program address space is used. Otherwise, the target picks
839 // the best address space based on the type information
840 return ty->isFunctionType() && !ty.hasAddressSpace()
841 ? cgm.getDataLayout().getProgramAddressSpace()
843}
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: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: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: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: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 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.