clang 22.0.0git
CIRGenTypes.cpp
Go to the documentation of this file.
1#include "CIRGenTypes.h"
2
4#include "CIRGenModule.h"
5
8#include "clang/AST/Type.h"
10
11#include <cassert>
12
13using namespace clang;
14using namespace clang::CIRGen;
15
17 : cgm(genModule), astContext(genModule.getASTContext()),
18 builder(cgm.getBuilder()), theCXXABI(cgm.getCXXABI()),
19 theABIInfo(cgm.getTargetCIRGenInfo().getABIInfo()) {}
20
22 for (auto i = functionInfos.begin(), e = functionInfos.end(); i != e;)
23 delete &*i++;
24}
25
26mlir::MLIRContext &CIRGenTypes::getMLIRContext() const {
27 return *builder.getContext();
28}
29
30/// Return true if the specified type in a function parameter or result position
31/// can be converted to a CIR type at this point. This boils down to being
32/// whether it is complete, as well as whether we've temporarily deferred
33/// expanding the type because we're in a recursive context.
35 // Some ABIs cannot have their member pointers represented in LLVM IR unless
36 // certain circumstances have been reached.
37 assert(!type->getAs<MemberPointerType>() && "NYI");
38
39 // If this isn't a tag type, we can convert it.
40 const TagType *tagType = type->getAs<TagType>();
41 if (!tagType)
42 return true;
43
44 // Function types involving incomplete class types are problematic in MLIR.
45 return !tagType->isIncompleteType();
46}
47
48/// Code to verify a given function type is complete, i.e. the return type and
49/// all of the parameter types are complete. Also check to see if we are in a
50/// RS_StructPointer context, and if so whether any struct types have been
51/// pended. If so, we don't want to ask the ABI lowering code to handle a type
52/// that cannot be converted to a CIR type.
55 return false;
56
57 if (const auto *fpt = dyn_cast<FunctionProtoType>(ft))
58 for (unsigned i = 0, e = fpt->getNumParams(); i != e; i++)
59 if (!isFuncParamTypeConvertible(fpt->getParamType(i)))
60 return false;
61
62 return true;
63}
64
65mlir::Type CIRGenTypes::convertFunctionTypeInternal(QualType qft) {
66 assert(qft.isCanonical());
68 // First, check whether we can build the full function type. If the function
69 // type depends on an incomplete type (e.g. a struct or enum), we cannot lower
70 // the function type.
71 if (!isFuncTypeConvertible(ft)) {
72 cgm.errorNYI(SourceLocation(), "function type involving an incomplete type",
73 qft);
74 return cir::FuncType::get(SmallVector<mlir::Type, 1>{}, cgm.voidTy);
75 }
76
77 const CIRGenFunctionInfo *fi;
78 if (const auto *fpt = dyn_cast<FunctionProtoType>(ft)) {
81 } else {
82 const FunctionNoProtoType *fnpt = cast<FunctionNoProtoType>(ft);
85 }
86
87 mlir::Type resultType = getFunctionType(*fi);
88
89 return resultType;
90}
91
92// This is CIR's version of CodeGenTypes::addRecordTypeName. It isn't shareable
93// because CIR has different uniquing requirements.
95 StringRef suffix) {
97 llvm::raw_svector_ostream outStream(typeName);
98
99 PrintingPolicy policy = recordDecl->getASTContext().getPrintingPolicy();
103 policy.PrintAsCanonical = true;
104 policy.SuppressTagKeyword = true;
105
106 if (recordDecl->getIdentifier())
107 QualType(astContext.getCanonicalTagType(recordDecl))
108 .print(outStream, policy);
109 else if (auto *typedefNameDecl = recordDecl->getTypedefNameForAnonDecl())
110 typedefNameDecl->printQualifiedName(outStream, policy);
111 else
112 outStream << builder.getUniqueAnonRecordName();
113
114 if (!suffix.empty())
115 outStream << suffix;
116
117 return builder.getUniqueRecordName(std::string(typeName));
118}
119
120/// Return true if the specified type is already completely laid out.
122 const auto it = recordDeclTypes.find(ty);
123 return it != recordDeclTypes.end() && it->second.isComplete();
124}
125
126// We have multiple forms of this function that call each other, so we need to
127// declare one in advance.
128static bool
130 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked);
131
132/// Return true if it is safe to convert the specified record decl to CIR and
133/// lay it out, false if doing so would cause us to get into a recursive
134/// compilation mess.
135static bool
137 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
138 // If we have already checked this type (maybe the same type is used by-value
139 // multiple times in multiple record fields, don't check again.
140 if (!alreadyChecked.insert(rd).second)
141 return true;
142
143 assert(rd->isCompleteDefinition() &&
144 "Expect RecordDecl to be CompleteDefinition");
145 const Type *key = cgt.getASTContext().getCanonicalTagType(rd).getTypePtr();
146
147 // If this type is already laid out, converting it is a noop.
148 if (cgt.isRecordLayoutComplete(key))
149 return true;
150
151 // If this type is currently being laid out, we can't recursively compile it.
152 if (cgt.isRecordBeingLaidOut(key))
153 return false;
154
155 // If this type would require laying out bases that are currently being laid
156 // out, don't do it. This includes virtual base classes which get laid out
157 // when a class is translated, even though they aren't embedded by-value into
158 // the class.
159 if (const CXXRecordDecl *crd = dyn_cast<CXXRecordDecl>(rd)) {
160 for (const clang::CXXBaseSpecifier &i : crd->bases())
161 if (!isSafeToConvert(i.getType()
162 ->castAs<RecordType>()
163 ->getDecl()
164 ->getDefinitionOrSelf(),
165 cgt, alreadyChecked))
166 return false;
167 }
168
169 // If this type would require laying out members that are currently being laid
170 // out, don't do it.
171 for (const FieldDecl *field : rd->fields())
172 if (!isSafeToConvert(field->getType(), cgt, alreadyChecked))
173 return false;
174
175 // If there are no problems, lets do it.
176 return true;
177}
178
179/// Return true if it is safe to convert this field type, which requires the
180/// record elements contained by-value to all be recursively safe to convert.
181static bool
183 llvm::SmallPtrSetImpl<const RecordDecl *> &alreadyChecked) {
184 // Strip off atomic type sugar.
185 if (const auto *at = qt->getAs<AtomicType>())
186 qt = at->getValueType();
187
188 // If this is a record, check it.
189 if (const auto *rd = qt->getAsRecordDecl())
190 return isSafeToConvert(rd, cgt, alreadyChecked);
191
192 // If this is an array, check the elements, which are embedded inline.
193 if (const auto *at = cgt.getASTContext().getAsArrayType(qt))
194 return isSafeToConvert(at->getElementType(), cgt, alreadyChecked);
195
196 // Otherwise, there is no concern about transforming this. We only care about
197 // things that are contained by-value in a record that can have another
198 // record as a member.
199 return true;
200}
201
202// Return true if it is safe to convert the specified record decl to CIR and lay
203// it out, false if doing so would cause us to get into a recursive compilation
204// mess.
205static bool isSafeToConvert(const RecordDecl *rd, CIRGenTypes &cgt) {
206 // If no records are being laid out, we can certainly do this one.
207 if (cgt.noRecordsBeingLaidOut())
208 return true;
209
211 return isSafeToConvert(rd, cgt, alreadyChecked);
212}
213
214/// Lay out a tagged decl type like struct or union.
216 // TagDecl's are not necessarily unique, instead use the (clang) type
217 // connected to the decl.
218 const Type *key = astContext.getCanonicalTagType(rd).getTypePtr();
219 cir::RecordType entry = recordDeclTypes[key];
220
221 // If we don't have an entry for this record yet, create one.
222 // We create an incomplete type initially. If `rd` is complete, we will
223 // add the members below.
224 if (!entry) {
225 auto name = getRecordTypeName(rd, "");
226 entry = builder.getIncompleteRecordTy(name, rd);
227 recordDeclTypes[key] = entry;
228 }
229
230 rd = rd->getDefinition();
231 if (!rd || !rd->isCompleteDefinition() || entry.isComplete())
232 return entry;
233
234 // If converting this type would cause us to infinitely loop, don't do it!
235 if (!isSafeToConvert(rd, *this)) {
236 deferredRecords.push_back(rd);
237 return entry;
238 }
239
240 // Okay, this is a definition of a type. Compile the implementation now.
241 bool insertResult = recordsBeingLaidOut.insert(key).second;
242 (void)insertResult;
243 assert(insertResult && "isSafeToCovert() should have caught this.");
244
245 // Force conversion of non-virtual base classes recursively.
246 if (const auto *cxxRecordDecl = dyn_cast<CXXRecordDecl>(rd)) {
247 for (const auto &base : cxxRecordDecl->bases()) {
248 if (base.isVirtual())
249 continue;
250 convertRecordDeclType(base.getType()->castAsRecordDecl());
251 }
252 }
253
254 // Layout fields.
255 std::unique_ptr<CIRGenRecordLayout> layout = computeRecordLayout(rd, &entry);
256 recordDeclTypes[key] = entry;
257 cirGenRecordLayouts[key] = std::move(layout);
258
259 // We're done laying out this record.
260 bool eraseResult = recordsBeingLaidOut.erase(key);
261 (void)eraseResult;
262 assert(eraseResult && "record not in RecordsBeingLaidOut set?");
263
264 // If this record blocked a FunctionType conversion, then recompute whatever
265 // was derived from that.
267
268 // If we're done converting the outer-most record, then convert any deferred
269 // records as well.
270 if (recordsBeingLaidOut.empty())
271 while (!deferredRecords.empty())
272 convertRecordDeclType(deferredRecords.pop_back_val());
273
274 return entry;
275}
276
278 type = astContext.getCanonicalType(type);
279 const Type *ty = type.getTypePtr();
280
281 // Process record types before the type cache lookup.
282 if (const auto *recordType = dyn_cast<RecordType>(type))
283 return convertRecordDeclType(recordType->getDecl()->getDefinitionOrSelf());
284
285 // Has the type already been processed?
286 TypeCacheTy::iterator tci = typeCache.find(ty);
287 if (tci != typeCache.end())
288 return tci->second;
289
290 // For types that haven't been implemented yet or are otherwise unsupported,
291 // report an error and return 'int'.
292
293 mlir::Type resultType = nullptr;
294 switch (ty->getTypeClass()) {
295 case Type::Record:
296 llvm_unreachable("Should have been handled above");
297
298 case Type::Builtin: {
299 switch (cast<BuiltinType>(ty)->getKind()) {
300 // void
301 case BuiltinType::Void:
302 resultType = cgm.voidTy;
303 break;
304
305 // bool
306 case BuiltinType::Bool:
307 resultType = cir::BoolType::get(&getMLIRContext());
308 break;
309
310 // Signed integral types.
311 case BuiltinType::Char_S:
312 case BuiltinType::Int:
313 case BuiltinType::Int128:
314 case BuiltinType::Long:
315 case BuiltinType::LongLong:
316 case BuiltinType::SChar:
317 case BuiltinType::Short:
318 case BuiltinType::WChar_S:
319 resultType =
320 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
321 /*isSigned=*/true);
322 break;
323 // Unsigned integral types.
324 case BuiltinType::Char8:
325 case BuiltinType::Char16:
326 case BuiltinType::Char32:
327 case BuiltinType::Char_U:
328 case BuiltinType::UChar:
329 case BuiltinType::UInt:
330 case BuiltinType::UInt128:
331 case BuiltinType::ULong:
332 case BuiltinType::ULongLong:
333 case BuiltinType::UShort:
334 case BuiltinType::WChar_U:
335 resultType =
336 cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
337 /*isSigned=*/false);
338 break;
339
340 // Floating-point types
341 case BuiltinType::Float16:
342 resultType = cgm.fP16Ty;
343 break;
344 case BuiltinType::Half:
345 if (astContext.getLangOpts().NativeHalfType ||
346 !astContext.getTargetInfo().useFP16ConversionIntrinsics()) {
347 resultType = cgm.fP16Ty;
348 } else {
349 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
350 resultType = cgm.sInt32Ty;
351 }
352 break;
353 case BuiltinType::BFloat16:
354 resultType = cgm.bFloat16Ty;
355 break;
356 case BuiltinType::Float:
357 assert(&astContext.getFloatTypeSemantics(type) ==
358 &llvm::APFloat::IEEEsingle() &&
359 "ClangIR NYI: 'float' in a format other than IEEE 32-bit");
360 resultType = cgm.floatTy;
361 break;
362 case BuiltinType::Double:
363 assert(&astContext.getFloatTypeSemantics(type) ==
364 &llvm::APFloat::IEEEdouble() &&
365 "ClangIR NYI: 'double' in a format other than IEEE 64-bit");
366 resultType = cgm.doubleTy;
367 break;
368 case BuiltinType::LongDouble:
369 resultType =
370 builder.getLongDoubleTy(astContext.getFloatTypeSemantics(type));
371 break;
372 case BuiltinType::Float128:
373 resultType = cgm.fP128Ty;
374 break;
375 case BuiltinType::Ibm128:
376 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
377 resultType = cgm.sInt32Ty;
378 break;
379
380 case BuiltinType::NullPtr:
381 // Add proper CIR type for it? this looks mostly useful for sema related
382 // things (like for overloads accepting void), for now, given that
383 // `sizeof(std::nullptr_t)` is equal to `sizeof(void *)`, model
384 // std::nullptr_t as !cir.ptr<!void>
385 resultType = builder.getVoidPtrTy();
386 break;
387
388 default:
389 cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
390 resultType = cgm.sInt32Ty;
391 break;
392 }
393 break;
394 }
395
396 case Type::Complex: {
397 const auto *ct = cast<clang::ComplexType>(ty);
398 mlir::Type elementTy = convertType(ct->getElementType());
399 resultType = cir::ComplexType::get(elementTy);
400 break;
401 }
402
403 case Type::LValueReference:
404 case Type::RValueReference: {
405 const ReferenceType *refTy = cast<ReferenceType>(ty);
406 QualType elemTy = refTy->getPointeeType();
407 auto pointeeType = convertTypeForMem(elemTy);
408 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
409 assert(resultType && "Cannot get pointer type?");
410 break;
411 }
412
413 case Type::Pointer: {
414 const PointerType *ptrTy = cast<PointerType>(ty);
415 QualType elemTy = ptrTy->getPointeeType();
416 assert(!elemTy->isConstantMatrixType() && "not implemented");
417
418 mlir::Type pointeeType = convertType(elemTy);
419
420 resultType = builder.getPointerTo(pointeeType, elemTy.getAddressSpace());
421 break;
422 }
423
424 case Type::VariableArray: {
426 if (a->getIndexTypeCVRQualifiers() != 0)
427 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
428 // VLAs resolve to the innermost element type; this matches
429 // the return of alloca, and there isn't any obviously better choice.
430 resultType = convertTypeForMem(a->getElementType());
431 break;
432 }
433
434 case Type::IncompleteArray: {
436 if (arrTy->getIndexTypeCVRQualifiers() != 0)
437 cgm.errorNYI(SourceLocation(), "non trivial array types", type);
438
439 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
440 // int X[] -> [0 x int], unless the element type is not sized. If it is
441 // unsized (e.g. an incomplete record) just use [0 x i8].
442 if (!cir::isSized(elemTy)) {
443 elemTy = cgm.sInt8Ty;
444 }
445
446 resultType = cir::ArrayType::get(elemTy, 0);
447 break;
448 }
449
450 case Type::ConstantArray: {
452 mlir::Type elemTy = convertTypeForMem(arrTy->getElementType());
453
454 // TODO(CIR): In LLVM, "lower arrays of undefined struct type to arrays of
455 // i8 just to have a concrete type"
456 if (!cir::isSized(elemTy)) {
457 cgm.errorNYI(SourceLocation(), "arrays of undefined struct type", type);
458 resultType = cgm.uInt32Ty;
459 break;
460 }
461
462 resultType = cir::ArrayType::get(elemTy, arrTy->getSize().getZExtValue());
463 break;
464 }
465
466 case Type::ExtVector:
467 case Type::Vector: {
468 const VectorType *vec = cast<VectorType>(ty);
469 const mlir::Type elemTy = convertType(vec->getElementType());
470 resultType = cir::VectorType::get(elemTy, vec->getNumElements());
471 break;
472 }
473
474 case Type::Enum: {
475 const auto *ed = ty->castAsEnumDecl();
476 if (auto integerType = ed->getIntegerType(); !integerType.isNull())
477 return convertType(integerType);
478 // Return a placeholder 'i32' type. This can be changed later when the
479 // type is defined (see UpdateCompletedType), but is likely to be the
480 // "right" answer.
481 resultType = cgm.uInt32Ty;
482 break;
483 }
484
485 case Type::MemberPointer: {
486 const auto *mpt = cast<MemberPointerType>(ty);
487
488 mlir::Type memberTy = convertType(mpt->getPointeeType());
489 auto clsTy = mlir::cast<cir::RecordType>(
490 convertType(QualType(mpt->getQualifier().getAsType(), 0)));
491 if (mpt->isMemberDataPointer()) {
492 resultType = cir::DataMemberType::get(memberTy, clsTy);
493 } else {
495 cgm.errorNYI(SourceLocation(), "MethodType");
496 }
497 break;
498 }
499
500 case Type::FunctionNoProto:
501 case Type::FunctionProto:
502 resultType = convertFunctionTypeInternal(type);
503 break;
504
505 case Type::BitInt: {
506 const auto *bitIntTy = cast<BitIntType>(type);
507 if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {
508 cgm.errorNYI(SourceLocation(), "large _BitInt type", type);
509 resultType = cgm.sInt32Ty;
510 } else {
511 resultType = cir::IntType::get(&getMLIRContext(), bitIntTy->getNumBits(),
512 bitIntTy->isSigned());
513 }
514 break;
515 }
516
517 case Type::Atomic: {
518 QualType valueType = cast<AtomicType>(ty)->getValueType();
519 resultType = convertTypeForMem(valueType);
520
521 // Pad out to the inflated size if necessary.
522 uint64_t valueSize = astContext.getTypeSize(valueType);
523 uint64_t atomicSize = astContext.getTypeSize(ty);
524 if (valueSize != atomicSize) {
525 cgm.errorNYI("convertType: atomic type value size != atomic size");
526 }
527
528 break;
529 }
530
531 default:
532 cgm.errorNYI(SourceLocation(), "processing of type",
533 type->getTypeClassName());
534 resultType = cgm.sInt32Ty;
535 break;
536 }
537
538 assert(resultType && "Type conversion not yet implemented");
539
540 typeCache[ty] = resultType;
541 return resultType;
542}
543
545 bool forBitField) {
546 assert(!qualType->isConstantMatrixType() && "Matrix types NYI");
547
548 mlir::Type convertedType = convertType(qualType);
549
550 assert(!forBitField && "Bit fields NYI");
551
552 // If this is a bit-precise integer type in a bitfield representation, map
553 // this integer to the target-specified size.
554 if (forBitField && qualType->isBitIntType())
555 assert(!qualType->isBitIntType() && "Bit field with type _BitInt NYI");
556
557 return convertedType;
558}
559
560/// Return record layout info for the given record decl.
561const CIRGenRecordLayout &
563 const auto *key = astContext.getCanonicalTagType(rd).getTypePtr();
564
565 // If we have already computed the layout, return it.
566 auto it = cirGenRecordLayouts.find(key);
567 if (it != cirGenRecordLayouts.end())
568 return *it->second;
569
570 // Compute the type information.
572
573 // Now try again.
574 it = cirGenRecordLayouts.find(key);
575
576 assert(it != cirGenRecordLayouts.end() &&
577 "Unable to find record layout information for type");
578 return *it->second;
579}
580
582 if (t->getAs<PointerType>())
583 return astContext.getTargetNullPointerValue(t) == 0;
584
585 if (const auto *at = astContext.getAsArrayType(t)) {
587 return true;
588
589 if (const auto *cat = dyn_cast<ConstantArrayType>(at))
590 if (astContext.getConstantArrayElementCount(cat) == 0)
591 return true;
592 }
593
594 if (const auto *rd = t->getAsRecordDecl())
595 return isZeroInitializable(rd);
596
597 if (t->getAs<MemberPointerType>()) {
598 cgm.errorNYI(SourceLocation(), "isZeroInitializable for MemberPointerType",
599 t);
600 return false;
601 }
602
603 return true;
604}
605
609
610const CIRGenFunctionInfo &
613 RequiredArgs required) {
614 assert(llvm::all_of(argTypes,
615 [](CanQualType t) { return t.isCanonicalAsParam(); }));
616 // Lookup or create unique function info.
617 llvm::FoldingSetNodeID id;
618 CIRGenFunctionInfo::Profile(id, required, returnType, argTypes);
619
620 void *insertPos = nullptr;
621 CIRGenFunctionInfo *fi = functionInfos.FindNodeOrInsertPos(id, insertPos);
622 if (fi) {
623 // We found a matching function info based on id. These asserts verify that
624 // it really is a match.
625 assert(
626 fi->getReturnType() == returnType &&
627 std::equal(fi->argTypesBegin(), fi->argTypesEnd(), argTypes.begin()) &&
628 "Bad match based on CIRGenFunctionInfo folding set id");
629 return *fi;
630 }
631
633
634 // Construction the function info. We co-allocate the ArgInfos.
635 fi = CIRGenFunctionInfo::create(returnType, argTypes, required);
636 functionInfos.InsertNode(fi, insertPos);
637
638 return *fi;
639}
640
642 assert(!dyn_cast<ObjCMethodDecl>(gd.getDecl()) &&
643 "This is reported as a FIXME in LLVM codegen");
644 const auto *fd = cast<FunctionDecl>(gd.getDecl());
645
649
651}
652
653// When we find the full definition for a TagDecl, replace the 'opaque' type we
654// previously made for it if applicable.
656 // If this is an enum being completed, then we flush all non-struct types
657 // from the cache. This allows function types and other things that may be
658 // derived from the enum to be recomputed.
659 if (const auto *ed = dyn_cast<EnumDecl>(td)) {
660 // Classic codegen clears the type cache if it contains an entry for this
661 // enum type that doesn't use i32 as the underlying type, but I can't find
662 // a test case that meets that condition. C++ doesn't allow forward
663 // declaration of enums, and C doesn't allow an incomplete forward
664 // declaration with a non-default type.
665 assert(
666 !typeCache.count(
667 ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()) ||
668 (convertType(ed->getIntegerType()) ==
669 typeCache[ed->getASTContext().getCanonicalTagType(ed)->getTypePtr()]));
670 // If necessary, provide the full definition of a type only used with a
671 // declaration so far.
673 return;
674 }
675
676 // If we completed a RecordDecl that we previously used and converted to an
677 // anonymous type, then go ahead and complete it now.
678 const auto *rd = cast<RecordDecl>(td);
679 if (rd->isDependentType())
680 return;
681
682 // Only complete if we converted it already. If we haven't converted it yet,
683 // we'll just do it lazily.
684 if (recordDeclTypes.count(astContext.getCanonicalTagType(rd).getTypePtr()))
686
687 // If necessary, provide the full definition of a type only used with a
688 // declaration so far.
690}
Defines the clang::ASTContext interface.
static bool isSafeToConvert(QualType qt, CIRGenTypes &cgt, llvm::SmallPtrSetImpl< const RecordDecl * > &alreadyChecked)
Return true if it is safe to convert this field type, which requires the record elements contained by...
static Decl::Kind getKind(const Decl *D)
C Language Family Type Representation.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
CanQualType getCanonicalTagType(const TagDecl *TD) const
QualType getElementType() const
Definition TypeBase.h:3735
unsigned getIndexTypeCVRQualifiers() const
Definition TypeBase.h:3745
const_arg_iterator argTypesEnd() const
static void Profile(llvm::FoldingSetNodeID &id, RequiredArgs required, CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes)
const_arg_iterator argTypesBegin() const
static CIRGenFunctionInfo * create(CanQualType resultType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
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:48
const CIRGenFunctionInfo & arrangeGlobalDeclaration(GlobalDecl gd)
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
const CIRGenFunctionInfo & arrangeFreeFunctionType(CanQual< FunctionProtoType > fpt)
bool isZeroInitializable(clang::QualType ty)
Return whether a type can be zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
bool isFuncTypeConvertible(const clang::FunctionType *ft)
Utility to check whether a function type can be converted to a CIR type (i.e.
CIRGenTypes(CIRGenModule &cgm)
bool isRecordBeingLaidOut(const clang::Type *ty) const
CIRGenBuilderTy & getBuilder() const
Definition CIRGenTypes.h:81
mlir::MLIRContext & getMLIRContext() const
const CIRGenFunctionInfo & arrangeCIRFunctionInfo(CanQualType returnType, llvm::ArrayRef< CanQualType > argTypes, RequiredArgs required)
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
bool isFuncParamTypeConvertible(clang::QualType type)
Return true if the specified type in a function parameter or result position can be converted to a CI...
void updateCompletedType(const clang::TagDecl *td)
UpdateCompletedType - when we find the full definition for a TagDecl, replace the 'opaque' type we pr...
std::string getRecordTypeName(const clang::RecordDecl *, llvm::StringRef suffix)
bool noRecordsBeingLaidOut() const
const ABIInfo & getABIInfo() const
const CIRGenFunctionInfo & arrangeFunctionDeclaration(const clang::FunctionDecl *fd)
Free functions are functions that are compatible with an ordinary C function pointer type.
clang::ASTContext & getASTContext() const
bool isRecordLayoutComplete(const clang::Type *ty) const
Return true if the specified type is already completely laid out.
mlir::Type convertType(clang::QualType type)
Convert a Clang type into a mlir::Type.
const CIRGenRecordLayout & getCIRGenRecordLayout(const clang::RecordDecl *rd)
Return record layout info for the given record decl.
std::unique_ptr< CIRGenRecordLayout > computeRecordLayout(const clang::RecordDecl *rd, cir::RecordType *ty)
mlir::Type convertRecordDeclType(const clang::RecordDecl *recordDecl)
Lay out a tagged decl type like struct or union.
mlir::Type convertTypeForMem(clang::QualType, bool forBitField=false)
Convert type T into an mlir::Type.
A class for recording the number of arguments that a function signature requires.
Represents a base class of a C++ class.
Definition DeclCXX.h:146
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
static CanQual< T > CreateUnsafe(QualType Other)
Builds a canonical type from a QualType.
bool isCanonicalAsParam() const
Determines if this canonical type is furthermore canonical as a parameter.
const T * getTypePtr() const
Retrieve the underlying type pointer, which refers to a canonical type.
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3761
llvm::APInt getSize() const
Return the constant array size as an APInt.
Definition TypeBase.h:3817
Represents a member of a struct/union/class.
Definition Decl.h:3160
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4465
QualType getReturnType() const
Definition TypeBase.h:4805
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
const Decl * getDecl() const
Definition GlobalDecl.h:106
Represents a C array with an unspecified size.
Definition TypeBase.h:3910
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition TypeBase.h:3654
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3329
QualType getPointeeType() const
Definition TypeBase.h:3339
A (possibly-)qualified type.
Definition TypeBase.h:937
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8293
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8419
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
bool isCanonical() const
Definition TypeBase.h:8350
Represents a struct/union/class.
Definition Decl.h:4321
field_range fields() const
Definition Decl.h:4524
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition Decl.h:4505
Base for LValueReferenceType and RValueReferenceType.
Definition TypeBase.h:3574
QualType getPointeeType() const
Definition TypeBase.h:3592
Encodes a location in the source.
Represents the declaration of a struct/union/class/enum.
Definition Decl.h:3717
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3812
The base class of the type hierarchy.
Definition TypeBase.h:1833
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isConstantMatrixType() const
Definition TypeBase.h:8697
EnumDecl * castAsEnumDecl() const
Definition Type.h:59
TypeClass getTypeClass() const
Definition TypeBase.h:2385
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9112
Represents a C array with a specified size that is not an integer-constant-expression.
Definition TypeBase.h:3967
Represents a GCC generic vector type.
Definition TypeBase.h:4176
unsigned getNumElements() const
Definition TypeBase.h:4191
QualType getElementType() const
Definition TypeBase.h:4190
Defines the clang::TargetInfo interface.
bool isSized(mlir::Type ty)
Returns true if the type is a CIR sized type.
Definition CIRTypes.cpp:30
@ Type
The l-value was considered opaque, so the alignment was determined from a type.
const internal::VariadicDynCastAllOfMatcher< Decl, TypedefNameDecl > typedefNameDecl
Matches typedef name declarations.
const AstTypeMatcher< TagType > tagType
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const AstTypeMatcher< RecordType > recordType
const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl
Matches C++ class declarations.
const internal::VariadicDynCastAllOfMatcher< Decl, RecordDecl > recordDecl
Matches class, struct, and union declarations.
const internal::VariadicAllOfMatcher< QualType > qualType
Matches QualTypes in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
Definition Address.h:330
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool skippedLayout()
static bool opCallCallConv()
static bool generateDebugInfo()
Describes how types, statements, expressions, and declarations should be printed.
unsigned SuppressTagKeyword
Whether type printing should skip printing the tag keyword.
unsigned AlwaysIncludeTypeForTemplateArgument
Whether to use type suffixes (eg: 1U) on integral non-type template parameters.
unsigned SuppressInlineNamespace
Suppress printing parts of scope specifiers that correspond to inline namespaces.
unsigned PrintAsCanonical
Whether to print entities as written or canonically.