clang 23.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"
25#include "clang/AST/TypeBase.h"
28#include "llvm/Support/ErrorHandling.h"
29
30using namespace clang;
31using namespace clang::CIRGen;
32
33namespace {
34
35class CIRGenItaniumCXXABI : public CIRGenCXXABI {
36protected:
37 /// All the vtables which have been defined.
38 llvm::DenseMap<const CXXRecordDecl *, cir::GlobalOp> vtables;
39
40public:
41 CIRGenItaniumCXXABI(CIRGenModule &cgm) : CIRGenCXXABI(cgm) {
44 }
45
46 AddedStructorArgs getImplicitConstructorArgs(CIRGenFunction &cgf,
47 const CXXConstructorDecl *d,
49 bool forVirtualBase,
50 bool delegating) override;
51
52 bool needsVTTParameter(clang::GlobalDecl gd) override;
53
54 AddedStructorArgCounts
55 buildStructorSignature(GlobalDecl gd,
56 llvm::SmallVectorImpl<CanQualType> &argTys) override;
57
58 void emitInstanceFunctionProlog(SourceLocation loc,
59 CIRGenFunction &cgf) override;
60
61 void addImplicitStructorParams(CIRGenFunction &cgf, QualType &resTy,
62 FunctionArgList &params) override;
63 mlir::Value getCXXDestructorImplicitParam(CIRGenFunction &cgf,
64 const CXXDestructorDecl *dd,
66 bool forVirtualBase,
67 bool delegating) override;
68 void emitCXXConstructors(const clang::CXXConstructorDecl *d) override;
69 void emitCXXDestructors(const clang::CXXDestructorDecl *d) override;
70 void emitCXXStructor(clang::GlobalDecl gd) override;
71
72 void emitDestructorCall(CIRGenFunction &cgf, const CXXDestructorDecl *dd,
73 CXXDtorType type, bool forVirtualBase,
74 bool delegating, Address thisAddr,
75 QualType thisTy) override;
76 void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor,
77 mlir::Value addr) override;
78 void emitVirtualObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de,
79 Address ptr, QualType elementType,
80 const CXXDestructorDecl *dtor) override;
81
82 void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;
83 void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override;
84
85 void emitBeginCatch(CIRGenFunction &cgf, const CXXCatchStmt *catchStmt,
86 mlir::Value ehToken) override;
87
88 bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
89 CXXDtorType dt) const override {
90 // Itanium does not emit any destructor variant as an inline thunk.
91 // Delegating may occur as an optimization, but all variants are either
92 // emitted with external linkage or as linkonce if they are inline and used.
93 return false;
94 }
95
96 bool isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
97 CIRGenFunction::VPtr vptr) override;
98
99 cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd,
100 CharUnits vptrOffset) override;
101 CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf,
102 clang::GlobalDecl gd, Address thisAddr,
103 mlir::Type ty,
104 SourceLocation loc) override;
105 mlir::Value emitVirtualDestructorCall(CIRGenFunction &cgf,
106 const CXXDestructorDecl *dtor,
107 CXXDtorType dtorType, Address thisAddr,
108 DeleteOrMemberCallExpr e) override;
109
110 bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override;
111 bool canSpeculativelyEmitVTableAsBaseClass(const CXXRecordDecl *RD) const;
112
113 mlir::Value getVTableAddressPoint(BaseSubobject base,
114 const CXXRecordDecl *vtableClass) override;
115 mlir::Value getVTableAddressPointInStructorWithVTT(
116 CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
117 const CXXRecordDecl *nearestVBase);
118
119 mlir::Value getVTableAddressPointInStructor(
120 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,
121 clang::BaseSubobject base,
122 const clang::CXXRecordDecl *nearestVBase) override;
123 void emitVTableDefinitions(CIRGenVTables &cgvt,
124 const CXXRecordDecl *rd) override;
125 void emitVirtualInheritanceTables(const CXXRecordDecl *rd) override;
126
127 void setThunkLinkage(cir::FuncOp thunk, bool forVTable, GlobalDecl gd,
128 bool returnAdjustment) override {
129 if (forVTable && !thunk.hasLocalLinkage())
130 thunk.setLinkage(cir::GlobalLinkageKind::AvailableExternallyLinkage);
131 const auto *nd = cast<NamedDecl>(gd.getDecl());
132 cgm.setGVProperties(thunk, nd);
133 }
134
135 bool exportThunk() override { return true; }
136
137 mlir::Value performThisAdjustment(CIRGenFunction &cgf, Address thisAddr,
138 const CXXRecordDecl *unadjustedClass,
139 const ThunkInfo &ti) override;
140
141 mlir::Value performReturnAdjustment(CIRGenFunction &cgf, Address ret,
142 const CXXRecordDecl *unadjustedClass,
143 const ReturnAdjustment &ra) override;
144
145 bool shouldTypeidBeNullChecked(QualType srcTy) override;
146 mlir::Value emitTypeid(CIRGenFunction &cgf, QualType SrcRecordTy,
147 Address thisPtr, mlir::Type StdTypeInfoPtrTy) override;
148 void emitBadTypeidCall(CIRGenFunction &cgf, mlir::Location loc) override;
149
150 mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
151 QualType ty) override;
152
153 StringRef getPureVirtualCallName() override { return "__cxa_pure_virtual"; }
154 StringRef getDeletedVirtualCallName() override {
155 return "__cxa_deleted_virtual";
156 }
157
158 CatchTypeInfo
159 getAddrOfCXXCatchHandlerType(mlir::Location loc, QualType ty,
160 QualType catchHandlerType) override {
161 auto rtti = dyn_cast<cir::GlobalViewAttr>(getAddrOfRTTIDescriptor(loc, ty));
162 assert(rtti && "expected GlobalViewAttr");
163 return CatchTypeInfo{rtti, 0};
164 }
165
166 bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {
167 return true;
168 }
169
170 size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
171 FunctionArgList &args) const override {
172 assert(!args.empty() && "expected the arglist to not be empty!");
173 return args.size() - 1;
174 }
175
176 void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) override;
177
178 mlir::Value
179 getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf,
180 Address thisAddr, const CXXRecordDecl *classDecl,
181 const CXXRecordDecl *baseClassDecl) override;
182
183 // The traditional clang CodeGen emits calls to `__dynamic_cast` directly into
184 // LLVM in the `emitDynamicCastCall` function. In CIR, `dynamic_cast`
185 // expressions are lowered to `cir.dyn_cast` ops instead of calls to runtime
186 // functions. So during CIRGen we don't need the `emitDynamicCastCall`
187 // function that clang CodeGen has.
188 mlir::Value emitDynamicCast(CIRGenFunction &cgf, mlir::Location loc,
189 QualType srcRecordTy, QualType destRecordTy,
190 cir::PointerType destCIRTy, bool isRefCast,
191 Address src) override;
192
193 cir::MethodAttr buildVirtualMethodAttr(cir::MethodType methodTy,
194 const CXXMethodDecl *md) override;
195
196 Address initializeArrayCookie(CIRGenFunction &cgf, Address newPtr,
197 mlir::Value numElements, const CXXNewExpr *e,
198 QualType elementType) override;
199
200 bool isZeroInitializable(const MemberPointerType *MPT) override;
201
202protected:
203 CharUnits getArrayCookieSizeImpl(QualType elementType) override;
204
205 /**************************** RTTI Uniqueness ******************************/
206 /// Returns true if the ABI requires RTTI type_info objects to be unique
207 /// across a program.
208 virtual bool shouldRTTIBeUnique() const { return true; }
209
210public:
211 /// What sort of unique-RTTI behavior should we use?
212 enum RTTIUniquenessKind {
213 /// We are guaranteeing, or need to guarantee, that the RTTI string
214 /// is unique.
215 RUK_Unique,
216
217 /// We are not guaranteeing uniqueness for the RTTI string, so we
218 /// can demote to hidden visibility but must use string comparisons.
219 RUK_NonUniqueHidden,
220
221 /// We are not guaranteeing uniqueness for the RTTI string, so we
222 /// have to use string comparisons, but we also have to emit it with
223 /// non-hidden visibility.
224 RUK_NonUniqueVisible
225 };
226
227 /// Return the required visibility status for the given type and linkage in
228 /// the current ABI.
229 RTTIUniquenessKind
230 classifyRTTIUniqueness(QualType canTy, cir::GlobalLinkageKind linkage) const;
231
232private:
233 bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *rd) const;
234 bool isVTableHidden(const CXXRecordDecl *rd) const;
235};
236
237} // namespace
238
239void CIRGenItaniumCXXABI::emitInstanceFunctionProlog(SourceLocation loc,
240 CIRGenFunction &cgf) {
241 // Naked functions have no prolog.
242 if (cgf.curFuncDecl && cgf.curFuncDecl->hasAttr<NakedAttr>()) {
244 "emitInstanceFunctionProlog: Naked");
245 }
246
247 /// Initialize the 'this' slot. In the Itanium C++ ABI, no prologue
248 /// adjustments are required, because they are all handled by thunks.
249 setCXXABIThisValue(cgf, loadIncomingCXXThis(cgf));
250
251 /// Initialize the 'vtt' slot if needed.
252 if (getStructorImplicitParamDecl(cgf)) {
253 cir::LoadOp val = cgf.getBuilder().createLoad(
254 cgf.getLoc(loc),
255 cgf.getAddrOfLocalVar(getStructorImplicitParamDecl(cgf)));
256 setStructorImplicitParamValue(cgf, val);
257 }
258
259 /// If this is a function that the ABI specifies returns 'this', initialize
260 /// the return slot to this' at the start of the function.
261 ///
262 /// Unlike the setting of return types, this is done within the ABI
263 /// implementation instead of by clients of CIRGenCXXBI because:
264 /// 1) getThisValue is currently protected
265 /// 2) in theory, an ABI could implement 'this' returns some other way;
266 /// HasThisReturn only specifies a contract, not the implementation
267 if (hasThisReturn(cgf.curGD)) {
269 "emitInstanceFunctionProlog: hasThisReturn");
270 }
271}
272
273CIRGenCXXABI::AddedStructorArgCounts
274CIRGenItaniumCXXABI::buildStructorSignature(
275 GlobalDecl gd, llvm::SmallVectorImpl<CanQualType> &argTys) {
276 clang::ASTContext &astContext = cgm.getASTContext();
277
278 // All parameters are already in place except VTT, which goes after 'this'.
279 // These are clang types, so we don't need to worry about sret yet.
280
281 // Check if we need to add a VTT parameter (which has type void **).
283 : gd.getDtorType() == Dtor_Base) &&
284 cast<CXXMethodDecl>(gd.getDecl())->getParent()->getNumVBases() != 0) {
286 argTys.insert(argTys.begin() + 1,
287 astContext.getPointerType(
289 return AddedStructorArgCounts::withPrefix(1);
290 }
291
292 return AddedStructorArgCounts{};
293}
294
295// Find out how to cirgen the complete destructor and constructor
296namespace {
297enum class StructorCIRGen { Emit, RAUW, Alias, COMDAT };
298}
299
300static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm,
301 const CXXMethodDecl *md) {
302 if (!cgm.getCodeGenOpts().CXXCtorDtorAliases)
303 return StructorCIRGen::Emit;
304
305 // The complete and base structors are not equivalent if there are any virtual
306 // bases, so emit separate functions.
307 if (md->getParent()->getNumVBases())
308 return StructorCIRGen::Emit;
309
310 GlobalDecl aliasDecl;
311 if (const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
312 aliasDecl = GlobalDecl(dd, Dtor_Complete);
313 } else {
314 const auto *cd = cast<CXXConstructorDecl>(md);
315 aliasDecl = GlobalDecl(cd, Ctor_Complete);
316 }
317
318 cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);
319
320 if (cir::isDiscardableIfUnused(linkage))
321 return StructorCIRGen::RAUW;
322
323 // FIXME: Should we allow available_externally aliases?
324 if (!cir::isValidLinkage(linkage))
325 return StructorCIRGen::RAUW;
326
327 if (cir::isWeakForLinker(linkage)) {
328 // Only ELF and wasm support COMDATs with arbitrary names (C5/D5).
329 if (cgm.getTarget().getTriple().isOSBinFormatELF() ||
330 cgm.getTarget().getTriple().isOSBinFormatWasm())
331 return StructorCIRGen::COMDAT;
332 return StructorCIRGen::Emit;
333 }
334
335 return StructorCIRGen::Alias;
336}
337
339 GlobalDecl aliasDecl,
340 GlobalDecl targetDecl) {
341 cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);
342
343 // Does this function alias already exists?
344 StringRef mangledName = cgm.getMangledName(aliasDecl);
345 auto globalValue = dyn_cast_or_null<cir::CIRGlobalValueInterface>(
346 cgm.getGlobalValue(mangledName));
347 if (globalValue && !globalValue.isDeclaration())
348 return;
349
350 auto entry = cast_or_null<cir::FuncOp>(cgm.getGlobalValue(mangledName));
351
352 // Retrieve aliasee info.
353 auto aliasee = cast<cir::FuncOp>(cgm.getAddrOfGlobal(targetDecl));
354
355 // Populate actual alias.
356 cgm.emitAliasForGlobal(mangledName, entry, aliasDecl, aliasee, linkage);
357}
358
359void CIRGenItaniumCXXABI::emitCXXStructor(GlobalDecl gd) {
360 auto *md = cast<CXXMethodDecl>(gd.getDecl());
361 StructorCIRGen cirGenType = getCIRGenToUse(cgm, md);
362 const auto *cd = dyn_cast<CXXConstructorDecl>(md);
363
364 if (cd ? gd.getCtorType() == Ctor_Complete
365 : gd.getDtorType() == Dtor_Complete) {
366 GlobalDecl baseDecl =
368 ;
369
370 if (cirGenType == StructorCIRGen::Alias ||
371 cirGenType == StructorCIRGen::COMDAT) {
372 emitConstructorDestructorAlias(cgm, gd, baseDecl);
373 return;
374 }
375
376 if (cirGenType == StructorCIRGen::RAUW) {
377 StringRef mangledName = cgm.getMangledName(gd);
378 mlir::Operation *aliasee = cgm.getAddrOfGlobal(baseDecl);
379 cgm.addReplacement(mangledName, aliasee);
380 return;
381 }
382 }
383
384 auto fn = cgm.codegenCXXStructor(gd);
385
386 cgm.maybeSetTrivialComdat(*md, fn);
387}
388
389void CIRGenItaniumCXXABI::addImplicitStructorParams(CIRGenFunction &cgf,
390 QualType &resTy,
391 FunctionArgList &params) {
392 const auto *md = cast<CXXMethodDecl>(cgf.curGD.getDecl());
394
395 // Check if we need a VTT parameter as well.
396 if (needsVTTParameter(cgf.curGD)) {
397 ASTContext &astContext = cgm.getASTContext();
398
399 // FIXME: avoid the fake decl
401 QualType t = astContext.getPointerType(astContext.VoidPtrTy);
402 auto *vttDecl = ImplicitParamDecl::Create(
403 astContext, /*DC=*/nullptr, md->getLocation(),
404 &astContext.Idents.get("vtt"), t, ImplicitParamKind::CXXVTT);
405 params.insert(params.begin() + 1, vttDecl);
406 getStructorImplicitParamDecl(cgf) = vttDecl;
407 }
408}
409
410void CIRGenItaniumCXXABI::emitCXXConstructors(const CXXConstructorDecl *d) {
411 // Just make sure we're in sync with TargetCXXABI.
413
414 // The constructor used for constructing this as a base class;
415 // ignores virtual bases.
416 cgm.emitGlobal(GlobalDecl(d, Ctor_Base));
417
418 // The constructor used for constructing this as a complete class;
419 // constructs the virtual bases, then calls the base constructor.
420 if (!d->getParent()->isAbstract()) {
421 // We don't need to emit the complete ctro if the class is abstract.
422 cgm.emitGlobal(GlobalDecl(d, Ctor_Complete));
423 }
424}
425
426void CIRGenItaniumCXXABI::emitCXXDestructors(const CXXDestructorDecl *d) {
427 // The destructor used for destructing this as a base class; ignores
428 // virtual bases.
429 cgm.emitGlobal(GlobalDecl(d, Dtor_Base));
430
431 // The destructor used for destructing this as a most-derived class;
432 // call the base destructor and then destructs any virtual bases.
433 cgm.emitGlobal(GlobalDecl(d, Dtor_Complete));
434
435 // The destructor in a virtual table is always a 'deleting'
436 // destructor, which calls the complete destructor and then uses the
437 // appropriate operator delete.
438 if (d->isVirtual())
439 cgm.emitGlobal(GlobalDecl(d, Dtor_Deleting));
440}
441
442CIRGenCXXABI::AddedStructorArgs CIRGenItaniumCXXABI::getImplicitConstructorArgs(
443 CIRGenFunction &cgf, const CXXConstructorDecl *d, CXXCtorType type,
444 bool forVirtualBase, bool delegating) {
445 if (!needsVTTParameter(GlobalDecl(d, type)))
446 return AddedStructorArgs{};
447
448 // Insert the implicit 'vtt' argument as the second argument. Make sure to
449 // correctly reflect its address space, which can differ from generic on
450 // some targets.
451 mlir::Value vtt =
452 cgf.getVTTParameter(GlobalDecl(d, type), forVirtualBase, delegating);
453 QualType vttTy =
456 return AddedStructorArgs::withPrefix({{vtt, vttTy}});
457}
458
459/// Return whether the given global decl needs a VTT (virtual table table)
460/// parameter, which it does if it's a base constructor or destructor with
461/// virtual bases.
462bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) {
463 auto *md = cast<CXXMethodDecl>(gd.getDecl());
464
465 // We don't have any virtual bases, just return early.
466 if (!md->getParent()->getNumVBases())
467 return false;
468
469 // Check if we have a base constructor.
471 return true;
472
473 // Check if we have a base destructor.
475 return true;
476
477 return false;
478}
479
480void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,
481 const CXXRecordDecl *rd) {
482 cir::GlobalOp vtable = getAddrOfVTable(rd, CharUnits());
483 if (vtable.hasInitializer())
484 return;
485
486 ItaniumVTableContext &vtContext = cgm.getItaniumVTableContext();
487 const VTableLayout &vtLayout = vtContext.getVTableLayout(rd);
488 cir::GlobalLinkageKind linkage = cgm.getVTableLinkage(rd);
489 mlir::Attribute rtti =
492
493 // Classic codegen uses ConstantInitBuilder here, which is a very general
494 // and feature-rich class to generate initializers for global values.
495 // For now, this is using a simpler approach to create the initializer in CIR.
496 cgvt.createVTableInitializer(vtable, vtLayout, rtti,
497 cir::isLocalLinkage(linkage));
498
499 // Set the correct linkage.
500 vtable.setLinkage(linkage);
501
502 if (cgm.supportsCOMDAT() && cir::isWeakForLinker(linkage))
503 vtable.setComdat(true);
504
505 // Set the right visibility.
506 cgm.setGVProperties(vtable, rd);
507
508 // If this is the magic class __cxxabiv1::__fundamental_type_info,
509 // we will emit the typeinfo for the fundamental types. This is the
510 // same behaviour as GCC.
511 const DeclContext *DC = rd->getDeclContext();
512 if (rd->getIdentifier() &&
513 rd->getIdentifier()->isStr("__fundamental_type_info") &&
514 isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
515 cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
516 DC->getParent()->isTranslationUnit()) {
517 cgm.errorNYI(rd->getSourceRange(),
518 "emitVTableDefinitions: __fundamental_type_info");
519 }
520
521 [[maybe_unused]] auto vtableAsGlobalValue =
522 dyn_cast<cir::CIRGlobalValueInterface>(*vtable);
523 assert(vtableAsGlobalValue && "VTable must support CIRGlobalValueInterface");
524 // Always emit type metadata on non-available_externally definitions, and on
525 // available_externally definitions if we are performing whole program
526 // devirtualization. For WPD we need the type metadata on all vtable
527 // definitions to ensure we associate derived classes with base classes
528 // defined in headers but with a strong definition only in a shared
529 // library.
531 if (cgm.getCodeGenOpts().WholeProgramVTables) {
532 cgm.errorNYI(rd->getSourceRange(),
533 "emitVTableDefinitions: WholeProgramVTables");
534 }
535
537 if (cgm.getLangOpts().RelativeCXXABIVTables) {
538 cgm.errorNYI(rd->getSourceRange(), "vtableRelativeLayout");
539 }
540}
541
542mlir::Value CIRGenItaniumCXXABI::emitVirtualDestructorCall(
543 CIRGenFunction &cgf, const CXXDestructorDecl *dtor, CXXDtorType dtorType,
544 Address thisAddr, DeleteOrMemberCallExpr expr) {
545 auto *callExpr = dyn_cast<const CXXMemberCallExpr *>(expr);
546 auto *delExpr = dyn_cast<const CXXDeleteExpr *>(expr);
547 assert((callExpr != nullptr) ^ (delExpr != nullptr));
548 assert(callExpr == nullptr || callExpr->arg_begin() == callExpr->arg_end());
549 assert(dtorType == Dtor_Deleting || dtorType == Dtor_Complete);
550
551 GlobalDecl globalDecl(dtor, dtorType);
552 const CIRGenFunctionInfo *fnInfo =
553 &cgm.getTypes().arrangeCXXStructorDeclaration(globalDecl);
554 const cir::FuncType &fnTy = cgm.getTypes().getFunctionType(*fnInfo);
555 auto callee = CIRGenCallee::forVirtual(callExpr, globalDecl, thisAddr, fnTy);
556
557 QualType thisTy =
558 callExpr ? callExpr->getObjectType() : delExpr->getDestroyedType();
559
560 cgf.emitCXXDestructorCall(globalDecl, callee, thisAddr.emitRawPointer(),
561 thisTy, nullptr, QualType(), nullptr);
562 return nullptr;
563}
564
565void CIRGenItaniumCXXABI::emitVirtualInheritanceTables(
566 const CXXRecordDecl *rd) {
567 CIRGenVTables &vtables = cgm.getVTables();
568 cir::GlobalOp vtt = vtables.getAddrOfVTT(rd);
569 vtables.emitVTTDefinition(vtt, cgm.getVTableLinkage(rd), rd);
570}
571
572namespace {
573class CIRGenItaniumRTTIBuilder {
574 CIRGenModule &cgm; // Per-module state.
575 const CIRGenItaniumCXXABI &cxxABI; // Per-module state.
576
577 /// The fields of the RTTI descriptor currently being built.
578 SmallVector<mlir::Attribute, 16> fields;
579
580 // Returns the mangled type name of the given type.
581 cir::GlobalOp getAddrOfTypeName(mlir::Location loc, QualType ty,
582 cir::GlobalLinkageKind linkage);
583
584 /// descriptor of the given type.
585 mlir::Attribute getAddrOfExternalRTTIDescriptor(mlir::Location loc,
586 QualType ty);
587
588 /// Build the vtable pointer for the given type.
589 void buildVTablePointer(mlir::Location loc, const Type *ty);
590
591 /// Build an abi::__si_class_type_info, used for single inheritance, according
592 /// to the Itanium C++ ABI, 2.9.5p6b.
593 void buildSIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd);
594
595 /// Build an abi::__vmi_class_type_info, used for
596 /// classes with bases that do not satisfy the abi::__si_class_type_info
597 /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
598 void buildVMIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd);
599
600 /// Build an abi::__pointer_type_info, used for pointer types, according
601 /// to the Itanium C++ ABI, 2.9.4p7.
602 void buildPointerTypeInfo(mlir::Location loc, QualType ty);
603
604 /// Build an abi::__pointer_to_member_type_info, used for pointer to member
605 /// types, according to the Itanium C++ ABI, 2.9.4p9.
606
607 /// Build an abi::__pointer_to_member_type_info
608 /// struct, used for member pointer types.
609 void buildPointerToMemberTypeInfo(mlir::Location loc,
610 const MemberPointerType *ty);
611
612public:
613 CIRGenItaniumRTTIBuilder(const CIRGenItaniumCXXABI &abi, CIRGenModule &cgm)
614 : cgm(cgm), cxxABI(abi) {}
615
616 /// Build the RTTI type info struct for the given type, or
617 /// link to an existing RTTI descriptor if one already exists.
618 mlir::Attribute buildTypeInfo(mlir::Location loc, QualType ty);
619
620 /// Build the RTTI type info struct for the given type.
621 mlir::Attribute buildTypeInfo(mlir::Location loc, QualType ty,
622 cir::GlobalLinkageKind linkage,
623 mlir::SymbolTable::Visibility visibility);
624};
625} // namespace
626
627// TODO(cir): Will be removed after sharing them with the classical codegen
628namespace {
629
630// Pointer type info flags.
631enum {
632 /// PTI_Const - Type has const qualifier.
633 PTI_Const = 0x1,
634
635 /// PTI_Volatile - Type has volatile qualifier.
636 PTI_Volatile = 0x2,
637
638 /// PTI_Restrict - Type has restrict qualifier.
639 PTI_Restrict = 0x4,
640
641 /// PTI_Incomplete - Type is incomplete.
642 PTI_Incomplete = 0x8,
643
644 /// PTI_ContainingClassIncomplete - Containing class is incomplete.
645 /// (in pointer to member).
646 PTI_ContainingClassIncomplete = 0x10,
647
648 /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
649 // PTI_TransactionSafe = 0x20,
650
651 /// PTI_Noexcept - Pointee is noexcept function (C++1z).
652 PTI_Noexcept = 0x40,
653};
654
655// VMI type info flags.
656enum {
657 /// VMI_NonDiamondRepeat - Class has non-diamond repeated inheritance.
658 VMI_NonDiamondRepeat = 0x1,
659
660 /// VMI_DiamondShaped - Class is diamond shaped.
661 VMI_DiamondShaped = 0x2
662};
663
664// Base class type info flags.
665enum {
666 /// BCTI_Virtual - Base class is virtual.
667 BCTI_Virtual = 0x1,
668
669 /// BCTI_Public - Base class is public.
670 BCTI_Public = 0x2
671};
672
673/// Given a builtin type, returns whether the type
674/// info for that type is defined in the standard library.
675/// TODO(cir): this can unified with LLVM codegen
676static bool typeInfoIsInStandardLibrary(const BuiltinType *ty) {
677 // Itanium C++ ABI 2.9.2:
678 // Basic type information (e.g. for "int", "bool", etc.) will be kept in
679 // the run-time support library. Specifically, the run-time support
680 // library should contain type_info objects for the types X, X* and
681 // X const*, for every X in: void, std::nullptr_t, bool, wchar_t, char,
682 // unsigned char, signed char, short, unsigned short, int, unsigned int,
683 // long, unsigned long, long long, unsigned long long, float, double,
684 // long double, char16_t, char32_t, and the IEEE 754r decimal and
685 // half-precision floating point types.
686 //
687 // GCC also emits RTTI for __int128.
688 // FIXME: We do not emit RTTI information for decimal types here.
689
690 // Types added here must also be added to emitFundamentalRTTIDescriptors.
691 switch (ty->getKind()) {
692 case BuiltinType::WasmExternRef:
693 case BuiltinType::HLSLResource:
694 llvm_unreachable("NYI");
695 case BuiltinType::Void:
696 case BuiltinType::NullPtr:
697 case BuiltinType::Bool:
698 case BuiltinType::WChar_S:
699 case BuiltinType::WChar_U:
700 case BuiltinType::Char_U:
701 case BuiltinType::Char_S:
702 case BuiltinType::UChar:
703 case BuiltinType::SChar:
704 case BuiltinType::Short:
705 case BuiltinType::UShort:
706 case BuiltinType::Int:
707 case BuiltinType::UInt:
708 case BuiltinType::Long:
709 case BuiltinType::ULong:
710 case BuiltinType::LongLong:
711 case BuiltinType::ULongLong:
712 case BuiltinType::Half:
713 case BuiltinType::Float:
714 case BuiltinType::Double:
715 case BuiltinType::LongDouble:
716 case BuiltinType::Float16:
717 case BuiltinType::Float128:
718 case BuiltinType::Ibm128:
719 case BuiltinType::Char8:
720 case BuiltinType::Char16:
721 case BuiltinType::Char32:
722 case BuiltinType::Int128:
723 case BuiltinType::UInt128:
724 return true;
725
726#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
727 case BuiltinType::Id:
728#include "clang/Basic/OpenCLImageTypes.def"
729#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:
730#include "clang/Basic/OpenCLExtensionTypes.def"
731 case BuiltinType::OCLSampler:
732 case BuiltinType::OCLEvent:
733 case BuiltinType::OCLClkEvent:
734 case BuiltinType::OCLQueue:
735 case BuiltinType::OCLReserveID:
736#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
737#include "clang/Basic/AArch64ACLETypes.def"
738#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
739#include "clang/Basic/PPCTypes.def"
740#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
741#include "clang/Basic/RISCVVTypes.def"
742#define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
743#include "clang/Basic/AMDGPUTypes.def"
744 case BuiltinType::ShortAccum:
745 case BuiltinType::Accum:
746 case BuiltinType::LongAccum:
747 case BuiltinType::UShortAccum:
748 case BuiltinType::UAccum:
749 case BuiltinType::ULongAccum:
750 case BuiltinType::ShortFract:
751 case BuiltinType::Fract:
752 case BuiltinType::LongFract:
753 case BuiltinType::UShortFract:
754 case BuiltinType::UFract:
755 case BuiltinType::ULongFract:
756 case BuiltinType::SatShortAccum:
757 case BuiltinType::SatAccum:
758 case BuiltinType::SatLongAccum:
759 case BuiltinType::SatUShortAccum:
760 case BuiltinType::SatUAccum:
761 case BuiltinType::SatULongAccum:
762 case BuiltinType::SatShortFract:
763 case BuiltinType::SatFract:
764 case BuiltinType::SatLongFract:
765 case BuiltinType::SatUShortFract:
766 case BuiltinType::SatUFract:
767 case BuiltinType::SatULongFract:
768 case BuiltinType::BFloat16:
769 return false;
770
771 case BuiltinType::Dependent:
772#define BUILTIN_TYPE(Id, SingletonId)
773#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
774#include "clang/AST/BuiltinTypes.def"
775 llvm_unreachable("asking for RRTI for a placeholder type!");
776
777 case BuiltinType::ObjCId:
778 case BuiltinType::ObjCClass:
779 case BuiltinType::ObjCSel:
780 llvm_unreachable("FIXME: Objective-C types are unsupported!");
781 }
782
783 llvm_unreachable("Invalid BuiltinType Kind!");
784}
785
786static bool typeInfoIsInStandardLibrary(const PointerType *pointerTy) {
787 QualType pointeeTy = pointerTy->getPointeeType();
788 const auto *builtinTy = dyn_cast<BuiltinType>(pointeeTy);
789 if (!builtinTy)
790 return false;
791
792 // Check the qualifiers.
793 Qualifiers quals = pointeeTy.getQualifiers();
794 quals.removeConst();
795
796 if (!quals.empty())
797 return false;
798
799 return typeInfoIsInStandardLibrary(builtinTy);
800}
801
802/// IsStandardLibraryRTTIDescriptor - Returns whether the type
803/// information for the given type exists in the standard library.
804static bool isStandardLibraryRttiDescriptor(QualType ty) {
805 // Type info for builtin types is defined in the standard library.
806 if (const auto *builtinTy = dyn_cast<BuiltinType>(ty))
807 return typeInfoIsInStandardLibrary(builtinTy);
808
809 // Type info for some pointer types to builtin types is defined in the
810 // standard library.
811 if (const auto *pointerTy = dyn_cast<PointerType>(ty))
812 return typeInfoIsInStandardLibrary(pointerTy);
813
814 return false;
815}
816
817/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
818/// the given type exists somewhere else, and that we should not emit the type
819/// information in this translation unit. Assumes that it is not a
820/// standard-library type.
821static bool shouldUseExternalRttiDescriptor(CIRGenModule &cgm, QualType ty) {
822 ASTContext &context = cgm.getASTContext();
823
824 // If RTTI is disabled, assume it might be disabled in the
825 // translation unit that defines any potential key function, too.
826 if (!context.getLangOpts().RTTI)
827 return false;
828
829 if (const auto *recordTy = dyn_cast<RecordType>(ty)) {
830 const auto *rd =
831 cast<CXXRecordDecl>(recordTy->getDecl())->getDefinitionOrSelf();
832 if (!rd->hasDefinition())
833 return false;
834
835 if (!rd->isDynamicClass())
836 return false;
837
838 // FIXME: this may need to be reconsidered if the key function
839 // changes.
840 // N.B. We must always emit the RTTI data ourselves if there exists a key
841 // function.
842 bool isDLLImport = rd->hasAttr<DLLImportAttr>();
843
844 // Don't import the RTTI but emit it locally.
845 if (cgm.getTriple().isOSCygMing())
846 return false;
847
848 if (cgm.getVTables().isVTableExternal(rd)) {
850 return true;
851
852 return !isDLLImport || cgm.getTriple().isWindowsItaniumEnvironment();
853 }
854
855 if (isDLLImport)
856 return true;
857 }
858
859 return false;
860}
861
862/// Contains virtual and non-virtual bases seen when traversing a class
863/// hierarchy.
864struct SeenBases {
865 llvm::SmallPtrSet<const CXXRecordDecl *, 16> nonVirtualBases;
866 llvm::SmallPtrSet<const CXXRecordDecl *, 16> virtualBases;
867};
868
869/// Compute the value of the flags member in abi::__vmi_class_type_info.
870///
871static unsigned computeVmiClassTypeInfoFlags(const CXXBaseSpecifier *base,
872 SeenBases &bases) {
873
874 unsigned flags = 0;
875 auto *baseDecl = base->getType()->castAsCXXRecordDecl();
876
877 if (base->isVirtual()) {
878 // Mark the virtual base as seen.
879 if (!bases.virtualBases.insert(baseDecl).second) {
880 // If this virtual base has been seen before, then the class is diamond
881 // shaped.
882 flags |= VMI_DiamondShaped;
883 } else {
884 if (bases.nonVirtualBases.count(baseDecl))
885 flags |= VMI_NonDiamondRepeat;
886 }
887 } else {
888 // Mark the non-virtual base as seen.
889 if (!bases.nonVirtualBases.insert(baseDecl).second) {
890 // If this non-virtual base has been seen before, then the class has non-
891 // diamond shaped repeated inheritance.
892 flags |= VMI_NonDiamondRepeat;
893 } else {
894 if (bases.virtualBases.count(baseDecl))
895 flags |= VMI_NonDiamondRepeat;
896 }
897 }
898
899 // Walk all bases.
900 for (const auto &bs : baseDecl->bases())
901 flags |= computeVmiClassTypeInfoFlags(&bs, bases);
902
903 return flags;
904}
905
906static unsigned computeVmiClassTypeInfoFlags(const CXXRecordDecl *rd) {
907 unsigned flags = 0;
908 SeenBases bases;
909
910 // Walk all bases.
911 for (const auto &bs : rd->bases())
912 flags |= computeVmiClassTypeInfoFlags(&bs, bases);
913
914 return flags;
915}
916
917// Return whether the given record decl has a "single,
918// public, non-virtual base at offset zero (i.e. the derived class is dynamic
919// iff the base is)", according to Itanium C++ ABI, 2.95p6b.
920// TODO(cir): this can unified with LLVM codegen
921static bool canUseSingleInheritance(const CXXRecordDecl *rd) {
922 // Check the number of bases.
923 if (rd->getNumBases() != 1)
924 return false;
925
926 // Get the base.
928
929 // Check that the base is not virtual.
930 if (base->isVirtual())
931 return false;
932
933 // Check that the base is public.
934 if (base->getAccessSpecifier() != AS_public)
935 return false;
936
937 // Check that the class is dynamic iff the base is.
938 auto *baseDecl = base->getType()->castAsCXXRecordDecl();
939 return baseDecl->isEmpty() ||
940 baseDecl->isDynamicClass() == rd->isDynamicClass();
941}
942
943/// IsIncompleteClassType - Returns whether the given record type is incomplete.
944static bool isIncompleteClassType(const RecordType *recordTy) {
945 return !recordTy->getDecl()->getDefinitionOrSelf()->isCompleteDefinition();
946}
947
948/// Returns whether the given type contains an
949/// incomplete class type. This is true if
950///
951/// * The given type is an incomplete class type.
952/// * The given type is a pointer type whose pointee type contains an
953/// incomplete class type.
954/// * The given type is a member pointer type whose class is an incomplete
955/// class type.
956/// * The given type is a member pointer type whoise pointee type contains an
957/// incomplete class type.
958/// is an indirect or direct pointer to an incomplete class type.
959static bool containsIncompleteClassType(QualType ty) {
960 if (const auto *recordTy = dyn_cast<RecordType>(ty)) {
961 if (isIncompleteClassType(recordTy))
962 return true;
963 }
964
965 if (const auto *pointerTy = dyn_cast<PointerType>(ty))
966 return containsIncompleteClassType(pointerTy->getPointeeType());
967
968 if (const auto *memberPointerTy = dyn_cast<MemberPointerType>(ty)) {
969 // Check if the class type is incomplete.
970 if (!memberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
971 return true;
972
973 return containsIncompleteClassType(memberPointerTy->getPointeeType());
974 }
975
976 return false;
977}
978
979static unsigned extractPBaseFlags(const ASTContext &ctx, QualType &ty) {
980 unsigned flags = 0;
981
982 if (ty.isConstQualified())
983 flags |= PTI_Const;
984 if (ty.isVolatileQualified())
985 flags |= PTI_Volatile;
986 if (ty.isRestrictQualified())
987 flags |= PTI_Restrict;
988
989 ty = ty.getUnqualifiedType();
990
991 if (containsIncompleteClassType(ty))
992 flags |= PTI_Incomplete;
993
994 if (const auto *proto = ty->getAs<FunctionProtoType>()) {
995 if (proto->isNothrow()) {
996 flags |= PTI_Noexcept;
998 }
999 }
1000
1001 return flags;
1002}
1003
1004const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) {
1005 // abi::__class_type_info.
1006 static const char *const classTypeInfo =
1007 "_ZTVN10__cxxabiv117__class_type_infoE";
1008 // abi::__si_class_type_info.
1009 static const char *const siClassTypeInfo =
1010 "_ZTVN10__cxxabiv120__si_class_type_infoE";
1011 // abi::__vmi_class_type_info.
1012 static const char *const vmiClassTypeInfo =
1013 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
1014
1015 switch (ty->getTypeClass()) {
1016#define TYPE(Class, Base)
1017#define ABSTRACT_TYPE(Class, Base)
1018#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
1019#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
1020#define DEPENDENT_TYPE(Class, Base) case Type::Class:
1021#include "clang/AST/TypeNodes.inc"
1022 llvm_unreachable("Non-canonical and dependent types shouldn't get here");
1023
1024 case Type::LValueReference:
1025 case Type::RValueReference:
1026 llvm_unreachable("References shouldn't get here");
1027
1028 case Type::Auto:
1029 case Type::DeducedTemplateSpecialization:
1030 llvm_unreachable("Undeduced type shouldn't get here");
1031
1032 case Type::Pipe:
1033 llvm_unreachable("Pipe types shouldn't get here");
1034
1035 case Type::ArrayParameter:
1036 llvm_unreachable("Array Parameter types should not get here.");
1037
1038 case Type::Builtin:
1039 case Type::BitInt:
1040 case Type::OverflowBehavior:
1041 // GCC treats vector and complex types as fundamental types.
1042 case Type::Vector:
1043 case Type::ExtVector:
1044 case Type::ConstantMatrix:
1045 case Type::Complex:
1046 case Type::Atomic:
1047 // FIXME: GCC treats block pointers as fundamental types?!
1048 case Type::BlockPointer:
1049 return "_ZTVN10__cxxabiv123__fundamental_type_infoE";
1050 case Type::ConstantArray:
1051 case Type::IncompleteArray:
1052 case Type::VariableArray:
1053 // abi::__array_type_info.
1054 return "_ZTVN10__cxxabiv117__array_type_infoE";
1055
1056 case Type::FunctionNoProto:
1057 case Type::FunctionProto:
1058 // abi::__function_type_info.
1059 return "_ZTVN10__cxxabiv120__function_type_infoE";
1060
1061 case Type::Enum:
1062 return "_ZTVN10__cxxabiv116__enum_type_infoE";
1063
1064 case Type::Record: {
1065 const auto *rd = cast<CXXRecordDecl>(cast<RecordType>(ty)->getDecl())
1066 ->getDefinitionOrSelf();
1067
1068 if (!rd->hasDefinition() || !rd->getNumBases()) {
1069 return classTypeInfo;
1070 }
1071
1072 if (canUseSingleInheritance(rd)) {
1073 return siClassTypeInfo;
1074 }
1075
1076 return vmiClassTypeInfo;
1077 }
1078
1079 case Type::ObjCObject:
1080 cgm.errorNYI("VTableClassNameForType: ObjCObject");
1081 break;
1082
1083 case Type::ObjCInterface:
1084 cgm.errorNYI("VTableClassNameForType: ObjCInterface");
1085 break;
1086
1087 case Type::ObjCObjectPointer:
1088 case Type::Pointer:
1089 // abi::__pointer_type_info.
1090 return "_ZTVN10__cxxabiv119__pointer_type_infoE";
1091
1092 case Type::MemberPointer:
1093 // abi::__pointer_to_member_type_info.
1094 return "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
1095
1096 case Type::HLSLAttributedResource:
1097 case Type::HLSLInlineSpirv:
1098 llvm_unreachable("HLSL doesn't support virtual functions");
1099 }
1100
1101 return nullptr;
1102}
1103} // namespace
1104
1105/// Return the linkage that the type info and type info name constants
1106/// should have for the given type.
1107static cir::GlobalLinkageKind getTypeInfoLinkage(CIRGenModule &cgm,
1108 QualType ty) {
1109 // In addition, it and all of the intermediate abi::__pointer_type_info
1110 // structs in the chain down to the abi::__class_type_info for the
1111 // incomplete class type must be prevented from resolving to the
1112 // corresponding type_info structs for the complete class type, possibly
1113 // by making them local static objects. Finally, a dummy class RTTI is
1114 // generated for the incomplete type that will not resolve to the final
1115 // complete class RTTI (because the latter need not exist), possibly by
1116 // making it a local static object.
1117 if (containsIncompleteClassType(ty))
1118 return cir::GlobalLinkageKind::InternalLinkage;
1119
1120 switch (ty->getLinkage()) {
1121 case Linkage::Invalid:
1122 llvm_unreachable("Linkage hasn't been computed!");
1123
1124 case Linkage::None:
1125 case Linkage::Internal:
1127 return cir::GlobalLinkageKind::InternalLinkage;
1128
1130 case Linkage::Module:
1131 case Linkage::External:
1132 // RTTI is not enabled, which means that this type info struct is going
1133 // to be used for exception handling. Give it linkonce_odr linkage.
1134 if (!cgm.getLangOpts().RTTI)
1135 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
1136
1137 if (const RecordType *record = dyn_cast<RecordType>(ty)) {
1138 const auto *rd =
1139 cast<CXXRecordDecl>(record->getDecl())->getDefinitionOrSelf();
1140 if (rd->hasAttr<WeakAttr>())
1141 return cir::GlobalLinkageKind::WeakODRLinkage;
1142
1143 if (cgm.getTriple().isWindowsItaniumEnvironment())
1144 if (rd->hasAttr<DLLImportAttr>() &&
1145 shouldUseExternalRttiDescriptor(cgm, ty))
1146 return cir::GlobalLinkageKind::ExternalLinkage;
1147
1148 // MinGW always uses LinkOnceODRLinkage for type info.
1149 if (rd->isDynamicClass() && !cgm.getASTContext()
1150 .getTargetInfo()
1151 .getTriple()
1152 .isWindowsGNUEnvironment())
1153 return cgm.getVTableLinkage(rd);
1154 }
1155
1156 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
1157 }
1158
1159 llvm_unreachable("Invalid linkage!");
1160}
1161
1162cir::GlobalOp
1163CIRGenItaniumRTTIBuilder::getAddrOfTypeName(mlir::Location loc, QualType ty,
1164 cir::GlobalLinkageKind linkage) {
1165 CIRGenBuilderTy &builder = cgm.getBuilder();
1166 SmallString<256> name;
1167 llvm::raw_svector_ostream out(name);
1169
1170 // We know that the mangled name of the type starts at index 4 of the
1171 // mangled name of the typename, so we can just index into it in order to
1172 // get the mangled name of the type.
1173 mlir::Attribute init = builder.getString(
1174 name.substr(4), cgm.convertType(cgm.getASTContext().CharTy),
1175 std::nullopt);
1176
1177 CharUnits align =
1179
1180 // builder.getString can return a #cir.zero if the string given to it only
1181 // contains null bytes. However, type names cannot be full of null bytes.
1182 // So cast Init to a ConstArrayAttr should be safe.
1183 auto initStr = cast<cir::ConstArrayAttr>(init);
1184
1185 cir::GlobalOp gv = cgm.createOrReplaceCXXRuntimeVariable(
1186 loc, name, initStr.getType(), linkage, align);
1188 return gv;
1189}
1190
1191mlir::Attribute
1192CIRGenItaniumRTTIBuilder::getAddrOfExternalRTTIDescriptor(mlir::Location loc,
1193 QualType ty) {
1194 // Mangle the RTTI name.
1195 SmallString<256> name;
1196 llvm::raw_svector_ostream out(name);
1198 CIRGenBuilderTy &builder = cgm.getBuilder();
1199
1200 // Look for an existing global.
1201 cir::GlobalOp gv = dyn_cast_or_null<cir::GlobalOp>(
1202 mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));
1203
1204 if (!gv) {
1205 // Create a new global variable.
1206 // From LLVM codegen => Note for the future: If we would ever like to do
1207 // deferred emission of RTTI, check if emitting vtables opportunistically
1208 // need any adjustment.
1209 gv = CIRGenModule::createGlobalOp(cgm, loc, name, builder.getUInt8PtrTy(),
1210 /*isConstant=*/true);
1211 const CXXRecordDecl *rd = ty->getAsCXXRecordDecl();
1212 cgm.setGVProperties(gv, rd);
1213
1214 // Import the typeinfo symbol when all non-inline virtual methods are
1215 // imported.
1216 if (cgm.getTarget().hasPS4DLLImportExport()) {
1217 cgm.errorNYI("getAddrOfExternalRTTIDescriptor: hasPS4DLLImportExport");
1218 }
1219 }
1220
1221 return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), gv);
1222}
1223
1224void CIRGenItaniumRTTIBuilder::buildVTablePointer(mlir::Location loc,
1225 const Type *ty) {
1226 CIRGenBuilderTy &builder = cgm.getBuilder();
1227 const char *vTableName = vTableClassNameForType(cgm, ty);
1228
1229 // Check if the alias exists. If it doesn't, then get or create the global.
1230 if (cgm.getLangOpts().RelativeCXXABIVTables) {
1231 cgm.errorNYI("buildVTablePointer: isRelativeLayout");
1232 return;
1233 }
1234
1235 mlir::Type vtableGlobalTy = builder.getPointerTo(builder.getUInt8PtrTy());
1236 llvm::Align align = cgm.getDataLayout().getABITypeAlign(vtableGlobalTy);
1237 cir::GlobalOp vTable = cgm.createOrReplaceCXXRuntimeVariable(
1238 loc, vTableName, vtableGlobalTy, cir::GlobalLinkageKind::ExternalLinkage,
1240
1241 // The vtable address point is 2.
1242 mlir::Attribute field{};
1243 if (cgm.getLangOpts().RelativeCXXABIVTables) {
1244 cgm.errorNYI("buildVTablePointer: isRelativeLayout");
1245 } else {
1246 SmallVector<mlir::Attribute, 4> offsets{
1247 cgm.getBuilder().getI32IntegerAttr(2)};
1248 auto indices = mlir::ArrayAttr::get(builder.getContext(), offsets);
1250 vTable, indices);
1251 }
1252
1253 assert(field && "expected attribute");
1254 fields.push_back(field);
1255}
1256
1257/// Build an abi::__si_class_type_info, used for single inheritance, according
1258/// to the Itanium C++ ABI, 2.95p6b.
1259void CIRGenItaniumRTTIBuilder::buildSIClassTypeInfo(mlir::Location loc,
1260 const CXXRecordDecl *rd) {
1261 // Itanium C++ ABI 2.9.5p6b:
1262 // It adds to abi::__class_type_info a single member pointing to the
1263 // type_info structure for the base type,
1264 mlir::Attribute baseTypeInfo =
1265 CIRGenItaniumRTTIBuilder(cxxABI, cgm)
1266 .buildTypeInfo(loc, rd->bases_begin()->getType());
1267 fields.push_back(baseTypeInfo);
1268}
1269
1270/// Build an abi::__vmi_class_type_info, used for
1271/// classes with bases that do not satisfy the abi::__si_class_type_info
1272/// constraints, according to the Itanium C++ ABI, 2.9.5p5c.
1273void CIRGenItaniumRTTIBuilder::buildVMIClassTypeInfo(mlir::Location loc,
1274 const CXXRecordDecl *rd) {
1275 mlir::Type unsignedIntLTy =
1277
1278 // Itanium C++ ABI 2.9.5p6c:
1279 // __flags is a word with flags describing details about the class
1280 // structure, which may be referenced by using the __flags_masks
1281 // enumeration. These flags refer to both direct and indirect bases.
1282 unsigned flags = computeVmiClassTypeInfoFlags(rd);
1283 fields.push_back(cir::IntAttr::get(unsignedIntLTy, flags));
1284
1285 // Itanium C++ ABI 2.9.5p6c:
1286 // __base_count is a word with the number of direct proper base class
1287 // descriptions that follow.
1288 fields.push_back(cir::IntAttr::get(unsignedIntLTy, rd->getNumBases()));
1289
1290 if (!rd->getNumBases())
1291 return;
1292
1293 // Now add the base class descriptions.
1294
1295 // Itanium C++ ABI 2.9.5p6c:
1296 // __base_info[] is an array of base class descriptions -- one for every
1297 // direct proper base. Each description is of the type:
1298 //
1299 // struct abi::__base_class_type_info {
1300 // public:
1301 // const __class_type_info *__base_type;
1302 // long __offset_flags;
1303 //
1304 // enum __offset_flags_masks {
1305 // __virtual_mask = 0x1,
1306 // __public_mask = 0x2,
1307 // __offset_shift = 8
1308 // };
1309 // };
1310
1311 // If we're in mingw and 'long' isn't wide enough for a pointer, use 'long
1312 // long' instead of 'long' for __offset_flags. libstdc++abi uses long long on
1313 // LLP64 platforms.
1314 // FIXME: Consider updating libc++abi to match, and extend this logic to all
1315 // LLP64 platforms.
1316 QualType offsetFlagsTy = cgm.getASTContext().LongTy;
1317 const TargetInfo &ti = cgm.getASTContext().getTargetInfo();
1318 if (ti.getTriple().isOSCygMing() &&
1319 ti.getPointerWidth(LangAS::Default) > ti.getLongWidth())
1320 offsetFlagsTy = cgm.getASTContext().LongLongTy;
1321 mlir::Type offsetFlagsLTy = cgm.convertType(offsetFlagsTy);
1322
1323 for (const CXXBaseSpecifier &base : rd->bases()) {
1324 // The __base_type member points to the RTTI for the base type.
1325 fields.push_back(CIRGenItaniumRTTIBuilder(cxxABI, cgm)
1326 .buildTypeInfo(loc, base.getType()));
1327
1328 CXXRecordDecl *baseDecl = base.getType()->castAsCXXRecordDecl();
1329 int64_t offsetFlags = 0;
1330
1331 // All but the lower 8 bits of __offset_flags are a signed offset.
1332 // For a non-virtual base, this is the offset in the object of the base
1333 // subobject. For a virtual base, this is the offset in the virtual table of
1334 // the virtual base offset for the virtual base referenced (negative).
1335 CharUnits offset;
1336 if (base.isVirtual())
1338 rd, baseDecl);
1339 else {
1340 const ASTRecordLayout &layout =
1342 offset = layout.getBaseClassOffset(baseDecl);
1343 }
1344 offsetFlags = uint64_t(offset.getQuantity()) << 8;
1345
1346 // The low-order byte of __offset_flags contains flags, as given by the
1347 // masks from the enumeration __offset_flags_masks.
1348 if (base.isVirtual())
1349 offsetFlags |= BCTI_Virtual;
1350 if (base.getAccessSpecifier() == AS_public)
1351 offsetFlags |= BCTI_Public;
1352
1353 fields.push_back(cir::IntAttr::get(offsetFlagsLTy, offsetFlags));
1354 }
1355}
1356
1357void CIRGenItaniumRTTIBuilder::buildPointerTypeInfo(mlir::Location loc,
1358 QualType ty) {
1359 // Itanium C++ ABI 2.9.4p7:
1360 // abi::__pbase_type_info is a base for both pointer types and
1361 // pointer-to-member types. It adds two data members:
1362 //
1363 // class __pbase_type_info : public std::type_info {
1364 // public:
1365 // unsigned int __flags;
1366 // const std::type_info *__pointee;
1367 //
1368 // enum __masks {
1369 // __const_mask = 0x1,
1370 // __volatile_mask = 0x2,
1371 // __restrict_mask = 0x4,
1372 // __incomplete_mask = 0x8,
1373 // __incomplete_class_mask = 0x10,
1374 // __transaction_safe_mask = 0x20
1375 // __noexcept_mask = 0x40
1376 // };
1377 // };
1378 const unsigned int flags = extractPBaseFlags(cgm.getASTContext(), ty);
1379
1380 mlir::Type unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy);
1381 mlir::Attribute flagsAttr = cir::IntAttr::get(unsignedIntTy, flags);
1382 fields.push_back(flagsAttr);
1383
1384 mlir::Attribute pointeeTypeInfo =
1385 CIRGenItaniumRTTIBuilder(cxxABI, cgm).buildTypeInfo(loc, ty);
1386 fields.push_back(pointeeTypeInfo);
1387}
1388
1389void CIRGenItaniumRTTIBuilder::buildPointerToMemberTypeInfo(
1390 mlir::Location loc, const MemberPointerType *ty) {
1391
1392 // The abi::__pointer_to_member_type_info type adds one field to
1393 // abi::__pbase_type_info:
1394 //
1395 // class __pointer_to_member_type_info : public __pbase_type_info {
1396 // public:
1397 // const abi::__class_type_info *__context;
1398 // };
1399 QualType pointeeTy = ty->getPointeeType();
1400
1401 unsigned flags = extractPBaseFlags(cgm.getASTContext(), pointeeTy);
1402
1403 const auto *rd = ty->getMostRecentCXXRecordDecl();
1404 if (!rd->hasDefinition())
1405 flags |= PTI_ContainingClassIncomplete;
1406
1407 mlir::Type unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy);
1408 mlir::Attribute flagsAttr = cir::IntAttr::get(unsignedIntTy, flags);
1409 fields.push_back(flagsAttr);
1410
1411 mlir::Attribute pointeeTypeInfo =
1412 CIRGenItaniumRTTIBuilder(cxxABI, cgm).buildTypeInfo(loc, pointeeTy);
1413 fields.push_back(pointeeTypeInfo);
1414
1415 CanQualType contextTy = cgm.getASTContext().getCanonicalTagType(rd);
1416 mlir::Attribute classTypeInfo =
1417 CIRGenItaniumRTTIBuilder(cxxABI, cgm).buildTypeInfo(loc, contextTy);
1418 fields.push_back(classTypeInfo);
1419}
1420
1421mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(mlir::Location loc,
1422 QualType ty) {
1423 // We want to operate on the canonical type.
1424 ty = ty.getCanonicalType();
1425
1426 // Check if we've already emitted an RTTI descriptor for this type.
1427 SmallString<256> name;
1428 llvm::raw_svector_ostream out(name);
1430
1431 auto oldGV = dyn_cast_or_null<cir::GlobalOp>(
1432 mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));
1433
1434 if (oldGV && !oldGV.isDeclaration()) {
1435 assert(!oldGV.hasAvailableExternallyLinkage() &&
1436 "available_externally typeinfos not yet implemented");
1438 oldGV);
1439 }
1440
1441 // Check if there is already an external RTTI descriptor for this type.
1442 if (isStandardLibraryRttiDescriptor(ty) ||
1443 shouldUseExternalRttiDescriptor(cgm, ty))
1444 return getAddrOfExternalRTTIDescriptor(loc, ty);
1445
1446 // Emit the standard library with external linkage.
1447 cir::GlobalLinkageKind linkage = getTypeInfoLinkage(cgm, ty);
1448
1449 // Give the type_info object and name the formal visibility of the
1450 // type itself.
1453
1454 mlir::SymbolTable::Visibility symVisibility;
1455 if (cir::isLocalLinkage(linkage))
1456 // If the linkage is local, only default visibility makes sense.
1457 symVisibility = mlir::SymbolTable::Visibility::Public;
1458 else if (cxxABI.classifyRTTIUniqueness(ty, linkage) ==
1459 CIRGenItaniumCXXABI::RUK_NonUniqueHidden) {
1460 cgm.errorNYI(
1461 "buildTypeInfo: classifyRTTIUniqueness == RUK_NonUniqueHidden");
1462 symVisibility = CIRGenModule::getMLIRVisibility(ty->getVisibility());
1463 } else
1464 symVisibility = CIRGenModule::getMLIRVisibility(ty->getVisibility());
1465
1466 return buildTypeInfo(loc, ty, linkage, symVisibility);
1467}
1468
1469mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(
1470 mlir::Location loc, QualType ty, cir::GlobalLinkageKind linkage,
1471 mlir::SymbolTable::Visibility visibility) {
1472 CIRGenBuilderTy &builder = cgm.getBuilder();
1473
1475
1476 // Add the vtable pointer.
1477 buildVTablePointer(loc, cast<Type>(ty));
1478
1479 // And the name.
1480 cir::GlobalOp typeName = getAddrOfTypeName(loc, ty, linkage);
1481 mlir::Attribute typeNameField;
1482
1483 // If we're supposed to demote the visibility, be sure to set a flag
1484 // to use a string comparison for type_info comparisons.
1485 CIRGenItaniumCXXABI::RTTIUniquenessKind rttiUniqueness =
1486 cxxABI.classifyRTTIUniqueness(ty, linkage);
1487 if (rttiUniqueness != CIRGenItaniumCXXABI::RUK_Unique) {
1488 // The flag is the sign bit, which on ARM64 is defined to be clear
1489 // for global pointers. This is very ARM64-specific.
1490 cgm.errorNYI(
1491 "buildTypeInfo: rttiUniqueness != CIRGenItaniumCXXABI::RUK_Unique");
1492 } else {
1493 typeNameField =
1494 builder.getGlobalViewAttr(builder.getUInt8PtrTy(), typeName);
1495 }
1496
1497 fields.push_back(typeNameField);
1498
1499 switch (ty->getTypeClass()) {
1500#define TYPE(Class, Base)
1501#define ABSTRACT_TYPE(Class, Base)
1502#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
1503#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
1504#define DEPENDENT_TYPE(Class, Base) case Type::Class:
1505#include "clang/AST/TypeNodes.inc"
1506 llvm_unreachable("Non-canonical and dependent types shouldn't get here");
1507
1508 // GCC treats vector types as fundamental types.
1509 case Type::Builtin:
1510 case Type::Vector:
1511 case Type::ExtVector:
1512 case Type::ConstantMatrix:
1513 case Type::Complex:
1514 case Type::BlockPointer:
1515 // Itanium C++ ABI 2.9.5p4:
1516 // abi::__fundamental_type_info adds no data members to std::type_info.
1517 break;
1518
1519 case Type::LValueReference:
1520 case Type::RValueReference:
1521 llvm_unreachable("References shouldn't get here");
1522
1523 case Type::Auto:
1524 case Type::DeducedTemplateSpecialization:
1525 llvm_unreachable("Undeduced type shouldn't get here");
1526
1527 case Type::Pipe:
1528 break;
1529
1530 case Type::BitInt:
1531 break;
1532
1533 case Type::OverflowBehavior:
1534 break;
1535
1536 case Type::ConstantArray:
1537 case Type::IncompleteArray:
1538 case Type::VariableArray:
1539 case Type::ArrayParameter:
1540 // Itanium C++ ABI 2.9.5p5:
1541 // abi::__array_type_info adds no data members to std::type_info.
1542 break;
1543
1544 case Type::FunctionNoProto:
1545 case Type::FunctionProto:
1546 // Itanium C++ ABI 2.9.5p5:
1547 // abi::__function_type_info adds no data members to std::type_info.
1548 break;
1549
1550 case Type::Enum:
1551 // Itanium C++ ABI 2.9.5p5:
1552 // abi::__enum_type_info adds no data members to std::type_info.
1553 break;
1554
1555 case Type::Record: {
1556 const auto *rd = cast<CXXRecordDecl>(cast<RecordType>(ty)->getDecl())
1557 ->getDefinitionOrSelf();
1558 if (!rd->hasDefinition() || !rd->getNumBases()) {
1559 // We don't need to emit any fields.
1560 break;
1561 }
1562
1563 if (canUseSingleInheritance(rd)) {
1564 buildSIClassTypeInfo(loc, rd);
1565 } else {
1566 buildVMIClassTypeInfo(loc, rd);
1567 }
1568
1569 break;
1570 }
1571
1572 case Type::ObjCObject:
1573 case Type::ObjCInterface:
1574 cgm.errorNYI("buildTypeInfo: ObjCObject & ObjCInterface");
1575 break;
1576
1577 case Type::ObjCObjectPointer:
1578 cgm.errorNYI("buildTypeInfo: ObjCObjectPointer");
1579 break;
1580
1581 case Type::Pointer:
1582 // We need to get the type info for the pointee type.
1583 buildPointerTypeInfo(loc, cast<PointerType>(ty)->getPointeeType());
1584 break;
1585
1586 case Type::MemberPointer:
1587 buildPointerToMemberTypeInfo(loc, cast<MemberPointerType>(ty));
1588 break;
1589
1590 case Type::Atomic:
1591 // No fields, at least for the moment.
1592 break;
1593
1594 case Type::HLSLAttributedResource:
1595 case Type::HLSLInlineSpirv:
1596 llvm_unreachable("HLSL doesn't support RTTI");
1597 }
1598
1600 cir::TypeInfoAttr init = builder.getTypeInfo(builder.getArrayAttr(fields));
1601
1602 SmallString<256> name;
1603 llvm::raw_svector_ostream out(name);
1605
1606 // Create new global and search for an existing global.
1607 auto oldGV = dyn_cast_or_null<cir::GlobalOp>(
1608 mlir::SymbolTable::lookupSymbolIn(cgm.getModule(), name));
1609
1610 cir::GlobalOp gv =
1611 CIRGenModule::createGlobalOp(cgm, loc, name, init.getType(),
1612 /*isConstant=*/true);
1613
1614 // Export the typeinfo in the same circumstances as the vtable is
1615 // exported.
1616 if (cgm.getTarget().hasPS4DLLImportExport()) {
1617 cgm.errorNYI("buildTypeInfo: target hasPS4DLLImportExport");
1618 return {};
1619 }
1620
1621 // If there's already an old global variable, replace it with the new one.
1622 if (oldGV) {
1623 // Replace occurrences of the old variable if needed.
1624 gv.setName(oldGV.getName());
1625 if (!oldGV->use_empty()) {
1626 cgm.errorNYI("buildTypeInfo: old GV !use_empty");
1627 return {};
1628 }
1629 oldGV->erase();
1630 }
1631
1632 if (cgm.supportsCOMDAT() && cir::isWeakForLinker(gv.getLinkage())) {
1634 cgm.errorNYI("buildTypeInfo: supportsCOMDAT & isWeakForLinker");
1635 return {};
1636 }
1637
1638 CharUnits align = cgm.getASTContext().toCharUnitsFromBits(
1639 cgm.getTarget().getPointerAlign(LangAS::Default));
1640 gv.setAlignmentAttr(cgm.getSize(align));
1641
1642 // The Itanium ABI specifies that type_info objects must be globally
1643 // unique, with one exception: if the type is an incomplete class
1644 // type or a (possibly indirect) pointer to one. That exception
1645 // affects the general case of comparing type_info objects produced
1646 // by the typeid operator, which is why the comparison operators on
1647 // std::type_info generally use the type_info name pointers instead
1648 // of the object addresses. However, the language's built-in uses
1649 // of RTTI generally require class types to be complete, even when
1650 // manipulating pointers to those class types. This allows the
1651 // implementation of dynamic_cast to rely on address equality tests,
1652 // which is much faster.
1653
1654 // All of this is to say that it's important that both the type_info
1655 // object and the type_info name be uniqued when weakly emitted.
1656
1657 mlir::SymbolTable::setSymbolVisibility(typeName, visibility);
1661
1662 mlir::SymbolTable::setSymbolVisibility(gv, visibility);
1666
1668 return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), gv);
1669}
1670
1671bool CIRGenItaniumCXXABI::shouldTypeidBeNullChecked(QualType srcTy) {
1672 return true;
1673}
1674
1675void CIRGenItaniumCXXABI::emitBadTypeidCall(CIRGenFunction &cgf,
1676 mlir::Location loc) {
1677 // void __cxa_bad_typeid();
1678 cir::FuncType fnTy =
1679 cgf.getBuilder().getFuncType({}, cgf.getBuilder().getVoidTy());
1680 mlir::NamedAttrList attrs;
1681 attrs.set(cir::CIRDialect::getNoReturnAttrName(),
1682 mlir::UnitAttr::get(&cgf.cgm.getMLIRContext()));
1683
1684 cgf.emitRuntimeCall(
1685 loc, cgf.cgm.createRuntimeFunction(fnTy, "__cxa_bad_typeid", attrs), {},
1686 attrs);
1687 cir::UnreachableOp::create(cgf.getBuilder(), loc);
1688}
1689
1690mlir::Value CIRGenItaniumCXXABI::emitTypeid(CIRGenFunction &cgf, QualType srcTy,
1691 Address thisPtr,
1692 mlir::Type typeInfoPtrTy) {
1693 auto *classDecl = srcTy->castAsCXXRecordDecl();
1694 mlir::Location loc = cgm.getLoc(classDecl->getSourceRange());
1695 mlir::Value vptr = cgf.getVTablePtr(loc, thisPtr, classDecl);
1696 mlir::Value vtbl;
1697
1698 // TODO(cir): In classic codegen relative layouts cause us to do a
1699 // 'load_relative' of -4 here. We probably don't want to reprensent this in
1700 // CIR at all, but we should have the NYI here since this could be
1701 // meaningful/notable for implementation of relative layout in the future.
1702 if (cgm.getLangOpts().RelativeCXXABIVTables)
1703 cgm.errorNYI("buildVTablePointer: isRelativeLayout");
1704 else
1705 vtbl = cir::VTableGetTypeInfoOp::create(
1706 cgf.getBuilder(), loc, cgf.getBuilder().getPointerTo(typeInfoPtrTy),
1707 vptr);
1708
1709 return cgf.getBuilder().createAlignedLoad(loc, typeInfoPtrTy, vtbl,
1710 cgf.getPointerAlign());
1711}
1712
1713mlir::Attribute CIRGenItaniumCXXABI::getAddrOfRTTIDescriptor(mlir::Location loc,
1714 QualType ty) {
1715 return CIRGenItaniumRTTIBuilder(*this, cgm).buildTypeInfo(loc, ty);
1716}
1717
1718/// What sort of uniqueness rules should we use for the RTTI for the
1719/// given type?
1720CIRGenItaniumCXXABI::RTTIUniquenessKind
1721CIRGenItaniumCXXABI::classifyRTTIUniqueness(
1722 QualType canTy, cir::GlobalLinkageKind linkage) const {
1723 if (shouldRTTIBeUnique())
1724 return RUK_Unique;
1725
1726 // It's only necessary for linkonce_odr or weak_odr linkage.
1727 if (linkage != cir::GlobalLinkageKind::LinkOnceODRLinkage &&
1728 linkage != cir::GlobalLinkageKind::WeakODRLinkage)
1729 return RUK_Unique;
1730
1731 // It's only necessary with default visibility.
1732 if (canTy->getVisibility() != DefaultVisibility)
1733 return RUK_Unique;
1734
1735 // If we're not required to publish this symbol, hide it.
1736 if (linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage)
1737 return RUK_NonUniqueHidden;
1738
1739 // If we're required to publish this symbol, as we might be under an
1740 // explicit instantiation, leave it with default visibility but
1741 // enable string-comparisons.
1742 assert(linkage == cir::GlobalLinkageKind::WeakODRLinkage);
1743 return RUK_NonUniqueVisible;
1744}
1745
1746void CIRGenItaniumCXXABI::emitDestructorCall(
1747 CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,
1748 bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) {
1749 GlobalDecl gd(dd, type);
1750 mlir::Value vtt =
1751 getCXXDestructorImplicitParam(cgf, dd, type, forVirtualBase, delegating);
1752 ASTContext &astContext = cgm.getASTContext();
1753 QualType vttTy = astContext.getPointerType(astContext.VoidPtrTy);
1755 CIRGenCallee callee =
1757
1758 cgf.emitCXXDestructorCall(gd, callee, thisAddr.getPointer(), thisTy, vtt,
1759 vttTy, nullptr);
1760}
1761
1762void CIRGenItaniumCXXABI::registerGlobalDtor(const VarDecl *vd,
1763 cir::FuncOp dtor,
1764 mlir::Value addr) {
1765 if (vd->isNoDestroy(cgm.getASTContext()))
1766 return;
1767
1768 if (vd->getTLSKind()) {
1769 cgm.errorNYI(vd->getSourceRange(), "registerGlobalDtor: TLS");
1770 return;
1771 }
1772
1773 // HLSL doesn't support atexit.
1774 if (cgm.getLangOpts().HLSL) {
1775 cgm.errorNYI(vd->getSourceRange(), "registerGlobalDtor: HLSL");
1776 return;
1777 }
1778
1779 // The default behavior is to use atexit. This is handled in lowering
1780 // prepare. Nothing to be done for CIR here.
1781}
1782
1783mlir::Value CIRGenItaniumCXXABI::getCXXDestructorImplicitParam(
1784 CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,
1785 bool forVirtualBase, bool delegating) {
1786 GlobalDecl gd(dd, type);
1787 return cgf.getVTTParameter(gd, forVirtualBase, delegating);
1788}
1789
1790// The idea here is creating a separate block for the throw with an
1791// `UnreachableOp` as the terminator. So, we branch from the current block
1792// to the throw block and create a block for the remaining operations.
1793static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc,
1794 mlir::Value exceptionPtr = {},
1795 mlir::FlatSymbolRefAttr typeInfo = {},
1796 mlir::FlatSymbolRefAttr dtor = {}) {
1797 mlir::Block *currentBlock = builder.getInsertionBlock();
1798 mlir::Region *region = currentBlock->getParent();
1799
1800 if (currentBlock->empty()) {
1801 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
1802 cir::UnreachableOp::create(builder, loc);
1803 } else {
1804 mlir::Block *throwBlock = builder.createBlock(region);
1805
1806 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
1807 cir::UnreachableOp::create(builder, loc);
1808
1809 builder.setInsertionPointToEnd(currentBlock);
1810 cir::BrOp::create(builder, loc, throwBlock);
1811 }
1812
1813 (void)builder.createBlock(region);
1814}
1815
1816void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &cgf, bool isNoReturn) {
1817 // void __cxa_rethrow();
1818 if (isNoReturn) {
1819 CIRGenBuilderTy &builder = cgf.getBuilder();
1820 assert(cgf.currSrcLoc && "expected source location");
1821 mlir::Location loc = *cgf.currSrcLoc;
1822 insertThrowAndSplit(builder, loc);
1823 } else {
1824 cgm.errorNYI("emitRethrow with isNoReturn false");
1825 }
1826}
1827
1828void CIRGenItaniumCXXABI::emitThrow(CIRGenFunction &cgf,
1829 const CXXThrowExpr *e) {
1830 // This differs a bit from LLVM codegen, CIR has native operations for some
1831 // cxa functions, and defers allocation size computation, always pass the dtor
1832 // symbol, etc. CIRGen also does not use getAllocateExceptionFn / getThrowFn.
1833
1834 // Now allocate the exception object.
1835 CIRGenBuilderTy &builder = cgf.getBuilder();
1836 QualType clangThrowType = e->getSubExpr()->getType();
1837 cir::PointerType throwTy =
1838 builder.getPointerTo(cgf.convertType(clangThrowType));
1839 uint64_t typeSize =
1840 cgf.getContext().getTypeSizeInChars(clangThrowType).getQuantity();
1841 mlir::Location subExprLoc = cgf.getLoc(e->getSubExpr()->getSourceRange());
1842
1843 // Defer computing allocation size to some later lowering pass.
1844 mlir::TypedValue<cir::PointerType> exceptionPtr =
1845 cir::AllocExceptionOp::create(builder, subExprLoc, throwTy,
1846 builder.getI64IntegerAttr(typeSize))
1847 .getAddr();
1848
1849 // Build expression and store its result into exceptionPtr.
1850 CharUnits exnAlign = cgf.getContext().getExnObjectAlignment();
1851 cgf.emitAnyExprToExn(e->getSubExpr(), Address(exceptionPtr, exnAlign));
1852
1853 // Get the RTTI symbol address.
1854 auto typeInfo = mlir::cast<cir::GlobalViewAttr>(
1855 cgm.getAddrOfRTTIDescriptor(subExprLoc, clangThrowType,
1856 /*forEH=*/true));
1857 assert(!typeInfo.getIndices() && "expected no indirection");
1858
1859 // The address of the destructor.
1860 //
1861 // Note: LLVM codegen already optimizes out the dtor if the
1862 // type is a record with trivial dtor (by passing down a
1863 // null dtor). In CIR, we forward this info and allow for
1864 // Lowering pass to skip passing the trivial function.
1865 //
1866 const auto *cxxrd = clangThrowType->getAsCXXRecordDecl();
1867 mlir::FlatSymbolRefAttr dtor{};
1868 if (cxxrd && !cxxrd->hasTrivialDestructor()) {
1869 // __cxa_throw is declared to take its destructor as void (*)(void *). We
1870 // must match that if function pointers can be authenticated with a
1871 // discriminator based on their type.
1873 CXXDestructorDecl *dtorD = cxxrd->getDestructor();
1874 dtor = mlir::FlatSymbolRefAttr::get(
1875 cgm.getAddrOfCXXStructor(GlobalDecl(dtorD, Dtor_Complete))
1876 .getSymNameAttr());
1877 }
1878
1879 // Now throw the exception.
1880 mlir::Location loc = cgf.getLoc(e->getSourceRange());
1881 insertThrowAndSplit(builder, loc, exceptionPtr, typeInfo.getSymbol(), dtor);
1882}
1883
1885 switch (cgm.getASTContext().getCXXABIKind()) {
1886 case TargetCXXABI::GenericItanium:
1887 case TargetCXXABI::GenericAArch64:
1888 return new CIRGenItaniumCXXABI(cgm);
1889
1890 case TargetCXXABI::AppleARM64:
1891 // The general Itanium ABI will do until we implement something that
1892 // requires special handling.
1894 return new CIRGenItaniumCXXABI(cgm);
1895
1896 default:
1897 llvm_unreachable("bad or NYI ABI kind");
1898 }
1899}
1900
1901cir::GlobalOp CIRGenItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *rd,
1902 CharUnits vptrOffset) {
1903 assert(vptrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");
1904 cir::GlobalOp &vtable = vtables[rd];
1905 if (vtable)
1906 return vtable;
1907
1908 // Queue up this vtable for possible deferred emission.
1909 cgm.addDeferredVTable(rd);
1910
1911 SmallString<256> name;
1912 llvm::raw_svector_ostream out(name);
1913 getMangleContext().mangleCXXVTable(rd, out);
1914
1915 const VTableLayout &vtLayout =
1917 mlir::Type vtableType = cgm.getVTables().getVTableType(vtLayout);
1918
1919 // Use pointer alignment for the vtable. Otherwise we would align them based
1920 // on the size of the initializer which doesn't make sense as only single
1921 // values are read.
1922 unsigned ptrAlign = cgm.getLangOpts().RelativeCXXABIVTables
1923 ? 32
1925
1927 cgm.getLoc(rd->getSourceRange()), name, vtableType,
1928 cir::GlobalLinkageKind::ExternalLinkage,
1929 cgm.getASTContext().toCharUnitsFromBits(ptrAlign));
1930 // LLVM codegen handles unnamedAddr
1932
1933 // In MS C++ if you have a class with virtual functions in which you are using
1934 // selective member import/export, then all virtual functions must be exported
1935 // unless they are inline, otherwise a link error will result. To match this
1936 // behavior, for such classes, we dllimport the vtable if it is defined
1937 // externally and all the non-inline virtual methods are marked dllimport, and
1938 // we dllexport the vtable if it is defined in this TU and all the non-inline
1939 // virtual methods are marked dllexport.
1940 if (cgm.getTarget().hasPS4DLLImportExport())
1941 cgm.errorNYI(rd->getSourceRange(),
1942 "getAddrOfVTable: PS4 DLL import/export");
1943
1944 cgm.setGVProperties(vtable, rd);
1945 return vtable;
1946}
1947
1948CIRGenCallee CIRGenItaniumCXXABI::getVirtualFunctionPointer(
1949 CIRGenFunction &cgf, clang::GlobalDecl gd, Address thisAddr, mlir::Type ty,
1950 SourceLocation srcLoc) {
1951 CIRGenBuilderTy &builder = cgm.getBuilder();
1952 mlir::Location loc = cgf.getLoc(srcLoc);
1953 cir::PointerType tyPtr = builder.getPointerTo(ty);
1954 auto *methodDecl = cast<CXXMethodDecl>(gd.getDecl());
1955 mlir::Value vtable = cgf.getVTablePtr(loc, thisAddr, methodDecl->getParent());
1956
1957 uint64_t vtableIndex = cgm.getItaniumVTableContext().getMethodVTableIndex(gd);
1958 mlir::Value vfunc{};
1959 if (cgf.shouldEmitVTableTypeCheckedLoad(methodDecl->getParent())) {
1960 cgm.errorNYI(loc, "getVirtualFunctionPointer: emitVTableTypeCheckedLoad");
1961 } else {
1963
1964 mlir::Value vfuncLoad;
1965 if (cgm.getLangOpts().RelativeCXXABIVTables) {
1967 cgm.errorNYI(loc, "getVirtualFunctionPointer: isRelativeLayout");
1968 } else {
1969 auto vtableSlotPtr = cir::VTableGetVirtualFnAddrOp::create(
1970 builder, loc, builder.getPointerTo(tyPtr), vtable, vtableIndex);
1971 vfuncLoad = builder.createAlignedLoad(loc, tyPtr, vtableSlotPtr,
1972 cgf.getPointerAlign());
1973 }
1974
1975 // Add !invariant.load md to virtual function load to indicate that
1976 // function didn't change inside vtable.
1977 // It's safe to add it without -fstrict-vtable-pointers, but it would not
1978 // help in devirtualization because it will only matter if we will have 2
1979 // the same virtual function loads from the same vtable load, which won't
1980 // happen without enabled devirtualization with -fstrict-vtable-pointers.
1981 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
1982 cgm.getCodeGenOpts().StrictVTablePointers) {
1983 cgm.errorNYI(loc, "getVirtualFunctionPointer: strictVTablePointers");
1984 }
1985 vfunc = vfuncLoad;
1986 }
1987
1988 CIRGenCallee callee(gd, vfunc.getDefiningOp());
1989 return callee;
1990}
1991
1992mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
1993 CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
1994 const CXXRecordDecl *nearestVBase) {
1995 assert((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&
1996 needsVTTParameter(cgf.curGD) && "This class doesn't have VTT");
1997
1998 // Get the secondary vpointer index.
1999 uint64_t virtualPointerIndex =
2000 cgm.getVTables().getSecondaryVirtualPointerIndex(vtableClass, base);
2001
2002 /// Load the VTT.
2003 mlir::Value vttPtr = cgf.loadCXXVTT();
2004 mlir::Location loc = cgf.getLoc(vtableClass->getSourceRange());
2005 // Calculate the address point from the VTT, and the offset may be zero.
2006 vttPtr = cgf.getBuilder().createVTTAddrPoint(loc, vttPtr.getType(), vttPtr,
2007 virtualPointerIndex);
2008 // And load the address point from the VTT.
2009 auto vptrType = cir::VPtrType::get(cgf.getBuilder().getContext());
2010 return cgf.getBuilder().createAlignedLoad(loc, vptrType, vttPtr,
2011 cgf.getPointerAlign());
2012}
2013
2014mlir::Value
2015CIRGenItaniumCXXABI::getVTableAddressPoint(BaseSubobject base,
2016 const CXXRecordDecl *vtableClass) {
2017 cir::GlobalOp vtable = getAddrOfVTable(vtableClass, CharUnits());
2018
2019 // Find the appropriate vtable within the vtable group, and the address point
2020 // within that vtable.
2021 VTableLayout::AddressPointLocation addressPoint =
2023 .getVTableLayout(vtableClass)
2024 .getAddressPoint(base);
2025
2026 mlir::OpBuilder &builder = cgm.getBuilder();
2027 auto vtablePtrTy = cir::VPtrType::get(builder.getContext());
2028
2029 return cir::VTableAddrPointOp::create(
2030 builder, cgm.getLoc(vtableClass->getSourceRange()), vtablePtrTy,
2031 mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()),
2032 cir::AddressPointAttr::get(cgm.getBuilder().getContext(),
2033 addressPoint.VTableIndex,
2034 addressPoint.AddressPointIndex));
2035}
2036
2037mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructor(
2038 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,
2039 clang::BaseSubobject base, const clang::CXXRecordDecl *nearestVBase) {
2040
2041 if ((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&
2042 needsVTTParameter(cgf.curGD)) {
2043 return getVTableAddressPointInStructorWithVTT(cgf, vtableClass, base,
2044 nearestVBase);
2045 }
2046 return getVTableAddressPoint(base, vtableClass);
2047}
2048
2049bool CIRGenItaniumCXXABI::isVirtualOffsetNeededForVTableField(
2050 CIRGenFunction &cgf, CIRGenFunction::VPtr vptr) {
2051 if (vptr.nearestVBase == nullptr)
2052 return false;
2053 return needsVTTParameter(cgf.curGD);
2054}
2055
2056mlir::Value CIRGenItaniumCXXABI::getVirtualBaseClassOffset(
2057 mlir::Location loc, CIRGenFunction &cgf, Address thisAddr,
2058 const CXXRecordDecl *classDecl, const CXXRecordDecl *baseClassDecl) {
2059 CIRGenBuilderTy &builder = cgf.getBuilder();
2060 mlir::Value vtablePtr = cgf.getVTablePtr(loc, thisAddr, classDecl);
2061 mlir::Value vtableBytePtr = builder.createBitcast(vtablePtr, cgm.uInt8PtrTy);
2062 CharUnits vbaseOffsetOffset =
2064 baseClassDecl);
2065 mlir::Value offsetVal =
2066 builder.getSInt64(vbaseOffsetOffset.getQuantity(), loc);
2067 auto vbaseOffsetPtr = cir::PtrStrideOp::create(builder, loc, cgm.uInt8PtrTy,
2068 vtableBytePtr, offsetVal);
2069
2070 mlir::Value vbaseOffset;
2071 if (cgm.getLangOpts().RelativeCXXABIVTables) {
2073 cgm.errorNYI(loc, "getVirtualBaseClassOffset: relative layout");
2074 } else {
2075 mlir::Value offsetPtr = builder.createBitcast(
2076 vbaseOffsetPtr, builder.getPointerTo(cgm.ptrDiffTy));
2077 vbaseOffset = builder.createLoad(
2078 loc, Address(offsetPtr, cgm.ptrDiffTy, cgf.getPointerAlign()));
2079 }
2080 return vbaseOffset;
2081}
2082
2083static cir::FuncOp getBadCastFn(CIRGenFunction &cgf) {
2084 // Prototype: void __cxa_bad_cast();
2085
2086 // TODO(cir): set the calling convention of the runtime function.
2088
2089 cir::FuncType fnTy =
2090 cgf.getBuilder().getFuncType({}, cgf.getBuilder().getVoidTy());
2091 return cgf.cgm.createRuntimeFunction(fnTy, "__cxa_bad_cast");
2092}
2093
2094static void emitCallToBadCast(CIRGenFunction &cgf, mlir::Location loc) {
2095 // TODO(cir): set the calling convention to the runtime function.
2097
2098 cgf.emitRuntimeCall(loc, getBadCastFn(cgf));
2099 cir::UnreachableOp::create(cgf.getBuilder(), loc);
2100 cgf.getBuilder().clearInsertionPoint();
2101}
2102
2103void CIRGenItaniumCXXABI::emitBadCastCall(CIRGenFunction &cgf,
2104 mlir::Location loc) {
2105 emitCallToBadCast(cgf, loc);
2106}
2107
2108// TODO(cir): This could be shared with classic codegen.
2110 const CXXRecordDecl *src,
2111 const CXXRecordDecl *dst) {
2112 CXXBasePaths paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
2113 /*DetectVirtual=*/false);
2114
2115 // If Dst is not derived from Src we can skip the whole computation below and
2116 // return that Src is not a public base of Dst. Record all inheritance paths.
2117 if (!dst->isDerivedFrom(src, paths))
2118 return CharUnits::fromQuantity(-2);
2119
2120 unsigned numPublicPaths = 0;
2121 CharUnits offset;
2122
2123 // Now walk all possible inheritance paths.
2124 for (const CXXBasePath &path : paths) {
2125 if (path.Access != AS_public) // Ignore non-public inheritance.
2126 continue;
2127
2128 ++numPublicPaths;
2129
2130 for (const CXXBasePathElement &pathElement : path) {
2131 // If the path contains a virtual base class we can't give any hint.
2132 // -1: no hint.
2133 if (pathElement.Base->isVirtual())
2134 return CharUnits::fromQuantity(-1);
2135
2136 if (numPublicPaths > 1) // Won't use offsets, skip computation.
2137 continue;
2138
2139 // Accumulate the base class offsets.
2140 const ASTRecordLayout &L =
2141 astContext.getASTRecordLayout(pathElement.Class);
2142 offset += L.getBaseClassOffset(
2143 pathElement.Base->getType()->getAsCXXRecordDecl());
2144 }
2145 }
2146
2147 // -2: Src is not a public base of Dst.
2148 if (numPublicPaths == 0)
2149 return CharUnits::fromQuantity(-2);
2150
2151 // -3: Src is a multiple public base type but never a virtual base type.
2152 if (numPublicPaths > 1)
2153 return CharUnits::fromQuantity(-3);
2154
2155 // Otherwise, the Src type is a unique public nonvirtual base type of Dst.
2156 // Return the offset of Src from the origin of Dst.
2157 return offset;
2158}
2159
2160static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf) {
2161 // Prototype:
2162 // void *__dynamic_cast(const void *sub,
2163 // global_as const abi::__class_type_info *src,
2164 // global_as const abi::__class_type_info *dst,
2165 // std::ptrdiff_t src2dst_offset);
2166
2167 mlir::Type voidPtrTy = cgf.getBuilder().getVoidPtrTy();
2168 mlir::Type rttiPtrTy = cgf.getBuilder().getUInt8PtrTy();
2169 mlir::Type ptrDiffTy = cgf.convertType(cgf.getContext().getPointerDiffType());
2170
2171 // TODO(cir): mark the function as willreturn readonly.
2174
2175 // TODO(cir): set the calling convention of the runtime function.
2177
2178 cir::FuncType FTy = cgf.getBuilder().getFuncType(
2179 {voidPtrTy, rttiPtrTy, rttiPtrTy, ptrDiffTy}, voidPtrTy);
2180 cir::FuncOp fn = cgf.cgm.createRuntimeFunction(FTy, "__dynamic_cast");
2181 fn->setAttr(cir::CIRDialect::getNoThrowAttrName(),
2182 mlir::UnitAttr::get(cgf.getBuilder().getContext()));
2183 return fn;
2184}
2185
2186static Address emitDynamicCastToVoid(CIRGenFunction &cgf, mlir::Location loc,
2187 QualType srcRecordTy, Address src) {
2188 bool vtableUsesRelativeLayout = cgf.cgm.getLangOpts().RelativeCXXABIVTables;
2189 mlir::Value ptr = cgf.getBuilder().createDynCastToVoid(
2190 loc, src.getPointer(), vtableUsesRelativeLayout);
2191 return Address{ptr, src.getAlignment()};
2192}
2193
2194static mlir::Value emitExactDynamicCast(CIRGenItaniumCXXABI &abi,
2195 CIRGenFunction &cgf, mlir::Location loc,
2196 QualType srcRecordTy,
2197 QualType destRecordTy,
2198 cir::PointerType destCIRTy,
2199 bool isRefCast, Address src) {
2200 // Find all the inheritance paths from SrcRecordTy to DestRecordTy.
2201 const CXXRecordDecl *srcDecl = srcRecordTy->getAsCXXRecordDecl();
2202 const CXXRecordDecl *destDecl = destRecordTy->getAsCXXRecordDecl();
2203 CXXBasePaths paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
2204 /*DetectVirtual=*/false);
2205 (void)destDecl->isDerivedFrom(srcDecl, paths);
2206
2207 // Find an offset within `destDecl` where a `srcDecl` instance and its vptr
2208 // might appear.
2209 std::optional<CharUnits> offset;
2210 for (const CXXBasePath &path : paths) {
2211 // dynamic_cast only finds public inheritance paths.
2212 if (path.Access != AS_public)
2213 continue;
2214
2215 CharUnits pathOffset;
2216 for (const CXXBasePathElement &pathElement : path) {
2217 // Find the offset along this inheritance step.
2218 const CXXRecordDecl *base =
2219 pathElement.Base->getType()->getAsCXXRecordDecl();
2220 if (pathElement.Base->isVirtual()) {
2221 // For a virtual base class, we know that the derived class is exactly
2222 // destDecl, so we can use the vbase offset from its layout.
2223 const ASTRecordLayout &layout =
2224 cgf.getContext().getASTRecordLayout(destDecl);
2225 pathOffset = layout.getVBaseClassOffset(base);
2226 } else {
2227 const ASTRecordLayout &layout =
2228 cgf.getContext().getASTRecordLayout(pathElement.Class);
2229 pathOffset += layout.getBaseClassOffset(base);
2230 }
2231 }
2232
2233 if (!offset) {
2234 offset = pathOffset;
2235 } else if (offset != pathOffset) {
2236 // base appears in at least two different places. Find the most-derived
2237 // object and see if it's a DestDecl. Note that the most-derived object
2238 // must be at least as aligned as this base class subobject, and must
2239 // have a vptr at offset 0.
2240 src = emitDynamicCastToVoid(cgf, loc, srcRecordTy, src);
2241 srcDecl = destDecl;
2242 offset = CharUnits::Zero();
2243 break;
2244 }
2245 }
2246
2247 CIRGenBuilderTy &builder = cgf.getBuilder();
2248
2249 if (!offset) {
2250 // If there are no public inheritance paths, the cast always fails.
2251 mlir::Value nullPtrValue = builder.getNullPtr(destCIRTy, loc);
2252 if (isRefCast) {
2253 mlir::Region *currentRegion = builder.getBlock()->getParent();
2254 emitCallToBadCast(cgf, loc);
2255
2256 // The call to bad_cast will terminate the block. Create a new block to
2257 // hold any follow up code.
2258 builder.createBlock(currentRegion, currentRegion->end());
2259 }
2260
2261 return nullPtrValue;
2262 }
2263
2264 // Compare the vptr against the expected vptr for the destination type at
2265 // this offset. Note that we do not know what type src points to in the case
2266 // where the derived class multiply inherits from the base class so we can't
2267 // use getVTablePtr, so we load the vptr directly instead.
2268
2269 mlir::Value expectedVPtr =
2270 abi.getVTableAddressPoint(BaseSubobject(srcDecl, *offset), destDecl);
2271
2272 // TODO(cir): handle address space here.
2274 mlir::Type vptrTy = expectedVPtr.getType();
2275 mlir::Type vptrPtrTy = builder.getPointerTo(vptrTy);
2276 Address srcVPtrPtr(builder.createBitcast(src.getPointer(), vptrPtrTy),
2277 src.getAlignment());
2278 mlir::Value srcVPtr = builder.createLoad(loc, srcVPtrPtr);
2279
2280 // TODO(cir): decorate SrcVPtr with TBAA info.
2282
2283 mlir::Value success =
2284 builder.createCompare(loc, cir::CmpOpKind::eq, srcVPtr, expectedVPtr);
2285
2286 auto emitCastResult = [&] {
2287 if (offset->isZero())
2288 return builder.createBitcast(src.getPointer(), destCIRTy);
2289
2290 // TODO(cir): handle address space here.
2292 mlir::Type u8PtrTy = builder.getUInt8PtrTy();
2293
2294 mlir::Value strideToApply =
2295 builder.getConstInt(loc, builder.getUInt64Ty(), -offset->getQuantity());
2296 mlir::Value srcU8Ptr = builder.createBitcast(src.getPointer(), u8PtrTy);
2297 mlir::Value resultU8Ptr = cir::PtrStrideOp::create(builder, loc, u8PtrTy,
2298 srcU8Ptr, strideToApply);
2299 return builder.createBitcast(resultU8Ptr, destCIRTy);
2300 };
2301
2302 if (isRefCast) {
2303 mlir::Value failed = builder.createNot(success);
2304 cir::IfOp::create(builder, loc, failed, /*withElseRegion=*/false,
2305 [&](mlir::OpBuilder &, mlir::Location) {
2306 emitCallToBadCast(cgf, loc);
2307 });
2308 return emitCastResult();
2309 }
2310
2311 return cir::TernaryOp::create(
2312 builder, loc, success,
2313 [&](mlir::OpBuilder &, mlir::Location) {
2314 auto result = emitCastResult();
2315 builder.createYield(loc, result);
2316 },
2317 [&](mlir::OpBuilder &, mlir::Location) {
2318 mlir::Value nullPtrValue = builder.getNullPtr(destCIRTy, loc);
2319 builder.createYield(loc, nullPtrValue);
2320 })
2321 .getResult();
2322}
2323
2324static cir::DynamicCastInfoAttr emitDynamicCastInfo(CIRGenFunction &cgf,
2325 mlir::Location loc,
2326 QualType srcRecordTy,
2327 QualType destRecordTy) {
2328 auto srcRtti = mlir::cast<cir::GlobalViewAttr>(
2329 cgf.cgm.getAddrOfRTTIDescriptor(loc, srcRecordTy));
2330 auto destRtti = mlir::cast<cir::GlobalViewAttr>(
2331 cgf.cgm.getAddrOfRTTIDescriptor(loc, destRecordTy));
2332
2333 cir::FuncOp runtimeFuncOp = getItaniumDynamicCastFn(cgf);
2334 cir::FuncOp badCastFuncOp = getBadCastFn(cgf);
2335 auto runtimeFuncRef = mlir::FlatSymbolRefAttr::get(runtimeFuncOp);
2336 auto badCastFuncRef = mlir::FlatSymbolRefAttr::get(badCastFuncOp);
2337
2338 const CXXRecordDecl *srcDecl = srcRecordTy->getAsCXXRecordDecl();
2339 const CXXRecordDecl *destDecl = destRecordTy->getAsCXXRecordDecl();
2340 CharUnits offsetHint = computeOffsetHint(cgf.getContext(), srcDecl, destDecl);
2341
2342 mlir::Type ptrdiffTy = cgf.convertType(cgf.getContext().getPointerDiffType());
2343 auto offsetHintAttr = cir::IntAttr::get(ptrdiffTy, offsetHint.getQuantity());
2344
2345 return cir::DynamicCastInfoAttr::get(srcRtti, destRtti, runtimeFuncRef,
2346 badCastFuncRef, offsetHintAttr);
2347}
2348
2349mlir::Value CIRGenItaniumCXXABI::emitDynamicCast(CIRGenFunction &cgf,
2350 mlir::Location loc,
2351 QualType srcRecordTy,
2352 QualType destRecordTy,
2353 cir::PointerType destCIRTy,
2354 bool isRefCast, Address src) {
2355 bool isCastToVoid = destRecordTy.isNull();
2356 assert((!isCastToVoid || !isRefCast) && "cannot cast to void reference");
2357
2358 if (isCastToVoid)
2359 return emitDynamicCastToVoid(cgf, loc, srcRecordTy, src).getPointer();
2360
2361 // If the destination is effectively final, the cast succeeds if and only
2362 // if the dynamic type of the pointer is exactly the destination type.
2363 if (destRecordTy->getAsCXXRecordDecl()->isEffectivelyFinal() &&
2364 cgf.cgm.getCodeGenOpts().OptimizationLevel > 0) {
2365 CIRGenBuilderTy &builder = cgf.getBuilder();
2366 // If this isn't a reference cast, check the pointer to see if it's null.
2367 if (!isRefCast) {
2368 mlir::Value srcPtrIsNull = builder.createPtrIsNull(src.getPointer());
2369 return cir::TernaryOp::create(
2370 builder, loc, srcPtrIsNull,
2371 [&](mlir::OpBuilder, mlir::Location) {
2372 builder.createYield(
2373 loc, builder.getNullPtr(destCIRTy, loc).getResult());
2374 },
2375 [&](mlir::OpBuilder &, mlir::Location) {
2376 mlir::Value exactCast = emitExactDynamicCast(
2377 *this, cgf, loc, srcRecordTy, destRecordTy, destCIRTy,
2378 isRefCast, src);
2379 builder.createYield(loc, exactCast);
2380 })
2381 .getResult();
2382 }
2383
2384 return emitExactDynamicCast(*this, cgf, loc, srcRecordTy, destRecordTy,
2385 destCIRTy, isRefCast, src);
2386 }
2387
2388 cir::DynamicCastInfoAttr castInfo =
2389 emitDynamicCastInfo(cgf, loc, srcRecordTy, destRecordTy);
2390 return cgf.getBuilder().createDynCast(loc, src.getPointer(), destCIRTy,
2391 isRefCast, castInfo);
2392}
2393
2394cir::MethodAttr
2395CIRGenItaniumCXXABI::buildVirtualMethodAttr(cir::MethodType methodTy,
2396 const CXXMethodDecl *md) {
2397 assert(md->isVirtual() && "only deal with virtual member functions");
2398
2400 uint64_t vtableOffset;
2401 if (cgm.getLangOpts().RelativeCXXABIVTables) {
2402 // Multiply by 4-byte relative offsets.
2403 vtableOffset = index * 4;
2404 } else {
2405 const ASTContext &astContext = cgm.getASTContext();
2406 CharUnits pointerWidth = astContext.toCharUnitsFromBits(
2407 astContext.getTargetInfo().getPointerWidth(LangAS::Default));
2408 vtableOffset = index * pointerWidth.getQuantity();
2409 }
2410
2411 return cir::MethodAttr::get(methodTy, vtableOffset);
2412}
2413/// The Itanium ABI always places an offset to the complete object
2414/// at entry -2 in the vtable.
2415void CIRGenItaniumCXXABI::emitVirtualObjectDelete(
2416 CIRGenFunction &cgf, const CXXDeleteExpr *delExpr, Address ptr,
2417 QualType elementType, const CXXDestructorDecl *dtor) {
2418 bool useGlobalDelete = delExpr->isGlobalDelete();
2419 if (useGlobalDelete) {
2420 cgf.cgm.errorNYI(delExpr->getSourceRange(),
2421 "emitVirtualObjectDelete: global delete");
2422 }
2423
2424 CXXDtorType dtorType = useGlobalDelete ? Dtor_Complete : Dtor_Deleting;
2425 emitVirtualDestructorCall(cgf, dtor, dtorType, ptr, delExpr);
2426}
2427
2428/************************** Array allocation cookies **************************/
2429
2430CharUnits CIRGenItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {
2431 // The array cookie is a size_t; pad that up to the element alignment.
2432 // The cookie is actually right-justified in that space.
2433 return std::max(
2434 cgm.getSizeSize(),
2435 cgm.getASTContext().getPreferredTypeAlignInChars(elementType));
2436}
2437
2438Address CIRGenItaniumCXXABI::initializeArrayCookie(CIRGenFunction &cgf,
2439 Address newPtr,
2440 mlir::Value numElements,
2441 const CXXNewExpr *e,
2442 QualType elementType) {
2443 assert(requiresArrayCookie(e));
2444
2445 // TODO: When sanitizer support is implemented, we'll need to
2446 // get the address space from `newPtr`.
2449
2450 ASTContext &ctx = cgm.getASTContext();
2451 CharUnits sizeSize = cgf.getSizeSize();
2452 mlir::Location loc = cgf.getLoc(e->getSourceRange());
2453
2454 // The size of the cookie.
2455 CharUnits cookieSize =
2456 std::max(sizeSize, ctx.getPreferredTypeAlignInChars(elementType));
2457 assert(cookieSize == getArrayCookieSizeImpl(elementType));
2458
2459 cir::PointerType u8PtrTy = cgf.getBuilder().getUInt8PtrTy();
2460 mlir::Value baseBytePtr =
2461 cgf.getBuilder().createPtrBitcast(newPtr.getPointer(), u8PtrTy);
2462
2463 // Compute an offset to the cookie.
2464 CharUnits cookieOffset = cookieSize - sizeSize;
2465 mlir::Value cookiePtrValue = baseBytePtr;
2466 if (!cookieOffset.isZero()) {
2467 mlir::Value offsetOp = cgf.getBuilder().getSignedInt(
2468 loc, cookieOffset.getQuantity(), /*width=*/32);
2469 cookiePtrValue =
2470 cgf.getBuilder().createPtrStride(loc, cookiePtrValue, offsetOp);
2471 }
2472
2473 CharUnits baseAlignment = newPtr.getAlignment();
2474 CharUnits cookiePtrAlignment = baseAlignment.alignmentAtOffset(cookieOffset);
2475 Address cookiePtr(cookiePtrValue, u8PtrTy, cookiePtrAlignment);
2476
2477 // Write the number of elements into the appropriate slot.
2478 Address numElementsPtr =
2479 cookiePtr.withElementType(cgf.getBuilder(), cgf.sizeTy);
2480 cgf.getBuilder().createStore(loc, numElements, numElementsPtr);
2481
2482 // Finally, compute a pointer to the actual data buffer by skipping
2483 // over the cookie completely.
2484 mlir::Value dataOffset =
2485 cgf.getBuilder().getSignedInt(loc, cookieSize.getQuantity(),
2486 /*width=*/32);
2487 mlir::Value dataPtr =
2488 cgf.getBuilder().createPtrStride(loc, baseBytePtr, dataOffset);
2489 mlir::Value finalPtr =
2490 cgf.getBuilder().createPtrBitcast(dataPtr, newPtr.getElementType());
2491 CharUnits finalAlignment = baseAlignment.alignmentAtOffset(cookieSize);
2492 return Address(finalPtr, newPtr.getElementType(), finalAlignment);
2493}
2494
2495namespace {
2496/// From traditional LLVM, useful info for LLVM lowering support:
2497/// A cleanup to call __cxa_end_catch. In many cases, the caught
2498/// exception type lets us state definitively that the thrown exception
2499/// type does not have a destructor. In particular:
2500/// - Catch-alls tell us nothing, so we have to conservatively
2501/// assume that the thrown exception might have a destructor.
2502/// - Catches by reference behave according to their base types.
2503/// - Catches of non-record types will only trigger for exceptions
2504/// of non-record types, which never have destructors.
2505/// - Catches of record types can trigger for arbitrary subclasses
2506/// of the caught type, so we have to assume the actual thrown
2507/// exception type might have a throwing destructor, even if the
2508/// caught type's destructor is trivial or nothrow.
2509struct CallEndCatch final : EHScopeStack::Cleanup {
2510 CallEndCatch(bool mightThrow, mlir::Value catchToken)
2511 : mightThrow(mightThrow), catchToken(catchToken) {}
2512 bool mightThrow;
2513 mlir::Value catchToken;
2514
2515 void emit(CIRGenFunction &cgf, Flags flags) override {
2516 // Traditional LLVM codegen would emit a call to __cxa_end_catch
2517 // here. For CIR, just let it pass since the cleanup is going
2518 // to be emitted on a later pass when lowering the catch region.
2519 // CGF.EmitRuntimeCallOrTryCall(getEndCatchFn(CGF.CGM));
2520 cir::EndCatchOp::create(cgf.getBuilder(), *cgf.currSrcLoc, catchToken);
2521 cir::YieldOp::create(cgf.getBuilder(), *cgf.currSrcLoc);
2522 }
2523};
2524} // namespace
2525
2526static mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken,
2527 mlir::Type exnPtrTy, bool endMightThrow) {
2528 auto catchTokenTy = cir::CatchTokenType::get(cgf.getBuilder().getContext());
2529 auto beginCatch = cir::BeginCatchOp::create(cgf.getBuilder(),
2530 cgf.getBuilder().getUnknownLoc(),
2531 catchTokenTy, exnPtrTy, ehToken);
2532
2533 cgf.ehStack.pushCleanup<CallEndCatch>(
2535 endMightThrow && !cgf.cgm.getLangOpts().AssumeNothrowExceptionDtor,
2536 beginCatch.getCatchToken());
2537
2538 return beginCatch.getExnPtr();
2539}
2540
2541/// A "special initializer" callback for initializing a catch
2542/// parameter during catch initialization.
2543static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken,
2544 const VarDecl &catchParam, Address paramAddr,
2545 SourceLocation loc) {
2546 CanQualType catchType =
2547 cgf.cgm.getASTContext().getCanonicalType(catchParam.getType());
2548 mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType);
2549
2550 // If we're catching by reference, we can just cast the object
2551 // pointer to the appropriate pointer.
2552 if (isa<ReferenceType>(catchType)) {
2553 QualType caughtType = cast<ReferenceType>(catchType)->getPointeeType();
2554 bool endCatchMightThrow = caughtType->isRecordType();
2555
2556 mlir::Value adjustedExn =
2557 callBeginCatch(cgf, ehToken, cirCatchTy, endCatchMightThrow);
2558
2559 // We have no way to tell the personality function that we're
2560 // catching by reference, so if we're catching a pointer,
2561 // __cxa_begin_catch will actually return that pointer by value.
2562 if (const PointerType *pt = dyn_cast<PointerType>(caughtType)) {
2563 QualType pointeeType = pt->getPointeeType();
2564 // When catching by reference, generally we should just ignore
2565 // this by-value pointer and use the exception object instead.
2566 if (!pointeeType->isRecordType()) {
2567 cgf.cgm.errorNYI(loc,
2568 "initCatchParam: catching a pointer of non-record");
2569 } else {
2570 // Pull the pointer for the reference type off.
2571 mlir::Type ptrTy = cgf.convertTypeForMem(caughtType);
2572
2573 // Create the temporary and write the adjusted pointer into it.
2574 Address exnPtrTmp = cgf.createTempAlloca(
2575 ptrTy, cgf.getPointerAlign(), cgf.getLoc(loc), "exn.byref.tmp");
2576 mlir::Value casted = cgf.getBuilder().createBitcast(adjustedExn, ptrTy);
2577 cgf.getBuilder().createStore(cgf.getLoc(loc), casted, exnPtrTmp);
2578
2579 // Bind the reference to the temporary.
2580 adjustedExn = exnPtrTmp.emitRawPointer();
2581 }
2582 }
2583
2584 mlir::Value exnCast =
2585 cgf.getBuilder().createBitcast(adjustedExn, cirCatchTy);
2586 cgf.getBuilder().createStore(cgf.getLoc(loc), exnCast, paramAddr);
2587 return;
2588 }
2589
2590 // Scalars and complexes.
2591 cir::TypeEvaluationKind tek = cgf.getEvaluationKind(catchType);
2592 if (tek != cir::TEK_Aggregate) {
2593 // Notes for LLVM lowering:
2594 // If the catch type is a pointer type, __cxa_begin_catch returns
2595 // the pointer by value.
2596 if (catchType->hasPointerRepresentation()) {
2597 mlir::Value catchParam =
2598 callBeginCatch(cgf, ehToken, cirCatchTy, /*endMightThrow=*/false);
2599 switch (catchType.getQualifiers().getObjCLifetime()) {
2601 cgf.cgm.errorNYI(loc,
2602 "initCatchParam: PointerRepresentation OCL_Strong");
2603 return;
2604
2607 cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation "
2608 "OCL_ExplicitNone & OCL_Autoreleasing");
2609 return;
2610
2612 cgf.getBuilder().createStore(cgf.getLoc(loc), catchParam, paramAddr);
2613 return;
2614
2616 cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation OCL_Weak");
2617 return;
2618 }
2619
2620 llvm_unreachable("bad ownership qualifier!");
2621 }
2622
2623 // Otherwise, it returns a pointer into the exception object.
2624 mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType);
2625 mlir::Value catchParam =
2626 callBeginCatch(cgf, ehToken, cgf.getBuilder().getPointerTo(cirCatchTy),
2627 /*endMightThrow=*/false);
2628 LValue srcLV = cgf.makeNaturalAlignAddrLValue(catchParam, catchType);
2629 LValue destLV = cgf.makeAddrLValue(paramAddr, catchType);
2630 switch (tek) {
2631 case cir::TEK_Complex: {
2632 mlir::Value load = cgf.emitLoadOfComplex(srcLV, loc);
2633 cgf.emitStoreOfComplex(cgf.getLoc(loc), load, destLV, /*isInit=*/true);
2634 return;
2635 }
2636 case cir::TEK_Scalar: {
2637 mlir::Value exnLoad = cgf.emitLoadOfScalar(srcLV, loc);
2638 cgf.emitStoreOfScalar(exnLoad, destLV, /*isInit=*/true);
2639 return;
2640 }
2641 case cir::TEK_Aggregate:
2642 llvm_unreachable("evaluation kind filtered out!");
2643 }
2644
2645 llvm_unreachable("bad evaluation kind");
2646 }
2647
2648 assert(isa<RecordType>(catchType) && "unexpected catch type!");
2649 auto *catchRD = catchType->getAsCXXRecordDecl();
2650 CharUnits caughtExnAlignment = cgf.cgm.getClassPointerAlignment(catchRD);
2651
2652 // Check for a copy expression. If we don't have a copy expression,
2653 // that means a trivial copy is okay.
2654 const Expr *copyExpr = catchParam.getInit();
2655 if (!copyExpr) {
2656 mlir::Type cirCatchPtrTy = cgf.getBuilder().getPointerTo(cirCatchTy);
2657 mlir::Value rawAdjustedExn =
2658 callBeginCatch(cgf, ehToken, cirCatchPtrTy, /*endMightThrow=*/true);
2659 Address adjustedExn(rawAdjustedExn, cirCatchTy, caughtExnAlignment);
2660 LValue dest = cgf.makeAddrLValue(paramAddr, catchType);
2661 LValue src = cgf.makeAddrLValue(adjustedExn, catchType);
2662 cgf.emitAggregateCopy(dest, src, catchType, AggValueSlot::DoesNotOverlap);
2663 return;
2664 }
2665
2666 cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Aggregate non-trivial copy");
2667}
2668
2669/// Begins a catch statement by initializing the catch variable and
2670/// calling __cxa_begin_catch.
2671void CIRGenItaniumCXXABI::emitBeginCatch(CIRGenFunction &cgf,
2672 const CXXCatchStmt *catchStmt,
2673 mlir::Value ehToken) {
2674 // We have to be very careful with the ordering of cleanups here:
2675 // C++ [except.throw]p4:
2676 // The destruction [of the exception temporary] occurs
2677 // immediately after the destruction of the object declared in
2678 // the exception-declaration in the handler.
2679 //
2680 // So the precise ordering is:
2681 // 1. Construct catch variable.
2682 // 2. __cxa_begin_catch
2683 // 3. Enter __cxa_end_catch cleanup
2684 // 4. Enter dtor cleanup
2685 //
2686 // We do this by using a slightly abnormal initialization process.
2687 // Delegation sequence:
2688 // - ExitCXXTryStmt opens a RunCleanupsScope
2689 // - EmitAutoVarAlloca creates the variable and debug info
2690 // - InitCatchParam initializes the variable from the exception
2691 // - CallBeginCatch calls __cxa_begin_catch
2692 // - CallBeginCatch enters the __cxa_end_catch cleanup
2693 // - EmitAutoVarCleanups enters the variable destructor cleanup
2694 // - EmitCXXTryStmt emits the code for the catch body
2695 // - EmitCXXTryStmt close the RunCleanupsScope
2696
2697 VarDecl *catchParam = catchStmt->getExceptionDecl();
2698 if (!catchParam) {
2699 callBeginCatch(cgf, ehToken, cgf.getBuilder().getVoidPtrTy(),
2700 /*endMightThrow=*/true);
2701 return;
2702 }
2703
2704 auto getCatchParamAllocaIP = [&]() {
2705 cir::CIRBaseBuilderTy::InsertPoint currIns =
2706 cgf.getBuilder().saveInsertionPoint();
2707 mlir::Operation *currParent = currIns.getBlock()->getParentOp();
2708
2709 mlir::Block *insertBlock = nullptr;
2710 if (auto scopeOp = currParent->getParentOfType<cir::ScopeOp>()) {
2711 insertBlock = &scopeOp.getScopeRegion().getBlocks().back();
2712 } else if (auto fnOp = currParent->getParentOfType<cir::FuncOp>()) {
2713 insertBlock = &fnOp.getRegion().getBlocks().back();
2714 } else {
2715 llvm_unreachable("unknown outermost scope-like parent");
2716 }
2717 return cgf.getBuilder().getBestAllocaInsertPoint(insertBlock);
2718 };
2719
2720 // Emit the local. Make sure the alloca's superseed the current scope, since
2721 // these are going to be consumed by `cir.catch`, which is not within the
2722 // current scope.
2723
2724 CIRGenFunction::AutoVarEmission var =
2725 cgf.emitAutoVarAlloca(*catchParam, getCatchParamAllocaIP());
2726 initCatchParam(cgf, ehToken, *catchParam, var.getObjectAddress(cgf),
2727 catchStmt->getBeginLoc());
2728 cgf.emitAutoVarCleanups(var);
2729}
2730
2731bool CIRGenItaniumCXXABI::hasAnyUnusedVirtualInlineFunction(
2732 const CXXRecordDecl *rd) const {
2733 const auto &vtableLayout = cgm.getItaniumVTableContext().getVTableLayout(rd);
2734
2735 for (const auto &vtableComponent : vtableLayout.vtable_components()) {
2736 // Skip empty slot.
2737 if (!vtableComponent.isUsedFunctionPointerKind())
2738 continue;
2739
2740 const CXXMethodDecl *method = vtableComponent.getFunctionDecl();
2741 const FunctionDecl *fd = method->getDefinition();
2742 const bool isInlined =
2743 method->getCanonicalDecl()->isInlined() || (fd && fd->isInlined());
2744 if (!isInlined)
2745 continue;
2746
2747 StringRef name = cgm.getMangledName(
2748 vtableComponent.getGlobalDecl(/*HasVectorDeletingDtors=*/false));
2749 auto entry = dyn_cast_or_null<cir::GlobalOp>(cgm.getGlobalValue(name));
2750 // This checks if virtual inline function has already been emitted.
2751 // Note that it is possible that this inline function would be emitted
2752 // after trying to emit vtable speculatively. Because of this we do
2753 // an extra pass after emitting all deferred vtables to find and emit
2754 // these vtables opportunistically.
2755 if (!entry || entry.isDeclaration())
2756 return true;
2757 }
2758 return false;
2759}
2760
2761bool CIRGenItaniumCXXABI::isVTableHidden(const CXXRecordDecl *rd) const {
2762 const auto &vtableLayout = cgm.getItaniumVTableContext().getVTableLayout(rd);
2763
2764 for (const auto &vtableComponent : vtableLayout.vtable_components()) {
2765 if (vtableComponent.isRTTIKind()) {
2766 const CXXRecordDecl *rttiDecl = vtableComponent.getRTTIDecl();
2767 if (rttiDecl->getVisibility() == Visibility::HiddenVisibility)
2768 return true;
2769 } else if (vtableComponent.isUsedFunctionPointerKind()) {
2770 const CXXMethodDecl *method = vtableComponent.getFunctionDecl();
2771 if (method->getVisibility() == Visibility::HiddenVisibility &&
2772 !method->isDefined())
2773 return true;
2774 }
2775 }
2776 return false;
2777}
2778
2779bool CIRGenItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass(
2780 const CXXRecordDecl *rd) const {
2781 // We don't emit available_externally vtables if we are in -fapple-kext mode
2782 // because kext mode does not permit devirtualization.
2783 if (cgm.getLangOpts().AppleKext)
2784 return false;
2785
2786 // If the vtable is hidden then it is not safe to emit an available_externally
2787 // copy of vtable.
2788 if (isVTableHidden(rd))
2789 return false;
2790
2791 if (cgm.getCodeGenOpts().ForceEmitVTables)
2792 return true;
2793
2794 // A speculative vtable can only be generated if all virtual inline functions
2795 // defined by this class are emitted. The vtable in the final program contains
2796 // for each virtual inline function not used in the current TU a function that
2797 // is equivalent to the unused function. The function in the actual vtable
2798 // does not have to be declared under the same symbol (e.g., a virtual
2799 // destructor that can be substituted with its base class's destructor). Since
2800 // inline functions are emitted lazily and this emissions does not account for
2801 // speculative emission of a vtable, we might generate a speculative vtable
2802 // with references to inline functions that are not emitted under that name.
2803 // This can lead to problems when devirtualizing a call to such a function,
2804 // that result in linking errors. Hence, if there are any unused virtual
2805 // inline function, we cannot emit the speculative vtable.
2806 // FIXME we can still emit a copy of the vtable if we
2807 // can emit definition of the inline functions.
2808 if (hasAnyUnusedVirtualInlineFunction(rd))
2809 return false;
2810
2811 // For a class with virtual bases, we must also be able to speculatively
2812 // emit the VTT, because CodeGen doesn't have separate notions of "can emit
2813 // the vtable" and "can emit the VTT". For a base subobject, this means we
2814 // need to be able to emit non-virtual base vtables.
2815 if (rd->getNumVBases()) {
2816 for (const auto &b : rd->bases()) {
2817 auto *brd = b.getType()->getAsCXXRecordDecl();
2818 assert(brd && "no class for base specifier");
2819 if (b.isVirtual() || !brd->isDynamicClass())
2820 continue;
2821 if (!canSpeculativelyEmitVTableAsBaseClass(brd))
2822 return false;
2823 }
2824 }
2825
2826 return true;
2827}
2828
2829bool CIRGenItaniumCXXABI::canSpeculativelyEmitVTable(
2830 const CXXRecordDecl *rd) const {
2831 if (!canSpeculativelyEmitVTableAsBaseClass(rd))
2832 return false;
2833
2835 return false;
2836
2837 // For a complete-object vtable (or more specifically, for the VTT), we need
2838 // to be able to speculatively emit the vtables of all dynamic virtual bases.
2839 for (const auto &b : rd->vbases()) {
2840 auto *brd = b.getType()->getAsCXXRecordDecl();
2841 assert(brd && "no class for base specifier");
2842 if (!brd->isDynamicClass())
2843 continue;
2844 if (!canSpeculativelyEmitVTableAsBaseClass(brd))
2845 return false;
2846 }
2847
2848 return true;
2849}
2850
2852 Address initialPtr,
2853 const CXXRecordDecl *unadjustedClass,
2854 int64_t nonVirtualAdjustment,
2855 int64_t virtualAdjustment,
2856 bool isReturnAdjustment) {
2857 if (!nonVirtualAdjustment && !virtualAdjustment)
2858 return initialPtr.getPointer();
2859
2860 CIRGenBuilderTy &builder = cgf.getBuilder();
2861 mlir::Location loc = builder.getUnknownLoc();
2862 cir::PointerType i8PtrTy = builder.getUInt8PtrTy();
2863 mlir::Value v = builder.createBitcast(initialPtr.getPointer(), i8PtrTy);
2864
2865 // In a base-to-derived cast, the non-virtual adjustment is applied first.
2866 if (nonVirtualAdjustment && !isReturnAdjustment) {
2867 cir::ConstantOp offsetConst = builder.getSInt64(nonVirtualAdjustment, loc);
2868 v = cir::PtrStrideOp::create(builder, loc, i8PtrTy, v, offsetConst);
2869 }
2870
2871 // Perform the virtual adjustment if we have one.
2872 mlir::Value resultPtr;
2873 if (virtualAdjustment) {
2874 mlir::Value vtablePtr = cgf.getVTablePtr(
2875 loc, Address(v, clang::CharUnits::One()), unadjustedClass);
2876 vtablePtr = builder.createBitcast(vtablePtr, i8PtrTy);
2877
2878 mlir::Value offset;
2879 mlir::Value offsetPtr =
2880 cir::PtrStrideOp::create(builder, loc, i8PtrTy, vtablePtr,
2881 builder.getSInt64(virtualAdjustment, loc));
2882 if (cgf.cgm.getLangOpts().RelativeCXXABIVTables) {
2884 cgf.cgm.errorNYI("virtual adjustment for relative layout vtables");
2885 } else {
2886 offset = builder.createAlignedLoad(loc, cgf.ptrDiffTy, offsetPtr,
2887 cgf.getPointerAlign());
2888 }
2889
2890 resultPtr = cir::PtrStrideOp::create(builder, loc, i8PtrTy, v, offset);
2891 } else {
2892 resultPtr = v;
2893 }
2894
2895 // In a derived-to-base conversion, the non-virtual adjustment is
2896 // applied second.
2897 if (nonVirtualAdjustment && isReturnAdjustment) {
2898 cir::ConstantOp offsetConst = builder.getSInt64(nonVirtualAdjustment, loc);
2899 resultPtr =
2900 cir::PtrStrideOp::create(builder, loc, i8PtrTy, resultPtr, offsetConst);
2901 }
2902
2903 // Cast back to original pointer type.
2904 return builder.createBitcast(resultPtr, initialPtr.getType());
2905}
2906
2907mlir::Value CIRGenItaniumCXXABI::performThisAdjustment(
2908 CIRGenFunction &cgf, Address thisAddr, const CXXRecordDecl *unadjustedClass,
2909 const ThunkInfo &ti) {
2910 return performTypeAdjustment(cgf, thisAddr, unadjustedClass,
2911 ti.This.NonVirtual,
2913 /*isReturnAdjustment=*/false);
2914}
2915
2916mlir::Value CIRGenItaniumCXXABI::performReturnAdjustment(
2917 CIRGenFunction &cgf, Address ret, const CXXRecordDecl *unadjustedClass,
2918 const ReturnAdjustment &ra) {
2919 return performTypeAdjustment(cgf, ret, unadjustedClass, ra.NonVirtual,
2921 /*isReturnAdjustment=*/true);
2922}
2923
2924bool CIRGenItaniumCXXABI::isZeroInitializable(const MemberPointerType *mpt) {
2925 return mpt->isMemberFunctionPointer();
2926}
static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
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 mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken, mlir::Type exnPtrTy, bool endMightThrow)
static Address emitDynamicCastToVoid(CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, Address src)
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 mlir::Value performTypeAdjustment(CIRGenFunction &cgf, Address initialPtr, const CXXRecordDecl *unadjustedClass, int64_t nonVirtualAdjustment, int64_t virtualAdjustment, bool isReturnAdjustment)
static mlir::Value emitExactDynamicCast(CIRGenItaniumCXXABI &abi, CIRGenFunction &cgf, mlir::Location loc, QualType srcRecordTy, QualType destRecordTy, cir::PointerType destCIRTy, bool isRefCast, Address src)
static void emitCallToBadCast(CIRGenFunction &cgf, mlir::Location loc)
static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken, const VarDecl &catchParam, Address paramAddr, SourceLocation loc)
A "special initializer" callback for initializing a catch parameter during catch initialization.
static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf)
static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm, const CXXMethodDecl *md)
static cir::FuncOp getBadCastFn(CIRGenFunction &cgf)
static RValue performReturnAdjustment(CIRGenFunction &cgf, QualType resultType, RValue rv, const ThunkInfo &thunk)
static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type)
Compute the flags for a __pbase_type_info, and remove the corresponding pieces from Type.
Defines the clang::Expr interface and subclasses for C++ expressions.
static QualType getPointeeType(const MemRegion *R)
C Language Family Type Representation.
__device__ __2f16 b
cir::GlobalViewAttr getGlobalViewAttr(cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
mlir::Value createPtrIsNull(mlir::Value ptr)
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride)
static OpBuilder::InsertPoint getBestAllocaInsertPoint(mlir::Block *block)
cir::PointerType getPointerTo(mlir::Type ty)
cir::ConstantOp getNullPtr(mlir::Type ty, mlir::Location loc)
mlir::Value createPtrBitcast(mlir::Value src, mlir::Type newPointeeTy)
mlir::Value getSignedInt(mlir::Location loc, int64_t val, unsigned numBits)
mlir::Value createBitcast(mlir::Value src, mlir::Type newTy)
cir::CmpOp createCompare(mlir::Location loc, cir::CmpOpKind kind, mlir::Value lhs, mlir::Value rhs)
mlir::Value createNot(mlir::Location loc, mlir::Value value)
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
cir::YieldOp createYield(mlir::Location loc, mlir::ValueRange value={})
Create a yield operation.
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:226
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
CanQualType LongTy
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
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:798
const LangOptions & getLangOpts() const
Definition ASTContext.h:952
QualType getFunctionTypeWithExceptionSpec(QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) const
Get a function type and produce the equivalent function type with the specified exception specificati...
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 getPreferredTypeAlignInChars(QualType T) const
Return the PreferredAlignment of a (complete) type T, in characters.
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:917
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
CanQualType getCanonicalTagType(const TagDecl *TD) const
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.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - 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:3262
mlir::Value getPointer() const
Definition Address.h:96
mlir::Type getElementType() const
Definition Address.h:123
clang::CharUnits getAlignment() const
Definition Address.h:136
mlir::Type getType() const
Definition Address.h:115
mlir::Value emitRawPointer() const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition Address.h:110
cir::TypeInfoAttr getTypeInfo(mlir::ArrayAttr fieldsAttr)
cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc)
cir::PointerType getUInt8PtrTy()
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 createDynCastToVoid(mlir::Location loc, mlir::Value src, bool vtableUseRelativeLayout)
mlir::Value createDynCast(mlir::Location loc, mlir::Value src, cir::PointerType destType, bool isRefCast, cir::DynamicCastInfoAttr info)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
mlir::Attribute getString(llvm::StringRef str, mlir::Type eltTy, std::optional< size_t > size, bool ensureNullTerm=true)
Get a cir::ConstArrayAttr for a string literal.
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal)
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:92
static CIRGenCallee forVirtual(const clang::CallExpr *ce, clang::GlobalDecl md, Address addr, cir::FuncType fTy)
Definition CIRGenCall.h:154
mlir::Type convertType(clang::QualType t)
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d, mlir::OpBuilder::InsertPoint ip={})
cir::AllocaOp createTempAlloca(mlir::Type ty, mlir::Location loc, const Twine &name="tmp", mlir::Value arraySize=nullptr, bool insertIntoFnEntryBlock=false)
This creates an alloca and inserts it into the entry block if ArraySize is nullptr,...
const clang::Decl * curFuncDecl
Address getAddrOfLocalVar(const clang::VarDecl *vd)
Return the address of a local variable.
void emitAnyExprToExn(const Expr *e, Address addr)
void emitAggregateCopy(LValue dest, LValue src, QualType eltTy, AggValueSlot::Overlap_t mayOverlap, bool isVolatile=false)
Emit an aggregate copy.
LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)
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.
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
mlir::Type convertTypeForMem(QualType t)
mlir::Value emitLoadOfComplex(LValue src, SourceLocation loc)
Load a complex number from the specified l-value.
void emitStoreOfScalar(mlir::Value value, Address addr, bool isVolatile, clang::QualType ty, LValueBaseInfo baseInfo, bool isInit=false, bool isNontemporal=false)
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.
void emitStoreOfComplex(mlir::Location loc, mlir::Value v, LValue dest, bool isInit)
EmitStoreOfComplex - Store a complex number into the specified l-value.
bool shouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *rd)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
CIRGenBuilderTy & getBuilder()
mlir::Value emitRuntimeCall(mlir::Location loc, cir::FuncOp callee, llvm::ArrayRef< mlir::Value > args={}, mlir::NamedAttrList attrs={})
mlir::Value emitLoadOfScalar(LValue lvalue, SourceLocation loc)
EmitLoadOfScalar - Load a scalar value from an address, taking care to appropriately convert from the...
LValue makeAddrLValue(Address addr, QualType ty, AlignmentSource source=AlignmentSource::Type)
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
void emitAutoVarCleanups(const AutoVarEmission &emission)
This class organizes the cross-function state that is used while generating CIR code.
static cir::GlobalOp createGlobalOp(CIRGenModule &cgm, mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::ptr::MemorySpaceAttrInterface addrSpace={}, mlir::Operation *insertPoint=nullptr)
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)
void addReplacement(llvm::StringRef name, mlir::Operation *op)
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.
clang::CharUnits getClassPointerAlignment(const clang::CXXRecordDecl *rd)
Return the best known alignment for an unknown pointer to a particular class.
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.
cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::NamedAttrList extraAttrs={}, bool isLocal=false, bool assumeConvergent=false)
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
void addDeferredVTable(const CXXRecordDecl *rd)
cir::FuncOp codegenCXXStructor(clang::GlobalDecl gd)
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::MLIRContext & getMLIRContext()
mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)
void maybeSetTrivialComdat(const clang::Decl &d, mlir::Operation *op)
CIRGenCXXABI & getCXXABI() const
void emitGlobal(clang::GlobalDecl gd)
Emit code for a single global function or variable declaration.
CIRGenVTables & getVTables()
cir::GlobalLinkageKind getVTableLinkage(const CXXRecordDecl *rd)
Return the appropriate linkage for the vtable, VTT, and type information of the given class.
const CIRGenFunctionInfo & arrangeCXXStructorDeclaration(clang::GlobalDecl gd)
cir::FuncType getFunctionType(const CIRGenFunctionInfo &info)
Get the CIR function type for.
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
SourceLocation getBeginLoc() const LLVM_READONLY
Definition StmtCXX.h:43
VarDecl * getExceptionDecl() const
Definition StmtCXX.h:49
bool isGlobalDelete() const
Definition ExprCXX.h:2652
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2136
bool isVirtual() const
Definition DeclCXX.h:2191
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2275
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition DeclCXX.h:2245
SourceRange getSourceRange() const
Definition ExprCXX.h:2611
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:2343
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
base_class_range vbases()
Definition DeclCXX.h:625
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
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
const Expr * getSubExpr() const
Definition ExprCXX.h:1229
static CanQual< Type > CreateUnsafe(QualType Other)
Qualifiers getQualifiers() const
Retrieve all qualifiers.
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
Definition CharUnits.h:207
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 One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
Definition CharUnits.h:53
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2122
bool isTranslationUnit() const
Definition DeclBase.h:2198
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
bool hasAttr() const
Definition DeclBase.h:585
bool shouldEmitInExternalSource() const
Whether the definition of the declaration should be emitted in external sources.
This represents one expression.
Definition Expr.h:112
QualType getType() const
Definition Expr.h:144
bool isInlined() const
Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...
Definition Decl.h:2936
FunctionDecl * getDefinition()
Get the definition for this declaration.
Definition Decl.h:2297
bool isDefined(const FunctionDecl *&Definition, bool CheckForPendingFriendDefinition=false) const
Returns true if the function has a definition that does not need to be instantiated.
Definition Decl.cpp:3248
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:5604
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
CXXRecordDecl * getMostRecentCXXRecordDecl() const
Note: this can trigger extra deserialization when external AST sources are used.
Definition Type.cpp:5535
QualType getPointeeType() const
Definition TypeBase.h:3721
bool isMemberFunctionPointer() const
Returns true if the member type (i.e.
Definition TypeBase.h:3725
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
Visibility getVisibility() const
Determines the visibility of this entity.
Definition Decl.h:444
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3378
QualType getPointeeType() const
Definition TypeBase.h:3388
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isVolatileQualified() const
Determine whether this type is volatile-qualified.
Definition TypeBase.h:8515
bool isRestrictQualified() const
Determine whether this type is restrict-qualified.
Definition TypeBase.h:8509
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:8471
QualType getCanonicalType() const
Definition TypeBase.h:8483
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8525
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8504
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
Definition TypeBase.h:361
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition TypeBase.h:354
@ OCL_None
There is no lifetime qualification on this type.
Definition TypeBase.h:350
@ OCL_Weak
Reading or writing from this object requires a barrier call.
Definition TypeBase.h:364
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
Definition TypeBase.h:367
ObjCLifetime getObjCLifetime() const
Definition TypeBase.h:545
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:343
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4895
bool hasConstructorVariants() const
Does this ABI have different entrypoints for complete-object and base-subobject constructors?
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:490
virtual bool hasPS4DLLImportExport() const
uint64_t getPointerAlign(LangAS AddrSpace) const
Definition TargetInfo.h:494
TargetCXXABI getCXXABI() const
Get the C++ ABI currently in use.
unsigned getLongWidth() const
getLongWidth/Align - Return the size of 'signed long' and 'unsigned long' for this target,...
Definition TargetInfo.h:536
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:3562
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
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:754
Visibility getVisibility() const
Determine the visibility of this type.
Definition TypeBase.h:3115
Linkage getLinkage() const
Determine the linkage of this type.
Definition Type.cpp:4974
TypeClass getTypeClass() const
Definition TypeBase.h:2433
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9261
bool isRecordType() const
Definition TypeBase.h:8795
AddressPointLocation getAddressPoint(BaseSubobject Base) const
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:926
TLSKind getTLSKind() const
Definition Decl.cpp:2181
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2203
bool isNoDestroy(const ASTContext &) const
Is destruction of this variable entirely suppressed?
Definition Decl.cpp:2849
const Expr * getInit() const
Definition Decl.h:1383
static bool isLocalLinkage(GlobalLinkageKind linkage)
Definition CIROpsEnums.h:51
static bool isValidLinkage(GlobalLinkageKind gl)
static bool isWeakForLinker(GlobalLinkageKind linkage)
Whether the definition of this global may be replaced at link time.
static 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:95
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 Variable var(Literal L)
Returns the variable of L.
Definition CNFFormula.h:64
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition PrimType.h:201
@ Address
A pointer to a ValueDecl.
Definition Primitives.h:28
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.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
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:125
@ 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:564
U cast(CodeGen::Address addr)
Definition Address.h:327
@ EST_None
no exception specification
@ 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 cxxabiAppleARM64CXXABI()
static bool opGlobalDLLImportExport()
static bool opGlobalPartition()
static bool pointerAuthentication()
static bool opFuncCallingConv()
static bool opFuncWillReturn()
static bool setComdat()
static bool protectedVisibility()
static bool cxxabiUseARMGuardVarABI()
static bool cxxabiUseARMMethodPtrABI()
static bool setDSOLocal()
static bool vtableRelativeLayout()
const clang::CXXRecordDecl * nearestVBase
clang::CharUnits getPointerAlign() const
clang::CharUnits getSizeSize() const
Represents an element in a path from a derived class to a base class.
union clang::ReturnAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
Definition Thunk.h:30
union clang::ThisAdjustment::VirtualAdjustment Virtual
int64_t NonVirtual
The non-virtual adjustment from the derived object to its nearest virtual base.
Definition Thunk.h:95
ThisAdjustment This
The this pointer adjustment.
Definition Thunk.h:159
struct clang::ReturnAdjustment::VirtualAdjustment::@103031170252120233124322035264172076254313213024 Itanium
int64_t VBaseOffsetOffset
The offset (in bytes), relative to the address point of the virtual base class offset.
Definition Thunk.h:39
struct clang::ThisAdjustment::VirtualAdjustment::@106065375072164260365214033034320247050276346205 Itanium
int64_t VCallOffsetOffset
The offset (in bytes), relative to the address point, of the virtual call offset.
Definition Thunk.h:104