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 mlir::Value getCXXDestructorImplicitParam(CIRGenFunction &cgf,
63 const CXXDestructorDecl *dd,
65 bool forVirtualBase,
66 bool delegating) override;
67 void emitCXXConstructors(const clang::CXXConstructorDecl *d) override;
68 void emitCXXDestructors(const clang::CXXDestructorDecl *d) override;
69 void emitCXXStructor(clang::GlobalDecl gd) override;
70
71 void emitDestructorCall(CIRGenFunction &cgf, const CXXDestructorDecl *dd,
72 CXXDtorType type, bool forVirtualBase,
73 bool delegating, Address thisAddr,
74 QualType thisTy) override;
75 void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor,
76 mlir::Value addr) override;
77
78 void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;
79 void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override;
80
81 bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
82 CXXDtorType dt) const override {
83 // Itanium does not emit any destructor variant as an inline thunk.
84 // Delegating may occur as an optimization, but all variants are either
85 // emitted with external linkage or as linkonce if they are inline and used.
86 return false;
87 }
88
89 bool isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
90 CIRGenFunction::VPtr vptr) override;
91
92 cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd,
93 CharUnits vptrOffset) override;
94 CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf,
95 clang::GlobalDecl gd, Address thisAddr,
96 mlir::Type ty,
97 SourceLocation loc) override;
98 mlir::Value emitVirtualDestructorCall(CIRGenFunction &cgf,
99 const CXXDestructorDecl *dtor,
100 CXXDtorType dtorType, Address thisAddr,
101 DeleteOrMemberCallExpr e) override;
102 mlir::Value getVTableAddressPoint(BaseSubobject base,
103 const CXXRecordDecl *vtableClass) override;
104 mlir::Value getVTableAddressPointInStructorWithVTT(
105 CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
106 const CXXRecordDecl *nearestVBase);
107
108 mlir::Value getVTableAddressPointInStructor(
109 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,
110 clang::BaseSubobject base,
111 const clang::CXXRecordDecl *nearestVBase) override;
112 void emitVTableDefinitions(CIRGenVTables &cgvt,
113 const CXXRecordDecl *rd) override;
114 void emitVirtualInheritanceTables(const CXXRecordDecl *rd) override;
115
116 mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
117 QualType ty) override;
118
119 bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {
120 return true;
121 }
122
123 mlir::Value
124 getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf,
125 Address thisAddr, const CXXRecordDecl *classDecl,
126 const CXXRecordDecl *baseClassDecl) override;
127
128 // The traditional clang CodeGen emits calls to `__dynamic_cast` directly into
129 // LLVM in the `emitDynamicCastCall` function. In CIR, `dynamic_cast`
130 // expressions are lowered to `cir.dyn_cast` ops instead of calls to runtime
131 // functions. So during CIRGen we don't need the `emitDynamicCastCall`
132 // function that clang CodeGen has.
133 mlir::Value emitDynamicCast(CIRGenFunction &cgf, mlir::Location loc,
134 QualType srcRecordTy, QualType destRecordTy,
135 cir::PointerType destCIRTy, bool isRefCast,
136 Address src) override;
137
138 /**************************** RTTI Uniqueness ******************************/
139protected:
140 /// Returns true if the ABI requires RTTI type_info objects to be unique
141 /// across a program.
142 virtual bool shouldRTTIBeUnique() const { return true; }
143
144public:
145 /// What sort of unique-RTTI behavior should we use?
146 enum RTTIUniquenessKind {
147 /// We are guaranteeing, or need to guarantee, that the RTTI string
148 /// is unique.
149 RUK_Unique,
150
151 /// We are not guaranteeing uniqueness for the RTTI string, so we
152 /// can demote to hidden visibility but must use string comparisons.
153 RUK_NonUniqueHidden,
154
155 /// We are not guaranteeing uniqueness for the RTTI string, so we
156 /// have to use string comparisons, but we also have to emit it with
157 /// non-hidden visibility.
158 RUK_NonUniqueVisible
159 };
160
161 /// Return the required visibility status for the given type and linkage in
162 /// the current ABI.
163 RTTIUniquenessKind
164 classifyRTTIUniqueness(QualType canTy, cir::GlobalLinkageKind linkage) const;
165};
166
167} // namespace
168
169void CIRGenItaniumCXXABI::emitInstanceFunctionProlog(SourceLocation loc,
170 CIRGenFunction &cgf) {
171 // Naked functions have no prolog.
172 if (cgf.curFuncDecl && cgf.curFuncDecl->hasAttr<NakedAttr>()) {
174 "emitInstanceFunctionProlog: Naked");
175 }
176
177 /// Initialize the 'this' slot. In the Itanium C++ ABI, no prologue
178 /// adjustments are required, because they are all handled by thunks.
179 setCXXABIThisValue(cgf, loadIncomingCXXThis(cgf));
180
181 /// Initialize the 'vtt' slot if needed.
182 if (getStructorImplicitParamDecl(cgf)) {
183 cir::LoadOp val = cgf.getBuilder().createLoad(
184 cgf.getLoc(loc),
185 cgf.getAddrOfLocalVar(getStructorImplicitParamDecl(cgf)));
186 setStructorImplicitParamValue(cgf, val);
187 }
188
189 /// If this is a function that the ABI specifies returns 'this', initialize
190 /// the return slot to this' at the start of the function.
191 ///
192 /// Unlike the setting of return types, this is done within the ABI
193 /// implementation instead of by clients of CIRGenCXXBI because:
194 /// 1) getThisValue is currently protected
195 /// 2) in theory, an ABI could implement 'this' returns some other way;
196 /// HasThisReturn only specifies a contract, not the implementation
197 if (hasThisReturn(cgf.curGD)) {
199 "emitInstanceFunctionProlog: hasThisReturn");
200 }
201}
202
203CIRGenCXXABI::AddedStructorArgCounts
204CIRGenItaniumCXXABI::buildStructorSignature(
205 GlobalDecl gd, llvm::SmallVectorImpl<CanQualType> &argTys) {
206 clang::ASTContext &astContext = cgm.getASTContext();
207
208 // All parameters are already in place except VTT, which goes after 'this'.
209 // These are clang types, so we don't need to worry about sret yet.
210
211 // Check if we need to add a VTT parameter (which has type void **).
213 : gd.getDtorType() == Dtor_Base) &&
214 cast<CXXMethodDecl>(gd.getDecl())->getParent()->getNumVBases() != 0) {
216 argTys.insert(argTys.begin() + 1,
217 astContext.getPointerType(
219 return AddedStructorArgCounts::withPrefix(1);
220 }
221
222 return AddedStructorArgCounts{};
223}
224
225// Find out how to cirgen the complete destructor and constructor
226namespace {
227enum class StructorCIRGen { Emit, RAUW, Alias, COMDAT };
228}
229
230static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm,
231 const CXXMethodDecl *md) {
232 if (!cgm.getCodeGenOpts().CXXCtorDtorAliases)
233 return StructorCIRGen::Emit;
234
235 // The complete and base structors are not equivalent if there are any virtual
236 // bases, so emit separate functions.
237 if (md->getParent()->getNumVBases())
238 return StructorCIRGen::Emit;
239
240 GlobalDecl aliasDecl;
241 if (const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
242 aliasDecl = GlobalDecl(dd, Dtor_Complete);
243 } else {
244 const auto *cd = cast<CXXConstructorDecl>(md);
245 aliasDecl = GlobalDecl(cd, Ctor_Complete);
246 }
247
248 cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);
249
250 if (cir::isDiscardableIfUnused(linkage))
251 return StructorCIRGen::RAUW;
252
253 // FIXME: Should we allow available_externally aliases?
254 if (!cir::isValidLinkage(linkage))
255 return StructorCIRGen::RAUW;
256
257 if (cir::isWeakForLinker(linkage)) {
258 // Only ELF and wasm support COMDATs with arbitrary names (C5/D5).
259 if (cgm.getTarget().getTriple().isOSBinFormatELF() ||
260 cgm.getTarget().getTriple().isOSBinFormatWasm())
261 return StructorCIRGen::COMDAT;
262 return StructorCIRGen::Emit;
263 }
264
265 return StructorCIRGen::Alias;
266}
267
269 GlobalDecl aliasDecl,
270 GlobalDecl targetDecl) {
271 cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);
272
273 // Does this function alias already exists?
274 StringRef mangledName = cgm.getMangledName(aliasDecl);
275 auto globalValue = dyn_cast_or_null<cir::CIRGlobalValueInterface>(
276 cgm.getGlobalValue(mangledName));
277 if (globalValue && !globalValue.isDeclaration())
278 return;
279
280 auto entry = cast_or_null<cir::FuncOp>(cgm.getGlobalValue(mangledName));
281
282 // Retrieve aliasee info.
283 auto aliasee = cast<cir::FuncOp>(cgm.getAddrOfGlobal(targetDecl));
284
285 // Populate actual alias.
286 cgm.emitAliasForGlobal(mangledName, entry, aliasDecl, aliasee, linkage);
287}
288
289void CIRGenItaniumCXXABI::emitCXXStructor(GlobalDecl gd) {
290 auto *md = cast<CXXMethodDecl>(gd.getDecl());
291 StructorCIRGen cirGenType = getCIRGenToUse(cgm, md);
292 const auto *cd = dyn_cast<CXXConstructorDecl>(md);
293
294 if (cd ? gd.getCtorType() == Ctor_Complete
295 : gd.getDtorType() == Dtor_Complete) {
296 GlobalDecl baseDecl =
298 ;
299
300 if (cirGenType == StructorCIRGen::Alias ||
301 cirGenType == StructorCIRGen::COMDAT) {
302 emitConstructorDestructorAlias(cgm, gd, baseDecl);
303 return;
304 }
305
306 if (cirGenType == StructorCIRGen::RAUW) {
307 StringRef mangledName = cgm.getMangledName(gd);
308 mlir::Operation *aliasee = cgm.getAddrOfGlobal(baseDecl);
309 cgm.addReplacement(mangledName, aliasee);
310 return;
311 }
312 }
313
314 auto fn = cgm.codegenCXXStructor(gd);
315
316 cgm.maybeSetTrivialComdat(*md, fn);
317}
318
319void CIRGenItaniumCXXABI::addImplicitStructorParams(CIRGenFunction &cgf,
320 QualType &resTy,
321 FunctionArgList &params) {
322 const auto *md = cast<CXXMethodDecl>(cgf.curGD.getDecl());
324
325 // Check if we need a VTT parameter as well.
326 if (needsVTTParameter(cgf.curGD)) {
327 ASTContext &astContext = cgm.getASTContext();
328
329 // FIXME: avoid the fake decl
331 QualType t = astContext.getPointerType(astContext.VoidPtrTy);
332 auto *vttDecl = ImplicitParamDecl::Create(
333 astContext, /*DC=*/nullptr, md->getLocation(),
334 &astContext.Idents.get("vtt"), t, ImplicitParamKind::CXXVTT);
335 params.insert(params.begin() + 1, vttDecl);
336 getStructorImplicitParamDecl(cgf) = vttDecl;
337 }
338}
339
340void CIRGenItaniumCXXABI::emitCXXConstructors(const CXXConstructorDecl *d) {
341 // Just make sure we're in sync with TargetCXXABI.
342 assert(cgm.getTarget().getCXXABI().hasConstructorVariants());
343
344 // The constructor used for constructing this as a base class;
345 // ignores virtual bases.
346 cgm.emitGlobal(GlobalDecl(d, Ctor_Base));
347
348 // The constructor used for constructing this as a complete class;
349 // constructs the virtual bases, then calls the base constructor.
350 if (!d->getParent()->isAbstract()) {
351 // We don't need to emit the complete ctro if the class is abstract.
352 cgm.emitGlobal(GlobalDecl(d, Ctor_Complete));
353 }
354}
355
356void CIRGenItaniumCXXABI::emitCXXDestructors(const CXXDestructorDecl *d) {
357 // The destructor used for destructing this as a base class; ignores
358 // virtual bases.
359 cgm.emitGlobal(GlobalDecl(d, Dtor_Base));
360
361 // The destructor used for destructing this as a most-derived class;
362 // call the base destructor and then destructs any virtual bases.
363 cgm.emitGlobal(GlobalDecl(d, Dtor_Complete));
364
365 // The destructor in a virtual table is always a 'deleting'
366 // destructor, which calls the complete destructor and then uses the
367 // appropriate operator delete.
368 if (d->isVirtual())
369 cgm.emitGlobal(GlobalDecl(d, Dtor_Deleting));
370}
371
372CIRGenCXXABI::AddedStructorArgs CIRGenItaniumCXXABI::getImplicitConstructorArgs(
373 CIRGenFunction &cgf, const CXXConstructorDecl *d, CXXCtorType type,
374 bool forVirtualBase, bool delegating) {
375 if (!needsVTTParameter(GlobalDecl(d, type)))
376 return AddedStructorArgs{};
377
378 // Insert the implicit 'vtt' argument as the second argument. Make sure to
379 // correctly reflect its address space, which can differ from generic on
380 // some targets.
381 mlir::Value vtt =
382 cgf.getVTTParameter(GlobalDecl(d, type), forVirtualBase, delegating);
383 QualType vttTy =
384 cgm.getASTContext().getPointerType(cgm.getASTContext().VoidPtrTy);
386 return AddedStructorArgs::withPrefix({{vtt, vttTy}});
387}
388
389/// Return whether the given global decl needs a VTT (virtual table table)
390/// parameter, which it does if it's a base constructor or destructor with
391/// virtual bases.
392bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) {
393 auto *md = cast<CXXMethodDecl>(gd.getDecl());
394
395 // We don't have any virtual bases, just return early.
396 if (!md->getParent()->getNumVBases())
397 return false;
398
399 // Check if we have a base constructor.
401 return true;
402
403 // Check if we have a base destructor.
405 return true;
406
407 return false;
408}
409
410void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,
411 const CXXRecordDecl *rd) {
412 cir::GlobalOp vtable = getAddrOfVTable(rd, CharUnits());
413 if (vtable.hasInitializer())
414 return;
415
416 ItaniumVTableContext &vtContext = cgm.getItaniumVTableContext();
417 const VTableLayout &vtLayout = vtContext.getVTableLayout(rd);
418 cir::GlobalLinkageKind linkage = cgm.getVTableLinkage(rd);
419 mlir::Attribute rtti =
420 cgm.getAddrOfRTTIDescriptor(cgm.getLoc(rd->getBeginLoc()),
421 cgm.getASTContext().getCanonicalTagType(rd));
422
423 // Classic codegen uses ConstantInitBuilder here, which is a very general
424 // and feature-rich class to generate initializers for global values.
425 // For now, this is using a simpler approach to create the initializer in CIR.
426 cgvt.createVTableInitializer(vtable, vtLayout, rtti,
427 cir::isLocalLinkage(linkage));
428
429 // Set the correct linkage.
430 vtable.setLinkage(linkage);
431
432 if (cgm.supportsCOMDAT() && cir::isWeakForLinker(linkage))
433 vtable.setComdat(true);
434
435 // Set the right visibility.
436 cgm.setGVProperties(vtable, rd);
437
438 // If this is the magic class __cxxabiv1::__fundamental_type_info,
439 // we will emit the typeinfo for the fundamental types. This is the
440 // same behaviour as GCC.
441 const DeclContext *DC = rd->getDeclContext();
442 if (rd->getIdentifier() &&
443 rd->getIdentifier()->isStr("__fundamental_type_info") &&
444 isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
445 cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
446 DC->getParent()->isTranslationUnit()) {
447 cgm.errorNYI(rd->getSourceRange(),
448 "emitVTableDefinitions: __fundamental_type_info");
449 }
450
451 auto vtableAsGlobalValue = dyn_cast<cir::CIRGlobalValueInterface>(*vtable);
452 assert(vtableAsGlobalValue && "VTable must support CIRGlobalValueInterface");
453 // Always emit type metadata on non-available_externally definitions, and on
454 // available_externally definitions if we are performing whole program
455 // devirtualization. For WPD we need the type metadata on all vtable
456 // definitions to ensure we associate derived classes with base classes
457 // defined in headers but with a strong definition only in a shared
458 // library.
460 if (cgm.getCodeGenOpts().WholeProgramVTables) {
461 cgm.errorNYI(rd->getSourceRange(),
462 "emitVTableDefinitions: WholeProgramVTables");
463 }
464
466 if (vtContext.isRelativeLayout()) {
467 cgm.errorNYI(rd->getSourceRange(), "vtableRelativeLayout");
468 }
469}
470
471mlir::Value CIRGenItaniumCXXABI::emitVirtualDestructorCall(
472 CIRGenFunction &cgf, const CXXDestructorDecl *dtor, CXXDtorType dtorType,
473 Address thisAddr, DeleteOrMemberCallExpr expr) {
474 auto *callExpr = dyn_cast<const CXXMemberCallExpr *>(expr);
475 auto *delExpr = dyn_cast<const CXXDeleteExpr *>(expr);
476 assert((callExpr != nullptr) ^ (delExpr != nullptr));
477 assert(callExpr == nullptr || callExpr->arg_begin() == callExpr->arg_end());
478 assert(dtorType == Dtor_Deleting || dtorType == Dtor_Complete);
479
480 GlobalDecl globalDecl(dtor, dtorType);
481 const CIRGenFunctionInfo *fnInfo =
482 &cgm.getTypes().arrangeCXXStructorDeclaration(globalDecl);
483 const cir::FuncType &fnTy = cgm.getTypes().getFunctionType(*fnInfo);
484 auto callee = CIRGenCallee::forVirtual(callExpr, globalDecl, thisAddr, fnTy);
485
486 QualType thisTy =
487 callExpr ? callExpr->getObjectType() : delExpr->getDestroyedType();
488
489 cgf.emitCXXDestructorCall(globalDecl, callee, thisAddr.emitRawPointer(),
490 thisTy, nullptr, QualType(), nullptr);
491 return nullptr;
492}
493
494void CIRGenItaniumCXXABI::emitVirtualInheritanceTables(
495 const CXXRecordDecl *rd) {
496 CIRGenVTables &vtables = cgm.getVTables();
497 cir::GlobalOp vtt = vtables.getAddrOfVTT(rd);
498 vtables.emitVTTDefinition(vtt, cgm.getVTableLinkage(rd), rd);
499}
500
501namespace {
502class CIRGenItaniumRTTIBuilder {
503 CIRGenModule &cgm; // Per-module state.
504 const CIRGenItaniumCXXABI &cxxABI; // Per-module state.
505
506 /// The fields of the RTTI descriptor currently being built.
507 SmallVector<mlir::Attribute, 16> fields;
508
509 // Returns the mangled type name of the given type.
510 cir::GlobalOp getAddrOfTypeName(mlir::Location loc, QualType ty,
511 cir::GlobalLinkageKind linkage);
512
513 /// descriptor of the given type.
514 mlir::Attribute getAddrOfExternalRTTIDescriptor(mlir::Location loc,
515 QualType ty);
516
517 /// Build the vtable pointer for the given type.
518 void buildVTablePointer(mlir::Location loc, const Type *ty);
519
520 /// Build an abi::__si_class_type_info, used for single inheritance, according
521 /// to the Itanium C++ ABI, 2.9.5p6b.
522 void buildSIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd);
523
524 /// Build an abi::__vmi_class_type_info, used for
525 /// classes with bases that do not satisfy the abi::__si_class_type_info
526 /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
527 void buildVMIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd);
528
529public:
530 CIRGenItaniumRTTIBuilder(const CIRGenItaniumCXXABI &abi, CIRGenModule &cgm)
531 : cgm(cgm), cxxABI(abi) {}
532
533 /// Build the RTTI type info struct for the given type, or
534 /// link to an existing RTTI descriptor if one already exists.
535 mlir::Attribute buildTypeInfo(mlir::Location loc, QualType ty);
536
537 /// Build the RTTI type info struct for the given type.
538 mlir::Attribute buildTypeInfo(mlir::Location loc, QualType ty,
539 cir::GlobalLinkageKind linkage,
540 mlir::SymbolTable::Visibility visibility);
541};
542} // namespace
543
544// TODO(cir): Will be removed after sharing them with the classical codegen
545namespace {
546
547// Pointer type info flags.
548enum {
549 /// PTI_Const - Type has const qualifier.
550 PTI_Const = 0x1,
551
552 /// PTI_Volatile - Type has volatile qualifier.
553 PTI_Volatile = 0x2,
554
555 /// PTI_Restrict - Type has restrict qualifier.
556 PTI_Restrict = 0x4,
557
558 /// PTI_Incomplete - Type is incomplete.
559 PTI_Incomplete = 0x8,
560
561 /// PTI_ContainingClassIncomplete - Containing class is incomplete.
562 /// (in pointer to member).
563 PTI_ContainingClassIncomplete = 0x10,
564
565 /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
566 // PTI_TransactionSafe = 0x20,
567
568 /// PTI_Noexcept - Pointee is noexcept function (C++1z).
569 PTI_Noexcept = 0x40,
570};
571
572// VMI type info flags.
573enum {
574 /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
575 VMI_NonDiamondRepeat = 0x1,
576
577 /// VMI_DiamondShaped - Class is diamond shaped.
578 VMI_DiamondShaped = 0x2
579};
580
581// Base class type info flags.
582enum {
583 /// BCTI_Virtual - Base class is virtual.
584 BCTI_Virtual = 0x1,
585
586 /// BCTI_Public - Base class is public.
587 BCTI_Public = 0x2
588};
589
590/// Given a builtin type, returns whether the type
591/// info for that type is defined in the standard library.
592/// TODO(cir): this can unified with LLVM codegen
593static bool typeInfoIsInStandardLibrary(const BuiltinType *ty) {
594 // Itanium C++ ABI 2.9.2:
595 // Basic type information (e.g. for "int", "bool", etc.) will be kept in
596 // the run-time support library. Specifically, the run-time support
597 // library should contain type_info objects for the types X, X* and
598 // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,
599 // unsigned char, signed char, short, unsigned short, int, unsigned int,
600 // long, unsigned long, long long, unsigned long long, float, double,
601 // long double, char16_t, char32_t, and the IEEE 754r decimal and
602 // half-precision floating point types.
603 //
604 // GCC also emits RTTI for __int128.
605 // FIXME: We do not emit RTTI information for decimal types here.
606
607 // Types added here must also be added to emitFundamentalRTTIDescriptors.
608 switch (ty->getKind()) {
609 case BuiltinType::WasmExternRef:
610 case BuiltinType::HLSLResource:
611 llvm_unreachable("NYI");
612 case BuiltinType::Void:
613 case BuiltinType::NullPtr:
614 case BuiltinType::Bool:
615 case BuiltinType::WChar_S:
616 case BuiltinType::WChar_U:
617 case BuiltinType::Char_U:
618 case BuiltinType::Char_S:
619 case BuiltinType::UChar:
620 case BuiltinType::SChar:
621 case BuiltinType::Short:
622 case BuiltinType::UShort:
623 case BuiltinType::Int:
624 case BuiltinType::UInt:
625 case BuiltinType::Long:
626 case BuiltinType::ULong:
627 case BuiltinType::LongLong:
628 case BuiltinType::ULongLong:
629 case BuiltinType::Half:
630 case BuiltinType::Float:
631 case BuiltinType::Double:
632 case BuiltinType::LongDouble:
633 case BuiltinType::Float16:
634 case BuiltinType::Float128:
635 case BuiltinType::Ibm128:
636 case BuiltinType::Char8:
637 case BuiltinType::Char16:
638 case BuiltinType::Char32:
639 case BuiltinType::Int128:
640 case BuiltinType::UInt128:
641 return true;
642
643#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
644 case BuiltinType::Id:
645#include "clang/Basic/OpenCLImageTypes.def"
646#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:
647#include "clang/Basic/OpenCLExtensionTypes.def"
648 case BuiltinType::OCLSampler:
649 case BuiltinType::OCLEvent:
650 case BuiltinType::OCLClkEvent:
651 case BuiltinType::OCLQueue:
652 case BuiltinType::OCLReserveID:
653#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
654#include "clang/Basic/AArch64ACLETypes.def"
655#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
656#include "clang/Basic/PPCTypes.def"
657#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
658#include "clang/Basic/RISCVVTypes.def"
659#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
660#include "clang/Basic/AMDGPUTypes.def"
661 case BuiltinType::ShortAccum:
662 case BuiltinType::Accum:
663 case BuiltinType::LongAccum:
664 case BuiltinType::UShortAccum:
665 case BuiltinType::UAccum:
666 case BuiltinType::ULongAccum:
667 case BuiltinType::ShortFract:
668 case BuiltinType::Fract:
669 case BuiltinType::LongFract:
670 case BuiltinType::UShortFract:
671 case BuiltinType::UFract:
672 case BuiltinType::ULongFract:
673 case BuiltinType::SatShortAccum:
674 case BuiltinType::SatAccum:
675 case BuiltinType::SatLongAccum:
676 case BuiltinType::SatUShortAccum:
677 case BuiltinType::SatUAccum:
678 case BuiltinType::SatULongAccum:
679 case BuiltinType::SatShortFract:
680 case BuiltinType::SatFract:
681 case BuiltinType::SatLongFract:
682 case BuiltinType::SatUShortFract:
683 case BuiltinType::SatUFract:
684 case BuiltinType::SatULongFract:
685 case BuiltinType::BFloat16:
686 return false;
687
688 case BuiltinType::Dependent:
689#define BUILTIN_TYPE(Id, SingletonId)
690#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
691#include "clang/AST/BuiltinTypes.def"
692 llvm_unreachable("asking for RRTI for a placeholder type!");
693
694 case BuiltinType::ObjCId:
695 case BuiltinType::ObjCClass:
696 case BuiltinType::ObjCSel:
697 llvm_unreachable("FIXME: Objective-C types are unsupported!");
698 }
699
700 llvm_unreachable("Invalid BuiltinType Kind!");
701}
702
703static bool typeInfoIsInStandardLibrary(const PointerType *pointerTy) {
704 QualType pointeeTy = pointerTy->getPointeeType();
705 const auto *builtinTy = dyn_cast<BuiltinType>(pointeeTy);
706 if (!builtinTy)
707 return false;
708
709 // Check the qualifiers.
710 Qualifiers quals = pointeeTy.getQualifiers();
711 quals.removeConst();
712
713 if (!quals.empty())
714 return false;
715
716 return typeInfoIsInStandardLibrary(builtinTy);
717}
718
719/// IsStandardLibraryRTTIDescriptor - Returns whether the type
720/// information for the given type exists in the standard library.
721static bool isStandardLibraryRttiDescriptor(QualType ty) {
722 // Type info for builtin types is defined in the standard library.
723 if (const auto *builtinTy = dyn_cast<BuiltinType>(ty))
724 return typeInfoIsInStandardLibrary(builtinTy);
725
726 // Type info for some pointer types to builtin types is defined in the
727 // standard library.
728 if (const auto *pointerTy = dyn_cast<PointerType>(ty))
729 return typeInfoIsInStandardLibrary(pointerTy);
730
731 return false;
732}
733
734/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
735/// the given type exists somewhere else, and that we should not emit the type
736/// information in this translation unit. Assumes that it is not a
737/// standard-library type.
738static bool shouldUseExternalRttiDescriptor(CIRGenModule &cgm, QualType ty) {
739 ASTContext &context = cgm.getASTContext();
740
741 // If RTTI is disabled, assume it might be disabled in the
742 // translation unit that defines any potential key function, too.
743 if (!context.getLangOpts().RTTI)
744 return false;
745
746 if (const auto *recordTy = dyn_cast<RecordType>(ty)) {
747 const auto *rd =
748 cast<CXXRecordDecl>(recordTy->getDecl())->getDefinitionOrSelf();
749 if (!rd->hasDefinition())
750 return false;
751
752 if (!rd->isDynamicClass())
753 return false;
754
755 // FIXME: this may need to be reconsidered if the key function
756 // changes.
757 // N.B. We must always emit the RTTI data ourselves if there exists a key
758 // function.
759 bool isDLLImport = rd->hasAttr<DLLImportAttr>();
760
761 // Don't import the RTTI but emit it locally.
762 if (cgm.getTriple().isOSCygMing())
763 return false;
764
765 if (cgm.getVTables().isVTableExternal(rd)) {
767 return true;
768
769 return !isDLLImport || cgm.getTriple().isWindowsItaniumEnvironment();
770 }
771
772 if (isDLLImport)
773 return true;
774 }
775
776 return false;
777}
778
779/// Contains virtual and non-virtual bases seen when traversing a class
780/// hierarchy.
781struct SeenBases {
782 llvm::SmallPtrSet<const CXXRecordDecl *, 16> nonVirtualBases;
783 llvm::SmallPtrSet<const CXXRecordDecl *, 16> virtualBases;
784};
785
786/// Compute the value of the flags member in abi::__vmi_class_type_info.
787///
788static unsigned computeVmiClassTypeInfoFlags(const CXXBaseSpecifier *base,
789 SeenBases &bases) {
790
791 unsigned flags = 0;
792 auto *baseDecl = base->getType()->castAsCXXRecordDecl();
793
794 if (base->isVirtual()) {
795 // Mark the virtual base as seen.
796 if (!bases.virtualBases.insert(baseDecl).second) {
797 // If this virtual base has been seen before, then the class is diamond
798 // shaped.
799 flags |= VMI_DiamondShaped;
800 } else {
801 if (bases.nonVirtualBases.count(baseDecl))
802 flags |= VMI_NonDiamondRepeat;
803 }
804 } else {
805 // Mark the non-virtual base as seen.
806 if (!bases.nonVirtualBases.insert(baseDecl).second) {
807 // If this non-virtual base has been seen before, then the class has non-
808 // diamond shaped repeated inheritance.
809 flags |= VMI_NonDiamondRepeat;
810 } else {
811 if (bases.virtualBases.count(baseDecl))
812 flags |= VMI_NonDiamondRepeat;
813 }
814 }
815
816 // Walk all bases.
817 for (const auto &bs : baseDecl->bases())
818 flags |= computeVmiClassTypeInfoFlags(&bs, bases);
819
820 return flags;
821}
822
823static unsigned computeVmiClassTypeInfoFlags(const CXXRecordDecl *rd) {
824 unsigned flags = 0;
825 SeenBases bases;
826
827 // Walk all bases.
828 for (const auto &bs : rd->bases())
829 flags |= computeVmiClassTypeInfoFlags(&bs, bases);
830
831 return flags;
832}
833
834// Return whether the given record decl has a "single,
835// public, non-virtual base at offset zero (i.e. the derived class is dynamic
836// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
837// TODO(cir): this can unified with LLVM codegen
838static bool canUseSingleInheritance(const CXXRecordDecl *rd) {
839 // Check the number of bases.
840 if (rd->getNumBases() != 1)
841 return false;
842
843 // Get the base.
845
846 // Check that the base is not virtual.
847 if (base->isVirtual())
848 return false;
849
850 // Check that the base is public.
851 if (base->getAccessSpecifier() != AS_public)
852 return false;
853
854 // Check that the class is dynamic iff the base is.
855 auto *baseDecl = base->getType()->castAsCXXRecordDecl();
856 return baseDecl->isEmpty() ||
857 baseDecl->isDynamicClass() == rd->isDynamicClass();
858}
859
860/// IsIncompleteClassType - Returns whether the given record type is incomplete.
861static bool isIncompleteClassType(const RecordType *recordTy) {
862 return !recordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition();
863}
864
865/// Returns whether the given type contains an
866/// incomplete class type. This is true if
867///
868/// * The given type is an incomplete class type.
869/// * The given type is a pointer type whose pointee type contains an
870/// incomplete class type.
871/// * The given type is a member pointer type whose class is an incomplete
872/// class type.
873/// * The given type is a member pointer type whoise pointee type contains an
874/// incomplete class type.
875/// is an indirect or direct pointer to an incomplete class type.
876static bool containsIncompleteClassType(QualType ty) {
877 if (const auto *recordTy = dyn_cast<RecordType>(ty)) {
878 if (isIncompleteClassType(recordTy))
879 return true;
880 }
881
882 if (const auto *pointerTy = dyn_cast<PointerType>(ty))
883 return containsIncompleteClassType(pointerTy->getPointeeType());
884
885 if (const auto *memberPointerTy = dyn_cast<MemberPointerType>(ty)) {
886 // Check if the class type is incomplete.
887 if (!memberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
888 return true;
889
890 return containsIncompleteClassType(memberPointerTy->getPointeeType());
891 }
892
893 return false;
894}
895
896const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) {
897 // abi::__class_type_info.
898 static const char *const classTypeInfo =
899 "_ZTVN10__cxxabiv117__class_type_infoE";
900 // abi::__si_class_type_info.
901 static const char *const siClassTypeInfo =
902 "_ZTVN10__cxxabiv120__si_class_type_infoE";
903 // abi::__vmi_class_type_info.
904 static const char *const vmiClassTypeInfo =
905 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
906
907 switch (ty->getTypeClass()) {
908#define TYPE(Class, Base)
909#define ABSTRACT_TYPE(Class, Base)
910#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
911#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
912#define DEPENDENT_TYPE(Class, Base) case Type::Class:
913#include "clang/AST/TypeNodes.inc"
914 llvm_unreachable("Non-canonical and dependent types shouldn't get here");
915
916 case Type::LValueReference:
917 case Type::RValueReference:
918 llvm_unreachable("References shouldn't get here");
919
920 case Type::Auto:
921 case Type::DeducedTemplateSpecialization:
922 llvm_unreachable("Undeduced type shouldn't get here");
923
924 case Type::Pipe:
925 llvm_unreachable("Pipe types shouldn't get here");
926
927 case Type::ArrayParameter:
928 llvm_unreachable("Array Parameter types should not get here.");
929
930 case Type::Builtin:
931 case Type::BitInt:
932 // GCC treats vector and complex types as fundamental types.
933 case Type::Vector:
934 case Type::ExtVector:
935 case Type::ConstantMatrix:
936 case Type::Complex:
937 case Type::Atomic:
938 // FIXME: GCC treats block pointers as fundamental types?!
939 case Type::BlockPointer:
940 return "_ZTVN10__cxxabiv123__fundamental_type_infoE";
941 case Type::ConstantArray:
942 case Type::IncompleteArray:
943 case Type::VariableArray:
944 cgm.errorNYI("VTableClassNameForType: __array_type_info");
945 break;
946
947 case Type::FunctionNoProto:
948 case Type::FunctionProto:
949 cgm.errorNYI("VTableClassNameForType: __function_type_info");
950 break;
951
952 case Type::Enum:
953 cgm.errorNYI("VTableClassNameForType: Enum");
954 break;
955
956 case Type::Record: {
957 const auto *rd = cast<CXXRecordDecl>(cast<RecordType>(ty)->getDecl())
958 ->getDefinitionOrSelf();
959
960 if (!rd->hasDefinition() || !rd->getNumBases()) {
961 return classTypeInfo;
962 }
963
964 if (canUseSingleInheritance(rd)) {
965 return siClassTypeInfo;
966 }
967
968 return vmiClassTypeInfo;
969 }
970
971 case Type::ObjCObject:
972 cgm.errorNYI("VTableClassNameForType: ObjCObject");
973 break;
974
975 case Type::ObjCInterface:
976 cgm.errorNYI("VTableClassNameForType: ObjCInterface");
977 break;
978
979 case Type::ObjCObjectPointer:
980 case Type::Pointer:
981 cgm.errorNYI("VTableClassNameForType: __pointer_type_info");
982 break;
983
984 case Type::MemberPointer:
985 cgm.errorNYI("VTableClassNameForType: __pointer_to_member_type_info");
986 break;
987
988 case Type::HLSLAttributedResource:
989 case Type::HLSLInlineSpirv:
990 llvm_unreachable("HLSL doesn't support virtual functions");
991 }
992
993 return nullptr;
994}
995} // namespace
996
997/// Return the linkage that the type info and type info name constants
998/// should have for the given type.
999static cir::GlobalLinkageKind getTypeInfoLinkage(CIRGenModule &cgm,
1000 QualType ty) {
1001 // In addition, it and all of the intermediate abi::__pointer_type_info
1002 // structs in the chain down to the abi::__class_type_info for the
1003 // incomplete class type must be prevented from resolving to the
1004 // corresponding type_info structs for the complete class type, possibly
1005 // by making them local static objects. Finally, a dummy class RTTI is
1006 // generated for the incomplete type that will not resolve to the final
1007 // complete class RTTI (because the latter need not exist), possibly by
1008 // making it a local static object.
1009 if (containsIncompleteClassType(ty))
1010 return cir::GlobalLinkageKind::InternalLinkage;
1011
1012 switch (ty->getLinkage()) {
1013 case Linkage::Invalid:
1014 llvm_unreachable("Linkage hasn't been computed!");
1015
1016 case Linkage::None:
1017 case Linkage::Internal:
1019 return cir::GlobalLinkageKind::InternalLinkage;
1020
1022 case Linkage::Module:
1023 case Linkage::External:
1024 // RTTI is not enabled, which means that this type info struct is going
1025 // to be used for exception handling. Give it linkonce_odr linkage.
1026 if (!cgm.getLangOpts().RTTI)
1027 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
1028
1029 if (const RecordType *record = dyn_cast<RecordType>(ty)) {
1030 const auto *rd =
1031 cast<CXXRecordDecl>(record->getDecl())->getDefinitionOrSelf();
1032 if (rd->hasAttr<WeakAttr>())
1033 return cir::GlobalLinkageKind::WeakODRLinkage;
1034
1035 if (cgm.getTriple().isWindowsItaniumEnvironment())
1036 if (rd->hasAttr<DLLImportAttr>() &&
1037 shouldUseExternalRttiDescriptor(cgm, ty))
1038 return cir::GlobalLinkageKind::ExternalLinkage;
1039
1040 // MinGW always uses LinkOnceODRLinkage for type info.
1041 if (rd->isDynamicClass() && !cgm.getASTContext()
1042 .getTargetInfo()
1043 .getTriple()
1044 .isWindowsGNUEnvironment())
1045 return cgm.getVTableLinkage(rd);
1046 }
1047
1048 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
1049 }
1050
1051 llvm_unreachable("Invalid linkage!");
1052}
1053
1054cir::GlobalOp
1055CIRGenItaniumRTTIBuilder::getAddrOfTypeName(mlir::Location loc, QualType ty,
1056 cir::GlobalLinkageKind linkage) {
1057 CIRGenBuilderTy &builder = cgm.getBuilder();
1058 SmallString<256> name;
1059 llvm::raw_svector_ostream out(name);
1061
1062 // We know that the mangled name of the type starts at index 4 of the
1063 // mangled name of the typename, so we can just index into it in order to
1064 // get the mangled name of the type.
1065 mlir::Attribute init = builder.getString(
1066 name.substr(4), cgm.convertType(cgm.getASTContext().CharTy),
1067 std::nullopt);
1068
1069 CharUnits align =
1071
1072 // builder.getString can return a #cir.zero if the string given to it only
1073 // contains null bytes. However, type names cannot be full of null bytes.
1074 // So cast Init to a ConstArrayAttr should be safe.
1075 auto initStr = cast<cir::ConstArrayAttr>(init);
1076
1077 cir::GlobalOp gv = cgm.createOrReplaceCXXRuntimeVariable(
1078 loc, name, initStr.getType(), linkage, align);
1080 return gv;
1081}
1082
1083mlir::Attribute
1084CIRGenItaniumRTTIBuilder::getAddrOfExternalRTTIDescriptor(mlir::Location loc,
1085 QualType ty) {
1086 // Mangle the RTTI name.
1087 SmallString<256> name;
1088 llvm::raw_svector_ostream out(name);
1090 CIRGenBuilderTy &builder = cgm.getBuilder();
1091
1092 // Look for an existing global.
1093 cir::GlobalOp gv = dyn_cast_or_null<cir::GlobalOp>(
1094 mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));
1095
1096 if (!gv) {
1097 // Create a new global variable.
1098 // From LLVM codegen => Note for the future: If we would ever like to do
1099 // deferred emission of RTTI, check if emitting vtables opportunistically
1100 // need any adjustment.
1101 gv = CIRGenModule::createGlobalOp(cgm, loc, name, builder.getUInt8PtrTy(),
1102 /*isConstant=*/true);
1103 const CXXRecordDecl *rd = ty->getAsCXXRecordDecl();
1104 cgm.setGVProperties(gv, rd);
1105
1106 // Import the typeinfo symbol when all non-inline virtual methods are
1107 // imported.
1108 if (cgm.getTarget().hasPS4DLLImportExport()) {
1109 cgm.errorNYI("getAddrOfExternalRTTIDescriptor: hasPS4DLLImportExport");
1110 }
1111 }
1112
1113 return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), gv);
1114}
1115
1116void CIRGenItaniumRTTIBuilder::buildVTablePointer(mlir::Location loc,
1117 const Type *ty) {
1118 CIRGenBuilderTy &builder = cgm.getBuilder();
1119 const char *vTableName = vTableClassNameForType(cgm, ty);
1120
1121 // Check if the alias exists. If it doesn't, then get or create the global.
1123 cgm.errorNYI("buildVTablePointer: isRelativeLayout");
1124 return;
1125 }
1126
1127 mlir::Type vtableGlobalTy = builder.getPointerTo(builder.getUInt8PtrTy());
1128 llvm::Align align = cgm.getDataLayout().getABITypeAlign(vtableGlobalTy);
1129 cir::GlobalOp vTable = cgm.createOrReplaceCXXRuntimeVariable(
1130 loc, vTableName, vtableGlobalTy, cir::GlobalLinkageKind::ExternalLinkage,
1132
1133 // The vtable address point is 2.
1134 mlir::Attribute field{};
1136 cgm.errorNYI("buildVTablePointer: isRelativeLayout");
1137 } else {
1138 SmallVector<mlir::Attribute, 4> offsets{
1139 cgm.getBuilder().getI32IntegerAttr(2)};
1140 auto indices = mlir::ArrayAttr::get(builder.getContext(), offsets);
1142 vTable, indices);
1143 }
1144
1145 assert(field && "expected attribute");
1146 fields.push_back(field);
1147}
1148
1149/// Build an abi::__si_class_type_info, used for single inheritance, according
1150/// to the Itanium C++ ABI, 2.95p6b.
1151void CIRGenItaniumRTTIBuilder::buildSIClassTypeInfo(mlir::Location loc,
1152 const CXXRecordDecl *rd) {
1153 // Itanium C++ ABI 2.9.5p6b:
1154 // It adds to abi::__class_type_info a single member pointing to the
1155 // type_info structure for the base type,
1156 mlir::Attribute baseTypeInfo =
1157 CIRGenItaniumRTTIBuilder(cxxABI, cgm)
1158 .buildTypeInfo(loc, rd->bases_begin()->getType());
1159 fields.push_back(baseTypeInfo);
1160}
1161
1162/// Build an abi::__vmi_class_type_info, used for
1163/// classes with bases that do not satisfy the abi::__si_class_type_info
1164/// constraints, according to the Itanium C++ ABI, 2.9.5p5c.
1165void CIRGenItaniumRTTIBuilder::buildVMIClassTypeInfo(mlir::Location loc,
1166 const CXXRecordDecl *rd) {
1167 mlir::Type unsignedIntLTy =
1169
1170 // Itanium C++ ABI 2.9.5p6c:
1171 // __flags is a word with flags describing details about the class
1172 // structure, which may be referenced by using the __flags_masks
1173 // enumeration. These flags refer to both direct and indirect bases.
1174 unsigned flags = computeVmiClassTypeInfoFlags(rd);
1175 fields.push_back(cir::IntAttr::get(unsignedIntLTy, flags));
1176
1177 // Itanium C++ ABI 2.9.5p6c:
1178 // __base_count is a word with the number of direct proper base class
1179 // descriptions that follow.
1180 fields.push_back(cir::IntAttr::get(unsignedIntLTy, rd->getNumBases()));
1181
1182 if (!rd->getNumBases())
1183 return;
1184
1185 // Now add the base class descriptions.
1186
1187 // Itanium C++ ABI 2.9.5p6c:
1188 // __base_info[] is an array of base class descriptions -- one for every
1189 // direct proper base. Each description is of the type:
1190 //
1191 // struct abi::__base_class_type_info {
1192 // public:
1193 // const __class_type_info *__base_type;
1194 // long __offset_flags;
1195 //
1196 // enum __offset_flags_masks {
1197 // __virtual_mask = 0x1,
1198 // __public_mask = 0x2,
1199 // __offset_shift = 8
1200 // };
1201 // };
1202
1203 // If we're in mingw and 'long' isn't wide enough for a pointer, use 'long
1204 // long' instead of 'long' for __offset_flags. libstdc++abi uses long long on
1205 // LLP64 platforms.
1206 // FIXME: Consider updating libc++abi to match, and extend this logic to all
1207 // LLP64 platforms.
1208 QualType offsetFlagsTy = cgm.getASTContext().LongTy;
1209 const TargetInfo &ti = cgm.getASTContext().getTargetInfo();
1210 if (ti.getTriple().isOSCygMing() &&
1211 ti.getPointerWidth(LangAS::Default) > ti.getLongWidth())
1212 offsetFlagsTy = cgm.getASTContext().LongLongTy;
1213 mlir::Type offsetFlagsLTy = cgm.convertType(offsetFlagsTy);
1214
1215 for (const CXXBaseSpecifier &base : rd->bases()) {
1216 // The __base_type member points to the RTTI for the base type.
1217 fields.push_back(CIRGenItaniumRTTIBuilder(cxxABI, cgm)
1218 .buildTypeInfo(loc, base.getType()));
1219
1220 CXXRecordDecl *baseDecl = base.getType()->castAsCXXRecordDecl();
1221 int64_t offsetFlags = 0;
1222
1223 // All but the lower 8 bits of __offset_flags are a signed offset.
1224 // For a non-virtual base, this is the offset in the object of the base
1225 // subobject. For a virtual base, this is the offset in the virtual table of
1226 // the virtual base offset for the virtual base referenced (negative).
1227 CharUnits offset;
1228 if (base.isVirtual())
1230 rd, baseDecl);
1231 else {
1232 const ASTRecordLayout &layout =
1234 offset = layout.getBaseClassOffset(baseDecl);
1235 }
1236 offsetFlags = uint64_t(offset.getQuantity()) << 8;
1237
1238 // The low-order byte of __offset_flags contains flags, as given by the
1239 // masks from the enumeration __offset_flags_masks.
1240 if (base.isVirtual())
1241 offsetFlags |= BCTI_Virtual;
1242 if (base.getAccessSpecifier() == AS_public)
1243 offsetFlags |= BCTI_Public;
1244
1245 fields.push_back(cir::IntAttr::get(offsetFlagsLTy, offsetFlags));
1246 }
1247}
1248
1249mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(mlir::Location loc,
1250 QualType ty) {
1251 // We want to operate on the canonical type.
1252 ty = ty.getCanonicalType();
1253
1254 // Check if we've already emitted an RTTI descriptor for this type.
1255 SmallString<256> name;
1256 llvm::raw_svector_ostream out(name);
1258
1259 auto oldGV = dyn_cast_or_null<cir::GlobalOp>(
1260 mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));
1261
1262 if (oldGV && !oldGV.isDeclaration()) {
1263 assert(!oldGV.hasAvailableExternallyLinkage() &&
1264 "available_externally typeinfos not yet implemented");
1266 oldGV);
1267 }
1268
1269 // Check if there is already an external RTTI descriptor for this type.
1270 if (isStandardLibraryRttiDescriptor(ty) ||
1271 shouldUseExternalRttiDescriptor(cgm, ty))
1272 return getAddrOfExternalRTTIDescriptor(loc, ty);
1273
1274 // Emit the standard library with external linkage.
1275 cir::GlobalLinkageKind linkage = getTypeInfoLinkage(cgm, ty);
1276
1277 // Give the type_info object and name the formal visibility of the
1278 // type itself.
1281
1282 mlir::SymbolTable::Visibility symVisibility;
1283 if (cir::isLocalLinkage(linkage))
1284 // If the linkage is local, only default visibility makes sense.
1285 symVisibility = mlir::SymbolTable::Visibility::Public;
1286 else if (cxxABI.classifyRTTIUniqueness(ty, linkage) ==
1287 CIRGenItaniumCXXABI::RUK_NonUniqueHidden) {
1288 cgm.errorNYI(
1289 "buildTypeInfo: classifyRTTIUniqueness == RUK_NonUniqueHidden");
1290 symVisibility = CIRGenModule::getMLIRVisibility(ty->getVisibility());
1291 } else
1292 symVisibility = CIRGenModule::getMLIRVisibility(ty->getVisibility());
1293
1294 return buildTypeInfo(loc, ty, linkage, symVisibility);
1295}
1296
1297mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(
1298 mlir::Location loc, QualType ty, cir::GlobalLinkageKind linkage,
1299 mlir::SymbolTable::Visibility visibility) {
1300 CIRGenBuilderTy &builder = cgm.getBuilder();
1301
1303
1304 // Add the vtable pointer.
1305 buildVTablePointer(loc, cast<Type>(ty));
1306
1307 // And the name.
1308 cir::GlobalOp typeName = getAddrOfTypeName(loc, ty, linkage);
1309 mlir::Attribute typeNameField;
1310
1311 // If we're supposed to demote the visibility, be sure to set a flag
1312 // to use a string comparison for type_info comparisons.
1313 CIRGenItaniumCXXABI::RTTIUniquenessKind rttiUniqueness =
1314 cxxABI.classifyRTTIUniqueness(ty, linkage);
1315 if (rttiUniqueness != CIRGenItaniumCXXABI::RUK_Unique) {
1316 // The flag is the sign bit, which on ARM64 is defined to be clear
1317 // for global pointers. This is very ARM64-specific.
1318 cgm.errorNYI(
1319 "buildTypeInfo: rttiUniqueness != CIRGenItaniumCXXABI::RUK_Unique");
1320 } else {
1321 typeNameField =
1322 builder.getGlobalViewAttr(builder.getUInt8PtrTy(), typeName);
1323 }
1324
1325 fields.push_back(typeNameField);
1326
1327 switch (ty->getTypeClass()) {
1328#define TYPE(Class, Base)
1329#define ABSTRACT_TYPE(Class, Base)
1330#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
1331#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
1332#define DEPENDENT_TYPE(Class, Base) case Type::Class:
1333#include "clang/AST/TypeNodes.inc"
1334 llvm_unreachable("Non-canonical and dependent types shouldn't get here");
1335
1336 // GCC treats vector types as fundamental types.
1337 case Type::Builtin:
1338 case Type::Vector:
1339 case Type::ExtVector:
1340 case Type::ConstantMatrix:
1341 case Type::Complex:
1342 case Type::BlockPointer:
1343 // Itanium C++ ABI 2.9.5p4:
1344 // abi::__fundamental_type_info adds no data members to std::type_info.
1345 break;
1346
1347 case Type::LValueReference:
1348 case Type::RValueReference:
1349 llvm_unreachable("References shouldn't get here");
1350
1351 case Type::Auto:
1352 case Type::DeducedTemplateSpecialization:
1353 llvm_unreachable("Undeduced type shouldn't get here");
1354
1355 case Type::Pipe:
1356 break;
1357
1358 case Type::BitInt:
1359 break;
1360
1361 case Type::ConstantArray:
1362 case Type::IncompleteArray:
1363 case Type::VariableArray:
1364 case Type::ArrayParameter:
1365 // Itanium C++ ABI 2.9.5p5:
1366 // abi::__array_type_info adds no data members to std::type_info.
1367 break;
1368
1369 case Type::FunctionNoProto:
1370 case Type::FunctionProto:
1371 // Itanium C++ ABI 2.9.5p5:
1372 // abi::__function_type_info adds no data members to std::type_info.
1373 break;
1374
1375 case Type::Enum:
1376 // Itanium C++ ABI 2.9.5p5:
1377 // abi::__enum_type_info adds no data members to std::type_info.
1378 break;
1379
1380 case Type::Record: {
1381 const auto *rd = cast<CXXRecordDecl>(cast<RecordType>(ty)->getDecl())
1382 ->getDefinitionOrSelf();
1383 if (!rd->hasDefinition() || !rd->getNumBases()) {
1384 // We don't need to emit any fields.
1385 break;
1386 }
1387
1388 if (canUseSingleInheritance(rd)) {
1389 buildSIClassTypeInfo(loc, rd);
1390 } else {
1391 buildVMIClassTypeInfo(loc, rd);
1392 }
1393
1394 break;
1395 }
1396
1397 case Type::ObjCObject:
1398 case Type::ObjCInterface:
1399 cgm.errorNYI("buildTypeInfo: ObjCObject & ObjCInterface");
1400 break;
1401
1402 case Type::ObjCObjectPointer:
1403 cgm.errorNYI("buildTypeInfo: ObjCObjectPointer");
1404 break;
1405
1406 case Type::Pointer:
1407 cgm.errorNYI("buildTypeInfo: Pointer");
1408 break;
1409
1410 case Type::MemberPointer:
1411 cgm.errorNYI("buildTypeInfo: MemberPointer");
1412 break;
1413
1414 case Type::Atomic:
1415 // No fields, at least for the moment.
1416 break;
1417
1418 case Type::HLSLAttributedResource:
1419 case Type::HLSLInlineSpirv:
1420 llvm_unreachable("HLSL doesn't support RTTI");
1421 }
1422
1424 cir::TypeInfoAttr init = builder.getTypeInfo(builder.getArrayAttr(fields));
1425
1426 SmallString<256> name;
1427 llvm::raw_svector_ostream out(name);
1429
1430 // Create new global and search for an existing global.
1431 auto oldGV = dyn_cast_or_null<cir::GlobalOp>(
1432 mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));
1433
1434 cir::GlobalOp gv =
1435 CIRGenModule::createGlobalOp(cgm, loc, name, init.getType(),
1436 /*isConstant=*/true);
1437
1438 // Export the typeinfo in the same circumstances as the vtable is
1439 // exported.
1440 if (cgm.getTarget().hasPS4DLLImportExport()) {
1441 cgm.errorNYI("buildTypeInfo: target hasPS4DLLImportExport");
1442 return {};
1443 }
1444
1445 // If there's already an old global variable, replace it with the new one.
1446 if (oldGV) {
1447 // Replace occurrences of the old variable if needed.
1448 gv.setName(oldGV.getName());
1449 if (!oldGV->use_empty()) {
1450 cgm.errorNYI("buildTypeInfo: old GV !use_empty");
1451 return {};
1452 }
1453 oldGV->erase();
1454 }
1455
1456 if (cgm.supportsCOMDAT() && cir::isWeakForLinker(gv.getLinkage())) {
1458 cgm.errorNYI("buildTypeInfo: supportsCOMDAT & isWeakForLinker");
1459 return {};
1460 }
1461
1462 CharUnits align = cgm.getASTContext().toCharUnitsFromBits(
1463 cgm.getTarget().getPointerAlign(LangAS::Default));
1464 gv.setAlignmentAttr(cgm.getSize(align));
1465
1466 // The Itanium ABI specifies that type_info objects must be globally
1467 // unique, with one exception: if the type is an incomplete class
1468 // type or a (possibly indirect) pointer to one. That exception
1469 // affects the general case of comparing type_info objects produced
1470 // by the typeid operator, which is why the comparison operators on
1471 // std::type_info generally use the type_info name pointers instead
1472 // of the object addresses. However, the language's built-in uses
1473 // of RTTI generally require class types to be complete, even when
1474 // manipulating pointers to those class types. This allows the
1475 // implementation of dynamic_cast to rely on address equality tests,
1476 // which is much faster.
1477
1478 // All of this is to say that it's important that both the type_info
1479 // object and the type_info name be uniqued when weakly emitted.
1480
1481 mlir::SymbolTable::setSymbolVisibility(typeName, visibility);
1485
1486 mlir::SymbolTable::setSymbolVisibility(gv, visibility);
1490
1492 return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), gv);
1493}
1494
1495mlir::Attribute CIRGenItaniumCXXABI::getAddrOfRTTIDescriptor(mlir::Location loc,
1496 QualType ty) {
1497 return CIRGenItaniumRTTIBuilder(*this, cgm).buildTypeInfo(loc, ty);
1498}
1499
1500/// What sort of uniqueness rules should we use for the RTTI for the
1501/// given type?
1502CIRGenItaniumCXXABI::RTTIUniquenessKind
1503CIRGenItaniumCXXABI::classifyRTTIUniqueness(
1504 QualType canTy, cir::GlobalLinkageKind linkage) const {
1505 if (shouldRTTIBeUnique())
1506 return RUK_Unique;
1507
1508 // It's only necessary for linkonce_odr or weak_odr linkage.
1509 if (linkage != cir::GlobalLinkageKind::LinkOnceODRLinkage &&
1510 linkage != cir::GlobalLinkageKind::WeakODRLinkage)
1511 return RUK_Unique;
1512
1513 // It's only necessary with default visibility.
1514 if (canTy->getVisibility() != DefaultVisibility)
1515 return RUK_Unique;
1516
1517 // If we're not required to publish this symbol, hide it.
1518 if (linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage)
1519 return RUK_NonUniqueHidden;
1520
1521 // If we're required to publish this symbol, as we might be under an
1522 // explicit instantiation, leave it with default visibility but
1523 // enable string-comparisons.
1524 assert(linkage == cir::GlobalLinkageKind::WeakODRLinkage);
1525 return RUK_NonUniqueVisible;
1526}
1527
1528void CIRGenItaniumCXXABI::emitDestructorCall(
1529 CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,
1530 bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) {
1531 GlobalDecl gd(dd, type);
1532 mlir::Value vtt =
1533 getCXXDestructorImplicitParam(cgf, dd, type, forVirtualBase, delegating);
1534 ASTContext &astContext = cgm.getASTContext();
1535 QualType vttTy = astContext.getPointerType(astContext.VoidPtrTy);
1537 CIRGenCallee callee =
1539
1540 cgf.emitCXXDestructorCall(gd, callee, thisAddr.getPointer(), thisTy, vtt,
1541 vttTy, nullptr);
1542}
1543
1544void CIRGenItaniumCXXABI::registerGlobalDtor(const VarDecl *vd,
1545 cir::FuncOp dtor,
1546 mlir::Value addr) {
1547 if (vd->isNoDestroy(cgm.getASTContext()))
1548 return;
1549
1550 if (vd->getTLSKind()) {
1551 cgm.errorNYI(vd->getSourceRange(), "registerGlobalDtor: TLS");
1552 return;
1553 }
1554
1555 // HLSL doesn't support atexit.
1556 if (cgm.getLangOpts().HLSL) {
1557 cgm.errorNYI(vd->getSourceRange(), "registerGlobalDtor: HLSL");
1558 return;
1559 }
1560
1561 // The default behavior is to use atexit. This is handled in lowering
1562 // prepare. Nothing to be done for CIR here.
1563}
1564
1565mlir::Value CIRGenItaniumCXXABI::getCXXDestructorImplicitParam(
1566 CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,
1567 bool forVirtualBase, bool delegating) {
1568 GlobalDecl gd(dd, type);
1569 return cgf.getVTTParameter(gd, forVirtualBase, delegating);
1570}
1571
1572// The idea here is creating a separate block for the throw with an
1573// `UnreachableOp` as the terminator. So, we branch from the current block
1574// to the throw block and create a block for the remaining operations.
1575static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc,
1576 mlir::Value exceptionPtr = {},
1577 mlir::FlatSymbolRefAttr typeInfo = {},
1578 mlir::FlatSymbolRefAttr dtor = {}) {
1579 mlir::Block *currentBlock = builder.getInsertionBlock();
1580 mlir::Region *region = currentBlock->getParent();
1581
1582 if (currentBlock->empty()) {
1583 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
1584 cir::UnreachableOp::create(builder, loc);
1585 } else {
1586 mlir::Block *throwBlock = builder.createBlock(region);
1587
1588 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
1589 cir::UnreachableOp::create(builder, loc);
1590
1591 builder.setInsertionPointToEnd(currentBlock);
1592 cir::BrOp::create(builder, loc, throwBlock);
1593 }
1594
1595 (void)builder.createBlock(region);
1596}
1597
1598void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &cgf, bool isNoReturn) {
1599 // void __cxa_rethrow();
1600 if (isNoReturn) {
1601 CIRGenBuilderTy &builder = cgf.getBuilder();
1602 assert(cgf.currSrcLoc && "expected source location");
1603 mlir::Location loc = *cgf.currSrcLoc;
1604 insertThrowAndSplit(builder, loc);
1605 } else {
1606 cgm.errorNYI("emitRethrow with isNoReturn false");
1607 }
1608}
1609
1610void CIRGenItaniumCXXABI::emitThrow(CIRGenFunction &cgf,
1611 const CXXThrowExpr *e) {
1612 // This differs a bit from LLVM codegen, CIR has native operations for some
1613 // cxa functions, and defers allocation size computation, always pass the dtor
1614 // symbol, etc. CIRGen also does not use getAllocateExceptionFn / getThrowFn.
1615
1616 // Now allocate the exception object.
1617 CIRGenBuilderTy &builder = cgf.getBuilder();
1618 QualType clangThrowType = e->getSubExpr()->getType();
1619 cir::PointerType throwTy =
1620 builder.getPointerTo(cgf.convertType(clangThrowType));
1621 uint64_t typeSize =
1622 cgf.getContext().getTypeSizeInChars(clangThrowType).getQuantity();
1623 mlir::Location subExprLoc = cgf.getLoc(e->getSubExpr()->getSourceRange());
1624
1625 // Defer computing allocation size to some later lowering pass.
1626 mlir::TypedValue<cir::PointerType> exceptionPtr =
1627 cir::AllocExceptionOp::create(builder, subExprLoc, throwTy,
1628 builder.getI64IntegerAttr(typeSize))
1629 .getAddr();
1630
1631 // Build expression and store its result into exceptionPtr.
1632 CharUnits exnAlign = cgf.getContext().getExnObjectAlignment();
1633 cgf.emitAnyExprToExn(e->getSubExpr(), Address(exceptionPtr, exnAlign));
1634
1635 // Get the RTTI symbol address.
1636 auto typeInfo = mlir::cast<cir::GlobalViewAttr>(
1637 cgm.getAddrOfRTTIDescriptor(subExprLoc, clangThrowType,
1638 /*forEH=*/true));
1639 assert(!typeInfo.getIndices() && "expected no indirection");
1640
1641 // The address of the destructor.
1642 //
1643 // Note: LLVM codegen already optimizes out the dtor if the
1644 // type is a record with trivial dtor (by passing down a
1645 // null dtor). In CIR, we forward this info and allow for
1646 // Lowering pass to skip passing the trivial function.
1647 //
1648 if (const RecordType *recordTy = clangThrowType->getAs<RecordType>()) {
1649 auto *rec = cast<CXXRecordDecl>(recordTy->getDecl()->getDefinition());
1651 if (!rec->hasTrivialDestructor()) {
1652 cgm.errorNYI("emitThrow: non-trivial destructor");
1653 return;
1654 }
1655 }
1656
1657 // Now throw the exception.
1658 mlir::Location loc = cgf.getLoc(e->getSourceRange());
1659 insertThrowAndSplit(builder, loc, exceptionPtr, typeInfo.getSymbol());
1660}
1661
1663 switch (cgm.getASTContext().getCXXABIKind()) {
1664 case TargetCXXABI::GenericItanium:
1665 case TargetCXXABI::GenericAArch64:
1666 return new CIRGenItaniumCXXABI(cgm);
1667
1668 case TargetCXXABI::AppleARM64:
1669 // The general Itanium ABI will do until we implement something that
1670 // requires special handling.
1672 return new CIRGenItaniumCXXABI(cgm);
1673
1674 default:
1675 llvm_unreachable("bad or NYI ABI kind");
1676 }
1677}
1678
1679cir::GlobalOp CIRGenItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *rd,
1680 CharUnits vptrOffset) {
1681 assert(vptrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");
1682 cir::GlobalOp &vtable = vtables[rd];
1683 if (vtable)
1684 return vtable;
1685
1686 // Queue up this vtable for possible deferred emission.
1688
1689 SmallString<256> name;
1690 llvm::raw_svector_ostream out(name);
1691 getMangleContext().mangleCXXVTable(rd, out);
1692
1693 const VTableLayout &vtLayout =
1695 mlir::Type vtableType = cgm.getVTables().getVTableType(vtLayout);
1696
1697 // Use pointer alignment for the vtable. Otherwise we would align them based
1698 // on the size of the initializer which doesn't make sense as only single
1699 // values are read.
1700 unsigned ptrAlign = cgm.getItaniumVTableContext().isRelativeLayout()
1701 ? 32
1703
1705 cgm.getLoc(rd->getSourceRange()), name, vtableType,
1706 cir::GlobalLinkageKind::ExternalLinkage,
1707 cgm.getASTContext().toCharUnitsFromBits(ptrAlign));
1708 // LLVM codegen handles unnamedAddr
1710
1711 // In MS C++ if you have a class with virtual functions in which you are using
1712 // selective member import/export, then all virtual functions must be exported
1713 // unless they are inline, otherwise a link error will result. To match this
1714 // behavior, for such classes, we dllimport the vtable if it is defined
1715 // externally and all the non-inline virtual methods are marked dllimport, and
1716 // we dllexport the vtable if it is defined in this TU and all the non-inline
1717 // virtual methods are marked dllexport.
1718 if (cgm.getTarget().hasPS4DLLImportExport())
1719 cgm.errorNYI(rd->getSourceRange(),
1720 "getAddrOfVTable: PS4 DLL import/export");
1721
1722 cgm.setGVProperties(vtable, rd);
1723 return vtable;
1724}
1725
1726CIRGenCallee CIRGenItaniumCXXABI::getVirtualFunctionPointer(
1727 CIRGenFunction &cgf, clang::GlobalDecl gd, Address thisAddr, mlir::Type ty,
1728 SourceLocation srcLoc) {
1729 CIRGenBuilderTy &builder = cgm.getBuilder();
1730 mlir::Location loc = cgf.getLoc(srcLoc);
1731 cir::PointerType tyPtr = builder.getPointerTo(ty);
1732 auto *methodDecl = cast<CXXMethodDecl>(gd.getDecl());
1733 mlir::Value vtable = cgf.getVTablePtr(loc, thisAddr, methodDecl->getParent());
1734
1735 uint64_t vtableIndex = cgm.getItaniumVTableContext().getMethodVTableIndex(gd);
1736 mlir::Value vfunc{};
1737 if (cgf.shouldEmitVTableTypeCheckedLoad(methodDecl->getParent())) {
1738 cgm.errorNYI(loc, "getVirtualFunctionPointer: emitVTableTypeCheckedLoad");
1739 } else {
1741
1742 mlir::Value vfuncLoad;
1745 cgm.errorNYI(loc, "getVirtualFunctionPointer: isRelativeLayout");
1746 } else {
1747 auto vtableSlotPtr = cir::VTableGetVirtualFnAddrOp::create(
1748 builder, loc, builder.getPointerTo(tyPtr), vtable, vtableIndex);
1749 vfuncLoad = builder.createAlignedLoad(loc, tyPtr, vtableSlotPtr,
1750 cgf.getPointerAlign());
1751 }
1752
1753 // Add !invariant.load md to virtual function load to indicate that
1754 // function didn't change inside vtable.
1755 // It's safe to add it without -fstrict-vtable-pointers, but it would not
1756 // help in devirtualization because it will only matter if we will have 2
1757 // the same virtual function loads from the same vtable load, which won't
1758 // happen without enabled devirtualization with -fstrict-vtable-pointers.
1759 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
1760 cgm.getCodeGenOpts().StrictVTablePointers) {
1761 cgm.errorNYI(loc, "getVirtualFunctionPointer: strictVTablePointers");
1762 }
1763 vfunc = vfuncLoad;
1764 }
1765
1766 CIRGenCallee callee(gd, vfunc.getDefiningOp());
1767 return callee;
1768}
1769
1770mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
1771 CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
1772 const CXXRecordDecl *nearestVBase) {
1773 assert((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&
1774 needsVTTParameter(cgf.curGD) && "This class doesn't have VTT");
1775
1776 // Get the secondary vpointer index.
1777 uint64_t virtualPointerIndex =
1778 cgm.getVTables().getSecondaryVirtualPointerIndex(vtableClass, base);
1779
1780 /// Load the VTT.
1781 mlir::Value vttPtr = cgf.loadCXXVTT();
1782 mlir::Location loc = cgf.getLoc(vtableClass->getSourceRange());
1783 // Calculate the address point from the VTT, and the offset may be zero.
1784 vttPtr = cgf.getBuilder().createVTTAddrPoint(loc, vttPtr.getType(), vttPtr,
1785 virtualPointerIndex);
1786 // And load the address point from the VTT.
1787 auto vptrType = cir::VPtrType::get(cgf.getBuilder().getContext());
1788 return cgf.getBuilder().createAlignedLoad(loc, vptrType, vttPtr,
1789 cgf.getPointerAlign());
1790}
1791
1792mlir::Value
1793CIRGenItaniumCXXABI::getVTableAddressPoint(BaseSubobject base,
1794 const CXXRecordDecl *vtableClass) {
1795 cir::GlobalOp vtable = getAddrOfVTable(vtableClass, CharUnits());
1796
1797 // Find the appropriate vtable within the vtable group, and the address point
1798 // within that vtable.
1799 VTableLayout::AddressPointLocation addressPoint =
1801 .getVTableLayout(vtableClass)
1802 .getAddressPoint(base);
1803
1804 mlir::OpBuilder &builder = cgm.getBuilder();
1805 auto vtablePtrTy = cir::VPtrType::get(builder.getContext());
1806
1807 return builder.create<cir::VTableAddrPointOp>(
1808 cgm.getLoc(vtableClass->getSourceRange()), vtablePtrTy,
1809 mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()),
1810 cir::AddressPointAttr::get(cgm.getBuilder().getContext(),
1811 addressPoint.VTableIndex,
1812 addressPoint.AddressPointIndex));
1813}
1814
1815mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructor(
1816 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,
1817 clang::BaseSubobject base, const clang::CXXRecordDecl *nearestVBase) {
1818
1819 if ((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&
1820 needsVTTParameter(cgf.curGD)) {
1821 return getVTableAddressPointInStructorWithVTT(cgf, vtableClass, base,
1822 nearestVBase);
1823 }
1824 return getVTableAddressPoint(base, vtableClass);
1825}
1826
1827bool CIRGenItaniumCXXABI::isVirtualOffsetNeededForVTableField(
1828 CIRGenFunction &cgf, CIRGenFunction::VPtr vptr) {
1829 if (vptr.nearestVBase == nullptr)
1830 return false;
1831 return needsVTTParameter(cgf.curGD);
1832}
1833
1834mlir::Value CIRGenItaniumCXXABI::getVirtualBaseClassOffset(
1835 mlir::Location loc, CIRGenFunction &cgf, Address thisAddr,
1836 const CXXRecordDecl *classDecl, const CXXRecordDecl *baseClassDecl) {
1837 CIRGenBuilderTy &builder = cgf.getBuilder();
1838 mlir::Value vtablePtr = cgf.getVTablePtr(loc, thisAddr, classDecl);
1839 mlir::Value vtableBytePtr = builder.createBitcast(vtablePtr, cgm.UInt8PtrTy);
1840 CharUnits vbaseOffsetOffset =
1842 baseClassDecl);
1843 mlir::Value offsetVal =
1844 builder.getSInt64(vbaseOffsetOffset.getQuantity(), loc);
1845 auto vbaseOffsetPtr = cir::PtrStrideOp::create(builder, loc, cgm.UInt8PtrTy,
1846 vtableBytePtr, offsetVal);
1847
1848 mlir::Value vbaseOffset;
1851 cgm.errorNYI(loc, "getVirtualBaseClassOffset: relative layout");
1852 } else {
1853 mlir::Value offsetPtr = builder.createBitcast(
1854 vbaseOffsetPtr, builder.getPointerTo(cgm.PtrDiffTy));
1855 vbaseOffset = builder.createLoad(
1856 loc, Address(offsetPtr, cgm.PtrDiffTy, cgf.getPointerAlign()));
1857 }
1858 return vbaseOffset;
1859}
1860
1861static cir::FuncOp getBadCastFn(CIRGenFunction &cgf) {
1862 // Prototype: void __cxa_bad_cast();
1863
1864 // TODO(cir): set the calling convention of the runtime function.
1866
1867 cir::FuncType fnTy =
1868 cgf.getBuilder().getFuncType({}, cgf.getBuilder().getVoidTy());
1869 return cgf.cgm.createRuntimeFunction(fnTy, "__cxa_bad_cast");
1870}
1871
1872// TODO(cir): This could be shared with classic codegen.
1874 const CXXRecordDecl *src,
1875 const CXXRecordDecl *dst) {
1876 CXXBasePaths paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
1877 /*DetectVirtual=*/false);
1878
1879 // If Dst is not derived from Src we can skip the whole computation below and
1880 // return that Src is not a public base of Dst. Record all inheritance paths.
1881 if (!dst->isDerivedFrom(src, paths))
1882 return CharUnits::fromQuantity(-2ULL);
1883
1884 unsigned numPublicPaths = 0;
1885 CharUnits offset;
1886
1887 // Now walk all possible inheritance paths.
1888 for (const CXXBasePath &path : paths) {
1889 if (path.Access != AS_public) // Ignore non-public inheritance.
1890 continue;
1891
1892 ++numPublicPaths;
1893
1894 for (const CXXBasePathElement &pathElement : path) {
1895 // If the path contains a virtual base class we can't give any hint.
1896 // -1: no hint.
1897 if (pathElement.Base->isVirtual())
1898 return CharUnits::fromQuantity(-1ULL);
1899
1900 if (numPublicPaths > 1) // Won't use offsets, skip computation.
1901 continue;
1902
1903 // Accumulate the base class offsets.
1904 const ASTRecordLayout &L =
1905 astContext.getASTRecordLayout(pathElement.Class);
1906 offset += L.getBaseClassOffset(
1907 pathElement.Base->getType()->getAsCXXRecordDecl());
1908 }
1909 }
1910
1911 // -2: Src is not a public base of Dst.
1912 if (numPublicPaths == 0)
1913 return CharUnits::fromQuantity(-2ULL);
1914
1915 // -3: Src is a multiple public base type but never a virtual base type.
1916 if (numPublicPaths > 1)
1917 return CharUnits::fromQuantity(-3ULL);
1918
1919 // Otherwise, the Src type is a unique public nonvirtual base type of Dst.
1920 // Return the offset of Src from the origin of Dst.
1921 return offset;
1922}
1923
1924static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf) {
1925 // Prototype:
1926 // void *__dynamic_cast(const void *sub,
1927 // global_as const abi::__class_type_info *src,
1928 // global_as const abi::__class_type_info *dst,
1929 // std::ptrdiff_t src2dst_offset);
1930
1931 mlir::Type voidPtrTy = cgf.getBuilder().getVoidPtrTy();
1932 mlir::Type rttiPtrTy = cgf.getBuilder().getUInt8PtrTy();
1933 mlir::Type ptrDiffTy = cgf.convertType(cgf.getContext().getPointerDiffType());
1934
1935 // TODO(cir): mark the function as nowind willreturn readonly.
1939
1940 // TODO(cir): set the calling convention of the runtime function.
1942
1943 cir::FuncType FTy = cgf.getBuilder().getFuncType(
1944 {voidPtrTy, rttiPtrTy, rttiPtrTy, ptrDiffTy}, voidPtrTy);
1945 return cgf.cgm.createRuntimeFunction(FTy, "__dynamic_cast");
1946}
1947
1948static cir::DynamicCastInfoAttr emitDynamicCastInfo(CIRGenFunction &cgf,
1949 mlir::Location loc,
1950 QualType srcRecordTy,
1951 QualType destRecordTy) {
1952 auto srcRtti = mlir::cast<cir::GlobalViewAttr>(
1953 cgf.cgm.getAddrOfRTTIDescriptor(loc, srcRecordTy));
1954 auto destRtti = mlir::cast<cir::GlobalViewAttr>(
1955 cgf.cgm.getAddrOfRTTIDescriptor(loc, destRecordTy));
1956
1957 cir::FuncOp runtimeFuncOp = getItaniumDynamicCastFn(cgf);
1958 cir::FuncOp badCastFuncOp = getBadCastFn(cgf);
1959 auto runtimeFuncRef = mlir::FlatSymbolRefAttr::get(runtimeFuncOp);
1960 auto badCastFuncRef = mlir::FlatSymbolRefAttr::get(badCastFuncOp);
1961
1962 const CXXRecordDecl *srcDecl = srcRecordTy->getAsCXXRecordDecl();
1963 const CXXRecordDecl *destDecl = destRecordTy->getAsCXXRecordDecl();
1964 CharUnits offsetHint = computeOffsetHint(cgf.getContext(), srcDecl, destDecl);
1965
1966 mlir::Type ptrdiffTy = cgf.convertType(cgf.getContext().getPointerDiffType());
1967 auto offsetHintAttr = cir::IntAttr::get(ptrdiffTy, offsetHint.getQuantity());
1968
1969 return cir::DynamicCastInfoAttr::get(srcRtti, destRtti, runtimeFuncRef,
1970 badCastFuncRef, offsetHintAttr);
1971}
1972
1973mlir::Value CIRGenItaniumCXXABI::emitDynamicCast(CIRGenFunction &cgf,
1974 mlir::Location loc,
1975 QualType srcRecordTy,
1976 QualType destRecordTy,
1977 cir::PointerType destCIRTy,
1978 bool isRefCast, Address src) {
1979 bool isCastToVoid = destRecordTy.isNull();
1980 assert((!isCastToVoid || !isRefCast) && "cannot cast to void reference");
1981
1982 if (isCastToVoid) {
1983 cgm.errorNYI(loc, "emitDynamicCastToVoid");
1984 return {};
1985 }
1986
1987 // If the destination is effectively final, the cast succeeds if and only
1988 // if the dynamic type of the pointer is exactly the destination type.
1989 if (destRecordTy->getAsCXXRecordDecl()->isEffectivelyFinal() &&
1990 cgf.cgm.getCodeGenOpts().OptimizationLevel > 0) {
1991 cgm.errorNYI(loc, "emitExactDynamicCast");
1992 return {};
1993 }
1994
1995 cir::DynamicCastInfoAttr castInfo =
1996 emitDynamicCastInfo(cgf, loc, srcRecordTy, destRecordTy);
1997 return cgf.getBuilder().createDynCast(loc, src.getPointer(), destCIRTy,
1998 isRefCast, castInfo);
1999}
static void emitConstructorDestructorAlias(CIRGenModule &cgm, GlobalDecl aliasDecl, GlobalDecl targetDecl)
static CharUnits computeOffsetHint(ASTContext &astContext, const CXXRecordDecl *src, const CXXRecordDecl *dst)
static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc, mlir::Value exceptionPtr={}, mlir::FlatSymbolRefAttr typeInfo={}, mlir::FlatSymbolRefAttr dtor={})
static cir::DynamicCastInfoAttr emitDynamicCastInfo(CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, QualType destRecordTy)
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 cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf)
static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm, const CXXMethodDecl *md)
static cir::FuncOp getBadCastFn(CIRGenFunction &cgf)
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)
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
llvm::Align getABITypeAlign(mlir::Type ty) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
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
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
CanQualType CharTy
CharUnits getExnObjectAlignment() const
Return the alignment (in bytes) of the thrown exception object.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
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
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
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:82
mlir::Value emitRawPointer() const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition Address.h:96
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)
cir::FuncType getFuncType(llvm::ArrayRef< mlir::Type > params, mlir::Type retTy, bool isVarArg=false)
mlir::Value createDynCast(mlir::Location loc, mlir::Value src, cir::PointerType destType, bool isRefCast, cir::DynamicCastInfoAttr info)
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
static CIRGenCallee forVirtual(const clang::CallExpr *ce, clang::GlobalDecl md, Address addr, cir::FuncType fTy)
Definition CIRGenCall.h:152
mlir::Type convertType(clang::QualType t)
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.
void emitAnyExprToExn(const Expr *e, Address addr)
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.
clang::ASTContext & getContext() const
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)
cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::ArrayAttr={}, bool isLocal=false, bool assumeConvergent=false)
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.
mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty, bool forEH=false)
Get the address of the RTTI descriptor for the given type.
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.
Represents a path from a specific derived class (which is not represented as part of the path) to a p...
BasePaths - Represents the set of paths from a derived class to one of its (direct or indirect) bases...
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
bool isEffectivelyFinal() const
Determine whether it's impossible for a class to be derived from this class.
Definition DeclCXX.cpp:2325
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
const Expr * getSubExpr() const
Definition ExprCXX.h:1229
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
QualType getType() const
Definition Expr.h:144
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:5522
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:295
QualType getPointeeType() const
Definition TypeBase.h:3338
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8318
QualType getCanonicalType() const
Definition TypeBase.h:8330
bool empty() const
Definition TypeBase.h:647
Encodes a location in the source.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4882
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:3547
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:4891
TypeClass getTypeClass() const
Definition TypeBase.h:2385
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9091
AddressPointLocation getAddressPoint(BaseSubobject Base) const
TLSKind getTLSKind() const
Definition Decl.cpp:2168
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2190
bool isNoDestroy(const ASTContext &) const
Is destruction of this variable entirely suppressed?
Definition Decl.cpp:2836
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.
llvm::Value * getCXXDestructorImplicitParam(CodeGenModule &CGM, llvm::BasicBlock *InsertBlock, llvm::BasicBlock::iterator InsertPoint, const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating)
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
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:562
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 opFuncReadOnly()
static bool setDLLStorageClass()
static bool hiddenVisibility()
static bool opFuncNoUnwind()
static bool cxxabiAppleARM64CXXABI()
static bool opGlobalDLLImportExport()
static bool opGlobalPartition()
static bool isTrivialCtorOrDtor()
static bool opFuncCallingConv()
static bool opFuncWillReturn()
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
Represents an element in a path from a derived class to a base class.