Thanks to visit codestin.com
Credit goes to clang.llvm.org

clang 22.0.0git
CIRGenItaniumCXXABI.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This provides C++ code generation targeting the Itanium C++ ABI. The class
10// in this file generates structures that follow the Itanium C++ ABI, which is
11// documented at:
12// https://itanium-cxx-abi.github.io/cxx-abi/abi.html
13// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
14//
15// It also supports the closely-related ARM ABI, documented at:
16// https://developer.arm.com/documentation/ihi0041/g/
17//
18//===----------------------------------------------------------------------===//
19
20#include "CIRGenCXXABI.h"
21#include "CIRGenFunction.h"
22
23#include "clang/AST/ExprCXX.h"
27#include "llvm/Support/ErrorHandling.h"
28
29using namespace clang;
30using namespace clang::CIRGen;
31
32namespace {
33
34class CIRGenItaniumCXXABI : public CIRGenCXXABI {
35protected:
36 /// All the vtables which have been defined.
37 llvm::DenseMap<const CXXRecordDecl *, cir::GlobalOp> vtables;
38
39public:
40 CIRGenItaniumCXXABI(CIRGenModule &cgm) : CIRGenCXXABI(cgm) {
43 }
44
45 AddedStructorArgs getImplicitConstructorArgs(CIRGenFunction &cgf,
46 const CXXConstructorDecl *d,
48 bool forVirtualBase,
49 bool delegating) override;
50
51 bool needsVTTParameter(clang::GlobalDecl gd) override;
52
53 AddedStructorArgCounts
54 buildStructorSignature(GlobalDecl gd,
55 llvm::SmallVectorImpl<CanQualType> &argTys) override;
56
57 void emitInstanceFunctionProlog(SourceLocation loc,
58 CIRGenFunction &cgf) override;
59
60 void addImplicitStructorParams(CIRGenFunction &cgf, QualType &resTy,
61 FunctionArgList &params) override;
62
63 void emitCXXConstructors(const clang::CXXConstructorDecl *d) override;
64 void emitCXXDestructors(const clang::CXXDestructorDecl *d) override;
65 void emitCXXStructor(clang::GlobalDecl gd) override;
66
67 void emitDestructorCall(CIRGenFunction &cgf, const CXXDestructorDecl *dd,
68 CXXDtorType type, bool forVirtualBase,
69 bool delegating, Address thisAddr,
70 QualType thisTy) override;
71
72 void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;
73
74 bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
75 CXXDtorType dt) const override {
76 // Itanium does not emit any destructor variant as an inline thunk.
77 // Delegating may occur as an optimization, but all variants are either
78 // emitted with external linkage or as linkonce if they are inline and used.
79 return false;
80 }
81
82 bool isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
83 CIRGenFunction::VPtr vptr) override;
84
85 cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd,
86 CharUnits vptrOffset) override;
87 CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf,
88 clang::GlobalDecl gd, Address thisAddr,
89 mlir::Type ty,
90 SourceLocation loc) override;
91
92 mlir::Value getVTableAddressPoint(BaseSubobject base,
93 const CXXRecordDecl *vtableClass) override;
94 mlir::Value getVTableAddressPointInStructorWithVTT(
95 CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
96 const CXXRecordDecl *nearestVBase);
97
98 mlir::Value getVTableAddressPointInStructor(
99 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,
100 clang::BaseSubobject base,
101 const clang::CXXRecordDecl *nearestVBase) override;
102 void emitVTableDefinitions(CIRGenVTables &cgvt,
103 const CXXRecordDecl *rd) override;
104 void emitVirtualInheritanceTables(const CXXRecordDecl *rd) override;
105
106 mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
107 QualType ty) override;
108
109 bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {
110 return true;
111 }
112
113 mlir::Value
114 getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf,
115 Address thisAddr, const CXXRecordDecl *classDecl,
116 const CXXRecordDecl *baseClassDecl) override;
117
118 /**************************** RTTI Uniqueness ******************************/
119protected:
120 /// Returns true if the ABI requires RTTI type_info objects to be unique
121 /// across a program.
122 virtual bool shouldRTTIBeUnique() const { return true; }
123
124public:
125 /// What sort of unique-RTTI behavior should we use?
126 enum RTTIUniquenessKind {
127 /// We are guaranteeing, or need to guarantee, that the RTTI string
128 /// is unique.
129 RUK_Unique,
130
131 /// We are not guaranteeing uniqueness for the RTTI string, so we
132 /// can demote to hidden visibility but must use string comparisons.
133 RUK_NonUniqueHidden,
134
135 /// We are not guaranteeing uniqueness for the RTTI string, so we
136 /// have to use string comparisons, but we also have to emit it with
137 /// non-hidden visibility.
138 RUK_NonUniqueVisible
139 };
140
141 /// Return the required visibility status for the given type and linkage in
142 /// the current ABI.
143 RTTIUniquenessKind
144 classifyRTTIUniqueness(QualType canTy, cir::GlobalLinkageKind linkage) const;
145};
146
147} // namespace
148
149void CIRGenItaniumCXXABI::emitInstanceFunctionProlog(SourceLocation loc,
150 CIRGenFunction &cgf) {
151 // Naked functions have no prolog.
152 if (cgf.curFuncDecl && cgf.curFuncDecl->hasAttr<NakedAttr>()) {
154 "emitInstanceFunctionProlog: Naked");
155 }
156
157 /// Initialize the 'this' slot. In the Itanium C++ ABI, no prologue
158 /// adjustments are required, because they are all handled by thunks.
159 setCXXABIThisValue(cgf, loadIncomingCXXThis(cgf));
160
161 /// Initialize the 'vtt' slot if needed.
162 if (getStructorImplicitParamDecl(cgf)) {
163 cir::LoadOp val = cgf.getBuilder().createLoad(
164 cgf.getLoc(loc),
165 cgf.getAddrOfLocalVar(getStructorImplicitParamDecl(cgf)));
166 setStructorImplicitParamValue(cgf, val);
167 }
168
169 /// If this is a function that the ABI specifies returns 'this', initialize
170 /// the return slot to this' at the start of the function.
171 ///
172 /// Unlike the setting of return types, this is done within the ABI
173 /// implementation instead of by clients of CIRGenCXXBI because:
174 /// 1) getThisValue is currently protected
175 /// 2) in theory, an ABI could implement 'this' returns some other way;
176 /// HasThisReturn only specifies a contract, not the implementation
177 if (hasThisReturn(cgf.curGD)) {
179 "emitInstanceFunctionProlog: hasThisReturn");
180 }
181}
182
183CIRGenCXXABI::AddedStructorArgCounts
184CIRGenItaniumCXXABI::buildStructorSignature(
185 GlobalDecl gd, llvm::SmallVectorImpl<CanQualType> &argTys) {
186 clang::ASTContext &astContext = cgm.getASTContext();
187
188 // All parameters are already in place except VTT, which goes after 'this'.
189 // These are clang types, so we don't need to worry about sret yet.
190
191 // Check if we need to add a VTT parameter (which has type void **).
193 : gd.getDtorType() == Dtor_Base) &&
194 cast<CXXMethodDecl>(gd.getDecl())->getParent()->getNumVBases() != 0) {
196 argTys.insert(argTys.begin() + 1,
197 astContext.getPointerType(
199 return AddedStructorArgCounts::withPrefix(1);
200 }
201
202 return AddedStructorArgCounts{};
203}
204
205// Find out how to cirgen the complete destructor and constructor
206namespace {
207enum class StructorCIRGen { Emit, RAUW, Alias, COMDAT };
208}
209
210static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm,
211 const CXXMethodDecl *md) {
212 if (!cgm.getCodeGenOpts().CXXCtorDtorAliases)
213 return StructorCIRGen::Emit;
214
215 // The complete and base structors are not equivalent if there are any virtual
216 // bases, so emit separate functions.
217 if (md->getParent()->getNumVBases())
218 return StructorCIRGen::Emit;
219
220 GlobalDecl aliasDecl;
221 if (const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
222 aliasDecl = GlobalDecl(dd, Dtor_Complete);
223 } else {
224 const auto *cd = cast<CXXConstructorDecl>(md);
225 aliasDecl = GlobalDecl(cd, Ctor_Complete);
226 }
227
228 cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);
229
230 if (cir::isDiscardableIfUnused(linkage))
231 return StructorCIRGen::RAUW;
232
233 // FIXME: Should we allow available_externally aliases?
234 if (!cir::isValidLinkage(linkage))
235 return StructorCIRGen::RAUW;
236
237 if (cir::isWeakForLinker(linkage)) {
238 // Only ELF and wasm support COMDATs with arbitrary names (C5/D5).
239 if (cgm.getTarget().getTriple().isOSBinFormatELF() ||
240 cgm.getTarget().getTriple().isOSBinFormatWasm())
241 return StructorCIRGen::COMDAT;
242 return StructorCIRGen::Emit;
243 }
244
245 return StructorCIRGen::Alias;
246}
247
249 GlobalDecl aliasDecl,
250 GlobalDecl targetDecl) {
251 cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);
252
253 // Does this function alias already exists?
254 StringRef mangledName = cgm.getMangledName(aliasDecl);
255 auto globalValue = dyn_cast_or_null<cir::CIRGlobalValueInterface>(
256 cgm.getGlobalValue(mangledName));
257 if (globalValue && !globalValue.isDeclaration())
258 return;
259
260 auto entry = cast_or_null<cir::FuncOp>(cgm.getGlobalValue(mangledName));
261
262 // Retrieve aliasee info.
263 auto aliasee = cast<cir::FuncOp>(cgm.getAddrOfGlobal(targetDecl));
264
265 // Populate actual alias.
266 cgm.emitAliasForGlobal(mangledName, entry, aliasDecl, aliasee, linkage);
267}
268
269void CIRGenItaniumCXXABI::emitCXXStructor(GlobalDecl gd) {
270 auto *md = cast<CXXMethodDecl>(gd.getDecl());
271 StructorCIRGen cirGenType = getCIRGenToUse(cgm, md);
272 const auto *cd = dyn_cast<CXXConstructorDecl>(md);
273
274 if (cd ? gd.getCtorType() == Ctor_Complete
275 : gd.getDtorType() == Dtor_Complete) {
276 GlobalDecl baseDecl =
278 ;
279
280 if (cirGenType == StructorCIRGen::Alias ||
281 cirGenType == StructorCIRGen::COMDAT) {
282 emitConstructorDestructorAlias(cgm, gd, baseDecl);
283 return;
284 }
285
286 if (cirGenType == StructorCIRGen::RAUW) {
287 StringRef mangledName = cgm.getMangledName(gd);
288 mlir::Operation *aliasee = cgm.getAddrOfGlobal(baseDecl);
289 cgm.addReplacement(mangledName, aliasee);
290 return;
291 }
292 }
293
294 auto fn = cgm.codegenCXXStructor(gd);
295
296 cgm.maybeSetTrivialComdat(*md, fn);
297}
298
299void CIRGenItaniumCXXABI::addImplicitStructorParams(CIRGenFunction &cgf,
300 QualType &resTy,
301 FunctionArgList &params) {
302 const auto *md = cast<CXXMethodDecl>(cgf.curGD.getDecl());
304
305 // Check if we need a VTT parameter as well.
306 if (needsVTTParameter(cgf.curGD)) {
307 ASTContext &astContext = cgm.getASTContext();
308
309 // FIXME: avoid the fake decl
311 QualType t = astContext.getPointerType(astContext.VoidPtrTy);
312 auto *vttDecl = ImplicitParamDecl::Create(
313 astContext, /*DC=*/nullptr, md->getLocation(),
314 &astContext.Idents.get("vtt"), t, ImplicitParamKind::CXXVTT);
315 params.insert(params.begin() + 1, vttDecl);
316 getStructorImplicitParamDecl(cgf) = vttDecl;
317 }
318}
319
320void CIRGenItaniumCXXABI::emitCXXConstructors(const CXXConstructorDecl *d) {
321 // Just make sure we're in sync with TargetCXXABI.
322 assert(cgm.getTarget().getCXXABI().hasConstructorVariants());
323
324 // The constructor used for constructing this as a base class;
325 // ignores virtual bases.
326 cgm.emitGlobal(GlobalDecl(d, Ctor_Base));
327
328 // The constructor used for constructing this as a complete class;
329 // constructs the virtual bases, then calls the base constructor.
330 if (!d->getParent()->isAbstract()) {
331 // We don't need to emit the complete ctro if the class is abstract.
332 cgm.emitGlobal(GlobalDecl(d, Ctor_Complete));
333 }
334}
335
336void CIRGenItaniumCXXABI::emitCXXDestructors(const CXXDestructorDecl *d) {
337 // The destructor used for destructing this as a base class; ignores
338 // virtual bases.
339 cgm.emitGlobal(GlobalDecl(d, Dtor_Base));
340
341 // The destructor used for destructing this as a most-derived class;
342 // call the base destructor and then destructs any virtual bases.
343 cgm.emitGlobal(GlobalDecl(d, Dtor_Complete));
344
345 // The destructor in a virtual table is always a 'deleting'
346 // destructor, which calls the complete destructor and then uses the
347 // appropriate operator delete.
348 if (d->isVirtual())
349 cgm.emitGlobal(GlobalDecl(d, Dtor_Deleting));
350}
351
352CIRGenCXXABI::AddedStructorArgs CIRGenItaniumCXXABI::getImplicitConstructorArgs(
353 CIRGenFunction &cgf, const CXXConstructorDecl *d, CXXCtorType type,
354 bool forVirtualBase, bool delegating) {
355 if (!needsVTTParameter(GlobalDecl(d, type)))
356 return AddedStructorArgs{};
357
358 // Insert the implicit 'vtt' argument as the second argument. Make sure to
359 // correctly reflect its address space, which can differ from generic on
360 // some targets.
361 mlir::Value vtt =
362 cgf.getVTTParameter(GlobalDecl(d, type), forVirtualBase, delegating);
363 QualType vttTy =
364 cgm.getASTContext().getPointerType(cgm.getASTContext().VoidPtrTy);
366 return AddedStructorArgs::withPrefix({{vtt, vttTy}});
367}
368
369/// Return whether the given global decl needs a VTT (virtual table table)
370/// parameter, which it does if it's a base constructor or destructor with
371/// virtual bases.
372bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) {
373 auto *md = cast<CXXMethodDecl>(gd.getDecl());
374
375 // We don't have any virtual bases, just return early.
376 if (!md->getParent()->getNumVBases())
377 return false;
378
379 // Check if we have a base constructor.
381 return true;
382
383 // Check if we have a base destructor.
385 return true;
386
387 return false;
388}
389
390void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,
391 const CXXRecordDecl *rd) {
392 cir::GlobalOp vtable = getAddrOfVTable(rd, CharUnits());
393 if (vtable.hasInitializer())
394 return;
395
396 ItaniumVTableContext &vtContext = cgm.getItaniumVTableContext();
397 const VTableLayout &vtLayout = vtContext.getVTableLayout(rd);
398 cir::GlobalLinkageKind linkage = cgm.getVTableLinkage(rd);
399 mlir::Attribute rtti =
400 cgm.getAddrOfRTTIDescriptor(cgm.getLoc(rd->getBeginLoc()),
401 cgm.getASTContext().getCanonicalTagType(rd));
402
403 // Classic codegen uses ConstantInitBuilder here, which is a very general
404 // and feature-rich class to generate initializers for global values.
405 // For now, this is using a simpler approach to create the initializer in CIR.
406 cgvt.createVTableInitializer(vtable, vtLayout, rtti,
407 cir::isLocalLinkage(linkage));
408
409 // Set the correct linkage.
410 vtable.setLinkage(linkage);
411
412 if (cgm.supportsCOMDAT() && cir::isWeakForLinker(linkage))
413 vtable.setComdat(true);
414
415 // Set the right visibility.
416 cgm.setGVProperties(vtable, rd);
417
418 // If this is the magic class __cxxabiv1::__fundamental_type_info,
419 // we will emit the typeinfo for the fundamental types. This is the
420 // same behaviour as GCC.
421 const DeclContext *DC = rd->getDeclContext();
422 if (rd->getIdentifier() &&
423 rd->getIdentifier()->isStr("__fundamental_type_info") &&
424 isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
425 cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
426 DC->getParent()->isTranslationUnit()) {
427 cgm.errorNYI(rd->getSourceRange(),
428 "emitVTableDefinitions: __fundamental_type_info");
429 }
430
431 auto vtableAsGlobalValue = dyn_cast<cir::CIRGlobalValueInterface>(*vtable);
432 assert(vtableAsGlobalValue && "VTable must support CIRGlobalValueInterface");
433 // Always emit type metadata on non-available_externally definitions, and on
434 // available_externally definitions if we are performing whole program
435 // devirtualization. For WPD we need the type metadata on all vtable
436 // definitions to ensure we associate derived classes with base classes
437 // defined in headers but with a strong definition only in a shared
438 // library.
440 if (cgm.getCodeGenOpts().WholeProgramVTables) {
441 cgm.errorNYI(rd->getSourceRange(),
442 "emitVTableDefinitions: WholeProgramVTables");
443 }
444
446 if (vtContext.isRelativeLayout()) {
447 cgm.errorNYI(rd->getSourceRange(), "vtableRelativeLayout");
448 }
449}
450
451void CIRGenItaniumCXXABI::emitVirtualInheritanceTables(
452 const CXXRecordDecl *rd) {
453 CIRGenVTables &vtables = cgm.getVTables();
454 cir::GlobalOp vtt = vtables.getAddrOfVTT(rd);
455 vtables.emitVTTDefinition(vtt, cgm.getVTableLinkage(rd), rd);
456}
457
458namespace {
459class CIRGenItaniumRTTIBuilder {
460 CIRGenModule &cgm; // Per-module state.
461 const CIRGenItaniumCXXABI &cxxABI; // Per-module state.
462
463 /// The fields of the RTTI descriptor currently being built.
464 SmallVector<mlir::Attribute, 16> fields;
465
466 // Returns the mangled type name of the given type.
467 cir::GlobalOp getAddrOfTypeName(mlir::Location loc, QualType ty,
468 cir::GlobalLinkageKind linkage);
469
470 /// descriptor of the given type.
471 mlir::Attribute getAddrOfExternalRTTIDescriptor(mlir::Location loc,
472 QualType ty);
473
474 /// Build the vtable pointer for the given type.
475 void buildVTablePointer(mlir::Location loc, const Type *ty);
476
477 /// Build an abi::__si_class_type_info, used for single inheritance, according
478 /// to the Itanium C++ ABI, 2.9.5p6b.
479 void buildSIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd);
480
481 /// Build an abi::__vmi_class_type_info, used for
482 /// classes with bases that do not satisfy the abi::__si_class_type_info
483 /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
484 void buildVMIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd);
485
486public:
487 CIRGenItaniumRTTIBuilder(const CIRGenItaniumCXXABI &abi, CIRGenModule &cgm)
488 : cgm(cgm), cxxABI(abi) {}
489
490 /// Build the RTTI type info struct for the given type, or
491 /// link to an existing RTTI descriptor if one already exists.
492 mlir::Attribute buildTypeInfo(mlir::Location loc, QualType ty);
493
494 /// Build the RTTI type info struct for the given type.
495 mlir::Attribute buildTypeInfo(mlir::Location loc, QualType ty,
496 cir::GlobalLinkageKind linkage,
497 mlir::SymbolTable::Visibility visibility);
498};
499} // namespace
500
501// TODO(cir): Will be removed after sharing them with the classical codegen
502namespace {
503
504// Pointer type info flags.
505enum {
506 /// PTI_Const - Type has const qualifier.
507 PTI_Const = 0x1,
508
509 /// PTI_Volatile - Type has volatile qualifier.
510 PTI_Volatile = 0x2,
511
512 /// PTI_Restrict - Type has restrict qualifier.
513 PTI_Restrict = 0x4,
514
515 /// PTI_Incomplete - Type is incomplete.
516 PTI_Incomplete = 0x8,
517
518 /// PTI_ContainingClassIncomplete - Containing class is incomplete.
519 /// (in pointer to member).
520 PTI_ContainingClassIncomplete = 0x10,
521
522 /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
523 // PTI_TransactionSafe = 0x20,
524
525 /// PTI_Noexcept - Pointee is noexcept function (C++1z).
526 PTI_Noexcept = 0x40,
527};
528
529// VMI type info flags.
530enum {
531 /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
532 VMI_NonDiamondRepeat = 0x1,
533
534 /// VMI_DiamondShaped - Class is diamond shaped.
535 VMI_DiamondShaped = 0x2
536};
537
538// Base class type info flags.
539enum {
540 /// BCTI_Virtual - Base class is virtual.
541 BCTI_Virtual = 0x1,
542
543 /// BCTI_Public - Base class is public.
544 BCTI_Public = 0x2
545};
546
547/// Given a builtin type, returns whether the type
548/// info for that type is defined in the standard library.
549/// TODO(cir): this can unified with LLVM codegen
550static bool typeInfoIsInStandardLibrary(const BuiltinType *ty) {
551 // Itanium C++ ABI 2.9.2:
552 // Basic type information (e.g. for "int", "bool", etc.) will be kept in
553 // the run-time support library. Specifically, the run-time support
554 // library should contain type_info objects for the types X, X* and
555 // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,
556 // unsigned char, signed char, short, unsigned short, int, unsigned int,
557 // long, unsigned long, long long, unsigned long long, float, double,
558 // long double, char16_t, char32_t, and the IEEE 754r decimal and
559 // half-precision floating point types.
560 //
561 // GCC also emits RTTI for __int128.
562 // FIXME: We do not emit RTTI information for decimal types here.
563
564 // Types added here must also be added to emitFundamentalRTTIDescriptors.
565 switch (ty->getKind()) {
566 case BuiltinType::WasmExternRef:
567 case BuiltinType::HLSLResource:
568 llvm_unreachable("NYI");
569 case BuiltinType::Void:
570 case BuiltinType::NullPtr:
571 case BuiltinType::Bool:
572 case BuiltinType::WChar_S:
573 case BuiltinType::WChar_U:
574 case BuiltinType::Char_U:
575 case BuiltinType::Char_S:
576 case BuiltinType::UChar:
577 case BuiltinType::SChar:
578 case BuiltinType::Short:
579 case BuiltinType::UShort:
580 case BuiltinType::Int:
581 case BuiltinType::UInt:
582 case BuiltinType::Long:
583 case BuiltinType::ULong:
584 case BuiltinType::LongLong:
585 case BuiltinType::ULongLong:
586 case BuiltinType::Half:
587 case BuiltinType::Float:
588 case BuiltinType::Double:
589 case BuiltinType::LongDouble:
590 case BuiltinType::Float16:
591 case BuiltinType::Float128:
592 case BuiltinType::Ibm128:
593 case BuiltinType::Char8:
594 case BuiltinType::Char16:
595 case BuiltinType::Char32:
596 case BuiltinType::Int128:
597 case BuiltinType::UInt128:
598 return true;
599
600#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
601 case BuiltinType::Id:
602#include "clang/Basic/OpenCLImageTypes.def"
603#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:
604#include "clang/Basic/OpenCLExtensionTypes.def"
605 case BuiltinType::OCLSampler:
606 case BuiltinType::OCLEvent:
607 case BuiltinType::OCLClkEvent:
608 case BuiltinType::OCLQueue:
609 case BuiltinType::OCLReserveID:
610#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
611#include "clang/Basic/AArch64ACLETypes.def"
612#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
613#include "clang/Basic/PPCTypes.def"
614#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
615#include "clang/Basic/RISCVVTypes.def"
616#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
617#include "clang/Basic/AMDGPUTypes.def"
618 case BuiltinType::ShortAccum:
619 case BuiltinType::Accum:
620 case BuiltinType::LongAccum:
621 case BuiltinType::UShortAccum:
622 case BuiltinType::UAccum:
623 case BuiltinType::ULongAccum:
624 case BuiltinType::ShortFract:
625 case BuiltinType::Fract:
626 case BuiltinType::LongFract:
627 case BuiltinType::UShortFract:
628 case BuiltinType::UFract:
629 case BuiltinType::ULongFract:
630 case BuiltinType::SatShortAccum:
631 case BuiltinType::SatAccum:
632 case BuiltinType::SatLongAccum:
633 case BuiltinType::SatUShortAccum:
634 case BuiltinType::SatUAccum:
635 case BuiltinType::SatULongAccum:
636 case BuiltinType::SatShortFract:
637 case BuiltinType::SatFract:
638 case BuiltinType::SatLongFract:
639 case BuiltinType::SatUShortFract:
640 case BuiltinType::SatUFract:
641 case BuiltinType::SatULongFract:
642 case BuiltinType::BFloat16:
643 return false;
644
645 case BuiltinType::Dependent:
646#define BUILTIN_TYPE(Id, SingletonId)
647#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
648#include "clang/AST/BuiltinTypes.def"
649 llvm_unreachable("asking for RRTI for a placeholder type!");
650
651 case BuiltinType::ObjCId:
652 case BuiltinType::ObjCClass:
653 case BuiltinType::ObjCSel:
654 llvm_unreachable("FIXME: Objective-C types are unsupported!");
655 }
656
657 llvm_unreachable("Invalid BuiltinType Kind!");
658}
659
660static bool typeInfoIsInStandardLibrary(const PointerType *pointerTy) {
661 QualType pointeeTy = pointerTy->getPointeeType();
662 const auto *builtinTy = dyn_cast<BuiltinType>(pointeeTy);
663 if (!builtinTy)
664 return false;
665
666 // Check the qualifiers.
667 Qualifiers quals = pointeeTy.getQualifiers();
668 quals.removeConst();
669
670 if (!quals.empty())
671 return false;
672
673 return typeInfoIsInStandardLibrary(builtinTy);
674}
675
676/// IsStandardLibraryRTTIDescriptor - Returns whether the type
677/// information for the given type exists in the standard library.
678static bool isStandardLibraryRttiDescriptor(QualType ty) {
679 // Type info for builtin types is defined in the standard library.
680 if (const auto *builtinTy = dyn_cast<BuiltinType>(ty))
681 return typeInfoIsInStandardLibrary(builtinTy);
682
683 // Type info for some pointer types to builtin types is defined in the
684 // standard library.
685 if (const auto *pointerTy = dyn_cast<PointerType>(ty))
686 return typeInfoIsInStandardLibrary(pointerTy);
687
688 return false;
689}
690
691/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
692/// the given type exists somewhere else, and that we should not emit the type
693/// information in this translation unit. Assumes that it is not a
694/// standard-library type.
695static bool shouldUseExternalRttiDescriptor(CIRGenModule &cgm, QualType ty) {
696 ASTContext &context = cgm.getASTContext();
697
698 // If RTTI is disabled, assume it might be disabled in the
699 // translation unit that defines any potential key function, too.
700 if (!context.getLangOpts().RTTI)
701 return false;
702
703 if (const auto *recordTy = dyn_cast<RecordType>(ty)) {
704 const CXXRecordDecl *rd =
705 cast<CXXRecordDecl>(recordTy->getOriginalDecl())->getDefinitionOrSelf();
706 if (!rd->hasDefinition())
707 return false;
708
709 if (!rd->isDynamicClass())
710 return false;
711
712 // FIXME: this may need to be reconsidered if the key function
713 // changes.
714 // N.B. We must always emit the RTTI data ourselves if there exists a key
715 // function.
716 bool isDLLImport = rd->hasAttr<DLLImportAttr>();
717
718 // Don't import the RTTI but emit it locally.
719 if (cgm.getTriple().isOSCygMing())
720 return false;
721
722 if (cgm.getVTables().isVTableExternal(rd)) {
724 return true;
725
726 return !isDLLImport || cgm.getTriple().isWindowsItaniumEnvironment();
727 }
728
729 if (isDLLImport)
730 return true;
731 }
732
733 return false;
734}
735
736/// Contains virtual and non-virtual bases seen when traversing a class
737/// hierarchy.
738struct SeenBases {
739 llvm::SmallPtrSet<const CXXRecordDecl *, 16> nonVirtualBases;
740 llvm::SmallPtrSet<const CXXRecordDecl *, 16> virtualBases;
741};
742
743/// Compute the value of the flags member in abi::__vmi_class_type_info.
744///
745static unsigned computeVmiClassTypeInfoFlags(const CXXBaseSpecifier *base,
746 SeenBases &bases) {
747
748 unsigned flags = 0;
749 auto *baseDecl = base->getType()->castAsCXXRecordDecl();
750
751 if (base->isVirtual()) {
752 // Mark the virtual base as seen.
753 if (!bases.virtualBases.insert(baseDecl).second) {
754 // If this virtual base has been seen before, then the class is diamond
755 // shaped.
756 flags |= VMI_DiamondShaped;
757 } else {
758 if (bases.nonVirtualBases.count(baseDecl))
759 flags |= VMI_NonDiamondRepeat;
760 }
761 } else {
762 // Mark the non-virtual base as seen.
763 if (!bases.nonVirtualBases.insert(baseDecl).second) {
764 // If this non-virtual base has been seen before, then the class has non-
765 // diamond shaped repeated inheritance.
766 flags |= VMI_NonDiamondRepeat;
767 } else {
768 if (bases.virtualBases.count(baseDecl))
769 flags |= VMI_NonDiamondRepeat;
770 }
771 }
772
773 // Walk all bases.
774 for (const auto &bs : baseDecl->bases())
775 flags |= computeVmiClassTypeInfoFlags(&bs, bases);
776
777 return flags;
778}
779
780static unsigned computeVmiClassTypeInfoFlags(const CXXRecordDecl *rd) {
781 unsigned flags = 0;
782 SeenBases bases;
783
784 // Walk all bases.
785 for (const auto &bs : rd->bases())
786 flags |= computeVmiClassTypeInfoFlags(&bs, bases);
787
788 return flags;
789}
790
791// Return whether the given record decl has a "single,
792// public, non-virtual base at offset zero (i.e. the derived class is dynamic
793// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
794// TODO(cir): this can unified with LLVM codegen
795static bool canUseSingleInheritance(const CXXRecordDecl *rd) {
796 // Check the number of bases.
797 if (rd->getNumBases() != 1)
798 return false;
799
800 // Get the base.
802
803 // Check that the base is not virtual.
804 if (base->isVirtual())
805 return false;
806
807 // Check that the base is public.
808 if (base->getAccessSpecifier() != AS_public)
809 return false;
810
811 // Check that the class is dynamic iff the base is.
812 auto *baseDecl = base->getType()->castAsCXXRecordDecl();
813 return baseDecl->isEmpty() ||
814 baseDecl->isDynamicClass() == rd->isDynamicClass();
815}
816
817/// IsIncompleteClassType - Returns whether the given record type is incomplete.
818static bool isIncompleteClassType(const RecordType *recordTy) {
819 return !recordTy->getOriginalDecl()
820 ->getDefinitionOrSelf()
821 ->isCompleteDefinition();
822}
823
824/// Returns whether the given type contains an
825/// incomplete class type. This is true if
826///
827/// * The given type is an incomplete class type.
828/// * The given type is a pointer type whose pointee type contains an
829/// incomplete class type.
830/// * The given type is a member pointer type whose class is an incomplete
831/// class type.
832/// * The given type is a member pointer type whoise pointee type contains an
833/// incomplete class type.
834/// is an indirect or direct pointer to an incomplete class type.
835static bool containsIncompleteClassType(QualType ty) {
836 if (const auto *recordTy = dyn_cast<RecordType>(ty)) {
837 if (isIncompleteClassType(recordTy))
838 return true;
839 }
840
841 if (const auto *pointerTy = dyn_cast<PointerType>(ty))
842 return containsIncompleteClassType(pointerTy->getPointeeType());
843
844 if (const auto *memberPointerTy = dyn_cast<MemberPointerType>(ty)) {
845 // Check if the class type is incomplete.
846 if (!memberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
847 return true;
848
849 return containsIncompleteClassType(memberPointerTy->getPointeeType());
850 }
851
852 return false;
853}
854
855const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) {
856 // abi::__class_type_info.
857 static const char *const classTypeInfo =
858 "_ZTVN10__cxxabiv117__class_type_infoE";
859 // abi::__si_class_type_info.
860 static const char *const siClassTypeInfo =
861 "_ZTVN10__cxxabiv120__si_class_type_infoE";
862 // abi::__vmi_class_type_info.
863 static const char *const vmiClassTypeInfo =
864 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
865
866 switch (ty->getTypeClass()) {
867#define TYPE(Class, Base)
868#define ABSTRACT_TYPE(Class, Base)
869#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
870#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
871#define DEPENDENT_TYPE(Class, Base) case Type::Class:
872#include "clang/AST/TypeNodes.inc"
873 llvm_unreachable("Non-canonical and dependent types shouldn't get here");
874
875 case Type::LValueReference:
876 case Type::RValueReference:
877 llvm_unreachable("References shouldn't get here");
878
879 case Type::Auto:
880 case Type::DeducedTemplateSpecialization:
881 llvm_unreachable("Undeduced type shouldn't get here");
882
883 case Type::Pipe:
884 llvm_unreachable("Pipe types shouldn't get here");
885
886 case Type::ArrayParameter:
887 llvm_unreachable("Array Parameter types should not get here.");
888
889 case Type::Builtin:
890 case Type::BitInt:
891 // GCC treats vector and complex types as fundamental types.
892 case Type::Vector:
893 case Type::ExtVector:
894 case Type::ConstantMatrix:
895 case Type::Complex:
896 case Type::Atomic:
897 // FIXME: GCC treats block pointers as fundamental types?!
898 case Type::BlockPointer:
899 cgm.errorNYI("VTableClassNameForType: __fundamental_type_info");
900 break;
901 case Type::ConstantArray:
902 case Type::IncompleteArray:
903 case Type::VariableArray:
904 cgm.errorNYI("VTableClassNameForType: __array_type_info");
905 break;
906
907 case Type::FunctionNoProto:
908 case Type::FunctionProto:
909 cgm.errorNYI("VTableClassNameForType: __function_type_info");
910 break;
911
912 case Type::Enum:
913 cgm.errorNYI("VTableClassNameForType: Enum");
914 break;
915
916 case Type::Record: {
917 const CXXRecordDecl *rd =
918 cast<CXXRecordDecl>(cast<RecordType>(ty)->getOriginalDecl())
919 ->getDefinitionOrSelf();
920
921 if (!rd->hasDefinition() || !rd->getNumBases()) {
922 return classTypeInfo;
923 }
924
925 if (canUseSingleInheritance(rd)) {
926 return siClassTypeInfo;
927 }
928
929 return vmiClassTypeInfo;
930 }
931
932 case Type::ObjCObject:
933 cgm.errorNYI("VTableClassNameForType: ObjCObject");
934 break;
935
936 case Type::ObjCInterface:
937 cgm.errorNYI("VTableClassNameForType: ObjCInterface");
938 break;
939
940 case Type::ObjCObjectPointer:
941 case Type::Pointer:
942 cgm.errorNYI("VTableClassNameForType: __pointer_type_info");
943 break;
944
945 case Type::MemberPointer:
946 cgm.errorNYI("VTableClassNameForType: __pointer_to_member_type_info");
947 break;
948
949 case Type::HLSLAttributedResource:
950 case Type::HLSLInlineSpirv:
951 llvm_unreachable("HLSL doesn't support virtual functions");
952 }
953
954 return nullptr;
955}
956} // namespace
957
958/// Return the linkage that the type info and type info name constants
959/// should have for the given type.
960static cir::GlobalLinkageKind getTypeInfoLinkage(CIRGenModule &cgm,
961 QualType ty) {
962 // In addition, it and all of the intermediate abi::__pointer_type_info
963 // structs in the chain down to the abi::__class_type_info for the
964 // incomplete class type must be prevented from resolving to the
965 // corresponding type_info structs for the complete class type, possibly
966 // by making them local static objects. Finally, a dummy class RTTI is
967 // generated for the incomplete type that will not resolve to the final
968 // complete class RTTI (because the latter need not exist), possibly by
969 // making it a local static object.
970 if (containsIncompleteClassType(ty))
971 return cir::GlobalLinkageKind::InternalLinkage;
972
973 switch (ty->getLinkage()) {
974 case Linkage::Invalid:
975 llvm_unreachable("Linkage hasn't been computed!");
976
977 case Linkage::None:
980 return cir::GlobalLinkageKind::InternalLinkage;
981
983 case Linkage::Module:
985 // RTTI is not enabled, which means that this type info struct is going
986 // to be used for exception handling. Give it linkonce_odr linkage.
987 if (!cgm.getLangOpts().RTTI)
988 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
989
990 if (const RecordType *record = dyn_cast<RecordType>(ty)) {
991 const CXXRecordDecl *rd =
992 cast<CXXRecordDecl>(record->getOriginalDecl())->getDefinitionOrSelf();
993 if (rd->hasAttr<WeakAttr>())
994 return cir::GlobalLinkageKind::WeakODRLinkage;
995
996 if (cgm.getTriple().isWindowsItaniumEnvironment())
997 if (rd->hasAttr<DLLImportAttr>() &&
998 shouldUseExternalRttiDescriptor(cgm, ty))
999 return cir::GlobalLinkageKind::ExternalLinkage;
1000
1001 // MinGW always uses LinkOnceODRLinkage for type info.
1002 if (rd->isDynamicClass() && !cgm.getASTContext()
1003 .getTargetInfo()
1004 .getTriple()
1005 .isWindowsGNUEnvironment())
1006 return cgm.getVTableLinkage(rd);
1007 }
1008
1009 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
1010 }
1011
1012 llvm_unreachable("Invalid linkage!");
1013}
1014
1015cir::GlobalOp
1016CIRGenItaniumRTTIBuilder::getAddrOfTypeName(mlir::Location loc, QualType ty,
1017 cir::GlobalLinkageKind linkage) {
1018 CIRGenBuilderTy &builder = cgm.getBuilder();
1019 SmallString<256> name;
1020 llvm::raw_svector_ostream out(name);
1022
1023 // We know that the mangled name of the type starts at index 4 of the
1024 // mangled name of the typename, so we can just index into it in order to
1025 // get the mangled name of the type.
1026 mlir::Attribute init = builder.getString(
1027 name.substr(4), cgm.convertType(cgm.getASTContext().CharTy),
1028 std::nullopt);
1029
1030 CharUnits align =
1032
1033 // builder.getString can return a #cir.zero if the string given to it only
1034 // contains null bytes. However, type names cannot be full of null bytes.
1035 // So cast Init to a ConstArrayAttr should be safe.
1036 auto initStr = cast<cir::ConstArrayAttr>(init);
1037
1038 cir::GlobalOp gv = cgm.createOrReplaceCXXRuntimeVariable(
1039 loc, name, initStr.getType(), linkage, align);
1041 return gv;
1042}
1043
1044mlir::Attribute
1045CIRGenItaniumRTTIBuilder::getAddrOfExternalRTTIDescriptor(mlir::Location loc,
1046 QualType ty) {
1047 // Mangle the RTTI name.
1048 SmallString<256> name;
1049 llvm::raw_svector_ostream out(name);
1051 CIRGenBuilderTy &builder = cgm.getBuilder();
1052
1053 // Look for an existing global.
1054 cir::GlobalOp gv = dyn_cast_or_null<cir::GlobalOp>(
1055 mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));
1056
1057 if (!gv) {
1058 // Create a new global variable.
1059 // From LLVM codegen => Note for the future: If we would ever like to do
1060 // deferred emission of RTTI, check if emitting vtables opportunistically
1061 // need any adjustment.
1062 gv = CIRGenModule::createGlobalOp(cgm, loc, name, builder.getUInt8PtrTy(),
1063 /*isConstant=*/true);
1064 const CXXRecordDecl *rd = ty->getAsCXXRecordDecl();
1065 cgm.setGVProperties(gv, rd);
1066
1067 // Import the typeinfo symbol when all non-inline virtual methods are
1068 // imported.
1069 if (cgm.getTarget().hasPS4DLLImportExport()) {
1070 cgm.errorNYI("getAddrOfExternalRTTIDescriptor: hasPS4DLLImportExport");
1071 }
1072 }
1073
1074 return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), gv);
1075}
1076
1077void CIRGenItaniumRTTIBuilder::buildVTablePointer(mlir::Location loc,
1078 const Type *ty) {
1079 CIRGenBuilderTy &builder = cgm.getBuilder();
1080 const char *vTableName = vTableClassNameForType(cgm, ty);
1081
1082 // Check if the alias exists. If it doesn't, then get or create the global.
1084 cgm.errorNYI("buildVTablePointer: isRelativeLayout");
1085 return;
1086 }
1087
1088 mlir::Type vtableGlobalTy = builder.getPointerTo(builder.getUInt8PtrTy());
1089 llvm::Align align = cgm.getDataLayout().getABITypeAlign(vtableGlobalTy);
1090 cir::GlobalOp vTable = cgm.createOrReplaceCXXRuntimeVariable(
1091 loc, vTableName, vtableGlobalTy, cir::GlobalLinkageKind::ExternalLinkage,
1093
1094 // The vtable address point is 2.
1095 mlir::Attribute field{};
1097 cgm.errorNYI("buildVTablePointer: isRelativeLayout");
1098 } else {
1099 SmallVector<mlir::Attribute, 4> offsets{
1100 cgm.getBuilder().getI32IntegerAttr(2)};
1101 auto indices = mlir::ArrayAttr::get(builder.getContext(), offsets);
1103 vTable, indices);
1104 }
1105
1106 assert(field && "expected attribute");
1107 fields.push_back(field);
1108}
1109
1110/// Build an abi::__si_class_type_info, used for single inheritance, according
1111/// to the Itanium C++ ABI, 2.95p6b.
1112void CIRGenItaniumRTTIBuilder::buildSIClassTypeInfo(mlir::Location loc,
1113 const CXXRecordDecl *rd) {
1114 // Itanium C++ ABI 2.9.5p6b:
1115 // It adds to abi::__class_type_info a single member pointing to the
1116 // type_info structure for the base type,
1117 mlir::Attribute baseTypeInfo =
1118 CIRGenItaniumRTTIBuilder(cxxABI, cgm)
1119 .buildTypeInfo(loc, rd->bases_begin()->getType());
1120 fields.push_back(baseTypeInfo);
1121}
1122
1123/// Build an abi::__vmi_class_type_info, used for
1124/// classes with bases that do not satisfy the abi::__si_class_type_info
1125/// constraints, according to the Itanium C++ ABI, 2.9.5p5c.
1126void CIRGenItaniumRTTIBuilder::buildVMIClassTypeInfo(mlir::Location loc,
1127 const CXXRecordDecl *rd) {
1128 mlir::Type unsignedIntLTy =
1130
1131 // Itanium C++ ABI 2.9.5p6c:
1132 // __flags is a word with flags describing details about the class
1133 // structure, which may be referenced by using the __flags_masks
1134 // enumeration. These flags refer to both direct and indirect bases.
1135 unsigned flags = computeVmiClassTypeInfoFlags(rd);
1136 fields.push_back(cir::IntAttr::get(unsignedIntLTy, flags));
1137
1138 // Itanium C++ ABI 2.9.5p6c:
1139 // __base_count is a word with the number of direct proper base class
1140 // descriptions that follow.
1141 fields.push_back(cir::IntAttr::get(unsignedIntLTy, rd->getNumBases()));
1142
1143 if (!rd->getNumBases())
1144 return;
1145
1146 // Now add the base class descriptions.
1147
1148 // Itanium C++ ABI 2.9.5p6c:
1149 // __base_info[] is an array of base class descriptions -- one for every
1150 // direct proper base. Each description is of the type:
1151 //
1152 // struct abi::__base_class_type_info {
1153 // public:
1154 // const __class_type_info *__base_type;
1155 // long __offset_flags;
1156 //
1157 // enum __offset_flags_masks {
1158 // __virtual_mask = 0x1,
1159 // __public_mask = 0x2,
1160 // __offset_shift = 8
1161 // };
1162 // };
1163
1164 // If we're in mingw and 'long' isn't wide enough for a pointer, use 'long
1165 // long' instead of 'long' for __offset_flags. libstdc++abi uses long long on
1166 // LLP64 platforms.
1167 // FIXME: Consider updating libc++abi to match, and extend this logic to all
1168 // LLP64 platforms.
1169 QualType offsetFlagsTy = cgm.getASTContext().LongTy;
1170 const TargetInfo &ti = cgm.getASTContext().getTargetInfo();
1171 if (ti.getTriple().isOSCygMing() &&
1172 ti.getPointerWidth(LangAS::Default) > ti.getLongWidth())
1173 offsetFlagsTy = cgm.getASTContext().LongLongTy;
1174 mlir::Type offsetFlagsLTy = cgm.convertType(offsetFlagsTy);
1175
1176 for (const CXXBaseSpecifier &base : rd->bases()) {
1177 // The __base_type member points to the RTTI for the base type.
1178 fields.push_back(CIRGenItaniumRTTIBuilder(cxxABI, cgm)
1179 .buildTypeInfo(loc, base.getType()));
1180
1181 CXXRecordDecl *baseDecl = base.getType()->castAsCXXRecordDecl();
1182 int64_t offsetFlags = 0;
1183
1184 // All but the lower 8 bits of __offset_flags are a signed offset.
1185 // For a non-virtual base, this is the offset in the object of the base
1186 // subobject. For a virtual base, this is the offset in the virtual table of
1187 // the virtual base offset for the virtual base referenced (negative).
1188 CharUnits offset;
1189 if (base.isVirtual())
1191 rd, baseDecl);
1192 else {
1193 const ASTRecordLayout &layout =
1195 offset = layout.getBaseClassOffset(baseDecl);
1196 }
1197 offsetFlags = uint64_t(offset.getQuantity()) << 8;
1198
1199 // The low-order byte of __offset_flags contains flags, as given by the
1200 // masks from the enumeration __offset_flags_masks.
1201 if (base.isVirtual())
1202 offsetFlags |= BCTI_Virtual;
1203 if (base.getAccessSpecifier() == AS_public)
1204 offsetFlags |= BCTI_Public;
1205
1206 fields.push_back(cir::IntAttr::get(offsetFlagsLTy, offsetFlags));
1207 }
1208}
1209
1210mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(mlir::Location loc,
1211 QualType ty) {
1212 // We want to operate on the canonical type.
1213 ty = ty.getCanonicalType();
1214
1215 // Check if we've already emitted an RTTI descriptor for this type.
1216 SmallString<256> name;
1217 llvm::raw_svector_ostream out(name);
1219
1220 auto oldGV = dyn_cast_or_null<cir::GlobalOp>(
1221 mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));
1222
1223 if (oldGV && !oldGV.isDeclaration()) {
1224 assert(!oldGV.hasAvailableExternallyLinkage() &&
1225 "available_externally typeinfos not yet implemented");
1227 oldGV);
1228 }
1229
1230 // Check if there is already an external RTTI descriptor for this type.
1231 if (isStandardLibraryRttiDescriptor(ty) ||
1232 shouldUseExternalRttiDescriptor(cgm, ty))
1233 return getAddrOfExternalRTTIDescriptor(loc, ty);
1234
1235 // Emit the standard library with external linkage.
1236 cir::GlobalLinkageKind linkage = getTypeInfoLinkage(cgm, ty);
1237
1238 // Give the type_info object and name the formal visibility of the
1239 // type itself.
1242
1243 mlir::SymbolTable::Visibility symVisibility;
1244 if (cir::isLocalLinkage(linkage))
1245 // If the linkage is local, only default visibility makes sense.
1246 symVisibility = mlir::SymbolTable::Visibility::Public;
1247 else if (cxxABI.classifyRTTIUniqueness(ty, linkage) ==
1248 CIRGenItaniumCXXABI::RUK_NonUniqueHidden) {
1249 cgm.errorNYI(
1250 "buildTypeInfo: classifyRTTIUniqueness == RUK_NonUniqueHidden");
1251 symVisibility = CIRGenModule::getMLIRVisibility(ty->getVisibility());
1252 } else
1253 symVisibility = CIRGenModule::getMLIRVisibility(ty->getVisibility());
1254
1255 return buildTypeInfo(loc, ty, linkage, symVisibility);
1256}
1257
1258mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(
1259 mlir::Location loc, QualType ty, cir::GlobalLinkageKind linkage,
1260 mlir::SymbolTable::Visibility visibility) {
1261 CIRGenBuilderTy &builder = cgm.getBuilder();
1262
1264
1265 // Add the vtable pointer.
1266 buildVTablePointer(loc, cast<Type>(ty));
1267
1268 // And the name.
1269 cir::GlobalOp typeName = getAddrOfTypeName(loc, ty, linkage);
1270 mlir::Attribute typeNameField;
1271
1272 // If we're supposed to demote the visibility, be sure to set a flag
1273 // to use a string comparison for type_info comparisons.
1274 CIRGenItaniumCXXABI::RTTIUniquenessKind rttiUniqueness =
1275 cxxABI.classifyRTTIUniqueness(ty, linkage);
1276 if (rttiUniqueness != CIRGenItaniumCXXABI::RUK_Unique) {
1277 // The flag is the sign bit, which on ARM64 is defined to be clear
1278 // for global pointers. This is very ARM64-specific.
1279 cgm.errorNYI(
1280 "buildTypeInfo: rttiUniqueness != CIRGenItaniumCXXABI::RUK_Unique");
1281 } else {
1282 typeNameField =
1283 builder.getGlobalViewAttr(builder.getUInt8PtrTy(), typeName);
1284 }
1285
1286 fields.push_back(typeNameField);
1287
1288 switch (ty->getTypeClass()) {
1289#define TYPE(Class, Base)
1290#define ABSTRACT_TYPE(Class, Base)
1291#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
1292#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
1293#define DEPENDENT_TYPE(Class, Base) case Type::Class:
1294#include "clang/AST/TypeNodes.inc"
1295 llvm_unreachable("Non-canonical and dependent types shouldn't get here");
1296
1297 // GCC treats vector types as fundamental types.
1298 case Type::Builtin:
1299 case Type::Vector:
1300 case Type::ExtVector:
1301 case Type::ConstantMatrix:
1302 case Type::Complex:
1303 case Type::BlockPointer:
1304 // Itanium C++ ABI 2.9.5p4:
1305 // abi::__fundamental_type_info adds no data members to std::type_info.
1306 break;
1307
1308 case Type::LValueReference:
1309 case Type::RValueReference:
1310 llvm_unreachable("References shouldn't get here");
1311
1312 case Type::Auto:
1313 case Type::DeducedTemplateSpecialization:
1314 llvm_unreachable("Undeduced type shouldn't get here");
1315
1316 case Type::Pipe:
1317 break;
1318
1319 case Type::BitInt:
1320 break;
1321
1322 case Type::ConstantArray:
1323 case Type::IncompleteArray:
1324 case Type::VariableArray:
1325 case Type::ArrayParameter:
1326 // Itanium C++ ABI 2.9.5p5:
1327 // abi::__array_type_info adds no data members to std::type_info.
1328 break;
1329
1330 case Type::FunctionNoProto:
1331 case Type::FunctionProto:
1332 // Itanium C++ ABI 2.9.5p5:
1333 // abi::__function_type_info adds no data members to std::type_info.
1334 break;
1335
1336 case Type::Enum:
1337 // Itanium C++ ABI 2.9.5p5:
1338 // abi::__enum_type_info adds no data members to std::type_info.
1339 break;
1340
1341 case Type::Record: {
1342 const auto *rd =
1343 cast<CXXRecordDecl>(cast<RecordType>(ty)->getOriginalDecl())
1344 ->getDefinitionOrSelf();
1345 if (!rd->hasDefinition() || !rd->getNumBases()) {
1346 // We don't need to emit any fields.
1347 break;
1348 }
1349
1350 if (canUseSingleInheritance(rd)) {
1351 buildSIClassTypeInfo(loc, rd);
1352 } else {
1353 buildVMIClassTypeInfo(loc, rd);
1354 }
1355
1356 break;
1357 }
1358
1359 case Type::ObjCObject:
1360 case Type::ObjCInterface:
1361 cgm.errorNYI("buildTypeInfo: ObjCObject & ObjCInterface");
1362 break;
1363
1364 case Type::ObjCObjectPointer:
1365 cgm.errorNYI("buildTypeInfo: ObjCObjectPointer");
1366 break;
1367
1368 case Type::Pointer:
1369 cgm.errorNYI("buildTypeInfo: Pointer");
1370 break;
1371
1372 case Type::MemberPointer:
1373 cgm.errorNYI("buildTypeInfo: MemberPointer");
1374 break;
1375
1376 case Type::Atomic:
1377 // No fields, at least for the moment.
1378 break;
1379
1380 case Type::HLSLAttributedResource:
1381 case Type::HLSLInlineSpirv:
1382 llvm_unreachable("HLSL doesn't support RTTI");
1383 }
1384
1386 cir::TypeInfoAttr init = builder.getTypeInfo(builder.getArrayAttr(fields));
1387
1388 SmallString<256> name;
1389 llvm::raw_svector_ostream out(name);
1391
1392 // Create new global and search for an existing global.
1393 auto oldGV = dyn_cast_or_null<cir::GlobalOp>(
1394 mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));
1395
1396 cir::GlobalOp gv =
1397 CIRGenModule::createGlobalOp(cgm, loc, name, init.getType(),
1398 /*isConstant=*/true);
1399
1400 // Export the typeinfo in the same circumstances as the vtable is
1401 // exported.
1402 if (cgm.getTarget().hasPS4DLLImportExport()) {
1403 cgm.errorNYI("buildTypeInfo: target hasPS4DLLImportExport");
1404 return {};
1405 }
1406
1407 // If there's already an old global variable, replace it with the new one.
1408 if (oldGV) {
1409 // Replace occurrences of the old variable if needed.
1410 gv.setName(oldGV.getName());
1411 if (!oldGV->use_empty()) {
1412 cgm.errorNYI("buildTypeInfo: old GV !use_empty");
1413 return {};
1414 }
1415 oldGV->erase();
1416 }
1417
1418 if (cgm.supportsCOMDAT() && cir::isWeakForLinker(gv.getLinkage())) {
1420 cgm.errorNYI("buildTypeInfo: supportsCOMDAT & isWeakForLinker");
1421 return {};
1422 }
1423
1424 CharUnits align = cgm.getASTContext().toCharUnitsFromBits(
1425 cgm.getTarget().getPointerAlign(LangAS::Default));
1426 gv.setAlignmentAttr(cgm.getSize(align));
1427
1428 // The Itanium ABI specifies that type_info objects must be globally
1429 // unique, with one exception: if the type is an incomplete class
1430 // type or a (possibly indirect) pointer to one. That exception
1431 // affects the general case of comparing type_info objects produced
1432 // by the typeid operator, which is why the comparison operators on
1433 // std::type_info generally use the type_info name pointers instead
1434 // of the object addresses. However, the language's built-in uses
1435 // of RTTI generally require class types to be complete, even when
1436 // manipulating pointers to those class types. This allows the
1437 // implementation of dynamic_cast to rely on address equality tests,
1438 // which is much faster.
1439
1440 // All of this is to say that it's important that both the type_info
1441 // object and the type_info name be uniqued when weakly emitted.
1442
1443 mlir::SymbolTable::setSymbolVisibility(typeName, visibility);
1447
1448 mlir::SymbolTable::setSymbolVisibility(gv, visibility);
1452
1454 return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), gv);
1455}
1456
1457mlir::Attribute CIRGenItaniumCXXABI::getAddrOfRTTIDescriptor(mlir::Location loc,
1458 QualType ty) {
1459 return CIRGenItaniumRTTIBuilder(*this, cgm).buildTypeInfo(loc, ty);
1460}
1461
1462/// What sort of uniqueness rules should we use for the RTTI for the
1463/// given type?
1464CIRGenItaniumCXXABI::RTTIUniquenessKind
1465CIRGenItaniumCXXABI::classifyRTTIUniqueness(
1466 QualType canTy, cir::GlobalLinkageKind linkage) const {
1467 if (shouldRTTIBeUnique())
1468 return RUK_Unique;
1469
1470 // It's only necessary for linkonce_odr or weak_odr linkage.
1471 if (linkage != cir::GlobalLinkageKind::LinkOnceODRLinkage &&
1472 linkage != cir::GlobalLinkageKind::WeakODRLinkage)
1473 return RUK_Unique;
1474
1475 // It's only necessary with default visibility.
1476 if (canTy->getVisibility() != DefaultVisibility)
1477 return RUK_Unique;
1478
1479 // If we're not required to publish this symbol, hide it.
1480 if (linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage)
1481 return RUK_NonUniqueHidden;
1482
1483 // If we're required to publish this symbol, as we might be under an
1484 // explicit instantiation, leave it with default visibility but
1485 // enable string-comparisons.
1486 assert(linkage == cir::GlobalLinkageKind::WeakODRLinkage);
1487 return RUK_NonUniqueVisible;
1488}
1489
1490void CIRGenItaniumCXXABI::emitDestructorCall(
1491 CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,
1492 bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) {
1493 GlobalDecl gd(dd, type);
1494 if (needsVTTParameter(gd)) {
1495 cgm.errorNYI(dd->getSourceRange(), "emitDestructorCall: VTT");
1496 }
1497
1498 mlir::Value vtt = nullptr;
1499 ASTContext &astContext = cgm.getASTContext();
1500 QualType vttTy = astContext.getPointerType(astContext.VoidPtrTy);
1502 CIRGenCallee callee =
1504
1505 cgf.emitCXXDestructorCall(gd, callee, thisAddr.getPointer(), thisTy, vtt,
1506 vttTy, nullptr);
1507}
1508
1509// The idea here is creating a separate block for the throw with an
1510// `UnreachableOp` as the terminator. So, we branch from the current block
1511// to the throw block and create a block for the remaining operations.
1512static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc,
1513 mlir::Value exceptionPtr = {},
1514 mlir::FlatSymbolRefAttr typeInfo = {},
1515 mlir::FlatSymbolRefAttr dtor = {}) {
1516 mlir::Block *currentBlock = builder.getInsertionBlock();
1517 mlir::Region *region = currentBlock->getParent();
1518
1519 if (currentBlock->empty()) {
1520 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
1521 cir::UnreachableOp::create(builder, loc);
1522 } else {
1523 mlir::Block *throwBlock = builder.createBlock(region);
1524
1525 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
1526 cir::UnreachableOp::create(builder, loc);
1527
1528 builder.setInsertionPointToEnd(currentBlock);
1529 cir::BrOp::create(builder, loc, throwBlock);
1530 }
1531
1532 (void)builder.createBlock(region);
1533}
1534
1535void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &cgf, bool isNoReturn) {
1536 // void __cxa_rethrow();
1537 if (isNoReturn) {
1538 CIRGenBuilderTy &builder = cgf.getBuilder();
1539 assert(cgf.currSrcLoc && "expected source location");
1540 mlir::Location loc = *cgf.currSrcLoc;
1541 insertThrowAndSplit(builder, loc);
1542 } else {
1543 cgm.errorNYI("emitRethrow with isNoReturn false");
1544 }
1545}
1546
1548 switch (cgm.getASTContext().getCXXABIKind()) {
1549 case TargetCXXABI::GenericItanium:
1550 case TargetCXXABI::GenericAArch64:
1551 return new CIRGenItaniumCXXABI(cgm);
1552
1553 case TargetCXXABI::AppleARM64:
1554 // The general Itanium ABI will do until we implement something that
1555 // requires special handling.
1557 return new CIRGenItaniumCXXABI(cgm);
1558
1559 default:
1560 llvm_unreachable("bad or NYI ABI kind");
1561 }
1562}
1563
1564cir::GlobalOp CIRGenItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *rd,
1565 CharUnits vptrOffset) {
1566 assert(vptrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");
1567 cir::GlobalOp &vtable = vtables[rd];
1568 if (vtable)
1569 return vtable;
1570
1571 // Queue up this vtable for possible deferred emission.
1573
1574 SmallString<256> name;
1575 llvm::raw_svector_ostream out(name);
1576 getMangleContext().mangleCXXVTable(rd, out);
1577
1578 const VTableLayout &vtLayout =
1580 mlir::Type vtableType = cgm.getVTables().getVTableType(vtLayout);
1581
1582 // Use pointer alignment for the vtable. Otherwise we would align them based
1583 // on the size of the initializer which doesn't make sense as only single
1584 // values are read.
1585 unsigned ptrAlign = cgm.getItaniumVTableContext().isRelativeLayout()
1586 ? 32
1588
1590 cgm.getLoc(rd->getSourceRange()), name, vtableType,
1591 cir::GlobalLinkageKind::ExternalLinkage,
1592 cgm.getASTContext().toCharUnitsFromBits(ptrAlign));
1593 // LLVM codegen handles unnamedAddr
1595
1596 // In MS C++ if you have a class with virtual functions in which you are using
1597 // selective member import/export, then all virtual functions must be exported
1598 // unless they are inline, otherwise a link error will result. To match this
1599 // behavior, for such classes, we dllimport the vtable if it is defined
1600 // externally and all the non-inline virtual methods are marked dllimport, and
1601 // we dllexport the vtable if it is defined in this TU and all the non-inline
1602 // virtual methods are marked dllexport.
1603 if (cgm.getTarget().hasPS4DLLImportExport())
1604 cgm.errorNYI(rd->getSourceRange(),
1605 "getAddrOfVTable: PS4 DLL import/export");
1606
1607 cgm.setGVProperties(vtable, rd);
1608 return vtable;
1609}
1610
1611CIRGenCallee CIRGenItaniumCXXABI::getVirtualFunctionPointer(
1612 CIRGenFunction &cgf, clang::GlobalDecl gd, Address thisAddr, mlir::Type ty,
1613 SourceLocation srcLoc) {
1614 CIRGenBuilderTy &builder = cgm.getBuilder();
1615 mlir::Location loc = cgf.getLoc(srcLoc);
1616 cir::PointerType tyPtr = builder.getPointerTo(ty);
1617 auto *methodDecl = cast<CXXMethodDecl>(gd.getDecl());
1618 mlir::Value vtable = cgf.getVTablePtr(loc, thisAddr, methodDecl->getParent());
1619
1620 uint64_t vtableIndex = cgm.getItaniumVTableContext().getMethodVTableIndex(gd);
1621 mlir::Value vfunc{};
1622 if (cgf.shouldEmitVTableTypeCheckedLoad(methodDecl->getParent())) {
1623 cgm.errorNYI(loc, "getVirtualFunctionPointer: emitVTableTypeCheckedLoad");
1624 } else {
1626
1627 mlir::Value vfuncLoad;
1630 cgm.errorNYI(loc, "getVirtualFunctionPointer: isRelativeLayout");
1631 } else {
1632 auto vtableSlotPtr = cir::VTableGetVirtualFnAddrOp::create(
1633 builder, loc, builder.getPointerTo(tyPtr), vtable, vtableIndex);
1634 vfuncLoad = builder.createAlignedLoad(loc, tyPtr, vtableSlotPtr,
1635 cgf.getPointerAlign());
1636 }
1637
1638 // Add !invariant.load md to virtual function load to indicate that
1639 // function didn't change inside vtable.
1640 // It's safe to add it without -fstrict-vtable-pointers, but it would not
1641 // help in devirtualization because it will only matter if we will have 2
1642 // the same virtual function loads from the same vtable load, which won't
1643 // happen without enabled devirtualization with -fstrict-vtable-pointers.
1644 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
1645 cgm.getCodeGenOpts().StrictVTablePointers) {
1646 cgm.errorNYI(loc, "getVirtualFunctionPointer: strictVTablePointers");
1647 }
1648 vfunc = vfuncLoad;
1649 }
1650
1651 CIRGenCallee callee(gd, vfunc.getDefiningOp());
1652 return callee;
1653}
1654
1655mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
1656 CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
1657 const CXXRecordDecl *nearestVBase) {
1658 assert((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&
1659 needsVTTParameter(cgf.curGD) && "This class doesn't have VTT");
1660
1661 // Get the secondary vpointer index.
1662 uint64_t virtualPointerIndex =
1663 cgm.getVTables().getSecondaryVirtualPointerIndex(vtableClass, base);
1664
1665 /// Load the VTT.
1666 mlir::Value vttPtr = cgf.loadCXXVTT();
1667 mlir::Location loc = cgf.getLoc(vtableClass->getSourceRange());
1668 // Calculate the address point from the VTT, and the offset may be zero.
1669 vttPtr = cgf.getBuilder().createVTTAddrPoint(loc, vttPtr.getType(), vttPtr,
1670 virtualPointerIndex);
1671 // And load the address point from the VTT.
1672 auto vptrType = cir::VPtrType::get(cgf.getBuilder().getContext());
1673 return cgf.getBuilder().createAlignedLoad(loc, vptrType, vttPtr,
1674 cgf.getPointerAlign());
1675}
1676
1677mlir::Value
1678CIRGenItaniumCXXABI::getVTableAddressPoint(BaseSubobject base,
1679 const CXXRecordDecl *vtableClass) {
1680 cir::GlobalOp vtable = getAddrOfVTable(vtableClass, CharUnits());
1681
1682 // Find the appropriate vtable within the vtable group, and the address point
1683 // within that vtable.
1684 VTableLayout::AddressPointLocation addressPoint =
1686 .getVTableLayout(vtableClass)
1687 .getAddressPoint(base);
1688
1689 mlir::OpBuilder &builder = cgm.getBuilder();
1690 auto vtablePtrTy = cir::VPtrType::get(builder.getContext());
1691
1692 return builder.create<cir::VTableAddrPointOp>(
1693 cgm.getLoc(vtableClass->getSourceRange()), vtablePtrTy,
1694 mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()),
1695 cir::AddressPointAttr::get(cgm.getBuilder().getContext(),
1696 addressPoint.VTableIndex,
1697 addressPoint.AddressPointIndex));
1698}
1699
1700mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructor(
1701 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,
1702 clang::BaseSubobject base, const clang::CXXRecordDecl *nearestVBase) {
1703
1704 if ((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&
1705 needsVTTParameter(cgf.curGD)) {
1706 return getVTableAddressPointInStructorWithVTT(cgf, vtableClass, base,
1707 nearestVBase);
1708 }
1709 return getVTableAddressPoint(base, vtableClass);
1710}
1711
1712bool CIRGenItaniumCXXABI::isVirtualOffsetNeededForVTableField(
1713 CIRGenFunction &cgf, CIRGenFunction::VPtr vptr) {
1714 if (vptr.nearestVBase == nullptr)
1715 return false;
1716 return needsVTTParameter(cgf.curGD);
1717}
1718
1719mlir::Value CIRGenItaniumCXXABI::getVirtualBaseClassOffset(
1720 mlir::Location loc, CIRGenFunction &cgf, Address thisAddr,
1721 const CXXRecordDecl *classDecl, const CXXRecordDecl *baseClassDecl) {
1722 CIRGenBuilderTy &builder = cgf.getBuilder();
1723 mlir::Value vtablePtr = cgf.getVTablePtr(loc, thisAddr, classDecl);
1724 mlir::Value vtableBytePtr = builder.createBitcast(vtablePtr, cgm.UInt8PtrTy);
1725 CharUnits vbaseOffsetOffset =
1727 baseClassDecl);
1728 mlir::Value offsetVal =
1729 builder.getSInt64(vbaseOffsetOffset.getQuantity(), loc);
1730 auto vbaseOffsetPtr = cir::PtrStrideOp::create(builder, loc, cgm.UInt8PtrTy,
1731 vtableBytePtr, offsetVal);
1732
1733 mlir::Value vbaseOffset;
1736 cgm.errorNYI(loc, "getVirtualBaseClassOffset: relative layout");
1737 } else {
1738 mlir::Value offsetPtr = builder.createBitcast(
1739 vbaseOffsetPtr, builder.getPointerTo(cgm.PtrDiffTy));
1740 vbaseOffset = builder.createLoad(
1741 loc, Address(offsetPtr, cgm.PtrDiffTy, cgf.getPointerAlign()));
1742 }
1743 return vbaseOffset;
1744}
static void emitConstructorDestructorAlias(CIRGenModule &cgm, GlobalDecl aliasDecl, GlobalDecl targetDecl)
static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc, mlir::Value exceptionPtr={}, mlir::FlatSymbolRefAttr typeInfo={}, mlir::FlatSymbolRefAttr dtor={})
static cir::GlobalLinkageKind getTypeInfoLinkage(CIRGenModule &cgm, QualType ty)
Return the linkage that the type info and type info name constants should have for the given type.
static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm, const CXXMethodDecl *md)
Defines the clang::Expr interface and subclasses for C++ expressions.
cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
llvm::Align getABITypeAlign(mlir::Type ty) const
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
CanQualType LongTy
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
IdentifierTable & Idents
Definition ASTContext.h:772
const LangOptions & getLangOpts() const
Definition ASTContext.h:926
CanQualType CharTy
CanQualType UnsignedIntTy
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:891
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
TargetCXXABI::Kind getCXXABIKind() const
Return the C++ ABI kind that should be used.
CanQualType LongLongTy
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
Kind getKind() const
Definition TypeBase.h:3212
mlir::Value getPointer() const
Definition Address.h:81
cir::TypeInfoAttr getTypeInfo(mlir::ArrayAttr fieldsAttr)
cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc)
cir::PointerType getUInt8PtrTy()
mlir::Attribute getString(llvm::StringRef str, mlir::Type eltTy, std::optional< size_t > size)
Get a cir::ConstArrayAttr for a string literal.
cir::LoadOp createAlignedLoad(mlir::Location loc, mlir::Type ty, mlir::Value ptr, llvm::MaybeAlign align)
mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy, mlir::Value addr, uint64_t offset)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)
Implements C++ ABI-specific code generation functions.
clang::MangleContext & getMangleContext()
Gets the mangle context.
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition CIRGenCall.h:90
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
const clang::Decl * curFuncDecl
Address getAddrOfLocalVar(const clang::VarDecl *vd)
Return the address of a local variable.
mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase, bool delegating)
Return the VTT parameter that should be passed to a base constructor/destructor with virtual bases.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
mlir::Value loadCXXVTT()
Load the VTT parameter to base constructors/destructors have virtual bases.
mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr, const clang::CXXRecordDecl *vtableClass)
Return the Value of the vtable pointer member pointed to by thisAddr.
bool shouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *rd)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
CIRGenBuilderTy & getBuilder()
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
This class organizes the cross-function state that is used while generating CIR code.
llvm::StringRef getMangledName(clang::GlobalDecl gd)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
cir::FuncOp getAddrOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
mlir::Type convertType(clang::QualType type)
mlir::IntegerAttr getSize(CharUnits size)
CIRGenBuilderTy & getBuilder()
ItaniumVTableContext & getItaniumVTableContext()
void setGVProperties(mlir::Operation *op, const NamedDecl *d) const
Set visibility, dllimport/dllexport and dso_local.
const clang::TargetInfo & getTarget() const
const llvm::Triple & getTriple() const
static mlir::SymbolTable::Visibility getMLIRVisibility(Visibility v)
cir::GlobalOp createOrReplaceCXXRuntimeVariable(mlir::Location loc, llvm::StringRef name, mlir::Type ty, cir::GlobalLinkageKind linkage, clang::CharUnits alignment)
Will return a global variable of the given type.
void emitAliasForGlobal(llvm::StringRef mangledName, mlir::Operation *op, GlobalDecl aliasGD, cir::FuncOp aliasee, cir::GlobalLinkageKind linkage)
const cir::CIRDataLayout getDataLayout() const
static void setInitializer(cir::GlobalOp &op, mlir::Attribute value)
cir::GlobalLinkageKind getFunctionLinkage(GlobalDecl gd)
const clang::CodeGenOptions & getCodeGenOpts() const
const clang::LangOptions & getLangOpts() const
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
mlir::Operation * getGlobalValue(llvm::StringRef ref)
mlir::ModuleOp getModule() const
mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)
static cir::GlobalOp createGlobalOp(CIRGenModule &cgm, mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::Operation *insertPoint=nullptr)
CIRGenCXXABI & getCXXABI() const
CIRGenVTables & getVTables()
cir::GlobalLinkageKind getVTableLinkage(const CXXRecordDecl *rd)
Return the appropriate linkage for the vtable, VTT, and type information of the given class.
cir::RecordType getVTableType(const clang::VTableLayout &layout)
Returns the type of a vtable with the given layout.
void createVTableInitializer(cir::GlobalOp &vtable, const clang::VTableLayout &layout, mlir::Attribute rtti, bool vtableHasLocalLinkage)
Add vtable components for the given vtable layout to the given global initializer.
void emitVTTDefinition(cir::GlobalOp vttOp, cir::GlobalLinkageKind linkage, const CXXRecordDecl *rd)
Emit the definition of the given vtable.
cir::GlobalOp getAddrOfVTT(const CXXRecordDecl *rd)
Get the address of the VTT for the given record decl.
bool isVTableExternal(const clang::CXXRecordDecl *rd)
At this point in the translation unit, does it appear that can we rely on the vtable being defined el...
uint64_t getSecondaryVirtualPointerIndex(const CXXRecordDecl *rd, BaseSubobject base)
Return the index in the VTT where the virtual pointer for the given subobject is located.
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
Definition DeclCXX.h:203
QualType getType() const
Retrieves the type of the base class.
Definition DeclCXX.h:249
AccessSpecifier getAccessSpecifier() const
Returns the access specifier for this base specifier.
Definition DeclCXX.h:230
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2129
bool isVirtual() const
Definition DeclCXX.h:2184
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2255
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
base_class_range bases()
Definition DeclCXX.h:608
unsigned getNumBases() const
Retrieves the number of base classes of this class.
Definition DeclCXX.h:602
base_class_iterator bases_begin()
Definition DeclCXX.h:615
const CXXBaseSpecifier * base_class_const_iterator
Iterator that traverses the base classes of a class.
Definition DeclCXX.h:520
bool isAbstract() const
Determine whether this class has a pure virtual function.
Definition DeclCXX.h:1221
bool isDynamicClass() const
Definition DeclCXX.h:574
bool hasDefinition() const
Definition DeclCXX.h:561
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition DeclCXX.h:623
static CanQual< Type > CreateUnsafe(QualType Other)
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition CharUnits.h:122
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2109
bool isTranslationUnit() const
Definition DeclBase.h:2185
SourceLocation getLocation() const
Definition DeclBase.h:439
DeclContext * getDeclContext()
Definition DeclBase.h:448
bool hasAttr() const
Definition DeclBase.h:577
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4490
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:57
GlobalDecl getWithCtorType(CXXCtorType Type)
Definition GlobalDecl.h:178
CXXCtorType getCtorType() const
Definition GlobalDecl.h:108
GlobalDecl getWithDtorType(CXXDtorType Type)
Definition GlobalDecl.h:185
CXXDtorType getDtorType() const
Definition GlobalDecl.h:113
const Decl * getDecl() const
Definition GlobalDecl.h:106
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Definition Decl.cpp:5474
uint64_t getMethodVTableIndex(GlobalDecl GD)
Locate a virtual function in the vtable.
const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, const CXXRecordDecl *VBase)
Return the offset in chars (relative to the vtable address point) where the offset of the virtual bas...
virtual void mangleCXXRTTI(QualType T, raw_ostream &)=0
virtual void mangleCXXRTTIName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:294
QualType getPointeeType() const
Definition TypeBase.h:3338
A (possibly-)qualified type.
Definition TypeBase.h:937
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8327
QualType getCanonicalType() const
Definition TypeBase.h:8339
bool empty() const
Definition TypeBase.h:647
Encodes a location in the source.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4834
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
uint64_t getPointerWidth(LangAS AddrSpace) const
Return the width of pointers on this target, for the specified address space.
Definition TargetInfo.h:486
virtual bool hasPS4DLLImportExport() const
uint64_t getPointerAlign(LangAS AddrSpace) const
Definition TargetInfo.h:490
unsigned getLongWidth() const
getLongWidth/Align - Return the size of 'signed long' and 'unsigned long' for this target,...
Definition TargetInfo.h:532
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:3544
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
Visibility getVisibility() const
Determine the visibility of this type.
Definition TypeBase.h:3065
Linkage getLinkage() const
Determine the linkage of this type.
Definition Type.cpp:4899
TypeClass getTypeClass() const
Definition TypeBase.h:2385
AddressPointLocation getAddressPoint(BaseSubobject Base) const
static bool isLocalLinkage(GlobalLinkageKind linkage)
Definition CIROpsEnums.h:51
static LLVM_ATTRIBUTE_UNUSED bool isDiscardableIfUnused(GlobalLinkageKind linkage)
Whether the definition of this global may be discarded if it is not used in its compilation unit.
Definition CIROpsEnums.h:93
static LLVM_ATTRIBUTE_UNUSED bool isValidLinkage(GlobalLinkageKind gl)
static LLVM_ATTRIBUTE_UNUSED bool isWeakForLinker(GlobalLinkageKind linkage)
Whether the definition of this global may be replaced at link time.
CIRGenCXXABI * CreateCIRGenItaniumCXXABI(CIRGenModule &cgm)
Creates and Itanium-family ABI.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition PrimType.h:185
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...
The JSON file list parser is used to communicate input to InstallAPI.
CXXCtorType
C++ constructor types.
Definition ABI.h:24
@ Ctor_Base
Base object ctor.
Definition ABI.h:26
@ Ctor_Complete
Complete object ctor.
Definition ABI.h:25
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ AS_public
Definition Specifiers.h:124
@ VisibleNone
No linkage according to the standard, but is visible from other translation units because of types de...
Definition Linkage.h:48
@ None
No linkage, which means that the entity is unique and can only be referred to from within its scope.
Definition Linkage.h:30
@ UniqueExternal
External linkage within a unique namespace.
Definition Linkage.h:44
@ Internal
Internal linkage, which indicates that the entity can be referred to from within the translation unit...
Definition Linkage.h:35
@ External
External linkage, which indicates that the entity can be referred to from other translation units.
Definition Linkage.h:58
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
Definition Linkage.h:54
CXXDtorType
C++ destructor types.
Definition ABI.h:34
@ Dtor_Base
Base object dtor.
Definition ABI.h:37
@ Dtor_Complete
Complete object dtor.
Definition ABI.h:36
@ Dtor_Deleting
Deleting dtor.
Definition ABI.h:35
@ Type
The name was classified as a type.
Definition Sema.h:561
U cast(CodeGen::Address addr)
Definition Address.h:327
@ DefaultVisibility
Objects with "default" visibility are seen by the dynamic linker and act like normal objects.
Definition Visibility.h:46
unsigned long uint64_t
long int64_t
static bool addressSpace()
static bool opGlobalUnnamedAddr()
static bool vtableEmitMetadata()
static bool emitTypeMetadataCodeForVCall()
static bool setDLLStorageClass()
static bool hiddenVisibility()
static bool cxxabiAppleARM64CXXABI()
static bool opGlobalDLLImportExport()
static bool opGlobalPartition()
static bool setComdat()
static bool protectedVisibility()
static bool deferredVtables()
static bool cxxabiUseARMGuardVarABI()
static bool cxxabiUseARMMethodPtrABI()
static bool setDSOLocal()
static bool vtableRelativeLayout()
const clang::CXXRecordDecl * nearestVBase
clang::CharUnits getPointerAlign() const