clang 24.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/Mangle.h"
26#include "clang/AST/TypeBase.h"
30#include "llvm/ADT/SmallString.h"
31#include "llvm/Support/ErrorHandling.h"
32#include "llvm/Support/raw_ostream.h"
33
34using namespace clang;
35using namespace clang::CIRGen;
36
37namespace {
38
39class CIRGenItaniumCXXABI : public CIRGenCXXABI {
40protected:
41 /// All the vtables which have been defined.
42 llvm::DenseMap<const CXXRecordDecl *, cir::GlobalOp> vtables;
43
44public:
45 CIRGenItaniumCXXABI(CIRGenModule &cgm) : CIRGenCXXABI(cgm) {
48 }
49
50 AddedStructorArgs getImplicitConstructorArgs(CIRGenFunction &cgf,
51 const CXXConstructorDecl *d,
53 bool forVirtualBase,
54 bool delegating) override;
55
56 bool needsVTTParameter(clang::GlobalDecl gd) override;
57
58 AddedStructorArgCounts
59 buildStructorSignature(GlobalDecl gd,
60 llvm::SmallVectorImpl<CanQualType> &argTys) override;
61
62 void emitInstanceFunctionProlog(SourceLocation loc,
63 CIRGenFunction &cgf) override;
64
65 void addImplicitStructorParams(CIRGenFunction &cgf, QualType &resTy,
66 FunctionArgList &params) override;
67 mlir::Value getCXXDestructorImplicitParam(CIRGenFunction &cgf,
68 const CXXDestructorDecl *dd,
70 bool forVirtualBase,
71 bool delegating) override;
72 void emitCXXConstructors(const clang::CXXConstructorDecl *d) override;
73 void emitCXXDestructors(const clang::CXXDestructorDecl *d) override;
74 void emitCXXStructor(clang::GlobalDecl gd) override;
75
76 void emitDestructorCall(CIRGenFunction &cgf, const CXXDestructorDecl *dd,
77 CXXDtorType type, bool forVirtualBase,
78 bool delegating, Address thisAddr,
79 QualType thisTy) override;
80 void registerGlobalDtor(const VarDecl *vd, cir::FuncOp dtor,
81 mlir::Value addr) override;
82 void emitVirtualObjectDelete(CIRGenFunction &cgf, const CXXDeleteExpr *de,
83 Address ptr, QualType elementType,
84 const CXXDestructorDecl *dtor) override;
85
86 void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;
87 void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override;
88
89 bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
90 CXXDtorType dt) const override {
91 // Itanium does not emit any destructor variant as an inline thunk.
92 // Delegating may occur as an optimization, but all variants are either
93 // emitted with external linkage or as linkonce if they are inline and used.
94 return false;
95 }
96
97 bool isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
98 CIRGenFunction::VPtr vptr) override;
99
100 cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd,
101 CharUnits vptrOffset) override;
102 CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf,
103 clang::GlobalDecl gd, Address thisAddr,
104 mlir::Type ty,
105 SourceLocation loc) override;
106 mlir::Value emitVirtualDestructorCall(CIRGenFunction &cgf,
107 const CXXDestructorDecl *dtor,
108 CXXDtorType dtorType, Address thisAddr,
109 DeleteOrMemberCallExpr e) override;
110
111 bool canSpeculativelyEmitVTable(const CXXRecordDecl *RD) const override;
112 bool canSpeculativelyEmitVTableAsBaseClass(const CXXRecordDecl *RD) const;
113
114 mlir::Value getVTableAddressPoint(BaseSubobject base,
115 const CXXRecordDecl *vtableClass) override;
116 cir::GlobalViewAttr
117 getVTableAddressPointAttr(BaseSubobject base,
118 const CXXRecordDecl *vtableClass) override;
119 mlir::Value getVTableAddressPointInStructorWithVTT(
120 CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
121 const CXXRecordDecl *nearestVBase);
122
123 mlir::Value getVTableAddressPointInStructor(
124 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,
125 clang::BaseSubobject base,
126 const clang::CXXRecordDecl *nearestVBase) override;
127 void emitVTableDefinitions(CIRGenVTables &cgvt,
128 const CXXRecordDecl *rd) override;
129 void emitVirtualInheritanceTables(const CXXRecordDecl *rd) override;
130
131 void setThunkLinkage(cir::FuncOp thunk, bool forVTable, GlobalDecl gd,
132 bool returnAdjustment) override {
133 if (forVTable && !thunk.hasLocalLinkage())
134 thunk.setLinkage(cir::GlobalLinkageKind::AvailableExternallyLinkage);
135 const auto *nd = cast<NamedDecl>(gd.getDecl());
136 cgm.setGVProperties(thunk, nd);
137 }
138
139 bool exportThunk() override { return true; }
140
141 mlir::Value performThisAdjustment(CIRGenFunction &cgf, Address thisAddr,
142 const CXXRecordDecl *unadjustedClass,
143 const ThunkInfo &ti) override;
144
145 mlir::Value performReturnAdjustment(CIRGenFunction &cgf, Address ret,
146 const CXXRecordDecl *unadjustedClass,
147 const ReturnAdjustment &ra) override;
148
149 bool shouldTypeidBeNullChecked(QualType srcTy) override;
150 mlir::Value emitTypeid(CIRGenFunction &cgf, QualType SrcRecordTy,
151 Address thisPtr, mlir::Type StdTypeInfoPtrTy) override;
152 void emitBadTypeidCall(CIRGenFunction &cgf, mlir::Location loc) override;
153
154 mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
155 QualType ty) override;
156
157 StringRef getPureVirtualCallName() override { return "__cxa_pure_virtual"; }
158 StringRef getDeletedVirtualCallName() override {
159 return "__cxa_deleted_virtual";
160 }
161
162 CatchTypeInfo
163 getAddrOfCXXCatchHandlerType(mlir::Location loc, QualType ty,
164 QualType catchHandlerType) override {
165 auto rtti = dyn_cast<cir::GlobalViewAttr>(getAddrOfRTTIDescriptor(loc, ty));
166 assert(rtti && "expected GlobalViewAttr");
167 return CatchTypeInfo{rtti, 0};
168 }
169
170 bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {
171 return true;
172 }
173
174 size_t getSrcArgforCopyCtor(const CXXConstructorDecl *,
175 FunctionArgList &args) const override {
176 assert(!args.empty() && "expected the arglist to not be empty!");
177 return args.size() - 1;
178 }
179
180 void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) override;
181
182 mlir::Value
183 getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf,
184 Address thisAddr, const CXXRecordDecl *classDecl,
185 const CXXRecordDecl *baseClassDecl) override;
186
187 // The traditional clang CodeGen emits calls to `__dynamic_cast` directly into
188 // LLVM in the `emitDynamicCastCall` function. In CIR, `dynamic_cast`
189 // expressions are lowered to `cir.dyn_cast` ops instead of calls to runtime
190 // functions. So during CIRGen we don't need the `emitDynamicCastCall`
191 // function that clang CodeGen has.
192 mlir::Value emitDynamicCast(CIRGenFunction &cgf, mlir::Location loc,
193 QualType srcRecordTy, QualType destRecordTy,
194 cir::PointerType destCIRTy, bool isRefCast,
195 Address src) override;
196
197 cir::MethodAttr buildVirtualMethodAttr(cir::MethodType methodTy,
198 const CXXMethodDecl *md) override;
199
200 Address initializeArrayCookie(CIRGenFunction &cgf, Address newPtr,
201 mlir::Value numElements, const CXXNewExpr *e,
202 QualType elementType) override;
203
204 bool isZeroInitializable(const MemberPointerType *MPT) override;
205
206protected:
207 CharUnits getArrayCookieSizeImpl(QualType elementType) override;
208
209 /**************************** RTTI Uniqueness ******************************/
210 /// Returns true if the ABI requires RTTI type_info objects to be unique
211 /// across a program.
212 virtual bool shouldRTTIBeUnique() const { return true; }
213
214public:
215 /// What sort of unique-RTTI behavior should we use?
216 enum RTTIUniquenessKind {
217 /// We are guaranteeing, or need to guarantee, that the RTTI string
218 /// is unique.
219 RUK_Unique,
220
221 /// We are not guaranteeing uniqueness for the RTTI string, so we
222 /// can demote to hidden visibility but must use string comparisons.
223 RUK_NonUniqueHidden,
224
225 /// We are not guaranteeing uniqueness for the RTTI string, so we
226 /// have to use string comparisons, but we also have to emit it with
227 /// non-hidden visibility.
228 RUK_NonUniqueVisible
229 };
230
231 /// Return the required visibility status for the given type and linkage in
232 /// the current ABI.
233 RTTIUniquenessKind
234 classifyRTTIUniqueness(QualType canTy, cir::GlobalLinkageKind linkage) const;
235
236private:
237 bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *rd) const;
238 bool isVTableHidden(const CXXRecordDecl *rd) const;
239};
240
241} // namespace
242
243void CIRGenItaniumCXXABI::emitInstanceFunctionProlog(SourceLocation loc,
244 CIRGenFunction &cgf) {
245 // Naked functions have no prolog.
246 if (cgf.curFuncDecl && cgf.curFuncDecl->hasAttr<NakedAttr>()) {
248 "emitInstanceFunctionProlog: Naked");
249 }
250
251 /// Initialize the 'this' slot. In the Itanium C++ ABI, no prologue
252 /// adjustments are required, because they are all handled by thunks.
253 setCXXABIThisValue(cgf, loadIncomingCXXThis(cgf));
254
255 /// Initialize the 'vtt' slot if needed.
256 if (getStructorImplicitParamDecl(cgf)) {
257 cir::LoadOp val = cgf.getBuilder().createLoad(
258 cgf.getLoc(loc),
259 cgf.getAddrOfLocalVar(getStructorImplicitParamDecl(cgf)));
260 setStructorImplicitParamValue(cgf, val);
261 }
262
263 /// If this is a function that the ABI specifies returns 'this', initialize
264 /// the return slot to this' at the start of the function.
265 ///
266 /// Unlike the setting of return types, this is done within the ABI
267 /// implementation instead of by clients of CIRGenCXXBI because:
268 /// 1) getThisValue is currently protected
269 /// 2) in theory, an ABI could implement 'this' returns some other way;
270 /// HasThisReturn only specifies a contract, not the implementation
271 if (hasThisReturn(cgf.curGD)) {
273 "emitInstanceFunctionProlog: hasThisReturn");
274 }
275}
276
277CIRGenCXXABI::AddedStructorArgCounts
278CIRGenItaniumCXXABI::buildStructorSignature(
279 GlobalDecl gd, llvm::SmallVectorImpl<CanQualType> &argTys) {
280 clang::ASTContext &astContext = cgm.getASTContext();
281
282 // All parameters are already in place except VTT, which goes after 'this'.
283 // These are clang types, so we don't need to worry about sret yet.
284
285 // Check if we need to add a VTT parameter (which has type void **).
287 : gd.getDtorType() == Dtor_Base) &&
288 cast<CXXMethodDecl>(gd.getDecl())->getParent()->getNumVBases() != 0) {
290 argTys.insert(argTys.begin() + 1,
291 astContext.getPointerType(
293 return AddedStructorArgCounts::withPrefix(1);
294 }
295
296 return AddedStructorArgCounts{};
297}
298
299// Find out how to cirgen the complete destructor and constructor
300namespace {
301enum class StructorCIRGen { Emit, RAUW, Alias, COMDAT };
302}
303
304static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm,
305 const CXXMethodDecl *md) {
306 if (!cgm.getCodeGenOpts().CXXCtorDtorAliases)
307 return StructorCIRGen::Emit;
308
309 // The complete and base structors are not equivalent if there are any virtual
310 // bases, so emit separate functions.
311 if (md->getParent()->getNumVBases())
312 return StructorCIRGen::Emit;
313
314 GlobalDecl aliasDecl;
315 if (const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
316 aliasDecl = GlobalDecl(dd, Dtor_Complete);
317 } else {
318 const auto *cd = cast<CXXConstructorDecl>(md);
319 aliasDecl = GlobalDecl(cd, Ctor_Complete);
320 }
321
322 cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);
323
324 if (cir::isDiscardableIfUnused(linkage))
325 return StructorCIRGen::RAUW;
326
327 // FIXME: Should we allow available_externally aliases?
328 if (!cir::isValidLinkage(linkage))
329 return StructorCIRGen::RAUW;
330
331 if (cir::isWeakForLinker(linkage)) {
332 // Only ELF and wasm support COMDATs with arbitrary names (C5/D5).
333 if (cgm.getTarget().getTriple().isOSBinFormatELF() ||
334 cgm.getTarget().getTriple().isOSBinFormatWasm())
335 return StructorCIRGen::COMDAT;
336 return StructorCIRGen::Emit;
337 }
338
339 return StructorCIRGen::Alias;
340}
341
343 GlobalDecl aliasDecl,
344 GlobalDecl targetDecl) {
345 cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);
346
347 // Does this function alias already exists?
348 StringRef mangledName = cgm.getMangledName(aliasDecl);
349 auto globalValue = dyn_cast_or_null<cir::CIRGlobalValueInterface>(
350 cgm.getGlobalValue(mangledName));
351 if (globalValue && !globalValue.isDeclaration())
352 return;
353
354 auto entry = cast_or_null<cir::FuncOp>(cgm.getGlobalValue(mangledName));
355
356 // Retrieve aliasee info.
357 auto aliasee = cast<cir::FuncOp>(cgm.getAddrOfGlobal(targetDecl));
358
359 // Populate actual alias.
360 cgm.emitAliasForGlobal(mangledName, entry, aliasDecl, aliasee, linkage);
361}
362
363void CIRGenItaniumCXXABI::emitCXXStructor(GlobalDecl gd) {
364 auto *md = cast<CXXMethodDecl>(gd.getDecl());
365 StructorCIRGen cirGenType = getCIRGenToUse(cgm, md);
366 const auto *cd = dyn_cast<CXXConstructorDecl>(md);
367 const CXXDestructorDecl *dd = cd ? nullptr : cast<CXXDestructorDecl>(md);
368
369 if (cd ? gd.getCtorType() == Ctor_Complete
370 : gd.getDtorType() == Dtor_Complete) {
371 GlobalDecl baseDecl =
373 ;
374
375 if (cirGenType == StructorCIRGen::Alias ||
376 cirGenType == StructorCIRGen::COMDAT) {
377 emitConstructorDestructorAlias(cgm, gd, baseDecl);
378 return;
379 }
380
381 if (cirGenType == StructorCIRGen::RAUW) {
382 StringRef mangledName = cgm.getMangledName(gd);
383 mlir::Operation *aliasee = cgm.getAddrOfGlobal(baseDecl);
384 cgm.addReplacement(mangledName, aliasee);
385 return;
386 }
387 }
388
389 auto fn = cgm.codegenCXXStructor(gd);
390
391 if (cirGenType == StructorCIRGen::COMDAT) {
392 llvm::SmallString<256> comdatKey;
393 llvm::raw_svector_ostream out(comdatKey);
394 ItaniumMangleContext &mangler =
396 if (dd)
397 mangler.mangleCXXDtorComdat(dd, out);
398 else
399 mangler.mangleCXXCtorComdat(cd, out);
400 fn.setComdat(llvm::StringRef(comdatKey));
401 } else {
402 cgm.maybeSetTrivialComdat(*md, fn);
403 }
404}
405
406void CIRGenItaniumCXXABI::addImplicitStructorParams(CIRGenFunction &cgf,
407 QualType &resTy,
408 FunctionArgList &params) {
409 const auto *md = cast<CXXMethodDecl>(cgf.curGD.getDecl());
411
412 // Check if we need a VTT parameter as well.
413 if (needsVTTParameter(cgf.curGD)) {
414 ASTContext &astContext = cgm.getASTContext();
415
416 // FIXME: avoid the fake decl
418 QualType t = astContext.getPointerType(astContext.VoidPtrTy);
419 auto *vttDecl = ImplicitParamDecl::Create(
420 astContext, /*DC=*/nullptr, md->getLocation(),
421 &astContext.Idents.get("vtt"), t, ImplicitParamKind::CXXVTT);
422 params.insert(params.begin() + 1, vttDecl);
423 getStructorImplicitParamDecl(cgf) = vttDecl;
424 }
425}
426
427void CIRGenItaniumCXXABI::emitCXXConstructors(const CXXConstructorDecl *d) {
428 // Just make sure we're in sync with TargetCXXABI.
430
431 // The constructor used for constructing this as a base class;
432 // ignores virtual bases.
433 cgm.emitGlobal(GlobalDecl(d, Ctor_Base));
434
435 // The constructor used for constructing this as a complete class;
436 // constructs the virtual bases, then calls the base constructor.
437 if (!d->getParent()->isAbstract()) {
438 // We don't need to emit the complete ctro if the class is abstract.
439 cgm.emitGlobal(GlobalDecl(d, Ctor_Complete));
440 }
441}
442
443void CIRGenItaniumCXXABI::emitCXXDestructors(const CXXDestructorDecl *d) {
444 // The destructor used for destructing this as a base class; ignores
445 // virtual bases.
446 cgm.emitGlobal(GlobalDecl(d, Dtor_Base));
447
448 // The destructor used for destructing this as a most-derived class;
449 // call the base destructor and then destructs any virtual bases.
450 cgm.emitGlobal(GlobalDecl(d, Dtor_Complete));
451
452 // The destructor in a virtual table is always a 'deleting'
453 // destructor, which calls the complete destructor and then uses the
454 // appropriate operator delete.
455 if (d->isVirtual())
456 cgm.emitGlobal(GlobalDecl(d, Dtor_Deleting));
457}
458
459CIRGenCXXABI::AddedStructorArgs CIRGenItaniumCXXABI::getImplicitConstructorArgs(
460 CIRGenFunction &cgf, const CXXConstructorDecl *d, CXXCtorType type,
461 bool forVirtualBase, bool delegating) {
462 if (!needsVTTParameter(GlobalDecl(d, type)))
463 return AddedStructorArgs{};
464
465 // Insert the implicit 'vtt' argument as the second argument. Make sure to
466 // correctly reflect its address space, which can differ from generic on
467 // some targets.
468 mlir::Value vtt =
469 cgf.getVTTParameter(GlobalDecl(d, type), forVirtualBase, delegating);
470 QualType vttTy =
473 return AddedStructorArgs::withPrefix({{vtt, vttTy}});
474}
475
476/// Return whether the given global decl needs a VTT (virtual table table)
477/// parameter, which it does if it's a base constructor or destructor with
478/// virtual bases.
479bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) {
480 auto *md = cast<CXXMethodDecl>(gd.getDecl());
481
482 // We don't have any virtual bases, just return early.
483 if (!md->getParent()->getNumVBases())
484 return false;
485
486 // Check if we have a base constructor.
488 return true;
489
490 // Check if we have a base destructor.
492 return true;
493
494 return false;
495}
496
497void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,
498 const CXXRecordDecl *rd) {
499 cir::GlobalOp vtable = getAddrOfVTable(rd, CharUnits());
500 if (vtable.hasInitializer())
501 return;
502
503 ItaniumVTableContext &vtContext = cgm.getItaniumVTableContext();
504 const VTableLayout &vtLayout = vtContext.getVTableLayout(rd);
505 cir::GlobalLinkageKind linkage = cgm.getVTableLinkage(rd);
506 mlir::Attribute rtti =
509
510 // Classic codegen uses ConstantInitBuilder here, which is a very general
511 // and feature-rich class to generate initializers for global values.
512 // For now, this is using a simpler approach to create the initializer in CIR.
513 cgvt.createVTableInitializer(vtable, vtLayout, rtti,
514 cir::isLocalLinkage(linkage));
515
516 // Set the correct linkage.
517 vtable.setLinkage(linkage);
518
519 if (cgm.supportsCOMDAT() && cir::isWeakForLinker(linkage))
520 vtable.setSelfComdat();
521
522 // Set the right visibility.
523 cgm.setGVProperties(vtable, rd);
524
525 // If this is the magic class __cxxabiv1::__fundamental_type_info,
526 // we will emit the typeinfo for the fundamental types. This is the
527 // same behaviour as GCC.
528 const DeclContext *DC = rd->getDeclContext();
529 if (rd->getIdentifier() &&
530 rd->getIdentifier()->isStr("__fundamental_type_info") &&
531 isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
532 cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
533 DC->getParent()->isTranslationUnit()) {
534 cgm.errorNYI(rd->getSourceRange(),
535 "emitVTableDefinitions: __fundamental_type_info");
536 }
537
538 [[maybe_unused]] auto vtableAsGlobalValue =
539 dyn_cast<cir::CIRGlobalValueInterface>(*vtable);
540 assert(vtableAsGlobalValue && "VTable must support CIRGlobalValueInterface");
541 // Always emit type metadata on non-available_externally definitions, and on
542 // available_externally definitions if we are performing whole program
543 // devirtualization. For WPD we need the type metadata on all vtable
544 // definitions to ensure we associate derived classes with base classes
545 // defined in headers but with a strong definition only in a shared
546 // library.
548 if (cgm.getCodeGenOpts().WholeProgramVTables) {
549 cgm.errorNYI(rd->getSourceRange(),
550 "emitVTableDefinitions: WholeProgramVTables");
551 }
552
554 if (cgm.getLangOpts().RelativeCXXABIVTables) {
555 cgm.errorNYI(rd->getSourceRange(), "vtableRelativeLayout");
556 }
557}
558
559mlir::Value CIRGenItaniumCXXABI::emitVirtualDestructorCall(
560 CIRGenFunction &cgf, const CXXDestructorDecl *dtor, CXXDtorType dtorType,
561 Address thisAddr, DeleteOrMemberCallExpr expr) {
562 auto *callExpr = dyn_cast<const CXXMemberCallExpr *>(expr);
563 auto *delExpr = dyn_cast<const CXXDeleteExpr *>(expr);
564 assert((callExpr != nullptr) ^ (delExpr != nullptr));
565 assert(callExpr == nullptr || callExpr->arg_begin() == callExpr->arg_end());
566 assert(dtorType == Dtor_Deleting || dtorType == Dtor_Complete);
567
568 GlobalDecl globalDecl(dtor, dtorType);
569 const CIRGenFunctionInfo *fnInfo =
570 &cgm.getTypes().arrangeCXXStructorDeclaration(globalDecl);
571 const cir::FuncType &fnTy = cgm.getTypes().getFunctionType(*fnInfo);
572 auto callee = CIRGenCallee::forVirtual(callExpr, globalDecl, thisAddr, fnTy);
573
574 QualType thisTy =
575 callExpr ? callExpr->getObjectType() : delExpr->getDestroyedType();
576
577 cgf.emitCXXDestructorCall(globalDecl, callee, thisAddr.emitRawPointer(),
578 thisTy, nullptr, QualType(), nullptr);
579 return nullptr;
580}
581
582void CIRGenItaniumCXXABI::emitVirtualInheritanceTables(
583 const CXXRecordDecl *rd) {
584 CIRGenVTables &vtables = cgm.getVTables();
585 cir::GlobalOp vtt = vtables.getAddrOfVTT(rd);
586 vtables.emitVTTDefinition(vtt, cgm.getVTableLinkage(rd), rd);
587}
588
589namespace {
590class CIRGenItaniumRTTIBuilder {
591 CIRGenModule &cgm; // Per-module state.
592 const CIRGenItaniumCXXABI &cxxABI; // Per-module state.
593
594 /// The fields of the RTTI descriptor currently being built.
595 SmallVector<mlir::Attribute, 16> fields;
596
597 // Returns the mangled type name of the given type.
598 cir::GlobalOp getAddrOfTypeName(mlir::Location loc, QualType ty,
599 cir::GlobalLinkageKind linkage);
600
601 /// descriptor of the given type.
602 mlir::Attribute getAddrOfExternalRTTIDescriptor(mlir::Location loc,
603 QualType ty);
604
605 /// Build the vtable pointer for the given type.
606 void buildVTablePointer(mlir::Location loc, const Type *ty);
607
608 /// Build an abi::__si_class_type_info, used for single inheritance, according
609 /// to the Itanium C++ ABI, 2.9.5p6b.
610 void buildSIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd);
611
612 /// Build an abi::__vmi_class_type_info, used for
613 /// classes with bases that do not satisfy the abi::__si_class_type_info
614 /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
615 void buildVMIClassTypeInfo(mlir::Location loc, const CXXRecordDecl *rd);
616
617 /// Build an abi::__pointer_type_info, used for pointer types, according
618 /// to the Itanium C++ ABI, 2.9.4p7.
619 void buildPointerTypeInfo(mlir::Location loc, QualType ty);
620
621 /// Build an abi::__pointer_to_member_type_info, used for pointer to member
622 /// types, according to the Itanium C++ ABI, 2.9.4p9.
623
624 /// Build an abi::__pointer_to_member_type_info
625 /// struct, used for member pointer types.
626 void buildPointerToMemberTypeInfo(mlir::Location loc,
627 const MemberPointerType *ty);
628
629public:
630 CIRGenItaniumRTTIBuilder(const CIRGenItaniumCXXABI &abi, CIRGenModule &cgm)
631 : cgm(cgm), cxxABI(abi) {}
632
633 /// Build the RTTI type info struct for the given type, or
634 /// link to an existing RTTI descriptor if one already exists.
635 mlir::Attribute buildTypeInfo(mlir::Location loc, QualType ty);
636
637 /// Build the RTTI type info struct for the given type.
638 mlir::Attribute buildTypeInfo(mlir::Location loc, QualType ty,
639 cir::GlobalLinkageKind linkage,
640 mlir::SymbolTable::Visibility visibility);
641};
642
643/// ShouldUseExternalRTTIDescriptor - Returns whether the type information for
644/// the given type exists somewhere else, and that we should not emit the type
645/// information in this translation unit. Assumes that it is not a
646/// standard-library type.
647static bool shouldUseExternalRttiDescriptor(CIRGenModule &cgm, QualType ty) {
648 ASTContext &context = cgm.getASTContext();
649
650 // If RTTI is disabled, assume it might be disabled in the
651 // translation unit that defines any potential key function, too.
652 if (!context.getLangOpts().RTTI)
653 return false;
654
655 if (const auto *recordTy = dyn_cast<RecordType>(ty)) {
656 const auto *rd =
657 cast<CXXRecordDecl>(recordTy->getDecl())->getDefinitionOrSelf();
658 if (!rd->hasDefinition())
659 return false;
660
661 if (!rd->isDynamicClass())
662 return false;
663
664 // FIXME: this may need to be reconsidered if the key function
665 // changes.
666 // N.B. We must always emit the RTTI data ourselves if there exists a key
667 // function.
668 bool isDLLImport = rd->hasAttr<DLLImportAttr>();
669
670 // Don't import the RTTI but emit it locally.
671 if (cgm.getTriple().isOSCygMing())
672 return false;
673
674 if (cgm.getVTables().isVTableExternal(rd)) {
676 return true;
677
678 return !isDLLImport || cgm.getTriple().isWindowsItaniumEnvironment();
679 }
680
681 if (isDLLImport)
682 return true;
683 }
684
685 return false;
686}
687
688const char *vTableClassNameForType(const CIRGenModule &cgm, const Type *ty) {
689 // abi::__class_type_info.
690 static const char *const classTypeInfo =
691 "_ZTVN10__cxxabiv117__class_type_infoE";
692 // abi::__si_class_type_info.
693 static const char *const siClassTypeInfo =
694 "_ZTVN10__cxxabiv120__si_class_type_infoE";
695 // abi::__vmi_class_type_info.
696 static const char *const vmiClassTypeInfo =
697 "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
698
699 switch (ty->getTypeClass()) {
700#define TYPE(Class, Base)
701#define ABSTRACT_TYPE(Class, Base)
702#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
703#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
704#define DEPENDENT_TYPE(Class, Base) case Type::Class:
705#include "clang/AST/TypeNodes.inc"
706 llvm_unreachable("Non-canonical and dependent types shouldn't get here");
707
708 case Type::LValueReference:
709 case Type::RValueReference:
710 llvm_unreachable("References shouldn't get here");
711
712 case Type::Auto:
713 case Type::DeducedTemplateSpecialization:
714 llvm_unreachable("Undeduced type shouldn't get here");
715
716 case Type::Pipe:
717 llvm_unreachable("Pipe types shouldn't get here");
718
719 case Type::ArrayParameter:
720 llvm_unreachable("Array Parameter types should not get here.");
721
722 case Type::Builtin:
723 case Type::BitInt:
724 case Type::OverflowBehavior:
725 // GCC treats vector and complex types as fundamental types.
726 case Type::Vector:
727 case Type::ExtVector:
728 case Type::ConstantMatrix:
729 case Type::Complex:
730 case Type::Atomic:
731 // FIXME: GCC treats block pointers as fundamental types?!
732 case Type::BlockPointer:
733 return "_ZTVN10__cxxabiv123__fundamental_type_infoE";
734 case Type::ConstantArray:
735 case Type::IncompleteArray:
736 case Type::VariableArray:
737 // abi::__array_type_info.
738 return "_ZTVN10__cxxabiv117__array_type_infoE";
739
740 case Type::FunctionNoProto:
741 case Type::FunctionProto:
742 // abi::__function_type_info.
743 return "_ZTVN10__cxxabiv120__function_type_infoE";
744
745 case Type::Enum:
746 return "_ZTVN10__cxxabiv116__enum_type_infoE";
747
748 case Type::Record: {
749 const auto *rd = cast<CXXRecordDecl>(cast<RecordType>(ty)->getDecl())
750 ->getDefinitionOrSelf();
751
752 if (!rd->hasDefinition() || !rd->getNumBases()) {
753 return classTypeInfo;
754 }
755
757 return siClassTypeInfo;
758 }
759
760 return vmiClassTypeInfo;
761 }
762
763 case Type::ObjCObject:
764 cgm.errorNYI("VTableClassNameForType: ObjCObject");
765 break;
766
767 case Type::ObjCInterface:
768 cgm.errorNYI("VTableClassNameForType: ObjCInterface");
769 break;
770
771 case Type::ObjCObjectPointer:
772 case Type::Pointer:
773 // abi::__pointer_type_info.
774 return "_ZTVN10__cxxabiv119__pointer_type_infoE";
775
776 case Type::MemberPointer:
777 // abi::__pointer_to_member_type_info.
778 return "_ZTVN10__cxxabiv129__pointer_to_member_type_infoE";
779
780 case Type::HLSLAttributedResource:
781 case Type::HLSLInlineSpirv:
782 llvm_unreachable("HLSL doesn't support virtual functions");
783 }
784
785 return nullptr;
786}
787} // namespace
788
789/// Return the linkage that the type info and type info name constants
790/// should have for the given type.
791static cir::GlobalLinkageKind getTypeInfoLinkage(CIRGenModule &cgm,
792 QualType ty) {
793 // In addition, it and all of the intermediate abi::__pointer_type_info
794 // structs in the chain down to the abi::__class_type_info for the
795 // incomplete class type must be prevented from resolving to the
796 // corresponding type_info structs for the complete class type, possibly
797 // by making them local static objects. Finally, a dummy class RTTI is
798 // generated for the incomplete type that will not resolve to the final
799 // complete class RTTI (because the latter need not exist), possibly by
800 // making it a local static object.
802 return cir::GlobalLinkageKind::InternalLinkage;
803
804 switch (ty->getLinkage()) {
805 case Linkage::Invalid:
806 llvm_unreachable("Linkage hasn't been computed!");
807
808 case Linkage::None:
811 return cir::GlobalLinkageKind::InternalLinkage;
812
814 case Linkage::Module:
816 // RTTI is not enabled, which means that this type info struct is going
817 // to be used for exception handling. Give it linkonce_odr linkage.
818 if (!cgm.getLangOpts().RTTI)
819 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
820
821 if (const RecordType *record = dyn_cast<RecordType>(ty)) {
822 const auto *rd =
823 cast<CXXRecordDecl>(record->getDecl())->getDefinitionOrSelf();
824 if (rd->hasAttr<WeakAttr>())
825 return cir::GlobalLinkageKind::WeakODRLinkage;
826
827 if (cgm.getTriple().isWindowsItaniumEnvironment())
828 if (rd->hasAttr<DLLImportAttr>() &&
829 shouldUseExternalRttiDescriptor(cgm, ty))
830 return cir::GlobalLinkageKind::ExternalLinkage;
831
832 // MinGW always uses LinkOnceODRLinkage for type info.
833 if (rd->isDynamicClass() && !cgm.getASTContext()
835 .getTriple()
836 .isWindowsGNUEnvironment())
837 return cgm.getVTableLinkage(rd);
838 }
839
840 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
841 }
842
843 llvm_unreachable("Invalid linkage!");
844}
845
846cir::GlobalOp
847CIRGenItaniumRTTIBuilder::getAddrOfTypeName(mlir::Location loc, QualType ty,
848 cir::GlobalLinkageKind linkage) {
849 CIRGenBuilderTy &builder = cgm.getBuilder();
850 SmallString<256> name;
851 llvm::raw_svector_ostream out(name);
853
854 // We know that the mangled name of the type starts at index 4 of the
855 // mangled name of the typename, so we can just index into it in order to
856 // get the mangled name of the type.
857 mlir::Attribute init = builder.getString(
858 name.substr(4), cgm.convertType(cgm.getASTContext().CharTy),
859 std::nullopt);
860
861 CharUnits align =
863
864 // builder.getString can return a #cir.zero if the string given to it only
865 // contains null bytes. However, type names cannot be full of null bytes.
866 // So cast Init to a ConstArrayAttr should be safe.
867 auto initStr = cast<cir::ConstArrayAttr>(init);
868
869 cir::GlobalOp gv = cgm.createOrReplaceCXXRuntimeVariable(
870 loc, name, initStr.getType(), linkage, align);
872 return gv;
873}
874
875mlir::Attribute
876CIRGenItaniumRTTIBuilder::getAddrOfExternalRTTIDescriptor(mlir::Location loc,
877 QualType ty) {
878 // Mangle the RTTI name.
879 SmallString<256> name;
880 llvm::raw_svector_ostream out(name);
882 CIRGenBuilderTy &builder = cgm.getBuilder();
883
884 // Look for an existing global.
885 cir::GlobalOp gv = dyn_cast_or_null<cir::GlobalOp>(cgm.getGlobalValue(name));
886
887 if (!gv) {
888 // Create a new global variable.
889 // From LLVM codegen => Note for the future: If we would ever like to do
890 // deferred emission of RTTI, check if emitting vtables opportunistically
891 // need any adjustment.
892 gv = cgm.createGlobalOp(loc, name, builder.getUInt8PtrTy(),
893 /*isConstant=*/true);
894 const CXXRecordDecl *rd = ty->getAsCXXRecordDecl();
895 cgm.setGVProperties(gv, rd);
896
897 // Import the typeinfo symbol when all non-inline virtual methods are
898 // imported.
899 if (cgm.getTarget().hasPS4DLLImportExport()) {
900 cgm.errorNYI("getAddrOfExternalRTTIDescriptor: hasPS4DLLImportExport");
901 }
902 }
903
904 return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), gv);
905}
906
907void CIRGenItaniumRTTIBuilder::buildVTablePointer(mlir::Location loc,
908 const Type *ty) {
909 CIRGenBuilderTy &builder = cgm.getBuilder();
910 const char *vTableName = vTableClassNameForType(cgm, ty);
911
912 // Check if the alias exists. If it doesn't, then get or create the global.
913 if (cgm.getLangOpts().RelativeCXXABIVTables) {
914 cgm.errorNYI("buildVTablePointer: isRelativeLayout");
915 return;
916 }
917
918 mlir::Type vtableGlobalTy = builder.getPointerTo(builder.getUInt8PtrTy());
919 llvm::Align align = cgm.getDataLayout().getABITypeAlign(vtableGlobalTy);
920 cir::GlobalOp vTable = cgm.createOrReplaceCXXRuntimeVariable(
921 loc, vTableName, vtableGlobalTy, cir::GlobalLinkageKind::ExternalLinkage,
923 // Note: createOrReplaceCXXRuntimeVariable isn't exactly what classic-codegen
924 // does here: it just does a getOrInsertGlobal at the module level. However,
925 // the above function does MOST of what we want, except it sets the global as
926 // constant, when we don't want that. So set it here instead.
927 vTable.setConstant(false);
928
929 // The vtable address point is 2.
930 mlir::Attribute field{};
931 if (cgm.getLangOpts().RelativeCXXABIVTables) {
932 cgm.errorNYI("buildVTablePointer: isRelativeLayout");
933 } else {
934 SmallVector<mlir::Attribute, 4> offsets{
935 cgm.getBuilder().getI32IntegerAttr(2)};
936 auto indices = mlir::ArrayAttr::get(builder.getContext(), offsets);
938 vTable, indices);
939 }
940
941 assert(field && "expected attribute");
942 fields.push_back(field);
943}
944
945/// Build an abi::__si_class_type_info, used for single inheritance, according
946/// to the Itanium C++ ABI, 2.95p6b.
947void CIRGenItaniumRTTIBuilder::buildSIClassTypeInfo(mlir::Location loc,
948 const CXXRecordDecl *rd) {
949 // Itanium C++ ABI 2.9.5p6b:
950 // It adds to abi::__class_type_info a single member pointing to the
951 // type_info structure for the base type,
952 mlir::Attribute baseTypeInfo =
953 CIRGenItaniumRTTIBuilder(cxxABI, cgm)
954 .buildTypeInfo(loc, rd->bases_begin()->getType());
955 fields.push_back(baseTypeInfo);
956}
957
958/// Build an abi::__vmi_class_type_info, used for
959/// classes with bases that do not satisfy the abi::__si_class_type_info
960/// constraints, according to the Itanium C++ ABI, 2.9.5p5c.
961void CIRGenItaniumRTTIBuilder::buildVMIClassTypeInfo(mlir::Location loc,
962 const CXXRecordDecl *rd) {
963 mlir::Type unsignedIntLTy =
965
966 // Itanium C++ ABI 2.9.5p6c:
967 // __flags is a word with flags describing details about the class
968 // structure, which may be referenced by using the __flags_masks
969 // enumeration. These flags refer to both direct and indirect bases.
971 fields.push_back(cir::IntAttr::get(unsignedIntLTy, flags));
972
973 // Itanium C++ ABI 2.9.5p6c:
974 // __base_count is a word with the number of direct proper base class
975 // descriptions that follow.
976 fields.push_back(cir::IntAttr::get(unsignedIntLTy, rd->getNumBases()));
977
978 if (!rd->getNumBases())
979 return;
980
981 // Now add the base class descriptions.
982
983 // Itanium C++ ABI 2.9.5p6c:
984 // __base_info[] is an array of base class descriptions -- one for every
985 // direct proper base. Each description is of the type:
986 //
987 // struct abi::__base_class_type_info {
988 // public:
989 // const __class_type_info *__base_type;
990 // long __offset_flags;
991 //
992 // enum __offset_flags_masks {
993 // __virtual_mask = 0x1,
994 // __public_mask = 0x2,
995 // __offset_shift = 8
996 // };
997 // };
998
999 // If we're in mingw and 'long' isn't wide enough for a pointer, use 'long
1000 // long' instead of 'long' for __offset_flags. libstdc++abi uses long long on
1001 // LLP64 platforms.
1002 // FIXME: Consider updating libc++abi to match, and extend this logic to all
1003 // LLP64 platforms.
1004 QualType offsetFlagsTy = cgm.getASTContext().LongTy;
1005 const TargetInfo &ti = cgm.getASTContext().getTargetInfo();
1006 if (ti.getTriple().isOSCygMing() &&
1007 ti.getPointerWidth(LangAS::Default) > ti.getLongWidth())
1008 offsetFlagsTy = cgm.getASTContext().LongLongTy;
1009 mlir::Type offsetFlagsLTy = cgm.convertType(offsetFlagsTy);
1010
1011 for (const CXXBaseSpecifier &base : rd->bases()) {
1012 // The __base_type member points to the RTTI for the base type.
1013 fields.push_back(CIRGenItaniumRTTIBuilder(cxxABI, cgm)
1014 .buildTypeInfo(loc, base.getType()));
1015
1016 CXXRecordDecl *baseDecl = base.getType()->castAsCXXRecordDecl();
1017 int64_t offsetFlags = 0;
1018
1019 // All but the lower 8 bits of __offset_flags are a signed offset.
1020 // For a non-virtual base, this is the offset in the object of the base
1021 // subobject. For a virtual base, this is the offset in the virtual table of
1022 // the virtual base offset for the virtual base referenced (negative).
1023 CharUnits offset;
1024 if (base.isVirtual())
1026 rd, baseDecl);
1027 else {
1028 const ASTRecordLayout &layout =
1030 offset = layout.getBaseClassOffset(baseDecl);
1031 }
1032 offsetFlags = uint64_t(offset.getQuantity()) << 8;
1033
1034 // The low-order byte of __offset_flags contains flags, as given by the
1035 // masks from the enumeration __offset_flags_masks.
1036 if (base.isVirtual())
1037 offsetFlags |= CodeGenUtils::BCTI_Virtual;
1038 if (base.getAccessSpecifier() == AS_public)
1039 offsetFlags |= CodeGenUtils::BCTI_Public;
1040
1041 fields.push_back(cir::IntAttr::get(offsetFlagsLTy, offsetFlags));
1042 }
1043}
1044
1045void CIRGenItaniumRTTIBuilder::buildPointerTypeInfo(mlir::Location loc,
1046 QualType ty) {
1047 // Itanium C++ ABI 2.9.4p7:
1048 // abi::__pbase_type_info is a base for both pointer types and
1049 // pointer-to-member types. It adds two data members:
1050 //
1051 // class __pbase_type_info : public std::type_info {
1052 // public:
1053 // unsigned int __flags;
1054 // const std::type_info *__pointee;
1055 //
1056 // enum __masks {
1057 // __const_mask = 0x1,
1058 // __volatile_mask = 0x2,
1059 // __restrict_mask = 0x4,
1060 // __incomplete_mask = 0x8,
1061 // __incomplete_class_mask = 0x10,
1062 // __transaction_safe_mask = 0x20
1063 // __noexcept_mask = 0x40
1064 // };
1065 // };
1066 const unsigned int flags =
1068
1069 mlir::Type unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy);
1070 mlir::Attribute flagsAttr = cir::IntAttr::get(unsignedIntTy, flags);
1071 fields.push_back(flagsAttr);
1072
1073 mlir::Attribute pointeeTypeInfo =
1074 CIRGenItaniumRTTIBuilder(cxxABI, cgm).buildTypeInfo(loc, ty);
1075 fields.push_back(pointeeTypeInfo);
1076}
1077
1078void CIRGenItaniumRTTIBuilder::buildPointerToMemberTypeInfo(
1079 mlir::Location loc, const MemberPointerType *ty) {
1080
1081 // The abi::__pointer_to_member_type_info type adds one field to
1082 // abi::__pbase_type_info:
1083 //
1084 // class __pointer_to_member_type_info : public __pbase_type_info {
1085 // public:
1086 // const abi::__class_type_info *__context;
1087 // };
1088 QualType pointeeTy = ty->getPointeeType();
1089
1090 unsigned flags =
1092
1093 const auto *rd = ty->getMostRecentCXXRecordDecl();
1094 if (!rd->hasDefinition())
1096
1097 mlir::Type unsignedIntTy = cgm.convertType(cgm.getASTContext().UnsignedIntTy);
1098 mlir::Attribute flagsAttr = cir::IntAttr::get(unsignedIntTy, flags);
1099 fields.push_back(flagsAttr);
1100
1101 mlir::Attribute pointeeTypeInfo =
1102 CIRGenItaniumRTTIBuilder(cxxABI, cgm).buildTypeInfo(loc, pointeeTy);
1103 fields.push_back(pointeeTypeInfo);
1104
1105 CanQualType contextTy = cgm.getASTContext().getCanonicalTagType(rd);
1106 mlir::Attribute classTypeInfo =
1107 CIRGenItaniumRTTIBuilder(cxxABI, cgm).buildTypeInfo(loc, contextTy);
1108 fields.push_back(classTypeInfo);
1109}
1110
1111mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(mlir::Location loc,
1112 QualType ty) {
1113 // We want to operate on the canonical type.
1114 ty = ty.getCanonicalType();
1115
1116 // Check if we've already emitted an RTTI descriptor for this type.
1117 SmallString<256> name;
1118 llvm::raw_svector_ostream out(name);
1120
1121 auto oldGV = dyn_cast_or_null<cir::GlobalOp>(cgm.getGlobalValue(name));
1122
1123 if (oldGV && !oldGV.isDeclaration()) {
1124 assert(!oldGV.hasAvailableExternallyLinkage() &&
1125 "available_externally typeinfos not yet implemented");
1127 oldGV);
1128 }
1129
1130 // Check if there is already an external RTTI descriptor for this type.
1132 shouldUseExternalRttiDescriptor(cgm, ty))
1133 return getAddrOfExternalRTTIDescriptor(loc, ty);
1134
1135 // Emit the standard library with external linkage.
1136 cir::GlobalLinkageKind linkage = getTypeInfoLinkage(cgm, ty);
1137
1138 // Give the type_info object and name the formal visibility of the
1139 // type itself.
1142
1143 mlir::SymbolTable::Visibility symVisibility;
1144 if (cir::isLocalLinkage(linkage))
1145 // If the linkage is local, only default visibility makes sense.
1146 symVisibility = mlir::SymbolTable::Visibility::Public;
1147 else if (cxxABI.classifyRTTIUniqueness(ty, linkage) ==
1148 CIRGenItaniumCXXABI::RUK_NonUniqueHidden) {
1149 cgm.errorNYI(
1150 "buildTypeInfo: classifyRTTIUniqueness == RUK_NonUniqueHidden");
1151 symVisibility = CIRGenModule::getMLIRVisibility(ty->getVisibility());
1152 } else
1153 symVisibility = CIRGenModule::getMLIRVisibility(ty->getVisibility());
1154
1155 return buildTypeInfo(loc, ty, linkage, symVisibility);
1156}
1157
1158mlir::Attribute CIRGenItaniumRTTIBuilder::buildTypeInfo(
1159 mlir::Location loc, QualType ty, cir::GlobalLinkageKind linkage,
1160 mlir::SymbolTable::Visibility visibility) {
1161 CIRGenBuilderTy &builder = cgm.getBuilder();
1162
1164
1165 // Add the vtable pointer.
1166 buildVTablePointer(loc, cast<Type>(ty));
1167
1168 // And the name.
1169 cir::GlobalOp typeName = getAddrOfTypeName(loc, ty, linkage);
1170 mlir::Attribute typeNameField;
1171
1172 // If we're supposed to demote the visibility, be sure to set a flag
1173 // to use a string comparison for type_info comparisons.
1174 CIRGenItaniumCXXABI::RTTIUniquenessKind rttiUniqueness =
1175 cxxABI.classifyRTTIUniqueness(ty, linkage);
1176 if (rttiUniqueness != CIRGenItaniumCXXABI::RUK_Unique) {
1177 // The flag is the sign bit, which on ARM64 is defined to be clear
1178 // for global pointers. This is very ARM64-specific.
1179 cgm.errorNYI(
1180 "buildTypeInfo: rttiUniqueness != CIRGenItaniumCXXABI::RUK_Unique");
1181 } else {
1182 typeNameField =
1183 builder.getGlobalViewAttr(builder.getUInt8PtrTy(), typeName);
1184 }
1185
1186 fields.push_back(typeNameField);
1187
1188 switch (ty->getTypeClass()) {
1189#define TYPE(Class, Base)
1190#define ABSTRACT_TYPE(Class, Base)
1191#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class:
1192#define NON_CANONICAL_TYPE(Class, Base) case Type::Class:
1193#define DEPENDENT_TYPE(Class, Base) case Type::Class:
1194#include "clang/AST/TypeNodes.inc"
1195 llvm_unreachable("Non-canonical and dependent types shouldn't get here");
1196
1197 // GCC treats vector types as fundamental types.
1198 case Type::Builtin:
1199 case Type::Vector:
1200 case Type::ExtVector:
1201 case Type::ConstantMatrix:
1202 case Type::Complex:
1203 case Type::BlockPointer:
1204 // Itanium C++ ABI 2.9.5p4:
1205 // abi::__fundamental_type_info adds no data members to std::type_info.
1206 break;
1207
1208 case Type::LValueReference:
1209 case Type::RValueReference:
1210 llvm_unreachable("References shouldn't get here");
1211
1212 case Type::Auto:
1213 case Type::DeducedTemplateSpecialization:
1214 llvm_unreachable("Undeduced type shouldn't get here");
1215
1216 case Type::Pipe:
1217 break;
1218
1219 case Type::BitInt:
1220 break;
1221
1222 case Type::OverflowBehavior:
1223 break;
1224
1225 case Type::ConstantArray:
1226 case Type::IncompleteArray:
1227 case Type::VariableArray:
1228 case Type::ArrayParameter:
1229 // Itanium C++ ABI 2.9.5p5:
1230 // abi::__array_type_info adds no data members to std::type_info.
1231 break;
1232
1233 case Type::FunctionNoProto:
1234 case Type::FunctionProto:
1235 // Itanium C++ ABI 2.9.5p5:
1236 // abi::__function_type_info adds no data members to std::type_info.
1237 break;
1238
1239 case Type::Enum:
1240 // Itanium C++ ABI 2.9.5p5:
1241 // abi::__enum_type_info adds no data members to std::type_info.
1242 break;
1243
1244 case Type::Record: {
1245 const auto *rd = cast<CXXRecordDecl>(cast<RecordType>(ty)->getDecl())
1246 ->getDefinitionOrSelf();
1247 if (!rd->hasDefinition() || !rd->getNumBases()) {
1248 // We don't need to emit any fields.
1249 break;
1250 }
1251
1253 buildSIClassTypeInfo(loc, rd);
1254 } else {
1255 buildVMIClassTypeInfo(loc, rd);
1256 }
1257
1258 break;
1259 }
1260
1261 case Type::ObjCObject:
1262 case Type::ObjCInterface:
1263 cgm.errorNYI("buildTypeInfo: ObjCObject & ObjCInterface");
1264 break;
1265
1266 case Type::ObjCObjectPointer:
1267 cgm.errorNYI("buildTypeInfo: ObjCObjectPointer");
1268 break;
1269
1270 case Type::Pointer:
1271 // We need to get the type info for the pointee type.
1272 buildPointerTypeInfo(loc, cast<PointerType>(ty)->getPointeeType());
1273 break;
1274
1275 case Type::MemberPointer:
1276 buildPointerToMemberTypeInfo(loc, cast<MemberPointerType>(ty));
1277 break;
1278
1279 case Type::Atomic:
1280 // No fields, at least for the moment.
1281 break;
1282
1283 case Type::HLSLAttributedResource:
1284 case Type::HLSLInlineSpirv:
1285 llvm_unreachable("HLSL doesn't support RTTI");
1286 }
1287
1289 cir::TypeInfoAttr init = builder.getTypeInfo(builder.getArrayAttr(fields));
1290
1291 SmallString<256> name;
1292 llvm::raw_svector_ostream out(name);
1294
1295 // Create new global and search for an existing global.
1296 auto oldGV = dyn_cast_or_null<cir::GlobalOp>(cgm.getGlobalValue(name));
1297
1298 cir::GlobalOp gv = cgm.createGlobalOp(loc, name, init.getType(),
1299 /*isConstant=*/true);
1300 gv.setLinkage(linkage);
1301
1302 // Export the typeinfo in the same circumstances as the vtable is
1303 // exported.
1304 if (cgm.getTarget().hasPS4DLLImportExport()) {
1305 cgm.errorNYI("buildTypeInfo: target hasPS4DLLImportExport");
1306 return {};
1307 }
1308
1309 // If there's already an old global variable, replace it with the new one.
1310 if (oldGV) {
1311 // Replace occurrences of the old variable if needed.
1312 gv.setName(oldGV.getName());
1313 if (!oldGV->use_empty()) {
1314 cgm.errorNYI("buildTypeInfo: old GV !use_empty");
1315 return {};
1316 }
1317 cgm.eraseGlobalSymbol(oldGV);
1318 oldGV->erase();
1319 }
1320
1321 if (cgm.supportsCOMDAT() && cir::isWeakForLinker(linkage))
1322 gv.setSelfComdat();
1323
1324 CharUnits align = cgm.getASTContext().toCharUnitsFromBits(
1325 cgm.getTarget().getPointerAlign(LangAS::Default));
1326 gv.setAlignmentAttr(cgm.getSize(align));
1327
1328 // The Itanium ABI specifies that type_info objects must be globally
1329 // unique, with one exception: if the type is an incomplete class
1330 // type or a (possibly indirect) pointer to one. That exception
1331 // affects the general case of comparing type_info objects produced
1332 // by the typeid operator, which is why the comparison operators on
1333 // std::type_info generally use the type_info name pointers instead
1334 // of the object addresses. However, the language's built-in uses
1335 // of RTTI generally require class types to be complete, even when
1336 // manipulating pointers to those class types. This allows the
1337 // implementation of dynamic_cast to rely on address equality tests,
1338 // which is much faster.
1339
1340 // All of this is to say that it's important that both the type_info
1341 // object and the type_info name be uniqued when weakly emitted.
1342
1343 mlir::SymbolTable::setSymbolVisibility(typeName, visibility);
1347
1348 mlir::SymbolTable::setSymbolVisibility(gv, visibility);
1352
1354 return builder.getGlobalViewAttr(builder.getUInt8PtrTy(), gv);
1355}
1356
1357bool CIRGenItaniumCXXABI::shouldTypeidBeNullChecked(QualType srcTy) {
1358 return true;
1359}
1360
1361void CIRGenItaniumCXXABI::emitBadTypeidCall(CIRGenFunction &cgf,
1362 mlir::Location loc) {
1363 // void __cxa_bad_typeid();
1364 cir::FuncType fnTy =
1365 cgf.getBuilder().getFuncType({}, cgf.getBuilder().getVoidTy());
1366 mlir::NamedAttrList attrs;
1367 attrs.set(cir::CIRDialect::getNoReturnAttrName(),
1368 mlir::UnitAttr::get(&cgf.cgm.getMLIRContext()));
1369
1370 cgf.emitRuntimeCall(
1371 loc, cgf.cgm.createRuntimeFunction(fnTy, "__cxa_bad_typeid", attrs), {},
1372 attrs);
1373 cir::UnreachableOp::create(cgf.getBuilder(), loc);
1374}
1375
1376mlir::Value CIRGenItaniumCXXABI::emitTypeid(CIRGenFunction &cgf, QualType srcTy,
1377 Address thisPtr,
1378 mlir::Type typeInfoPtrTy) {
1379 auto *classDecl = srcTy->castAsCXXRecordDecl();
1380 mlir::Location loc = cgm.getLoc(classDecl->getSourceRange());
1381 mlir::Value vptr = cgf.getVTablePtr(loc, thisPtr, classDecl);
1382 mlir::Value vtbl;
1383
1384 // TODO(cir): In classic codegen relative layouts cause us to do a
1385 // 'load_relative' of -4 here. We probably don't want to reprensent this in
1386 // CIR at all, but we should have the NYI here since this could be
1387 // meaningful/notable for implementation of relative layout in the future.
1388 if (cgm.getLangOpts().RelativeCXXABIVTables)
1389 cgm.errorNYI("buildVTablePointer: isRelativeLayout");
1390 else
1391 vtbl = cir::VTableGetTypeInfoOp::create(
1392 cgf.getBuilder(), loc, cgf.getBuilder().getPointerTo(typeInfoPtrTy),
1393 vptr);
1394
1395 return cgf.getBuilder().createAlignedLoad(loc, typeInfoPtrTy, vtbl,
1396 cgf.getPointerAlign());
1397}
1398
1399mlir::Attribute CIRGenItaniumCXXABI::getAddrOfRTTIDescriptor(mlir::Location loc,
1400 QualType ty) {
1401 return CIRGenItaniumRTTIBuilder(*this, cgm).buildTypeInfo(loc, ty);
1402}
1403
1404/// What sort of uniqueness rules should we use for the RTTI for the
1405/// given type?
1406CIRGenItaniumCXXABI::RTTIUniquenessKind
1407CIRGenItaniumCXXABI::classifyRTTIUniqueness(
1408 QualType canTy, cir::GlobalLinkageKind linkage) const {
1409 if (shouldRTTIBeUnique())
1410 return RUK_Unique;
1411
1412 // It's only necessary for linkonce_odr or weak_odr linkage.
1413 if (linkage != cir::GlobalLinkageKind::LinkOnceODRLinkage &&
1414 linkage != cir::GlobalLinkageKind::WeakODRLinkage)
1415 return RUK_Unique;
1416
1417 // It's only necessary with default visibility.
1418 if (canTy->getVisibility() != DefaultVisibility)
1419 return RUK_Unique;
1420
1421 // If we're not required to publish this symbol, hide it.
1422 if (linkage == cir::GlobalLinkageKind::LinkOnceODRLinkage)
1423 return RUK_NonUniqueHidden;
1424
1425 // If we're required to publish this symbol, as we might be under an
1426 // explicit instantiation, leave it with default visibility but
1427 // enable string-comparisons.
1428 assert(linkage == cir::GlobalLinkageKind::WeakODRLinkage);
1429 return RUK_NonUniqueVisible;
1430}
1431
1432void CIRGenItaniumCXXABI::emitDestructorCall(
1433 CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,
1434 bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) {
1435 GlobalDecl gd(dd, type);
1436 mlir::Value vtt =
1437 getCXXDestructorImplicitParam(cgf, dd, type, forVirtualBase, delegating);
1438 ASTContext &astContext = cgm.getASTContext();
1439 QualType vttTy = astContext.getPointerType(astContext.VoidPtrTy);
1441 CIRGenCallee callee =
1443
1444 cgf.emitCXXDestructorCall(gd, callee, thisAddr.getPointer(), thisTy, vtt,
1445 vttTy, nullptr);
1446}
1447
1448void CIRGenItaniumCXXABI::registerGlobalDtor(const VarDecl *vd,
1449 cir::FuncOp dtor,
1450 mlir::Value addr) {
1451 if (vd->isNoDestroy(cgm.getASTContext()))
1452 return;
1453
1454 // HLSL doesn't support atexit.
1455 if (cgm.getLangOpts().HLSL) {
1456 cgm.errorNYI(vd->getSourceRange(), "registerGlobalDtor: HLSL");
1457 return;
1458 }
1459
1460 // The default behavior is to use atexit. This is handled in lowering
1461 // prepare. Nothing to be done for CIR here.
1462}
1463
1464mlir::Value CIRGenItaniumCXXABI::getCXXDestructorImplicitParam(
1465 CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type,
1466 bool forVirtualBase, bool delegating) {
1467 GlobalDecl gd(dd, type);
1468 return cgf.getVTTParameter(gd, forVirtualBase, delegating);
1469}
1470
1471// The idea here is creating a separate block for the throw with an
1472// `UnreachableOp` as the terminator. So, we branch from the current block
1473// to the throw block and create a block for the remaining operations.
1474static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc,
1475 mlir::Value exceptionPtr = {},
1476 mlir::FlatSymbolRefAttr typeInfo = {},
1477 mlir::FlatSymbolRefAttr dtor = {}) {
1478 mlir::Block *currentBlock = builder.getInsertionBlock();
1479 mlir::Region *region = currentBlock->getParent();
1480
1481 if (currentBlock->empty()) {
1482 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
1483 cir::UnreachableOp::create(builder, loc);
1484 } else {
1485 mlir::Block *throwBlock = builder.createBlock(region);
1486
1487 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
1488 cir::UnreachableOp::create(builder, loc);
1489
1490 builder.setInsertionPointToEnd(currentBlock);
1491 cir::BrOp::create(builder, loc, throwBlock);
1492 }
1493
1494 (void)builder.createBlock(region);
1495}
1496
1497void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &cgf, bool isNoReturn) {
1498 // void __cxa_rethrow();
1499 if (isNoReturn) {
1500 CIRGenBuilderTy &builder = cgf.getBuilder();
1501 assert(cgf.currSrcLoc && "expected source location");
1502 mlir::Location loc = cgf.getLoc(*cgf.currSrcLoc);
1503 insertThrowAndSplit(builder, loc);
1504 } else {
1505 cgm.errorNYI("emitRethrow with isNoReturn false");
1506 }
1507}
1508
1509void CIRGenItaniumCXXABI::emitThrow(CIRGenFunction &cgf,
1510 const CXXThrowExpr *e) {
1511 // This differs a bit from LLVM codegen, CIR has native operations for some
1512 // cxa functions, and defers allocation size computation, always pass the dtor
1513 // symbol, etc. CIRGen also does not use getAllocateExceptionFn / getThrowFn.
1514
1515 // Now allocate the exception object.
1516 CIRGenBuilderTy &builder = cgf.getBuilder();
1517 QualType clangThrowType = e->getSubExpr()->getType();
1518 cir::PointerType throwTy =
1519 builder.getPointerTo(cgf.convertType(clangThrowType));
1520 uint64_t typeSize =
1521 cgf.getContext().getTypeSizeInChars(clangThrowType).getQuantity();
1522 mlir::Location subExprLoc = cgf.getLoc(e->getSubExpr()->getSourceRange());
1523
1524 // Defer computing allocation size to some later lowering pass.
1525 mlir::TypedValue<cir::PointerType> exceptionPtr =
1526 cir::AllocExceptionOp::create(builder, subExprLoc, throwTy,
1527 builder.getI64IntegerAttr(typeSize))
1528 .getAddr();
1529
1530 // Build expression and store its result into exceptionPtr.
1531 CharUnits exnAlign = cgf.getContext().getExnObjectAlignment();
1532 cgf.emitAnyExprToExn(e->getSubExpr(), Address(exceptionPtr, exnAlign));
1533
1534 // Get the RTTI symbol address.
1535 auto typeInfo = mlir::cast<cir::GlobalViewAttr>(
1536 cgm.getAddrOfRTTIDescriptor(subExprLoc, clangThrowType,
1537 /*forEH=*/true));
1538 assert(!typeInfo.getIndices() && "expected no indirection");
1539
1540 // The address of the destructor.
1541 //
1542 // Note: LLVM codegen already optimizes out the dtor if the
1543 // type is a record with trivial dtor (by passing down a
1544 // null dtor). In CIR, we forward this info and allow for
1545 // Lowering pass to skip passing the trivial function.
1546 //
1547 const auto *cxxrd = clangThrowType->getAsCXXRecordDecl();
1548 mlir::FlatSymbolRefAttr dtor{};
1549 if (cxxrd && !cxxrd->hasTrivialDestructor()) {
1550 // __cxa_throw is declared to take its destructor as void (*)(void *). We
1551 // must match that if function pointers can be authenticated with a
1552 // discriminator based on their type.
1554 CXXDestructorDecl *dtorD = cxxrd->getDestructor();
1555 dtor = mlir::FlatSymbolRefAttr::get(
1556 cgm.getAddrOfCXXStructor(GlobalDecl(dtorD, Dtor_Complete))
1557 .getSymNameAttr());
1558 }
1559
1560 // Now throw the exception.
1561 mlir::Location loc = cgf.getLoc(e->getSourceRange());
1562 insertThrowAndSplit(builder, loc, exceptionPtr, typeInfo.getSymbol(), dtor);
1563}
1564
1566 switch (cgm.getASTContext().getCXXABIKind()) {
1567 case TargetCXXABI::GenericItanium:
1568 case TargetCXXABI::GenericAArch64:
1569 case TargetCXXABI::GenericARM:
1570 return new CIRGenItaniumCXXABI(cgm);
1571
1572 case TargetCXXABI::AppleARM64:
1573 // The general Itanium ABI will do until we implement something that
1574 // requires special handling.
1576 return new CIRGenItaniumCXXABI(cgm);
1577
1578 default:
1579 llvm_unreachable("bad or NYI ABI kind");
1580 }
1581}
1582
1583cir::GlobalOp CIRGenItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *rd,
1584 CharUnits vptrOffset) {
1585 assert(vptrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");
1586 cir::GlobalOp &vtable = vtables[rd];
1587 if (vtable)
1588 return vtable;
1589
1590 // Queue up this vtable for possible deferred emission.
1591 cgm.addDeferredVTable(rd);
1592
1593 SmallString<256> name;
1594 llvm::raw_svector_ostream out(name);
1595 getMangleContext().mangleCXXVTable(rd, out);
1596
1597 const VTableLayout &vtLayout =
1599 mlir::Type vtableType = cgm.getVTables().getVTableType(vtLayout);
1600
1601 // Use pointer alignment for the vtable. Otherwise we would align them based
1602 // on the size of the initializer which doesn't make sense as only single
1603 // values are read.
1604 unsigned ptrAlign = cgm.getLangOpts().RelativeCXXABIVTables
1605 ? 32
1607
1609 cgm.getLoc(rd->getSourceRange()), name, vtableType,
1610 cir::GlobalLinkageKind::ExternalLinkage,
1611 cgm.getASTContext().toCharUnitsFromBits(ptrAlign));
1612 // LLVM codegen handles unnamedAddr
1614
1615 // In MS C++ if you have a class with virtual functions in which you are using
1616 // selective member import/export, then all virtual functions must be exported
1617 // unless they are inline, otherwise a link error will result. To match this
1618 // behavior, for such classes, we dllimport the vtable if it is defined
1619 // externally and all the non-inline virtual methods are marked dllimport, and
1620 // we dllexport the vtable if it is defined in this TU and all the non-inline
1621 // virtual methods are marked dllexport.
1622 if (cgm.getTarget().hasPS4DLLImportExport())
1623 cgm.errorNYI(rd->getSourceRange(),
1624 "getAddrOfVTable: PS4 DLL import/export");
1625
1626 cgm.setGVProperties(vtable, rd);
1627 return vtable;
1628}
1629
1630CIRGenCallee CIRGenItaniumCXXABI::getVirtualFunctionPointer(
1631 CIRGenFunction &cgf, clang::GlobalDecl gd, Address thisAddr, mlir::Type ty,
1632 SourceLocation srcLoc) {
1633 CIRGenBuilderTy &builder = cgm.getBuilder();
1634 mlir::Location loc = cgf.getLoc(srcLoc);
1635 cir::PointerType tyPtr = builder.getPointerTo(ty);
1636 auto *methodDecl = cast<CXXMethodDecl>(gd.getDecl());
1637 mlir::Value vtable = cgf.getVTablePtr(loc, thisAddr, methodDecl->getParent());
1638
1639 uint64_t vtableIndex = cgm.getItaniumVTableContext().getMethodVTableIndex(gd);
1640 mlir::Value vfunc{};
1641 if (cgf.shouldEmitVTableTypeCheckedLoad(methodDecl->getParent())) {
1642 cgm.errorNYI(loc, "getVirtualFunctionPointer: emitVTableTypeCheckedLoad");
1643 } else {
1645
1646 mlir::Value vfuncLoad;
1647 if (cgm.getLangOpts().RelativeCXXABIVTables) {
1649 cgm.errorNYI(loc, "getVirtualFunctionPointer: isRelativeLayout");
1650 } else {
1651 auto vtableSlotPtr = cir::VTableGetVirtualFnAddrOp::create(
1652 builder, loc, builder.getPointerTo(tyPtr), vtable, vtableIndex);
1653 vfuncLoad = builder.createAlignedLoad(loc, tyPtr, vtableSlotPtr,
1654 cgf.getPointerAlign());
1655 }
1656
1657 // Set invariant on the cir.load of virtual function pointer to indicate
1658 // that function didn't change inside vtable.
1659 // It's safe to add it without -fstrict-vtable-pointers, but it would not
1660 // help in devirtualization because it will only matter if we will have 2
1661 // the same virtual function loads from the same vtable load, which won't
1662 // happen without enabled devirtualization with -fstrict-vtable-pointers.
1663 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
1664 cgm.getCodeGenOpts().StrictVTablePointers)
1665 if (auto loadOp = vfuncLoad.getDefiningOp<cir::LoadOp>())
1666 loadOp.setInvariant(true);
1667
1668 vfunc = vfuncLoad;
1669 }
1670
1671 CIRGenCallee callee(gd, vfunc.getDefiningOp());
1672 return callee;
1673}
1674
1675mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
1676 CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base,
1677 const CXXRecordDecl *nearestVBase) {
1678 assert((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&
1679 needsVTTParameter(cgf.curGD) && "This class doesn't have VTT");
1680
1681 // Get the secondary vpointer index.
1682 uint64_t virtualPointerIndex =
1683 cgm.getVTables().getSecondaryVirtualPointerIndex(vtableClass, base);
1684
1685 /// Load the VTT.
1686 mlir::Value vttPtr = cgf.loadCXXVTT();
1687 mlir::Location loc = cgf.getLoc(vtableClass->getSourceRange());
1688 // Calculate the address point from the VTT, and the offset may be zero.
1689 vttPtr = cgf.getBuilder().createVTTAddrPoint(loc, vttPtr.getType(), vttPtr,
1690 virtualPointerIndex);
1691 // And load the address point from the VTT.
1692 auto vptrType = cir::VPtrType::get(cgf.getBuilder().getContext());
1693 return cgf.getBuilder().createAlignedLoad(loc, vptrType, vttPtr,
1694 cgf.getPointerAlign());
1695}
1696
1697mlir::Value
1698CIRGenItaniumCXXABI::getVTableAddressPoint(BaseSubobject base,
1699 const CXXRecordDecl *vtableClass) {
1700 cir::GlobalOp vtable = getAddrOfVTable(vtableClass, CharUnits());
1701
1702 // Find the appropriate vtable within the vtable group, and the address point
1703 // within that vtable.
1704 VTableLayout::AddressPointLocation addressPoint =
1706 .getVTableLayout(vtableClass)
1707 .getAddressPoint(base);
1708
1709 mlir::OpBuilder &builder = cgm.getBuilder();
1710 auto vtablePtrTy = cir::VPtrType::get(builder.getContext());
1711
1712 return cir::VTableAddrPointOp::create(
1713 builder, cgm.getLoc(vtableClass->getSourceRange()), vtablePtrTy,
1714 mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()),
1715 cir::AddressPointAttr::get(cgm.getBuilder().getContext(),
1716 addressPoint.VTableIndex,
1717 addressPoint.AddressPointIndex));
1718}
1719
1720cir::GlobalViewAttr CIRGenItaniumCXXABI::getVTableAddressPointAttr(
1721 BaseSubobject base, const CXXRecordDecl *vtableClass) {
1722 cir::GlobalOp vtable = getAddrOfVTable(vtableClass, CharUnits());
1723
1724 // Find the appropriate vtable within the vtable group, and the address point
1725 // within that vtable.
1726 VTableLayout::AddressPointLocation addressPoint =
1728 .getVTableLayout(vtableClass)
1729 .getAddressPoint(base);
1730
1731 CIRGenBuilderTy &builder = cgm.getBuilder();
1732 mlir::ArrayAttr indices = builder.getArrayAttr(
1733 {builder.getI32IntegerAttr(addressPoint.VTableIndex),
1734 builder.getI32IntegerAttr(addressPoint.AddressPointIndex)});
1735 return cir::GlobalViewAttr::get(
1736 cir::VPtrType::get(builder.getContext()),
1737 mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()), indices,
1738 /*addressPoint=*/true);
1739}
1740
1741mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructor(
1742 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,
1743 clang::BaseSubobject base, const clang::CXXRecordDecl *nearestVBase) {
1744
1745 if ((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&
1746 needsVTTParameter(cgf.curGD)) {
1747 return getVTableAddressPointInStructorWithVTT(cgf, vtableClass, base,
1748 nearestVBase);
1749 }
1750 return getVTableAddressPoint(base, vtableClass);
1751}
1752
1753bool CIRGenItaniumCXXABI::isVirtualOffsetNeededForVTableField(
1754 CIRGenFunction &cgf, CIRGenFunction::VPtr vptr) {
1755 if (vptr.nearestVBase == nullptr)
1756 return false;
1757 return needsVTTParameter(cgf.curGD);
1758}
1759
1760mlir::Value CIRGenItaniumCXXABI::getVirtualBaseClassOffset(
1761 mlir::Location loc, CIRGenFunction &cgf, Address thisAddr,
1762 const CXXRecordDecl *classDecl, const CXXRecordDecl *baseClassDecl) {
1763 CIRGenBuilderTy &builder = cgf.getBuilder();
1764 mlir::Value vtablePtr = cgf.getVTablePtr(loc, thisAddr, classDecl);
1765 mlir::Value vtableBytePtr = builder.createBitcast(vtablePtr, cgm.uInt8PtrTy);
1766 CharUnits vbaseOffsetOffset =
1768 baseClassDecl);
1769 mlir::Value offsetVal =
1770 builder.getSInt64(vbaseOffsetOffset.getQuantity(), loc);
1771 auto vbaseOffsetPtr = cir::PtrStrideOp::create(builder, loc, cgm.uInt8PtrTy,
1772 vtableBytePtr, offsetVal);
1773
1774 mlir::Value vbaseOffset;
1775 if (cgm.getLangOpts().RelativeCXXABIVTables) {
1777 cgm.errorNYI(loc, "getVirtualBaseClassOffset: relative layout");
1778 } else {
1779 mlir::Value offsetPtr = builder.createBitcast(
1780 vbaseOffsetPtr, builder.getPointerTo(cgm.ptrDiffTy));
1781 vbaseOffset = builder.createLoad(
1782 loc, Address(offsetPtr, cgm.ptrDiffTy, cgf.getPointerAlign()));
1783 }
1784 return vbaseOffset;
1785}
1786
1787static cir::FuncOp getBadCastFn(CIRGenFunction &cgf) {
1788 // Prototype: void __cxa_bad_cast();
1789
1790 // TODO(cir): set the calling convention of the runtime function.
1792
1793 cir::FuncType fnTy =
1794 cgf.getBuilder().getFuncType({}, cgf.getBuilder().getVoidTy());
1795 return cgf.cgm.createRuntimeFunction(fnTy, "__cxa_bad_cast");
1796}
1797
1798static void emitCallToBadCast(CIRGenFunction &cgf, mlir::Location loc) {
1799 // TODO(cir): set the calling convention to the runtime function.
1801
1802 mlir::NamedAttrList attrs;
1803 attrs.set(cir::CIRDialect::getNoReturnAttrName(),
1804 mlir::UnitAttr::get(&cgf.cgm.getMLIRContext()));
1805
1806 cgf.emitRuntimeCall(loc, getBadCastFn(cgf), {}, attrs);
1807 cir::UnreachableOp::create(cgf.getBuilder(), loc);
1808 cgf.getBuilder().clearInsertionPoint();
1809}
1810
1811void CIRGenItaniumCXXABI::emitBadCastCall(CIRGenFunction &cgf,
1812 mlir::Location loc) {
1813 emitCallToBadCast(cgf, loc);
1814}
1815
1816static cir::FuncOp getItaniumDynamicCastFn(CIRGenFunction &cgf) {
1817 // Prototype:
1818 // void *__dynamic_cast(const void *sub,
1819 // global_as const abi::__class_type_info *src,
1820 // global_as const abi::__class_type_info *dst,
1821 // std::ptrdiff_t src2dst_offset);
1822
1823 mlir::Type voidPtrTy = cgf.getBuilder().getVoidPtrTy();
1824 mlir::Type rttiPtrTy = cgf.getBuilder().getUInt8PtrTy();
1825 mlir::Type ptrDiffTy = cgf.convertType(cgf.getContext().getPointerDiffType());
1826
1827 // TODO(cir): mark the function as willreturn readonly.
1830
1831 // TODO(cir): set the calling convention of the runtime function.
1833
1834 cir::FuncType FTy = cgf.getBuilder().getFuncType(
1835 {voidPtrTy, rttiPtrTy, rttiPtrTy, ptrDiffTy}, voidPtrTy);
1836 cir::FuncOp fn = cgf.cgm.createRuntimeFunction(FTy, "__dynamic_cast");
1837 fn->setAttr(cir::CIRDialect::getNoThrowAttrName(),
1838 mlir::UnitAttr::get(cgf.getBuilder().getContext()));
1839 return fn;
1840}
1841
1842static Address emitDynamicCastToVoid(CIRGenFunction &cgf, mlir::Location loc,
1843 QualType srcRecordTy, Address src) {
1844 bool vtableUsesRelativeLayout = cgf.cgm.getLangOpts().RelativeCXXABIVTables;
1845 mlir::Value ptr = cgf.getBuilder().createDynCastToVoid(
1846 loc, src.getPointer(), vtableUsesRelativeLayout);
1847 return Address{ptr, src.getAlignment()};
1848}
1849
1850static mlir::Value emitExactDynamicCast(CIRGenItaniumCXXABI &abi,
1851 CIRGenFunction &cgf, mlir::Location loc,
1852 QualType srcRecordTy,
1853 QualType destRecordTy,
1854 cir::PointerType destCIRTy,
1855 bool isRefCast, Address src) {
1856 // Find all the inheritance paths from SrcRecordTy to DestRecordTy.
1857 const CXXRecordDecl *srcDecl = srcRecordTy->getAsCXXRecordDecl();
1858 const CXXRecordDecl *destDecl = destRecordTy->getAsCXXRecordDecl();
1859 CXXBasePaths paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
1860 /*DetectVirtual=*/false);
1861 (void)destDecl->isDerivedFrom(srcDecl, paths);
1862
1863 // Find an offset within `destDecl` where a `srcDecl` instance and its vptr
1864 // might appear.
1865 std::optional<CharUnits> offset;
1866 for (const CXXBasePath &path : paths) {
1867 // dynamic_cast only finds public inheritance paths.
1868 if (path.Access != AS_public)
1869 continue;
1870
1871 CharUnits pathOffset;
1872 for (const CXXBasePathElement &pathElement : path) {
1873 // Find the offset along this inheritance step.
1874 const CXXRecordDecl *base =
1875 pathElement.Base->getType()->getAsCXXRecordDecl();
1876 if (pathElement.Base->isVirtual()) {
1877 // For a virtual base class, we know that the derived class is exactly
1878 // destDecl, so we can use the vbase offset from its layout.
1879 const ASTRecordLayout &layout =
1880 cgf.getContext().getASTRecordLayout(destDecl);
1881 pathOffset = layout.getVBaseClassOffset(base);
1882 } else {
1883 const ASTRecordLayout &layout =
1884 cgf.getContext().getASTRecordLayout(pathElement.Class);
1885 pathOffset += layout.getBaseClassOffset(base);
1886 }
1887 }
1888
1889 if (!offset) {
1890 offset = pathOffset;
1891 } else if (offset != pathOffset) {
1892 // base appears in at least two different places. Find the most-derived
1893 // object and see if it's a DestDecl. Note that the most-derived object
1894 // must be at least as aligned as this base class subobject, and must
1895 // have a vptr at offset 0.
1896 src = emitDynamicCastToVoid(cgf, loc, srcRecordTy, src);
1897 srcDecl = destDecl;
1898 offset = CharUnits::Zero();
1899 break;
1900 }
1901 }
1902
1903 CIRGenBuilderTy &builder = cgf.getBuilder();
1904
1905 if (!offset) {
1906 // If there are no public inheritance paths, the cast always fails.
1907 mlir::Value nullPtrValue = builder.getNullPtr(destCIRTy, loc);
1908 if (isRefCast) {
1909 mlir::Region *currentRegion = builder.getBlock()->getParent();
1910 emitCallToBadCast(cgf, loc);
1911
1912 // The call to bad_cast will terminate the block. Create a new block to
1913 // hold any follow up code.
1914 builder.createBlock(currentRegion, currentRegion->end());
1915 }
1916
1917 return nullPtrValue;
1918 }
1919
1920 // Compare the vptr against the expected vptr for the destination type at
1921 // this offset. Note that we do not know what type src points to in the case
1922 // where the derived class multiply inherits from the base class so we can't
1923 // use getVTablePtr, so we load the vptr directly instead.
1924
1925 mlir::Value expectedVPtr =
1926 abi.getVTableAddressPoint(BaseSubobject(srcDecl, *offset), destDecl);
1927
1928 // TODO(cir): handle address space here.
1930 mlir::Type vptrTy = expectedVPtr.getType();
1931 mlir::Type vptrPtrTy = builder.getPointerTo(vptrTy);
1932 Address srcVPtrPtr(builder.createBitcast(src.getPointer(), vptrPtrTy),
1933 src.getAlignment());
1934 mlir::Value srcVPtr = builder.createLoad(loc, srcVPtrPtr);
1935
1936 // TODO(cir): decorate SrcVPtr with TBAA info.
1938
1939 mlir::Value success =
1940 builder.createCompare(loc, cir::CmpOpKind::eq, srcVPtr, expectedVPtr);
1941
1942 auto emitCastResult = [&] {
1943 if (offset->isZero())
1944 return builder.createBitcast(src.getPointer(), destCIRTy);
1945
1946 // TODO(cir): handle address space here.
1948 mlir::Type u8PtrTy = builder.getUInt8PtrTy();
1949
1950 mlir::Value strideToApply =
1951 builder.getConstInt(loc, builder.getUInt64Ty(), -offset->getQuantity());
1952 mlir::Value srcU8Ptr = builder.createBitcast(src.getPointer(), u8PtrTy);
1953 mlir::Value resultU8Ptr = cir::PtrStrideOp::create(builder, loc, u8PtrTy,
1954 srcU8Ptr, strideToApply);
1955 return builder.createBitcast(resultU8Ptr, destCIRTy);
1956 };
1957
1958 if (isRefCast) {
1959 mlir::Value failed = builder.createNot(success);
1960 cir::IfOp::create(builder, loc, failed, /*withElseRegion=*/false,
1961 [&](mlir::OpBuilder &, mlir::Location) {
1962 emitCallToBadCast(cgf, loc);
1963 });
1964 return emitCastResult();
1965 }
1966
1967 return cir::TernaryOp::create(
1968 builder, loc, success,
1969 [&](mlir::OpBuilder &, mlir::Location) {
1970 auto result = emitCastResult();
1971 builder.createYield(loc, result);
1972 },
1973 [&](mlir::OpBuilder &, mlir::Location) {
1974 mlir::Value nullPtrValue = builder.getNullPtr(destCIRTy, loc);
1975 builder.createYield(loc, nullPtrValue);
1976 })
1977 .getResult();
1978}
1979
1980static cir::DynamicCastInfoAttr emitDynamicCastInfo(CIRGenFunction &cgf,
1981 mlir::Location loc,
1982 QualType srcRecordTy,
1983 QualType destRecordTy) {
1984 auto srcRtti = mlir::cast<cir::GlobalViewAttr>(
1985 cgf.cgm.getAddrOfRTTIDescriptor(loc, srcRecordTy.getUnqualifiedType()));
1986 auto destRtti = mlir::cast<cir::GlobalViewAttr>(
1987 cgf.cgm.getAddrOfRTTIDescriptor(loc, destRecordTy.getUnqualifiedType()));
1988
1989 cir::FuncOp runtimeFuncOp = getItaniumDynamicCastFn(cgf);
1990 cir::FuncOp badCastFuncOp = getBadCastFn(cgf);
1991 auto runtimeFuncRef = mlir::FlatSymbolRefAttr::get(runtimeFuncOp);
1992 auto badCastFuncRef = mlir::FlatSymbolRefAttr::get(badCastFuncOp);
1993
1994 const CXXRecordDecl *srcDecl = srcRecordTy->getAsCXXRecordDecl();
1995 const CXXRecordDecl *destDecl = destRecordTy->getAsCXXRecordDecl();
1996 CharUnits offsetHint =
1997 CodeGenUtils::computeOffsetHint(cgf.getContext(), srcDecl, destDecl);
1998
1999 mlir::Type ptrdiffTy = cgf.convertType(cgf.getContext().getPointerDiffType());
2000 auto offsetHintAttr = cir::IntAttr::get(ptrdiffTy, offsetHint.getQuantity());
2001
2002 return cir::DynamicCastInfoAttr::get(srcRtti, destRtti, runtimeFuncRef,
2003 badCastFuncRef, offsetHintAttr);
2004}
2005
2006mlir::Value CIRGenItaniumCXXABI::emitDynamicCast(CIRGenFunction &cgf,
2007 mlir::Location loc,
2008 QualType srcRecordTy,
2009 QualType destRecordTy,
2010 cir::PointerType destCIRTy,
2011 bool isRefCast, Address src) {
2012 bool isCastToVoid = destRecordTy.isNull();
2013 assert((!isCastToVoid || !isRefCast) && "cannot cast to void reference");
2014
2015 if (isCastToVoid)
2016 return emitDynamicCastToVoid(cgf, loc, srcRecordTy, src).getPointer();
2017
2018 // If the destination is effectively final, the cast succeeds if and only
2019 // if the dynamic type of the pointer is exactly the destination type.
2020 if (destRecordTy->getAsCXXRecordDecl()->isEffectivelyFinal() &&
2021 cgf.cgm.getCodeGenOpts().OptimizationLevel > 0) {
2022 CIRGenBuilderTy &builder = cgf.getBuilder();
2023 // If this isn't a reference cast, check the pointer to see if it's null.
2024 if (!isRefCast) {
2025 mlir::Value srcPtrIsNull = builder.createPtrIsNull(src.getPointer());
2026 return cir::TernaryOp::create(
2027 builder, loc, srcPtrIsNull,
2028 [&](mlir::OpBuilder, mlir::Location) {
2029 builder.createYield(
2030 loc, builder.getNullPtr(destCIRTy, loc).getResult());
2031 },
2032 [&](mlir::OpBuilder &, mlir::Location) {
2033 mlir::Value exactCast = emitExactDynamicCast(
2034 *this, cgf, loc, srcRecordTy, destRecordTy, destCIRTy,
2035 isRefCast, src);
2036 builder.createYield(loc, exactCast);
2037 })
2038 .getResult();
2039 }
2040
2041 return emitExactDynamicCast(*this, cgf, loc, srcRecordTy, destRecordTy,
2042 destCIRTy, isRefCast, src);
2043 }
2044
2045 cir::DynamicCastInfoAttr castInfo =
2046 emitDynamicCastInfo(cgf, loc, srcRecordTy, destRecordTy);
2047 return cgf.getBuilder().createDynCast(loc, src.getPointer(), destCIRTy,
2048 isRefCast, castInfo);
2049}
2050
2051cir::MethodAttr
2052CIRGenItaniumCXXABI::buildVirtualMethodAttr(cir::MethodType methodTy,
2053 const CXXMethodDecl *md) {
2054 assert(md->isVirtual() && "only deal with virtual member functions");
2055
2057 uint64_t vtableOffset;
2058 if (cgm.getLangOpts().RelativeCXXABIVTables) {
2059 // Multiply by 4-byte relative offsets.
2060 vtableOffset = index * 4;
2061 } else {
2062 const ASTContext &astContext = cgm.getASTContext();
2063 CharUnits pointerWidth = astContext.toCharUnitsFromBits(
2064 astContext.getTargetInfo().getPointerWidth(LangAS::Default));
2065 vtableOffset = index * pointerWidth.getQuantity();
2066 }
2067
2068 return cir::MethodAttr::get(methodTy, vtableOffset);
2069}
2070/// The Itanium ABI always places an offset to the complete object
2071/// at entry -2 in the vtable.
2072void CIRGenItaniumCXXABI::emitVirtualObjectDelete(
2073 CIRGenFunction &cgf, const CXXDeleteExpr *delExpr, Address ptr,
2074 QualType elementType, const CXXDestructorDecl *dtor) {
2075 bool useGlobalDelete = delExpr->isGlobalDelete();
2076 if (useGlobalDelete) {
2077 cgf.cgm.errorNYI(delExpr->getSourceRange(),
2078 "emitVirtualObjectDelete: global delete");
2079 }
2080
2081 CXXDtorType dtorType = useGlobalDelete ? Dtor_Complete : Dtor_Deleting;
2082 emitVirtualDestructorCall(cgf, dtor, dtorType, ptr, delExpr);
2083}
2084
2085/************************** Array allocation cookies **************************/
2086
2087CharUnits CIRGenItaniumCXXABI::getArrayCookieSizeImpl(QualType elementType) {
2088 // The array cookie is a size_t; pad that up to the element alignment.
2089 // The cookie is actually right-justified in that space.
2090 return std::max(
2091 cgm.getSizeSize(),
2092 cgm.getASTContext().getPreferredTypeAlignInChars(elementType));
2093}
2094
2095Address CIRGenItaniumCXXABI::initializeArrayCookie(CIRGenFunction &cgf,
2096 Address newPtr,
2097 mlir::Value numElements,
2098 const CXXNewExpr *e,
2099 QualType elementType) {
2100 assert(requiresArrayCookie(e));
2101
2102 // TODO: When sanitizer support is implemented, we'll need to
2103 // get the address space from `newPtr`.
2105
2106 ASTContext &ctx = cgm.getASTContext();
2107 CharUnits sizeSize = cgf.getSizeSize();
2108 mlir::Location loc = cgf.getLoc(e->getSourceRange());
2109
2110 // The size of the cookie.
2111 CharUnits cookieSize =
2112 std::max(sizeSize, ctx.getPreferredTypeAlignInChars(elementType));
2113 assert(cookieSize == getArrayCookieSizeImpl(elementType));
2114
2115 mlir::Type u8Ty = cgf.getBuilder().getUInt8Ty();
2116 mlir::Value baseBytePtr =
2117 cgf.getBuilder().createPtrBitcast(newPtr.getPointer(), u8Ty);
2118
2119 // Compute an offset to the cookie.
2120 CharUnits cookieOffset = cookieSize - sizeSize;
2121 mlir::Value cookiePtrValue = baseBytePtr;
2122 if (!cookieOffset.isZero()) {
2123 mlir::Value offsetOp = cgf.getBuilder().getSignedInt(
2124 loc, cookieOffset.getQuantity(), /*width=*/32);
2125 cookiePtrValue =
2126 cgf.getBuilder().createPtrStride(loc, cookiePtrValue, offsetOp);
2127 }
2128
2129 CharUnits baseAlignment = newPtr.getAlignment();
2130 CharUnits cookiePtrAlignment = baseAlignment.alignmentAtOffset(cookieOffset);
2131 Address cookiePtr(cookiePtrValue, u8Ty, cookiePtrAlignment);
2132
2133 // Write the number of elements into the appropriate slot.
2134 Address numElementsPtr =
2135 cookiePtr.withElementType(cgf.getBuilder(), cgf.sizeTy);
2136 cgf.getBuilder().createStore(loc, numElements, numElementsPtr);
2137
2138 // Finally, compute a pointer to the actual data buffer by skipping
2139 // over the cookie completely.
2140 mlir::Value dataOffset =
2141 cgf.getBuilder().getSignedInt(loc, cookieSize.getQuantity(),
2142 /*width=*/32);
2143 mlir::Value dataPtr =
2144 cgf.getBuilder().createPtrStride(loc, baseBytePtr, dataOffset);
2145 mlir::Value finalPtr =
2146 cgf.getBuilder().createPtrBitcast(dataPtr, newPtr.getElementType());
2147 CharUnits finalAlignment = baseAlignment.alignmentAtOffset(cookieSize);
2148 return Address(finalPtr, newPtr.getElementType(), finalAlignment);
2149}
2150
2151bool CIRGenItaniumCXXABI::hasAnyUnusedVirtualInlineFunction(
2152 const CXXRecordDecl *rd) const {
2153 const auto &vtableLayout = cgm.getItaniumVTableContext().getVTableLayout(rd);
2154
2155 for (const auto &vtableComponent : vtableLayout.vtable_components()) {
2156 // Skip empty slot.
2157 if (!vtableComponent.isUsedFunctionPointerKind())
2158 continue;
2159
2160 const CXXMethodDecl *method = vtableComponent.getFunctionDecl();
2161 const FunctionDecl *fd = method->getDefinition();
2162 const bool isInlined =
2163 method->getCanonicalDecl()->isInlined() || (fd && fd->isInlined());
2164 if (!isInlined)
2165 continue;
2166
2167 StringRef name = cgm.getMangledName(
2168 vtableComponent.getGlobalDecl(/*HasVectorDeletingDtors=*/false));
2169 auto entry = dyn_cast_or_null<cir::GlobalOp>(cgm.getGlobalValue(name));
2170 // This checks if virtual inline function has already been emitted.
2171 // Note that it is possible that this inline function would be emitted
2172 // after trying to emit vtable speculatively. Because of this we do
2173 // an extra pass after emitting all deferred vtables to find and emit
2174 // these vtables opportunistically.
2175 if (!entry || entry.isDeclaration())
2176 return true;
2177 }
2178 return false;
2179}
2180
2181bool CIRGenItaniumCXXABI::isVTableHidden(const CXXRecordDecl *rd) const {
2182 const auto &vtableLayout = cgm.getItaniumVTableContext().getVTableLayout(rd);
2183
2184 for (const auto &vtableComponent : vtableLayout.vtable_components()) {
2185 if (vtableComponent.isRTTIKind()) {
2186 const CXXRecordDecl *rttiDecl = vtableComponent.getRTTIDecl();
2187 if (rttiDecl->getVisibility() == Visibility::HiddenVisibility)
2188 return true;
2189 } else if (vtableComponent.isUsedFunctionPointerKind()) {
2190 const CXXMethodDecl *method = vtableComponent.getFunctionDecl();
2191 if (method->getVisibility() == Visibility::HiddenVisibility &&
2192 !method->isDefined())
2193 return true;
2194 }
2195 }
2196 return false;
2197}
2198
2199bool CIRGenItaniumCXXABI::canSpeculativelyEmitVTableAsBaseClass(
2200 const CXXRecordDecl *rd) const {
2201 // We don't emit available_externally vtables if we are in -fapple-kext mode
2202 // because kext mode does not permit devirtualization.
2203 if (cgm.getLangOpts().AppleKext)
2204 return false;
2205
2206 // If the vtable is hidden then it is not safe to emit an available_externally
2207 // copy of vtable.
2208 if (isVTableHidden(rd))
2209 return false;
2210
2211 if (cgm.getCodeGenOpts().ForceEmitVTables)
2212 return true;
2213
2214 // A speculative vtable can only be generated if all virtual inline functions
2215 // defined by this class are emitted. The vtable in the final program contains
2216 // for each virtual inline function not used in the current TU a function that
2217 // is equivalent to the unused function. The function in the actual vtable
2218 // does not have to be declared under the same symbol (e.g., a virtual
2219 // destructor that can be substituted with its base class's destructor). Since
2220 // inline functions are emitted lazily and this emissions does not account for
2221 // speculative emission of a vtable, we might generate a speculative vtable
2222 // with references to inline functions that are not emitted under that name.
2223 // This can lead to problems when devirtualizing a call to such a function,
2224 // that result in linking errors. Hence, if there are any unused virtual
2225 // inline function, we cannot emit the speculative vtable.
2226 // FIXME we can still emit a copy of the vtable if we
2227 // can emit definition of the inline functions.
2228 if (hasAnyUnusedVirtualInlineFunction(rd))
2229 return false;
2230
2231 // For a class with virtual bases, we must also be able to speculatively
2232 // emit the VTT, because CodeGen doesn't have separate notions of "can emit
2233 // the vtable" and "can emit the VTT". For a base subobject, this means we
2234 // need to be able to emit non-virtual base vtables.
2235 if (rd->getNumVBases()) {
2236 for (const auto &b : rd->bases()) {
2237 auto *brd = b.getType()->getAsCXXRecordDecl();
2238 assert(brd && "no class for base specifier");
2239 if (b.isVirtual() || !brd->isDynamicClass())
2240 continue;
2241 if (!canSpeculativelyEmitVTableAsBaseClass(brd))
2242 return false;
2243 }
2244 }
2245
2246 return true;
2247}
2248
2249bool CIRGenItaniumCXXABI::canSpeculativelyEmitVTable(
2250 const CXXRecordDecl *rd) const {
2251 if (!canSpeculativelyEmitVTableAsBaseClass(rd))
2252 return false;
2253
2255 return false;
2256
2257 // For a complete-object vtable (or more specifically, for the VTT), we need
2258 // to be able to speculatively emit the vtables of all dynamic virtual bases.
2259 for (const auto &b : rd->vbases()) {
2260 auto *brd = b.getType()->getAsCXXRecordDecl();
2261 assert(brd && "no class for base specifier");
2262 if (!brd->isDynamicClass())
2263 continue;
2264 if (!canSpeculativelyEmitVTableAsBaseClass(brd))
2265 return false;
2266 }
2267
2268 return true;
2269}
2270
2272 Address initialPtr,
2273 const CXXRecordDecl *unadjustedClass,
2274 int64_t nonVirtualAdjustment,
2275 int64_t virtualAdjustment,
2276 bool isReturnAdjustment) {
2277 if (!nonVirtualAdjustment && !virtualAdjustment)
2278 return initialPtr.getPointer();
2279
2280 CIRGenBuilderTy &builder = cgf.getBuilder();
2281 mlir::Location loc = builder.getUnknownLoc();
2282 cir::PointerType ui8DefaultASPtrTy = builder.getUInt8PtrTy();
2283 mlir::Value v =
2284 builder.createPtrBitcast(initialPtr.getPointer(), builder.getUInt8Ty());
2285 auto i8PtrTy = mlir::cast<cir::PointerType>(v.getType());
2286
2287 // In a base-to-derived cast, the non-virtual adjustment is applied first.
2288 if (nonVirtualAdjustment && !isReturnAdjustment) {
2289 cir::ConstantOp offsetConst = builder.getSInt64(nonVirtualAdjustment, loc);
2290 v = cir::PtrStrideOp::create(builder, loc, i8PtrTy, v, offsetConst);
2291 }
2292
2293 // Perform the virtual adjustment if we have one.
2294 mlir::Value resultPtr;
2295 if (virtualAdjustment) {
2296 mlir::Value vtablePtr = cgf.getVTablePtr(
2297 loc, Address(v, clang::CharUnits::One()), unadjustedClass);
2298 vtablePtr = builder.createBitcast(vtablePtr, ui8DefaultASPtrTy);
2299
2300 mlir::Value offset;
2301 mlir::Value offsetPtr =
2302 cir::PtrStrideOp::create(builder, loc, ui8DefaultASPtrTy, vtablePtr,
2303 builder.getSInt64(virtualAdjustment, loc));
2304 if (cgf.cgm.getLangOpts().RelativeCXXABIVTables) {
2306 cgf.cgm.errorNYI("virtual adjustment for relative layout vtables");
2307 } else {
2308 offset = builder.createAlignedLoad(loc, cgf.ptrDiffTy, offsetPtr,
2309 cgf.getPointerAlign());
2310 }
2311
2312 resultPtr = cir::PtrStrideOp::create(builder, loc, i8PtrTy, v, offset);
2313 } else {
2314 resultPtr = v;
2315 }
2316
2317 // In a derived-to-base conversion, the non-virtual adjustment is
2318 // applied second.
2319 if (nonVirtualAdjustment && isReturnAdjustment) {
2320 cir::ConstantOp offsetConst = builder.getSInt64(nonVirtualAdjustment, loc);
2321 resultPtr =
2322 cir::PtrStrideOp::create(builder, loc, i8PtrTy, resultPtr, offsetConst);
2323 }
2324
2325 // Cast back to original pointer type.
2326 return builder.createBitcast(resultPtr, initialPtr.getType());
2327}
2328
2329mlir::Value CIRGenItaniumCXXABI::performThisAdjustment(
2330 CIRGenFunction &cgf, Address thisAddr, const CXXRecordDecl *unadjustedClass,
2331 const ThunkInfo &ti) {
2332 return performTypeAdjustment(cgf, thisAddr, unadjustedClass,
2333 ti.This.NonVirtual,
2335 /*isReturnAdjustment=*/false);
2336}
2337
2338mlir::Value CIRGenItaniumCXXABI::performReturnAdjustment(
2339 CIRGenFunction &cgf, Address ret, const CXXRecordDecl *unadjustedClass,
2340 const ReturnAdjustment &ra) {
2341 return performTypeAdjustment(cgf, ret, unadjustedClass, ra.NonVirtual,
2343 /*isReturnAdjustment=*/true);
2344}
2345
2346bool CIRGenItaniumCXXABI::isZeroInitializable(const MemberPointerType *mpt) {
2347 return mpt->isMemberFunctionPointer();
2348}
static void emitConstructorDestructorAlias(CIRGenModule &cgm, GlobalDecl aliasDecl, GlobalDecl targetDecl)
static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc, mlir::Value exceptionPtr={}, mlir::FlatSymbolRefAttr typeInfo={}, mlir::FlatSymbolRefAttr dtor={})
static 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 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)
Defines the clang::Expr interface and subclasses for C++ expressions.
static QualType getPointeeType(const MemRegion *R)
C Language Family Type Representation.
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)
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
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
CanQualType LongTy
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
IdentifierTable & Idents
Definition ASTContext.h:852
const LangOptions & getLangOpts() const
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:971
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.
mlir::Value getPointer() const
Definition Address.h:98
mlir::Type getElementType() const
Definition Address.h:125
clang::CharUnits getAlignment() const
Definition Address.h:138
mlir::Type getType() const
Definition Address.h:117
mlir::Value emitRawPointer() const
Return the pointer contained in this class after authenticating it and adding offset to it if necessa...
Definition Address.h:112
cir::TypeInfoAttr getTypeInfo(mlir::ArrayAttr fieldsAttr)
cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc)
cir::PointerType getUInt8PtrTy()
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false, bool isNontemporal=false)
cir::StoreOp createStore(mlir::Location loc, mlir::Value val, Address dst, bool isVolatile=false, bool isNontemporal=false, mlir::IntegerAttr align={}, cir::SyncScopeKindAttr scope={}, cir::MemOrderAttr order={})
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)
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)
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:156
mlir::Type convertType(clang::QualType t)
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
const clang::Decl * curFuncDecl
Address getAddrOfLocalVar(const clang::VarDecl *vd)
Return the address of a local variable.
void emitAnyExprToExn(const Expr *e, Address addr)
mlir::Value getVTTParameter(GlobalDecl gd, bool forVirtualBase, bool delegating)
Return the VTT parameter that should be passed to a base constructor/destructor with virtual bases.
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
mlir::Value loadCXXVTT()
Load the VTT parameter to base constructors/destructors have virtual bases.
mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr, const clang::CXXRecordDecl *vtableClass)
Return the Value of the vtable pointer member pointed to by thisAddr.
bool shouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *rd)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
CIRGenBuilderTy & getBuilder()
mlir::Value emitRuntimeCall(mlir::Location loc, cir::FuncOp callee, llvm::ArrayRef< mlir::Value > args={}, mlir::NamedAttrList attrs={})
std::optional< SourceRange > currSrcLoc
Use to track source locations across nested visitor traversals.
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
clang::ASTContext & getContext() const
This class organizes the cross-function state that is used while generating CIR code.
llvm::StringRef getMangledName(clang::GlobalDecl gd)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
cir::FuncOp getAddrOfCXXStructor(clang::GlobalDecl gd, const CIRGenFunctionInfo *fnInfo=nullptr, cir::FuncType fnType=nullptr, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
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.
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)
const cir::CIRDataLayout & getDataLayout() const
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)
void eraseGlobalSymbol(mlir::Operation *op)
static void setInitializer(cir::GlobalOp &op, mlir::Attribute value)
cir::GlobalLinkageKind getFunctionLinkage(GlobalDecl gd)
const clang::CodeGenOptions & getCodeGenOpts() const
const clang::LangOptions & getLangOpts() const
cir::GlobalOp createGlobalOp(mlir::Location loc, llvm::StringRef name, mlir::Type t, bool isConstant=false, mlir::ptr::MemorySpaceAttrInterface addrSpace={}, mlir::Operation *insertPoint=nullptr)
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::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...
QualType getType() const
Retrieves the type of the base class.
Definition DeclCXX.h:249
bool isGlobalDelete() const
Definition ExprCXX.h:2656
Represents a static or instance method of a struct/union/class.
Definition DeclCXX.h:2153
bool isVirtual() const
Definition DeclCXX.h:2208
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition DeclCXX.h:2296
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition DeclCXX.h:2266
SourceRange getSourceRange() const
Definition ExprCXX.h:2615
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:2341
base_class_range bases()
Definition DeclCXX.h:609
unsigned getNumBases() const
Retrieves the number of base classes of this class.
Definition DeclCXX.h:603
base_class_iterator bases_begin()
Definition DeclCXX.h:616
base_class_range vbases()
Definition DeclCXX.h:626
bool isAbstract() const
Determine whether this class has a pure virtual function.
Definition DeclCXX.h:1231
bool isDynamicClass() const
Definition DeclCXX.h:575
bool hasDefinition() const
Definition DeclCXX.h:562
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition DeclCXX.h:624
bool isDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is derived from the class Base.
const Expr * getSubExpr() const
Definition ExprCXX.h:1233
static CanQual< Type > CreateUnsafe(QualType Other)
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:177
bool isZero() const
Test whether the quantity equals zero.
Definition CharUnits.h:101
QuantityType getQuantity() const
Get the raw integer representation of this quantity.
Definition CharUnits.h:155
static CharUnits One()
Construct a CharUnits quantity of one.
Definition CharUnits.h:55
static CharUnits fromQuantity(QuantityType Quantity)
Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:58
static CharUnits Zero()
Construct a CharUnits quantity of zero.
Definition CharUnits.h:52
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2108
bool isTranslationUnit() const
Definition DeclBase.h:2204
SourceLocation getLocation() const
Definition DeclBase.h:448
DeclContext * getDeclContext()
Definition DeclBase.h:457
bool hasAttr() const
Definition DeclBase.h:586
bool shouldEmitInExternalSource() const
Whether the definition of the declaration should be emitted in external sources.
QualType getType() const
Definition Expr.h:146
bool isInlined() const
Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...
Definition Decl.h:3068
FunctionDecl * getDefinition()
Get the definition for this declaration.
Definition Decl.h:2408
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:3251
GlobalDecl - represents a global declaration.
Definition GlobalDecl.h:60
GlobalDecl getWithCtorType(CXXCtorType Type)
Definition GlobalDecl.h:176
CXXCtorType getCtorType() const
Definition GlobalDecl.h:117
GlobalDecl getWithDtorType(CXXDtorType Type)
Definition GlobalDecl.h:183
CXXDtorType getDtorType() const
Definition GlobalDecl.h:122
const Decl * getDecl() const
Definition GlobalDecl.h:115
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, const IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
Definition Decl.cpp:5697
virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &)=0
virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &)=0
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:5845
QualType getPointeeType() const
Definition TypeBase.h:3769
bool isMemberFunctionPointer() const
Returns true if the member type (i.e.
Definition TypeBase.h:3773
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:297
Visibility getVisibility() const
Determines the visibility of this entity.
Definition Decl.h:446
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
QualType getCanonicalType() const
Definition TypeBase.h:8630
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8672
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:4988
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:497
virtual bool hasPS4DLLImportExport() const
uint64_t getPointerAlign(LangAS AddrSpace) const
Definition TargetInfo.h:501
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:543
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:3698
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
CXXRecordDecl * castAsCXXRecordDecl() const
Definition Type.h:36
Visibility getVisibility() const
Determine the visibility of this type.
Definition TypeBase.h:3146
Linkage getLinkage() const
Determine the linkage of this type.
Definition Type.cpp:5200
TypeClass getTypeClass() const
Definition TypeBase.h:2449
AddressPointLocation getAddressPoint(BaseSubobject Base) const
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:2171
bool isNoDestroy(const ASTContext &) const
Is destruction of this variable entirely suppressed?
Definition Decl.cpp:2828
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.
unsigned extractPBaseFlags(const ASTContext &Ctx, QualType &Type)
Compute the flags for a __pbase_type_info, and remove the corresponding pieces from Type.
bool containsIncompleteClassType(QualType Ty)
Returns whether the given type contains an incomplete class type.
bool canUseSingleInheritance(const CXXRecordDecl *RD)
Return whether the given record decl has a "single, public, non-virtual base at offset zero (i....
unsigned computeVMIClassTypeInfoFlags(const CXXRecordDecl *RD)
Compute the value of the flags member in abi::__vmi_class_type_info.
CharUnits computeOffsetHint(ASTContext &Ctx, const CXXRecordDecl *Src, const CXXRecordDecl *Dst)
Compute the src2dst_offset hint as described in the Itanium C++ ABI [2.9.7].
bool isStandardLibraryRTTIDescriptor(QualType Ty)
Returns whether the type information for the given type exists in the standard library.
@ BCTI_Virtual
BCTI_Virtual - Base class is virtual.
@ BCTI_Public
BCTI_Public - Base class is public.
@ PTI_ContainingClassIncomplete
PTI_ContainingClassIncomplete - Containing class is incomplete.
llvm::Value * getCXXDestructorImplicitParam(CodeGenModule &CGM, llvm::BasicBlock *InsertBlock, llvm::BasicBlock::iterator InsertPoint, const CXXDestructorDecl *D, CXXDtorType Type, bool ForVirtualBase, bool Delegating)
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
const internal::VariadicDynCastAllOfMatcher< Stmt, Expr > expr
Matches expressions.
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition PrimType.h:218
@ 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...
Top level wrappers for InstallAPI frontend operations.
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:128
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ 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
U cast(CodeGen::Address addr)
Definition Address.h:327
@ DefaultVisibility
Objects with "default" visibility are seen by the dynamic linker and act like normal objects.
Definition Visibility.h:46
unsigned long uint64_t
__builtin_bitreverse32 uint32_t __builtin_riscv_aaddu_u32 __builtin_riscv_asubu_u32 __builtin_elementwise_add_sat __builtin_elementwise_sub_sat int32_t uint32_t uint32_t __builtin_riscv_mhacc_i32 __builtin_riscv_mhaccu_u32 __builtin_riscv_mhaccsu_i32 __builtin_riscv_mulq_i32 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 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