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