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