clang 24.0.0git
CIRGenTypes.cpp
Go to the documentation of this file.
1#include "CIRGenTypes.h"
2
3#include "CIRGenCXXABI.h"
4#include "CIRGenCall.h"
6#include "CIRGenModule.h"
7#include "mlir/IR/BuiltinTypes.h"
8
12#include "clang/AST/Type.h"
16
17#include <cassert>
18
19using namespace clang;
20using namespace clang::CIRGen;
21
23 : cgm(genModule), astContext(genModule.getASTContext()),
24 builder(cgm.getBuilder()), theCXXABI(cgm.getCXXABI()),
25 theABIInfo(cgm.getTargetCIRGenInfo().getABIInfo()) {}
26
28 for (auto i = functionInfos.begin(), e = functionInfos.end(); i != e;)
29 delete &*i++;
30}
31
32mlir::MLIRContext &CIRGenTypes::getMLIRContext() const {
33 return *builder.getContext();
34}
35
36/// Return true if the specified type in a function parameter or result position
37/// can be converted to a CIR type at this point. This boils down to being
38/// whether it is complete, as well as whether we've temporarily deferred
39/// expanding the type because we're in a recursive context.
41 // Some ABIs cannot have their member pointers represented in LLVM IR unless
42 // certain circumstances have been reached, but in CIR we represent member
43 // pointer types abstractly at this point so they are always convertible.
44 if (type->getAs<MemberPointerType>())
45 return true;
46
47 // If this isn't a tag type, we can convert it.
48 const TagType *tagType = type->getAs<TagType>();
49 if (!tagType)
50 return true;
51
52 // Function types involving incomplete class types are problematic in MLIR.
53 return !tagType->isIncompleteType();
54}
55
56/// Code to verify a given function type is complete, i.e. the return type and
57/// all of the parameter types are complete. Also check to see if we are in a
58/// RS_StructPointer context, and if so whether any struct types have been
59/// pended. If so, we don't want to ask the ABI lowering code to handle a type
60/// that cannot be converted to a CIR type.
63 return false;
64
65 if (const auto *fpt = dyn_cast<FunctionProtoType>(ft))
66 for (unsigned i = 0, e = fpt->getNumParams(); i != e; i++)
67 if (!isFuncParamTypeConvertible(fpt->getParamType(i)))
68 return false;
69
70 return true;
71}
72
73mlir::Type CIRGenTypes::convertFunctionTypeInternal(QualType qft) {
74 assert(qft.isCanonical());
76
77 // In classic codegen, if the function type depends on an incomplete type
78 // (e.g. a struct or enum), it cannot lower the function type due to ABI
79 // handling requirements and returns a placeholder. In CIR, ABI handling is
80 // deferred until after codegen, and record types are identified by name, so
81 // incomplete record type references in the function type will automatically
82 // see the complete type once the record is defined. We can always produce a
83 // proper function type here.
84
85 const CIRGenFunctionInfo *fi;
86 if (const auto *fpt = dyn_cast<FunctionProtoType>(ft)) {
89 } else {
93 }
94
95 mlir::Type resultType = getFunctionType(*fi);
96
97 return resultType;
98}
99
100// This is CIR's version of CodeGenTypes::addRecordTypeName. It isn't shareable
101// because CIR has different uniquing requirements.
103 StringRef suffix) {
104 llvm::SmallString<256> typeName;
105 llvm::raw_svector_ostream outStream(typeName);
106
107 PrintingPolicy policy = recordDecl->getASTContext().getPrintingPolicy();
110 policy.AlwaysIncludeTypeForTemplateArgument = true;
111 policy.PrintAsCanonical = true;
112 policy.SuppressTagKeyword = true;
113
114 if (recordDecl->getIdentifier())
115 QualType(astContext.getCanonicalTagType(recordDecl))
116 .print(outStream, policy);
117 else if (auto *typedefNameDecl = recordDecl->getTypedefNameForAnonDecl())
118 typedefNameDecl->printQualifiedName(outStream, policy);
119 else
120 outStream << builder.getUniqueAnonRecordName();
121
122 if (!suffix.empty())
123 outStream << suffix;
124
125 return builder.getUniqueRecordName(std::string(typeName));
126}
127
128/// Return true if the specified type is already completely laid out.
130 const auto it = recordDeclTypes.find(ty);
131 return it != recordDeclTypes.end() && it->second.isComplete();
132}
133
134// We have multiple forms of this function that call each other, so we need to
135// declare one in advance.
136static bool
138 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);
139
140/// Return true if it is safe to convert the specified record decl to CIR and
141/// lay it out, false if doing so would cause us to get into a recursive
142/// compilation mess.
143static bool
145 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
146 // If we have already checked this type (maybe the same type is used by-value
147 // multiple times in multiple record fields, don't check again.
148 if (!alreadyChecked.insert(rd).second)
149 return true;
150
151 assert(rd->isCompleteDefinition() &&
152 "Expect RecordDecl to be CompleteDefinition");
153 const Type *key = cgt.getASTContext().getCanonicalTagType(rd).getTypePtr();
154
155 // If this type is already laid out, converting it is a noop.
156 if (cgt.isRecordLayoutComplete(key))
157 return true;
158
159 // Check the cross-call cache. This avoids redundant recursive field walks
160 // for the same record types across different convertRecordDeclType calls
161 // during a single layout phase.
162 if (cgt.isCachedSafeToConvert(key))
163 return true;
164
165 // If this type is currently being laid out, we can't recursively compile it.
166 if (cgt.isRecordBeingLaidOut(key))
167 return false;
168
169 // If this type would require laying out bases that are currently being laid
170 // out, don't do it. This includes virtual base classes which get laid out
171 // when a class is translated, even though they aren't embedded by-value into
172 // the class.
173 if (const CXXRecordDecl *crd = dyn_cast<CXXRecordDecl>(rd)) {
174 for (const clang::CXXBaseSpecifier &i : crd->bases())
175 if (!isSafeToConvert(i.getType()
176 ->castAs<RecordType>()
177 ->getDecl()
178 ->getDefinitionOrSelf(),
179 cgt, alreadyChecked))
180 return false;
181 }
182
183 // If this type would require laying out members that are currently being laid
184 // out, don't do it.
185 for (const FieldDecl *field : rd->fields())
186 if (!isSafeToConvert(field->getType(), cgt, alreadyChecked))
187 return false;
188
189 // Cache the positive result. This will be cleared when recordsBeingLaidOut
190 // changes.
191 cgt.cacheSafeToConvert(key);
192
193 // If there are no problems, lets do it.
194 return true;
195}
196
197/// Return true if it is safe to convert this field type, which requires the
198/// record elements contained by-value to all be recursively safe to convert.
199static bool
201 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
202 // Strip off atomic type sugar.
203 if (const auto *at = qt->getAs<AtomicType>())
204 qt = at->getValueType();
205
206 // If this is a record, check it.
207 if (const auto *rd = qt->getAsRecordDecl())
208 return isSafeToConvert(rd, cgt, alreadyChecked);
209
210 // If this is an array, check the elements, which are embedded inline.
211 if (const auto *at = cgt.getASTContext().getAsArrayType(qt))
212 return isSafeToConvert(at->getElementType(), cgt, alreadyChecked);
213
214 // Otherwise, there is no concern about transforming this. We only care about
215 // things that are contained by-value in a record that can have another
216 // record as a member.
217 return true;
218}
219
220// Return true if it is safe to convert the specified record decl to CIR and lay
221// it out, false if doing so would cause us to get into a recursive compilation
222// mess.
223static bool isSafeToConvert(const RecordDecl *rd, CIRGenTypes &cgt) {
224 // If no records are being laid out, we can certainly do this one.
225 if (cgt.noRecordsBeingLaidOut())
226 return true;
227
229 return isSafeToConvert(rd, cgt, alreadyChecked);
230}
231
235
237 return astContext.getTypeSize(type) !=
238 astContext.getTypeSize(type->getValueType());
239}
240
241/// Lay out a tagged decl type like struct or union.
243 // TagDecl's are not necessarily unique, instead use the (clang) type
244 // connected to the decl.
245 const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();
246 cir::RecordType entry = recordDeclTypes[key];
247
248 // If we don't have an entry for this record yet, create one.
249 // We create an incomplete type initially. If `rd` is complete, we will
250 // add the members below.
251 if (!entry) {
252 auto name = getRecordTypeName(rd, "");
253 entry = builder.getIncompleteRecordTy(name, rd);
254 recordDeclTypes[key] = entry;
255 }
256
257 rd = rd->getDefinition();
258 if (!rd || !rd->isCompleteDefinition() || entry.isComplete())
259 return entry;
260
261 // If converting this type would cause us to infinitely loop, don't do it!
262 if (!isSafeToConvert(rd, *this)) {
263 deferredRecords.push_back(rd);
264 return entry;
265 }
266
267 // Okay, this is a definition of a type. Compile the implementation now.
268 bool insertResult = recordsBeingLaidOut.insert(key).second;
269 (void)insertResult;
270 assert(insertResult && "isSafeToCovert() should have caught this.");
271
272 // Invalidate the safety cache since recordsBeingLaidOut changed.
273 safeToConvertCache.clear();
274
275 // Force conversion of non-virtual base classes recursively.
276 if (const auto *cxxRecordDecl = dyn_cast<CXXRecordDecl>(rd)) {
277 for (const auto &base : cxxRecordDecl->bases()) {
278 if (base.isVirtual())
279 continue;
280 convertRecordDeclType(base.getType()->castAsRecordDecl());
281 }
282 }
283
284 // Layout fields.
285 std::unique_ptr<CIRGenRecordLayout> layout = computeRecordLayout(rd, &entry);
286 recordDeclTypes[key] = entry;
287 cirGenRecordLayouts[key] = std::move(layout);
288
289 // We're done laying out this record.
290 bool eraseResult = recordsBeingLaidOut.erase(key);
291 (void)eraseResult;
292 assert(eraseResult && "record not in RecordsBeingLaidOut set?");
293
294 // Invalidate the safety cache since recordsBeingLaidOut changed.
295 safeToConvertCache.clear();
296
297 // If we're done converting the outer-most record, then convert any deferred
298 // records as well.
299 if (recordsBeingLaidOut.empty())
300 while (!deferredRecords.empty())
301 convertRecordDeclType(deferredRecords.pop_back_val());
302
303 return entry;
304}
305
307 type = astContext.getCanonicalType(type);
308 const Type *ty = type.getTypePtr();
309
310 if (astContext.getLangOpts().CUDAIsDevice) {
311 if (type->isCUDADeviceBuiltinSurfaceType()) {
312 if (mlir::Type ty =
313 cgm.getTargetCIRGenInfo().getCUDADeviceBuiltinSurfaceDeviceType())
314 return ty;
315 } else if (type->isCUDADeviceBuiltinTextureType()) {
316 if (mlir::Type ty =
317 cgm.getTargetCIRGenInfo().getCUDADeviceBuiltinTextureDeviceType())
318 return ty;
319
321 }
322 }
323
324 // Process record types before the type cache lookup.
325 if (const auto *recordType = dyn_cast<RecordType>(type))
326 return convertRecordDeclType(recordType->getDecl()->getDefinitionOrSelf());
327
328 // Has the type already been processed?
329 TypeCacheTy::iterator tci = typeCache.find(ty);
330 if (tci != typeCache.end())
331 return tci->second;
332
333 // For types that haven't been implemented yet or are otherwise unsupported,
334 // report an error and return 'int'.
335
336 mlir::Type resultType = nullptr;
337 switch (ty->getTypeClass()) {
338 case Type::Record:
339 llvm_unreachable("Should have been handled above");
340
341 case Type::Builtin: {
342 switch (cast<BuiltinType>(ty)->getKind()) {
343 // void
344 case BuiltinType::Void:
345 resultType = cgm.voidTy;
346 break;
347
348 // bool
349 case BuiltinType::Bool:
350 resultType = cir::BoolType::get(&getMLIRContext());
351 break;
352
353 // Signed integral types.
354 case BuiltinType::Char_S:
355 case BuiltinType::Int:
356 case BuiltinType::Int128:
357 case BuiltinType::Long:
358 case BuiltinType::LongLong:
359 case BuiltinType::SChar:
360 case BuiltinType::Short:
361 case BuiltinType::WChar_S:
362 case BuiltinType::Accum:
363 case BuiltinType::Fract:
364 case BuiltinType::LongAccum:
365 case BuiltinType::LongFract:
366 case BuiltinType::ShortAccum:
367 case BuiltinType::ShortFract:
368 // Saturated signed types.
369 case BuiltinType::SatAccum:
370 case BuiltinType::SatFract:
371 case BuiltinType::SatLongAccum:
372 case BuiltinType::SatLongFract:
373 case BuiltinType::SatShortAccum:
374 case BuiltinType::SatShortFract:
375 resultType =
376 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
377 /*isSigned=*/true);
378 break;
379
380 // SVE types
381 case BuiltinType::SveInt8:
382 resultType =
383 cir::VectorType::get(builder.getSInt8Ty(), 16, /*is_scalable=*/true);
384 break;
385 case BuiltinType::SveUint8:
386 resultType =
387 cir::VectorType::get(builder.getUInt8Ty(), 16, /*is_scalable=*/true);
388 break;
389 case BuiltinType::SveInt16:
390 resultType =
391 cir::VectorType::get(builder.getSInt16Ty(), 8, /*is_scalable=*/true);
392 break;
393 case BuiltinType::SveUint16:
394 resultType =
395 cir::VectorType::get(builder.getUInt16Ty(), 8, /*is_scalable=*/true);
396 break;
397 case BuiltinType::SveFloat16:
398 resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
399 /*is_scalable=*/true);
400 break;
401 case BuiltinType::SveBFloat16:
402 resultType = cir::VectorType::get(builder.getBfloat16Ty(), 8,
403 /*is_scalable=*/true);
404 break;
405 case BuiltinType::SveInt32:
406 resultType =
407 cir::VectorType::get(builder.getSInt32Ty(), 4, /*is_scalable=*/true);
408 break;
409 case BuiltinType::SveUint32:
410 resultType =
411 cir::VectorType::get(builder.getUInt32Ty(), 4, /*is_scalable=*/true);
412 break;
413 case BuiltinType::SveFloat32:
414 resultType = cir::VectorType::get(builder.getSingleTy(), 4,
415 /*is_scalable=*/true);
416 break;
417 case BuiltinType::SveInt64:
418 resultType =
419 cir::VectorType::get(builder.getSInt64Ty(), 2, /*is_scalable=*/true);
420 break;
421 case BuiltinType::SveUint64:
422 resultType =
423 cir::VectorType::get(builder.getUInt64Ty(), 2, /*is_scalable=*/true);
424 break;
425 case BuiltinType::SveFloat64:
426 resultType = cir::VectorType::get(builder.getDoubleTy(), 2,
427 /*is_scalable=*/true);
428 break;
429 case BuiltinType::SveBool:
430 resultType = cir::VectorType::get(builder.getUIntNTy(1), 16,
431 /*is_scalable=*/true);
432 break;
433
434 // Unsigned integral types.
435 case BuiltinType::Char8:
436 case BuiltinType::Char16:
437 case BuiltinType::Char32:
438 case BuiltinType::Char_U:
439 case BuiltinType::UChar:
440 case BuiltinType::UInt:
441 case BuiltinType::UInt128:
442 case BuiltinType::ULong:
443 case BuiltinType::ULongLong:
444 case BuiltinType::UShort:
445 case BuiltinType::WChar_U:
446 case BuiltinType::UAccum:
447 case BuiltinType::UFract:
448 case BuiltinType::ULongAccum:
449 case BuiltinType::ULongFract:
450 case BuiltinType::UShortAccum:
451 case BuiltinType::UShortFract:
452 // Saturated unsigned types.
453 case BuiltinType::SatUAccum:
454 case BuiltinType::SatUFract:
455 case BuiltinType::SatULongAccum:
456 case BuiltinType::SatULongFract:
457 case BuiltinType::SatUShortAccum:
458 case BuiltinType::SatUShortFract:
459 resultType =
460 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
461 /*isSigned=*/false);
462 break;
463
464 // Floating-point types
465 case BuiltinType::Float16:
466 resultType = cgm.fP16Ty;
467 break;
468 case BuiltinType::Half:
469 resultType = cgm.fP16Ty;
470 break;
471 case BuiltinType::BFloat16:
472 resultType = cgm.bFloat16Ty;
473 break;
474 case BuiltinType::MFloat8:
475 resultType = cgm.uInt8Ty;
476 break;
477 case BuiltinType::Float:
478 assert(&astContext.getFloatTypeSemantics(type) ==
479 &llvm::APFloat::IEEEsingle() &&
480 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");
481 resultType = cgm.floatTy;
482 break;
483 case BuiltinType::Double:
484 assert(&astContext.getFloatTypeSemantics(type) ==
485 &llvm::APFloat::IEEEdouble() &&
486 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");
487 resultType = cgm.doubleTy;
488 break;
489 case BuiltinType::LongDouble:
490 resultType =
491 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(type));
492 break;
493 case BuiltinType::Float128:
494 resultType = cgm.fP128Ty;
495 break;
496 case BuiltinType::Ibm128:
497 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
498 resultType = cgm.sInt32Ty;
499 break;
500
501 case BuiltinType::NullPtr:
502 // Add proper CIR type for it? this looks mostly useful for sema related
503 // things (like for overloads accepting void), for now, given that
504 // `sizeof(std::nullptr_t)` is equal to `sizeof(void *)`, model
505 // std::nullptr_t as !cir.ptr<!void>
506 resultType = builder.getVoidPtrTy();
507 break;
508
509#define AMDGPU_OPAQUE_PTR_TYPE(Name, Id, SingletonId, Width, Align, AS) \
510 case BuiltinType::Id: { \
511 if (BuiltinType::Id == BuiltinType::AMDGPUTexture) { \
512 resultType = cir::VectorType::get(builder.getSInt32Ty(), 8); \
513 } else { \
514 resultType = builder.getPointerTo( \
515 cgm.voidTy, \
516 cir::TargetAddressSpaceAttr::get(&getMLIRContext(), AS)); \
517 } \
518 break; \
519 }
520#define AMDGPU_NAMED_BARRIER_TYPE(Name, Id, SingletonId, Width, Align, Scope) \
521 case BuiltinType::Id: \
522 llvm_unreachable("NYI");
523#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) \
524 case BuiltinType::Id: \
525 llvm_unreachable("NYI");
526#include "clang/Basic/AMDGPUTypes.def"
527
528 default:
529 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
530 resultType = cgm.sInt32Ty;
531 break;
532 }
533 break;
534 }
535
536 case Type::Complex: {
537 const auto *ct = cast<clang::ComplexType>(ty);
538 mlir::Type elementTy = convertType(ct->getElementType());
539 resultType = cir::ComplexType::get(elementTy);
540 break;
541 }
542
543 case Type::LValueReference:
544 case Type::RValueReference: {
545 const ReferenceType *refTy = cast<ReferenceType>(ty);
546 QualType elemTy = refTy->getPointeeType();
547 auto pointeeType = convertTypeForMem(elemTy);
548 resultType =
549 builder.getPointerTo(pointeeType, getPointerAddressSpace(elemTy));
550 assert(resultType && "Cannot get pointer type?");
551 break;
552 }
553
554 case Type::Pointer: {
555 const PointerType *ptrTy = cast<PointerType>(ty);
556 QualType elemTy = ptrTy->getPointeeType();
557 mlir::Type pointeeType = convertType(elemTy);
558
559 resultType =
560 builder.getPointerTo(pointeeType, getPointerAddressSpace(elemTy));
561 break;
562 }
563
564 case Type::VariableArray: {
566 if (a->getIndexTypeCVRQualifiers() != 0)
567 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
568 // VLAs resolve to the innermost element type; this matches
569 // the return of alloca, and there isn't any obviously better choice.
570 resultType = convertTypeForMem(a->getElementType());
571 break;
572 }
573
574 case Type::IncompleteArray: {
576 if (arrTy->getIndexTypeCVRQualifiers() != 0)
577 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
578
579 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
580 // int X[] -> [0 x int], unless the element type is not sized. If it is
581 // unsized (e.g. an incomplete record) just use [0 x i8].
582 if (!cir::isSized(elemTy)) {
583 elemTy = cgm.sInt8Ty;
584 }
585
586 resultType = cir::ArrayType::get(elemTy, 0);
587 break;
588 }
589
590 case Type::ConstantArray: {
592 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
593 // In classic codegen, arrays of unsized types which it assumes are "arrays
594 // of undefined struct type" are lowered to arrays of i8 "just to have a
595 // concrete type", but in CIR, we can get here with abstract types like
596 // !cir.method and !cir.data_member, so we just create an array of the type
597 // and handle it during lowering if we still don't have a sized type.
598 resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue());
599 break;
600 }
601
602 case Type::ExtVector:
603 case Type::Vector: {
604 const VectorType *vec = cast<VectorType>(ty);
605 const mlir::Type elemTy = convertType(vec->getElementType());
606 resultType = cir::VectorType::get(elemTy, vec->getNumElements());
607 break;
608 }
609
610 case Type::ConstantMatrix: {
612 const mlir::Type elemTy = convertType(mt->getElementType());
613 resultType =
614 cir::MatrixType::get(elemTy, mt->getNumRows(), mt->getNumColumns());
615 break;
616 }
617
618 case Type::Enum: {
619 const auto *ed = ty->castAsEnumDecl();
620 if (auto integerType = ed->getIntegerType(); !integerType.isNull())
621 return convertType(integerType);
622 // Return a placeholder 'i32' type. This can be changed later when the
623 // type is defined (see UpdateCompletedType), but is likely to be the
624 // "right" answer.
625 resultType = cgm.uInt32Ty;
626 break;
627 }
628
629 case Type::MemberPointer: {
630 const auto *mpt = cast<MemberPointerType>(ty);
631
632 NestedNameSpecifier mptNNS = mpt->getQualifier();
633 auto clsTy = mlir::cast<cir::RecordType>(
634 convertType(QualType(mptNNS.getAsType(), 0)));
635 if (mpt->isMemberDataPointer()) {
636 mlir::Type memberTy = convertType(mpt->getPointeeType());
637 resultType = cir::DataMemberType::get(memberTy, clsTy);
638 } else {
639 auto memberFuncTy = getFunctionType(cgm.getTypes().arrangeCXXMethodType(
640 mptNNS.getAsRecordDecl(),
641 mpt->getPointeeType()->getAs<clang::FunctionProtoType>(),
642 /*methodDecl=*/nullptr));
643 resultType = cir::MethodType::get(memberFuncTy, clsTy);
644 }
645 break;
646 }
647
648 case Type::FunctionNoProto:
649 case Type::FunctionProto:
650 resultType = convertFunctionTypeInternal(type);
651 break;
652
653 case Type::BitInt: {
654 const auto *bitIntTy = cast<BitIntType>(type);
655 unsigned numBits = bitIntTy->getNumBits();
656 assert(numBits <= cir::IntType::maxBitwidth() &&
657 "_BitInt width exceeds CIR IntType maximum");
658 resultType =
659 cir::IntType::get(&getMLIRContext(), numBits, bitIntTy->isSigned(),
660 /*isBitInt=*/true);
661 break;
662 }
663
664 case Type::Atomic: {
665 QualType valueType = cast<AtomicType>(ty)->getValueType();
666 resultType = convertTypeForMem(valueType);
667
668 // Pad out to the inflated size if necessary.
669 uint64_t valueSize = astContext.getTypeSize(valueType);
670 uint64_t atomicSize = astContext.getTypeSize(ty);
671 if (valueSize != atomicSize) {
672 assert(valueSize < atomicSize);
673 auto paddingArray =
674 cir::ArrayType::get(cgm.sInt8Ty, (atomicSize - valueSize) / 8);
675 mlir::Type elements[] = {resultType, paddingArray};
676 cir::RecordMemberKind kinds[] = {cir::RecordMemberKind::Data,
677 cir::RecordMemberKind::Pad};
678 resultType =
679 cir::StructType::get(&getMLIRContext(), /*members=*/elements,
680 /*packed=*/false, /*is_class=*/false, kinds);
681 }
682
683 break;
684 }
685
686 default:
687 cgm.errorNYI(SourceLocation(), "processing of type",
688 type->getTypeClassName());
689 resultType = cgm.sInt32Ty;
690 break;
691 }
692
693 assert(resultType && "Type conversion not yet implemented");
694
695 typeCache[ty] = resultType;
696 return resultType;
697}
698
700 bool forBitField) {
701 if (astContext.getLangOpts().HLSL && qualType->isConstantMatrixType()) {
702 if (isMatrixRowMajor(astContext.getLangOpts(), qualType)) {
703 cgm.errorNYI("convertTypeForMem: HLSL & Matrix row major");
704 }
705 }
706
707 mlir::Type convertedType = convertType(qualType);
708
709 assert(!forBitField && "Bit fields NYI");
710
711 // If this is a bit-precise integer type in a bitfield representation, map
712 // this integer to the target-specified size.
713 if (forBitField && qualType->isBitIntType())
714 assert(!qualType->isBitIntType() && "Bit field with type _BitInt NYI");
715
716 return convertedType;
717}
718
719/// Return record layout info for the given record decl.
720const CIRGenRecordLayout &
722 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
723
724 // If we have already computed the layout, return it.
725 auto it = cirGenRecordLayouts.find(key);
726 if (it != cirGenRecordLayouts.end())
727 return *it->second;
728
729 // Compute the type information.
731
732 // Now try again.
733 it = cirGenRecordLayouts.find(key);
734
735 assert(it != cirGenRecordLayouts.end() &&
736 "Unable to find record layout information for type");
737 return *it->second;
738}
739
741 if (t->getAs<PointerType>() || t->isNullPtrType())
742 return astContext.getTargetNullPointerValue(t) == 0;
743
744 if (const auto *at = astContext.getAsArrayType(t)) {
746 return true;
747
748 if (const auto *cat = dyn_cast<ConstantArrayType>(at))
749 if (astContext.getConstantArrayElementCount(cat) == 0)
750 return true;
751
752 t = astContext.getBaseElementType(t);
753 }
754
755 if (const auto *rd = t->getAsRecordDecl())
756 return isZeroInitializable(rd);
757
758 if (const auto *mpt = t->getAs<MemberPointerType>())
759 return theCXXABI.isZeroInitializable(mpt);
760
761 if (t->getAs<HLSLInlineSpirvType>())
762 cgm.errorNYI(SourceLocation(),
763 "isZeroInitializable for HLSLInlineSpirvType");
764
765 return true;
766}
767
771
772cir::CallingConv
774 switch (cc) {
775 case CC_C:
776 // SPIR/SPIR-V lowers the default CC to spir_func, not plain C.
777 if (cgm.getTriple().isSPIROrSPIRV())
778 return cir::CallingConv::SpirFunction;
779 return cir::CallingConv::C;
780 case CC_DeviceKernel:
781 return cgm.getTargetCIRGenInfo().getDeviceKernelCallingConv();
782 default:
783 // TODO(cir): Support the remaining target-specific calling conventions.
784 cgm.errorNYI(SourceLocation(), "calling convention",
786 return cir::CallingConv::C;
787 }
788}
789
790/// Whether a by-value ABI type is `_Atomic` or contains an `_Atomic` member.
791/// Pointers and references are not walked: `_Atomic(T)*` is just a pointer.
794 if (ty->isAtomicType())
795 return true;
796
797 if (const ArrayType *arrayTy = ctx.getAsArrayType(ty))
798 return typeContainsAtomicForABI(arrayTy->getElementType(), ctx);
799
800 const RecordDecl *rd = ty->getAsRecordDecl();
801 if (!rd || !rd->getDefinition())
802 return false;
803
804 if (const CXXRecordDecl *cxxRD = dyn_cast<CXXRecordDecl>(rd)) {
805 for (const CXXBaseSpecifier &base : cxxRD->bases())
806 if (typeContainsAtomicForABI(base.getType(), ctx))
807 return true;
808 }
809
810 for (const FieldDecl *field : rd->fields())
811 if (typeContainsAtomicForABI(field->getType(), ctx))
812 return true;
813 return false;
814}
815
817 CanQualType returnType, bool isInstanceMethod,
819 RequiredArgs required) {
820 assert(llvm::all_of(argTypes,
821 [](CanQualType t) { return t.isCanonicalAsParam(); }));
822 auto containsAtomic = [&](CanQualType t) {
823 return typeContainsAtomicForABI(t, astContext);
824 };
825 if (containsAtomic(returnType) || llvm::any_of(argTypes, containsAtomic))
826 cgm.errorNYI("passing or returning atomic types");
827 // Lookup or create unique function info.
828 llvm::FoldingSetNodeID id;
829 CIRGenFunctionInfo::Profile(id, isInstanceMethod, info, required, returnType,
830 argTypes);
831
832 llvm::FoldingSetInsertToken insertToken;
833 CIRGenFunctionInfo *fi = functionInfos.lookup(id, insertToken);
834 if (fi) {
835 // We found a matching function info based on id. These asserts verify that
836 // it really is a match.
837 assert(
838 fi->getReturnType() == returnType &&
839 std::equal(fi->argTypesBegin(), fi->argTypesEnd(), argTypes.begin()) &&
840 "Bad match based on CIRGenFunctionInfo folding set id");
841 return *fi;
842 }
843
844 cir::CallingConv cirCC = clangCallConvToCIRCallConv(info.getCC());
845
846 // Construction the function info. We co-allocate the ArgInfos.
847 fi = CIRGenFunctionInfo::create(cirCC, info, isInstanceMethod, returnType,
848 argTypes, required);
849 functionInfos.insert(fi, insertToken);
850
851 return *fi;
852}
853
854const CIRGenFunctionInfo &
856 const FunctionArgList &args) {
858 for (const VarDecl *arg : args)
859 argTypes.push_back(astContext.getCanonicalParamType(arg->getType()));
860
861 // Classic CodeGen passes FnInfoOpts::None here; that is the no-op case, so
862 // nothing is needed even once CIR models FnInfoOpts.
864 resultType->getCanonicalTypeUnqualified(), /*isInstanceMethod=*/false,
866}
867
869 assert(!dyn_cast<ObjCMethodDecl>(gd.getDecl()) &&
870 "This is reported as a FIXME in LLVM codegen");
871 const auto *fd = cast<FunctionDecl>(gd.getDecl());
872
876
878}
879
880// When we find the full definition for a TagDecl, replace the 'opaque' type we
881// previously made for it if applicable.
883 // If this is an enum being completed, then we flush all non-struct types
884 // from the cache. This allows function types and other things that may be
885 // derived from the enum to be recomputed.
886 if ([[maybe_unused]] const auto *ed = dyn_cast<EnumDecl>(td)) {
887 // Classic codegen clears the type cache if it contains an entry for this
888 // enum type that doesn't use i32 as the underlying type, but I can't find
889 // a test case that meets that condition. C++ doesn't allow forward
890 // declaration of enums, and C doesn't allow an incomplete forward
891 // declaration with a non-default type.
892 assert(
893 !typeCache.count(
894 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
895 (convertType(ed->getIntegerType()) ==
896 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
897 // If necessary, provide the full definition of a type only used with a
898 // declaration so far.
900 return;
901 }
902
903 // If we completed a RecordDecl that we previously used and converted to an
904 // anonymous type, then go ahead and complete it now.
905 const auto *rd = cast<RecordDecl>(td);
906 if (rd->isDependentType())
907 return;
908
909 // Only complete if we converted it already. If we haven't converted it yet,
910 // we'll just do it lazily.
911 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
913
914 // If necessary, provide the full definition of a type only used with a
915 // declaration so far.
917}
918
919mlir::ptr::MemorySpaceAttrInterface
921 // An explicit source address space is carried directly.
922 if (pointeeTy.getAddressSpace() != LangAS::Default)
924 pointeeTy.getAddressSpace());
925
926 // Resolve a default-address-space pointee through getTargetAddressSpace, as
927 // classic CodeGen does. This is only non-zero for languages that default to
928 // a non-default address space (e.g. generic for SYCL device data), and uses
929 // the program address space for functions.
930 unsigned targetAS = getTargetAddressSpace(pointeeTy);
931 if (targetAS == 0)
932 return {};
933 return cir::TargetAddressSpaceAttr::get(&getMLIRContext(), targetAS);
934}
935
937 // Return the address space for the type. If the type is a
938 // function type without an address space qualifier, the
939 // program address space is used. Otherwise, the target picks
940 // the best address space based on the type information
941 return ty->isFunctionType() && !ty.hasAddressSpace()
942 ? cgm.getDataLayout().getProgramAddressSpace()
944}
Defines the clang::ASTContext interface.
static bool typeContainsAtomicForABI(QualType ty, ASTContext &ctx)
Whether a by-value ABI type is _Atomic or contains an _Atomic member.
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)
Defines AST-level helper utilities for matrix types.
C Language Family Type Representation.
C++ view class that accepts both !cir.struct and !cir.union types.
Definition CIRTypes.h:149
bool isComplete() const
Definition CIRTypes.h:168
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:245
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
CanQualType getCanonicalTagType(const TagDecl *TD) const
unsigned getTargetAddressSpace(LangAS AS) const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3820
QualType getElementType() const
Definition TypeBase.h:3832
unsigned getIndexTypeCVRQualifiers() const
Definition TypeBase.h:3842
const_arg_iterator argTypesEnd() const
static CIRGenFunctionInfo * create(cir::CallingConv cirCC, 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:51
cir::CallingConv clangCallConvToCIRCallConv(clang::CallingConv cc)
Convert a clang calling convention to a CIR calling convention.
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
mlir::ptr::MemorySpaceAttrInterface getPointerAddressSpace(clang::QualType pointeeTy) const
Returns the CIR address space for a pointer/reference to pointeeTy, or a null attribute for the defau...
CIRGenBuilderTy & getBuilder() const
Definition CIRGenTypes.h:90
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.
const CIRGenFunctionInfo & arrangeDeviceKernelCallerDeclaration(clang::QualType resultType, const FunctionArgList &args)
Arrange the function info for a device kernel caller entry point (e.g.
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.
Type for representing both the decl and type of parameters to a function.
Definition CIRGenCall.h:193
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:3858
llvm::APInt getSize() const
Return the constant array size as an APInt.
Definition TypeBase.h:3914
Represents a concrete matrix type with constant number of rows and columns.
Definition TypeBase.h:4490
unsigned getNumColumns() const
Returns the number of columns in the matrix.
Definition TypeBase.h:4512
unsigned getNumRows() const
Returns the number of rows in the matrix.
Definition TypeBase.h:4509
Represents a member of a struct/union/class.
Definition Decl.h:3299
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:4994
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5416
A class which abstracts out some details necessary for making a call.
Definition TypeBase.h:4723
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4612
static StringRef getNameForCallConv(CallingConv CC)
Definition Type.cpp:3849
QualType getReturnType() const
Definition TypeBase.h:4952
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:60
const Decl * getDecl() const
Definition GlobalDecl.h:115
Represents a C array with an unspecified size.
Definition TypeBase.h:4007
QualType getElementType() const
Returns type of the elements being stored in the matrix.
Definition TypeBase.h:4454
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3751
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:3403
QualType getPointeeType() const
Definition TypeBase.h:3413
A (possibly-)qualified type.
Definition TypeBase.h:938
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8446
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8572
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
QualType getCanonicalType() const
Definition TypeBase.h:8498
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8540
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Definition TypeBase.h:8567
bool isCanonical() const
Definition TypeBase.h:8503
Represents a struct/union/class.
Definition Decl.h:4464
field_range fields() const
Definition Decl.h:4667
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition Decl.h:4648
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3678
QualType getPointeeType() const
Definition TypeBase.h:3700
Encodes a location in the source.
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3856
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3957
The base class of the type hierarchy.
Definition TypeBase.h:1879
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
CanQualType getCanonicalTypeUnqualified() const
bool isAtomicType() const
Definition TypeBase.h:8875
EnumDecl * castAsEnumDecl() const
Definition Type.h:59
bool isFunctionType() const
Definition TypeBase.h:8679
TypeClass getTypeClass() const
Definition TypeBase.h:2449
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
bool isNullPtrType() const
Definition TypeBase.h:9109
Represents a variable declaration or definition.
Definition Decl.h:933
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:4064
Represents a GCC generic vector type.
Definition TypeBase.h:4273
unsigned getNumElements() const
Definition TypeBase.h:4288
QualType getElementType() const
Definition TypeBase.h:4287
Defines the clang::TargetInfo interface.
mlir::ptr::MemorySpaceAttrInterface toCIRAddressSpaceAttr(mlir::MLIRContext &ctx, clang::LangAS langAS)
Convert an AST LangAS to the appropriate CIR address space attribute 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.
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
Definition Address.h:330
QualType pointeeType(QualType T)
bool isInstanceMethod(const Decl *D)
Definition Attr.h:158
bool isMatrixRowMajor(const LangOptions &LangOpts, QualType T)
Returns true if matrices of T should be laid out in row-major order.
Definition MatrixUtils.h:25
CallingConv
CallingConv - Specifies the calling convention that a function uses.
Definition Specifiers.h:282
@ CC_DeviceKernel
Definition Specifiers.h:295
U cast(CodeGen::Address addr)
Definition Address.h:327
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 SuppressInlineNamespace
Suppress printing parts of scope specifiers that correspond to inline namespaces.