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