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 = cir::VectorType::getScalable(builder.getSInt8Ty(), 16);
383 break;
384 case BuiltinType::SveUint8:
385 resultType = cir::VectorType::getScalable(builder.getUInt8Ty(), 16);
386 break;
387 case BuiltinType::SveInt16:
388 resultType = cir::VectorType::getScalable(builder.getSInt16Ty(), 8);
389 break;
390 case BuiltinType::SveUint16:
391 resultType = cir::VectorType::getScalable(builder.getUInt16Ty(), 8);
392 break;
393 case BuiltinType::SveFloat16:
394 resultType = cir::VectorType::getScalable(builder.getFp16Ty(), 8);
395 break;
396 case BuiltinType::SveBFloat16:
397 resultType = cir::VectorType::getScalable(builder.getBfloat16Ty(), 8);
398 break;
399 case BuiltinType::SveInt32:
400 resultType = cir::VectorType::getScalable(builder.getSInt32Ty(), 4);
401 break;
402 case BuiltinType::SveUint32:
403 resultType = cir::VectorType::getScalable(builder.getUInt32Ty(), 4);
404 break;
405 case BuiltinType::SveFloat32:
406 resultType = cir::VectorType::getScalable(builder.getSingleTy(), 4);
407 break;
408 case BuiltinType::SveInt64:
409 resultType = cir::VectorType::getScalable(builder.getSInt64Ty(), 2);
410 break;
411 case BuiltinType::SveUint64:
412 resultType = cir::VectorType::getScalable(builder.getUInt64Ty(), 2);
413 break;
414 case BuiltinType::SveFloat64:
415 resultType = cir::VectorType::getScalable(builder.getDoubleTy(), 2);
416 break;
417 case BuiltinType::SveBool:
418 resultType = cir::VectorType::getScalable(builder.getUIntNTy(1), 16);
419 break;
420
421 // Unsigned integral types.
422 case BuiltinType::Char8:
423 case BuiltinType::Char16:
424 case BuiltinType::Char32:
425 case BuiltinType::Char_U:
426 case BuiltinType::UChar:
427 case BuiltinType::UInt:
428 case BuiltinType::UInt128:
429 case BuiltinType::ULong:
430 case BuiltinType::ULongLong:
431 case BuiltinType::UShort:
432 case BuiltinType::WChar_U:
433 case BuiltinType::UAccum:
434 case BuiltinType::UFract:
435 case BuiltinType::ULongAccum:
436 case BuiltinType::ULongFract:
437 case BuiltinType::UShortAccum:
438 case BuiltinType::UShortFract:
439 // Saturated unsigned types.
440 case BuiltinType::SatUAccum:
441 case BuiltinType::SatUFract:
442 case BuiltinType::SatULongAccum:
443 case BuiltinType::SatULongFract:
444 case BuiltinType::SatUShortAccum:
445 case BuiltinType::SatUShortFract:
446 resultType =
447 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
448 /*isSigned=*/false);
449 break;
450
451 // Floating-point types
452 case BuiltinType::Float16:
453 resultType = cgm.fP16Ty;
454 break;
455 case BuiltinType::Half:
456 resultType = cgm.fP16Ty;
457 break;
458 case BuiltinType::BFloat16:
459 resultType = cgm.bFloat16Ty;
460 break;
461 case BuiltinType::MFloat8:
462 resultType = cgm.uInt8Ty;
463 break;
464 case BuiltinType::Float:
465 assert(&astContext.getFloatTypeSemantics(type) ==
466 &llvm::APFloat::IEEEsingle() &&
467 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");
468 resultType = cgm.floatTy;
469 break;
470 case BuiltinType::Double:
471 assert(&astContext.getFloatTypeSemantics(type) ==
472 &llvm::APFloat::IEEEdouble() &&
473 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");
474 resultType = cgm.doubleTy;
475 break;
476 case BuiltinType::LongDouble:
477 resultType =
478 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(type));
479 break;
480 case BuiltinType::Float128:
481 resultType = cgm.fP128Ty;
482 break;
483 case BuiltinType::Ibm128:
484 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
485 resultType = cgm.sInt32Ty;
486 break;
487
488 case BuiltinType::NullPtr:
489 // Add proper CIR type for it? this looks mostly useful for sema related
490 // things (like for overloads accepting void), for now, given that
491 // `sizeof(std::nullptr_t)` is equal to `sizeof(void *)`, model
492 // std::nullptr_t as !cir.ptr<!void>
493 resultType = builder.getVoidPtrTy();
494 break;
495
496#define AMDGPU_OPAQUE_PTR_TYPE(Name, Id, SingletonId, Width, Align, AS) \
497 case BuiltinType::Id: { \
498 if (BuiltinType::Id == BuiltinType::AMDGPUTexture) { \
499 resultType = cir::VectorType::getFixed(builder.getSInt32Ty(), 8); \
500 } else { \
501 resultType = builder.getPointerTo( \
502 cgm.voidTy, \
503 cir::TargetAddressSpaceAttr::get(&getMLIRContext(), AS)); \
504 } \
505 break; \
506 }
507#define AMDGPU_NAMED_BARRIER_TYPE(Name, Id, SingletonId, Width, Align, Scope) \
508 case BuiltinType::Id: \
509 llvm_unreachable("NYI");
510#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) \
511 case BuiltinType::Id: \
512 llvm_unreachable("NYI");
513#include "clang/Basic/AMDGPUTypes.def"
514
515 default:
516 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
517 resultType = cgm.sInt32Ty;
518 break;
519 }
520 break;
521 }
522
523 case Type::Complex: {
524 const auto *ct = cast<clang::ComplexType>(ty);
525 mlir::Type elementTy = convertType(ct->getElementType());
526 resultType = cir::ComplexType::get(elementTy);
527 break;
528 }
529
530 case Type::LValueReference:
531 case Type::RValueReference: {
532 const ReferenceType *refTy = cast<ReferenceType>(ty);
533 QualType elemTy = refTy->getPointeeType();
534 auto pointeeType = convertTypeForMem(elemTy);
535 resultType =
536 builder.getPointerTo(pointeeType, getPointerAddressSpace(elemTy));
537 assert(resultType && "Cannot get pointer type?");
538 break;
539 }
540
541 case Type::Pointer: {
542 const PointerType *ptrTy = cast<PointerType>(ty);
543 QualType elemTy = ptrTy->getPointeeType();
544 mlir::Type pointeeType = convertType(elemTy);
545
546 resultType =
547 builder.getPointerTo(pointeeType, getPointerAddressSpace(elemTy));
548 break;
549 }
550
551 case Type::VariableArray: {
553 // CVR index qualifiers are ONLY valid on parameter arrays, which are
554 // automatically decayed to pointer, so they can't reach here. All other
555 // uses (outside of a top-level function parameter) is rejected by Sema, so
556 // we don't have to worry about these reaching here.
557 assert(a->getIndexTypeCVRQualifiers() == 0 &&
558 "Parameter types cannot make it here");
559 // VLAs resolve to the innermost element type; this matches
560 // the return of alloca, and there isn't any obviously better choice.
561 resultType = convertTypeForMem(a->getElementType());
562 break;
563 }
564
565 case Type::IncompleteArray: {
567 // CVR index qualifiers are ONLY valid on parameter arrays, which are
568 // automatically decayed to pointer, so they can't reach here. All other
569 // uses (outside of a top-level function parameter) is rejected by Sema, so
570 // we don't have to worry about these reaching here.
571 assert(arrTy->getIndexTypeCVRQualifiers() == 0 &&
572 "Parameter types cannot make it here");
573 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
574 // int X[] -> [0 x int], unless the element type is not sized. If it is
575 // unsized (e.g. an incomplete record) just use [0 x i8].
576 if (!cir::isSized(elemTy)) {
577 elemTy = cgm.sInt8Ty;
578 }
579
580 resultType = cir::ArrayType::get(elemTy, 0);
581 break;
582 }
583
584 case Type::ConstantArray: {
586 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
587 // In classic codegen, arrays of unsized types which it assumes are "arrays
588 // of undefined struct type" are lowered to arrays of i8 "just to have a
589 // concrete type", but in CIR, we can get here with abstract types like
590 // !cir.method and !cir.data_member, so we just create an array of the type
591 // and handle it during lowering if we still don't have a sized type.
592 resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue());
593 break;
594 }
595
596 case Type::ExtVector:
597 case Type::Vector: {
598 const VectorType *vec = cast<VectorType>(ty);
599 const mlir::Type elemTy = convertType(vec->getElementType());
600 resultType = cir::VectorType::getFixed(elemTy, vec->getNumElements());
601 break;
602 }
603
604 case Type::ConstantMatrix: {
606 const mlir::Type elemTy = convertType(mt->getElementType());
607 resultType =
608 cir::MatrixType::get(elemTy, mt->getNumRows(), mt->getNumColumns());
609 break;
610 }
611
612 case Type::Enum: {
613 const auto *ed = ty->castAsEnumDecl();
614 if (auto integerType = ed->getIntegerType(); !integerType.isNull())
615 return convertType(integerType);
616 // Return a placeholder 'i32' type. This can be changed later when the
617 // type is defined (see UpdateCompletedType), but is likely to be the
618 // "right" answer.
619 resultType = cgm.uInt32Ty;
620 break;
621 }
622
623 case Type::MemberPointer: {
624 const auto *mpt = cast<MemberPointerType>(ty);
625
626 NestedNameSpecifier mptNNS = mpt->getQualifier();
627 auto clsTy = mlir::cast<cir::RecordType>(
628 convertType(QualType(mptNNS.getAsType(), 0)));
629 if (mpt->isMemberDataPointer()) {
630 mlir::Type memberTy = convertType(mpt->getPointeeType());
631 resultType = cir::DataMemberType::get(memberTy, clsTy);
632 } else {
633 auto memberFuncTy = getFunctionType(cgm.getTypes().arrangeCXXMethodType(
634 mptNNS.getAsRecordDecl(),
635 mpt->getPointeeType()->getAs<clang::FunctionProtoType>(),
636 /*methodDecl=*/nullptr));
637 resultType = cir::MethodType::get(memberFuncTy, clsTy);
638 }
639 break;
640 }
641
642 case Type::FunctionNoProto:
643 case Type::FunctionProto:
644 resultType = convertFunctionTypeInternal(type);
645 break;
646
647 case Type::BitInt: {
648 const auto *bitIntTy = cast<BitIntType>(type);
649 unsigned numBits = bitIntTy->getNumBits();
650 assert(numBits <= cir::IntType::maxBitwidth() &&
651 "_BitInt width exceeds CIR IntType maximum");
652 resultType =
653 cir::IntType::get(&getMLIRContext(), numBits, bitIntTy->isSigned(),
654 /*isBitInt=*/true);
655 break;
656 }
657
658 case Type::Atomic: {
659 QualType valueType = cast<AtomicType>(ty)->getValueType();
660 resultType = convertTypeForMem(valueType);
661
662 // Pad out to the inflated size if necessary.
663 uint64_t valueSize = astContext.getTypeSize(valueType);
664 uint64_t atomicSize = astContext.getTypeSize(ty);
665 if (valueSize != atomicSize) {
666 assert(valueSize < atomicSize);
667 auto paddingArray =
668 cir::ArrayType::get(cgm.sInt8Ty, (atomicSize - valueSize) / 8);
669 mlir::Type elements[] = {resultType, paddingArray};
670 cir::RecordMemberKind kinds[] = {cir::RecordMemberKind::Data,
671 cir::RecordMemberKind::Pad};
672 resultType =
673 cir::StructType::get(&getMLIRContext(), /*members=*/elements,
674 /*packed=*/false, /*is_class=*/false, kinds);
675 }
676
677 break;
678 }
679
680 default:
681 cgm.errorNYI(SourceLocation(), "processing of type",
682 type->getTypeClassName());
683 resultType = cgm.sInt32Ty;
684 break;
685 }
686
687 assert(resultType && "Type conversion not yet implemented");
688
689 typeCache[ty] = resultType;
690 return resultType;
691}
692
694 bool forBitField) {
695 if (astContext.getLangOpts().HLSL && qualType->isConstantMatrixType()) {
696 if (isMatrixRowMajor(astContext.getLangOpts(), qualType)) {
697 cgm.errorNYI("convertTypeForMem: HLSL & Matrix row major");
698 }
699 }
700
701 mlir::Type convertedType = convertType(qualType);
702
703 assert(!forBitField && "Bit fields NYI");
704
705 // If this is a bit-precise integer type in a bitfield representation, map
706 // this integer to the target-specified size.
707 if (forBitField && qualType->isBitIntType())
708 assert(!qualType->isBitIntType() && "Bit field with type _BitInt NYI");
709
710 return convertedType;
711}
712
713/// Return record layout info for the given record decl.
714const CIRGenRecordLayout &
716 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
717
718 // If we have already computed the layout, return it.
719 auto it = cirGenRecordLayouts.find(key);
720 if (it != cirGenRecordLayouts.end())
721 return *it->second;
722
723 // Compute the type information.
725
726 // Now try again.
727 it = cirGenRecordLayouts.find(key);
728
729 assert(it != cirGenRecordLayouts.end() &&
730 "Unable to find record layout information for type");
731 return *it->second;
732}
733
735 if (t->getAs<PointerType>() || t->isNullPtrType())
736 return astContext.getTargetNullPointerValue(t) == 0;
737
738 if (const auto *at = astContext.getAsArrayType(t)) {
740 return true;
741
742 if (const auto *cat = dyn_cast<ConstantArrayType>(at))
743 if (astContext.getConstantArrayElementCount(cat) == 0)
744 return true;
745
746 t = astContext.getBaseElementType(t);
747 }
748
749 if (const auto *rd = t->getAsRecordDecl())
750 return isZeroInitializable(rd);
751
752 if (const auto *mpt = t->getAs<MemberPointerType>())
753 return theCXXABI.isZeroInitializable(mpt);
754
755 if (t->getAs<HLSLInlineSpirvType>())
756 cgm.errorNYI(SourceLocation(),
757 "isZeroInitializable for HLSLInlineSpirvType");
758
759 return true;
760}
761
765
766cir::CallingConv
768 switch (cc) {
769 case CC_C:
770 // SPIR/SPIR-V lowers the default CC to spir_func, not plain C.
771 if (cgm.getTriple().isSPIROrSPIRV())
772 return cir::CallingConv::SpirFunction;
773 return cir::CallingConv::C;
774 case CC_DeviceKernel:
775 return cgm.getTargetCIRGenInfo().getDeviceKernelCallingConv();
776 default:
777 // TODO(cir): Support the remaining target-specific calling conventions.
778 cgm.errorNYI(SourceLocation(), "calling convention",
780 return cir::CallingConv::C;
781 }
782}
783
784/// Whether a by-value ABI type is `_Atomic` or contains an `_Atomic` member.
785/// Pointers and references are not walked: `_Atomic(T)*` is just a pointer.
788 if (ty->isAtomicType())
789 return true;
790
791 if (const ArrayType *arrayTy = ctx.getAsArrayType(ty))
792 return typeContainsAtomicForABI(arrayTy->getElementType(), ctx);
793
794 const RecordDecl *rd = ty->getAsRecordDecl();
795 if (!rd || !rd->getDefinition())
796 return false;
797
798 if (const CXXRecordDecl *cxxRD = dyn_cast<CXXRecordDecl>(rd)) {
799 for (const CXXBaseSpecifier &base : cxxRD->bases())
800 if (typeContainsAtomicForABI(base.getType(), ctx))
801 return true;
802 }
803
804 for (const FieldDecl *field : rd->fields())
805 if (typeContainsAtomicForABI(field->getType(), ctx))
806 return true;
807 return false;
808}
809
811 CanQualType returnType, bool isInstanceMethod,
813 RequiredArgs required) {
814 assert(llvm::all_of(argTypes,
815 [](CanQualType t) { return t.isCanonicalAsParam(); }));
816 auto containsAtomic = [&](CanQualType t) {
817 return typeContainsAtomicForABI(t, astContext);
818 };
819 if (containsAtomic(returnType) || llvm::any_of(argTypes, containsAtomic))
820 cgm.errorNYI("passing or returning atomic types");
821 // Lookup or create unique function info.
822 llvm::FoldingSetNodeID id;
823 CIRGenFunctionInfo::Profile(id, isInstanceMethod, info, required, returnType,
824 argTypes);
825
826 llvm::FoldingSetInsertToken insertToken;
827 CIRGenFunctionInfo *fi = functionInfos.lookup(id, insertToken);
828 if (fi) {
829 // We found a matching function info based on id. These asserts verify that
830 // it really is a match.
831 assert(
832 fi->getReturnType() == returnType &&
833 std::equal(fi->argTypesBegin(), fi->argTypesEnd(), argTypes.begin()) &&
834 "Bad match based on CIRGenFunctionInfo folding set id");
835 return *fi;
836 }
837
838 cir::CallingConv cirCC = clangCallConvToCIRCallConv(info.getCC());
839
840 // Construction the function info. We co-allocate the ArgInfos.
841 fi = CIRGenFunctionInfo::create(cirCC, info, isInstanceMethod, returnType,
842 argTypes, required);
843 functionInfos.insert(fi, insertToken);
844
845 return *fi;
846}
847
848const CIRGenFunctionInfo &
850 const FunctionArgList &args) {
852 for (const VarDecl *arg : args)
853 argTypes.push_back(astContext.getCanonicalParamType(arg->getType()));
854
855 // Classic CodeGen passes FnInfoOpts::None here; that is the no-op case, so
856 // nothing is needed even once CIR models FnInfoOpts.
858 resultType->getCanonicalTypeUnqualified(), /*isInstanceMethod=*/false,
860}
861
863 assert(!dyn_cast<ObjCMethodDecl>(gd.getDecl()) &&
864 "This is reported as a FIXME in LLVM codegen");
865 const auto *fd = cast<FunctionDecl>(gd.getDecl());
866
870
872}
873
874// When we find the full definition for a TagDecl, replace the 'opaque' type we
875// previously made for it if applicable.
877 // If this is an enum being completed, then we flush all non-struct types
878 // from the cache. This allows function types and other things that may be
879 // derived from the enum to be recomputed.
880 if ([[maybe_unused]] const auto *ed = dyn_cast<EnumDecl>(td)) {
881 // Classic codegen clears the type cache if it contains an entry for this
882 // enum type that doesn't use i32 as the underlying type, but I can't find
883 // a test case that meets that condition. C++ doesn't allow forward
884 // declaration of enums, and C doesn't allow an incomplete forward
885 // declaration with a non-default type.
886 assert(
887 !typeCache.count(
888 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
889 (convertType(ed->getIntegerType()) ==
890 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
891 // If necessary, provide the full definition of a type only used with a
892 // declaration so far.
894 return;
895 }
896
897 // If we completed a RecordDecl that we previously used and converted to an
898 // anonymous type, then go ahead and complete it now.
899 const auto *rd = cast<RecordDecl>(td);
900 if (rd->isDependentType())
901 return;
902
903 // Only complete if we converted it already. If we haven't converted it yet,
904 // we'll just do it lazily.
905 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
907
908 // If necessary, provide the full definition of a type only used with a
909 // declaration so far.
911}
912
913mlir::ptr::MemorySpaceAttrInterface
915 // An explicit source address space is carried directly.
916 if (pointeeTy.getAddressSpace() != LangAS::Default)
918 pointeeTy.getAddressSpace());
919
920 // Resolve a default-address-space pointee through getTargetAddressSpace, as
921 // classic CodeGen does. This is only non-zero for languages that default to
922 // a non-default address space (e.g. generic for SYCL device data), and uses
923 // the program address space for functions.
924 unsigned targetAS = getTargetAddressSpace(pointeeTy);
925 if (targetAS == 0)
926 return {};
927 return cir::TargetAddressSpaceAttr::get(&getMLIRContext(), targetAS);
928}
929
931 // Return the address space for the type. If the type is a
932 // function type without an address space qualifier, the
933 // program address space is used. Otherwise, the target picks
934 // the best address space based on the type information
935 return ty->isFunctionType() && !ty.hasAddressSpace()
936 ? cgm.getDataLayout().getProgramAddressSpace()
938}
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:150
bool isComplete() const
Definition CIRTypes.h:169
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:195
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:4622
unsigned getNumColumns() const
Returns the number of columns in the matrix.
Definition TypeBase.h:4644
unsigned getNumRows() const
Returns the number of rows in the matrix.
Definition TypeBase.h:4641
Represents a member of a struct/union/class.
Definition Decl.h:3341
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition TypeBase.h:5126
Represents a prototype with parameter type info, e.g.
Definition TypeBase.h:5548
A class which abstracts out some details necessary for making a call.
Definition TypeBase.h:4855
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4744
static StringRef getNameForCallConv(CallingConv CC)
Definition Type.cpp:3847
QualType getReturnType() const
Definition TypeBase.h:5084
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:4586
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:8578
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8704
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
QualType getCanonicalType() const
Definition TypeBase.h:8630
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8672
bool hasAddressSpace() const
Check if this type has any address space qualifier.
Definition TypeBase.h:8699
bool isCanonical() const
Definition TypeBase.h:8635
Represents a struct/union/class.
Definition Decl.h:4506
field_range fields() const
Definition Decl.h:4709
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition Decl.h:4690
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:3898
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3999
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:9007
EnumDecl * castAsEnumDecl() const
Definition Type.h:59
bool isFunctionType() const
Definition TypeBase.h:8811
TypeClass getTypeClass() const
Definition TypeBase.h:2449
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9431
bool isNullPtrType() const
Definition TypeBase.h:9241
Represents a variable declaration or definition.
Definition Decl.h:934
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:4398
unsigned getNumElements() const
Definition TypeBase.h:4413
QualType getElementType() const
Definition TypeBase.h:4412
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:36
@ 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.