clang 22.0.0git
CIRGenItaniumCXXABI.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This provides C++ code generation targeting the Itanium C++ ABI. The class
10// in this file generates structures that follow the Itanium C++ ABI, which is
11// documented at:
12// https://itanium-cxx-abi.github.io/cxx-abi/abi.html
13// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
14//
15// It also supports the closely-related ARM ABI, documented at:
16// https://developer.arm.com/documentation/ihi0041/g/
17//
18//===----------------------------------------------------------------------===//
19
20#include "CIRGenCXXABI.h"
21#include "CIRGenFunction.h"
22
23#include "clang/AST/ExprCXX.h"
27#include "llvm/Support/ErrorHandling.h"
28
29using namespace clang;
30using namespace clang::CIRGen;
31
32namespace {
33
34class CIRGenItaniumCXXABI : public CIRGenCXXABI {
35protected:
36 /// All the vtables which have been defined.
37 llvm::DenseMap<const CXXRecordDecl *, cir::GlobalOp> vtables;
38
39public:
40 CIRGenItaniumCXXABI(CIRGenModule &cgm) : CIRGenCXXABI(cgm) {
43 }
44
45 bool needsVTTParameter(clang::GlobalDecl gd) override;
46
48 CIRGenFunction &cgf) override;
49
50 void emitCXXConstructors(const clang::CXXConstructorDecl *d) override;
51 void emitCXXDestructors(const clang::CXXDestructorDecl *d) override;
52 void emitCXXStructor(clang::GlobalDecl gd) override;
53
55 CXXDtorType type, bool forVirtualBase,
56 bool delegating, Address thisAddr,
57 QualType thisTy) override;
58
59 void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;
60
62 CXXDtorType dt) const override {
63 // Itanium does not emit any destructor variant as an inline thunk.
64 // Delegating may occur as an optimization, but all variants are either
65 // emitted with external linkage or as linkonce if they are inline and used.
66 return false;
67 }
68
70 CIRGenFunction::VPtr vptr) override;
71
72 cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd,
73 CharUnits vptrOffset) override;
75 clang::GlobalDecl gd, Address thisAddr,
76 mlir::Type ty,
77 SourceLocation loc) override;
78
79 mlir::Value getVTableAddressPoint(BaseSubobject base,
80 const CXXRecordDecl *vtableClass) override;
81
83 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,
85 const clang::CXXRecordDecl *nearestVBase) override;
87 const CXXRecordDecl *rd) override;
88
89 bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {
90 return true;
91 }
92};
93
94} // namespace
95
96void CIRGenItaniumCXXABI::emitInstanceFunctionProlog(SourceLocation loc,
97 CIRGenFunction &cgf) {
98 // Naked functions have no prolog.
99 if (cgf.curFuncDecl && cgf.curFuncDecl->hasAttr<NakedAttr>()) {
101 "emitInstanceFunctionProlog: Naked");
102 }
103
104 /// Initialize the 'this' slot. In the Itanium C++ ABI, no prologue
105 /// adjustments are required, because they are all handled by thunks.
106 setCXXABIThisValue(cgf, loadIncomingCXXThis(cgf));
107
108 /// Classic codegen has code here to initialize the 'vtt' slot if
109 // getStructorImplicitParamDecl(cgf) returns a non-null value, but in the
110 // current implementation (of classic codegen) it never does.
112
113 /// If this is a function that the ABI specifies returns 'this', initialize
114 /// the return slot to this' at the start of the function.
115 ///
116 /// Unlike the setting of return types, this is done within the ABI
117 /// implementation instead of by clients of CIRGenCXXBI because:
118 /// 1) getThisValue is currently protected
119 /// 2) in theory, an ABI could implement 'this' returns some other way;
120 /// HasThisReturn only specifies a contract, not the implementation
121 if (hasThisReturn(cgf.curGD)) {
123 "emitInstanceFunctionProlog: hasThisReturn");
124 }
125}
126
127// Find out how to cirgen the complete destructor and constructor
128namespace {
129enum class StructorCIRGen { Emit, RAUW, Alias, COMDAT };
130}
131
132static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm,
133 const CXXMethodDecl *md) {
134 if (!cgm.getCodeGenOpts().CXXCtorDtorAliases)
135 return StructorCIRGen::Emit;
136
137 // The complete and base structors are not equivalent if there are any virtual
138 // bases, so emit separate functions.
139 if (md->getParent()->getNumVBases()) {
140 // The return value is correct here, but other support for this is NYI.
141 cgm.errorNYI(md->getSourceRange(), "getCIRGenToUse: virtual bases");
142 return StructorCIRGen::Emit;
143 }
144
145 GlobalDecl aliasDecl;
146 if (const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
147 aliasDecl = GlobalDecl(dd, Dtor_Complete);
148 } else {
149 const auto *cd = cast<CXXConstructorDecl>(md);
150 aliasDecl = GlobalDecl(cd, Ctor_Complete);
151 }
152
153 cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);
154
155 if (cir::isDiscardableIfUnused(linkage))
156 return StructorCIRGen::RAUW;
157
158 // FIXME: Should we allow available_externally aliases?
159 if (!cir::isValidLinkage(linkage))
160 return StructorCIRGen::RAUW;
161
162 if (cir::isWeakForLinker(linkage)) {
163 // Only ELF and wasm support COMDATs with arbitrary names (C5/D5).
164 if (cgm.getTarget().getTriple().isOSBinFormatELF() ||
165 cgm.getTarget().getTriple().isOSBinFormatWasm())
166 return StructorCIRGen::COMDAT;
167 return StructorCIRGen::Emit;
168 }
169
170 return StructorCIRGen::Alias;
171}
172
174 GlobalDecl aliasDecl,
175 GlobalDecl targetDecl) {
176 cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);
177
178 // Does this function alias already exists?
179 StringRef mangledName = cgm.getMangledName(aliasDecl);
180 auto globalValue = dyn_cast_or_null<cir::CIRGlobalValueInterface>(
181 cgm.getGlobalValue(mangledName));
182 if (globalValue && !globalValue.isDeclaration())
183 return;
184
185 auto entry = cast_or_null<cir::FuncOp>(cgm.getGlobalValue(mangledName));
186
187 // Retrieve aliasee info.
188 auto aliasee = cast<cir::FuncOp>(cgm.getAddrOfGlobal(targetDecl));
189
190 // Populate actual alias.
191 cgm.emitAliasForGlobal(mangledName, entry, aliasDecl, aliasee, linkage);
192}
193
194void CIRGenItaniumCXXABI::emitCXXStructor(GlobalDecl gd) {
195 auto *md = cast<CXXMethodDecl>(gd.getDecl());
196 StructorCIRGen cirGenType = getCIRGenToUse(cgm, md);
197 const auto *cd = dyn_cast<CXXConstructorDecl>(md);
198
199 if (cd ? gd.getCtorType() == Ctor_Complete
200 : gd.getDtorType() == Dtor_Complete) {
201 GlobalDecl baseDecl =
203 ;
204
205 if (cirGenType == StructorCIRGen::Alias ||
206 cirGenType == StructorCIRGen::COMDAT) {
207 emitConstructorDestructorAlias(cgm, gd, baseDecl);
208 return;
209 }
210
211 if (cirGenType == StructorCIRGen::RAUW) {
212 StringRef mangledName = cgm.getMangledName(gd);
213 mlir::Operation *aliasee = cgm.getAddrOfGlobal(baseDecl);
214 cgm.addReplacement(mangledName, aliasee);
215 return;
216 }
217 }
218
219 auto fn = cgm.codegenCXXStructor(gd);
220
221 cgm.maybeSetTrivialComdat(*md, fn);
222}
223
224void CIRGenItaniumCXXABI::emitCXXConstructors(const CXXConstructorDecl *d) {
225 // Just make sure we're in sync with TargetCXXABI.
226 assert(cgm.getTarget().getCXXABI().hasConstructorVariants());
227
228 // The constructor used for constructing this as a base class;
229 // ignores virtual bases.
230 cgm.emitGlobal(GlobalDecl(d, Ctor_Base));
231
232 // The constructor used for constructing this as a complete class;
233 // constructs the virtual bases, then calls the base constructor.
234 if (!d->getParent()->isAbstract()) {
235 // We don't need to emit the complete ctro if the class is abstract.
236 cgm.emitGlobal(GlobalDecl(d, Ctor_Complete));
237 }
238}
239
240void CIRGenItaniumCXXABI::emitCXXDestructors(const CXXDestructorDecl *d) {
241 // The destructor used for destructing this as a base class; ignores
242 // virtual bases.
243 cgm.emitGlobal(GlobalDecl(d, Dtor_Base));
244
245 // The destructor used for destructing this as a most-derived class;
246 // call the base destructor and then destructs any virtual bases.
247 cgm.emitGlobal(GlobalDecl(d, Dtor_Complete));
248
249 // The destructor in a virtual table is always a 'deleting'
250 // destructor, which calls the complete destructor and then uses the
251 // appropriate operator delete.
252 if (d->isVirtual())
253 cgm.emitGlobal(GlobalDecl(d, Dtor_Deleting));
254}
255
256/// Return whether the given global decl needs a VTT (virtual table table)
257/// parameter, which it does if it's a base constructor or destructor with
258/// virtual bases.
259bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) {
260 auto *md = cast<CXXMethodDecl>(gd.getDecl());
261
262 // We don't have any virtual bases, just return early.
263 if (!md->getParent()->getNumVBases())
264 return false;
265
266 // Check if we have a base constructor.
267 if (isa<CXXConstructorDecl>(md) && gd.getCtorType() == Ctor_Base)
268 return true;
269
270 // Check if we have a base destructor.
271 if (isa<CXXDestructorDecl>(md) && gd.getDtorType() == Dtor_Base)
272 return true;
273
274 return false;
275}
276
277void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,
278 const CXXRecordDecl *rd) {
279 cir::GlobalOp vtable = getAddrOfVTable(rd, CharUnits());
280 if (vtable.hasInitializer())
281 return;
282
283 ItaniumVTableContext &vtContext = cgm.getItaniumVTableContext();
284 const VTableLayout &vtLayout = vtContext.getVTableLayout(rd);
285 cir::GlobalLinkageKind linkage = cgm.getVTableLinkage(rd);
286 mlir::Attribute rtti =
287 cgm.getAddrOfRTTIDescriptor(cgm.getLoc(rd->getBeginLoc()),
288 cgm.getASTContext().getCanonicalTagType(rd));
289
290 // Classic codegen uses ConstantInitBuilder here, which is a very general
291 // and feature-rich class to generate initializers for global values.
292 // For now, this is using a simpler approach to create the initializer in CIR.
293 cgvt.createVTableInitializer(vtable, vtLayout, rtti,
294 cir::isLocalLinkage(linkage));
295
296 // Set the correct linkage.
297 vtable.setLinkage(linkage);
298
299 if (cgm.supportsCOMDAT() && cir::isWeakForLinker(linkage))
300 vtable.setComdat(true);
301
302 // Set the right visibility.
303 cgm.setGVProperties(vtable, rd);
304
305 // If this is the magic class __cxxabiv1::__fundamental_type_info,
306 // we will emit the typeinfo for the fundamental types. This is the
307 // same behaviour as GCC.
308 const DeclContext *DC = rd->getDeclContext();
309 if (rd->getIdentifier() &&
310 rd->getIdentifier()->isStr("__fundamental_type_info") &&
311 isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
312 cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
313 DC->getParent()->isTranslationUnit()) {
314 cgm.errorNYI(rd->getSourceRange(),
315 "emitVTableDefinitions: __fundamental_type_info");
316 }
317
318 auto vtableAsGlobalValue = dyn_cast<cir::CIRGlobalValueInterface>(*vtable);
319 assert(vtableAsGlobalValue && "VTable must support CIRGlobalValueInterface");
320 // Always emit type metadata on non-available_externally definitions, and on
321 // available_externally definitions if we are performing whole program
322 // devirtualization. For WPD we need the type metadata on all vtable
323 // definitions to ensure we associate derived classes with base classes
324 // defined in headers but with a strong definition only in a shared
325 // library.
327 if (cgm.getCodeGenOpts().WholeProgramVTables) {
328 cgm.errorNYI(rd->getSourceRange(),
329 "emitVTableDefinitions: WholeProgramVTables");
330 }
331
333 if (vtContext.isRelativeLayout()) {
334 cgm.errorNYI(rd->getSourceRange(), "vtableRelativeLayout");
335 }
336}
337
338void CIRGenItaniumCXXABI::emitDestructorCall(
340 bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) {
341 GlobalDecl gd(dd, type);
342 if (needsVTTParameter(gd)) {
343 cgm.errorNYI(dd->getSourceRange(), "emitDestructorCall: VTT");
344 }
345
346 mlir::Value vtt = nullptr;
347 ASTContext &astContext = cgm.getASTContext();
348 QualType vttTy = astContext.getPointerType(astContext.VoidPtrTy);
350 CIRGenCallee callee =
351 CIRGenCallee::forDirect(cgm.getAddrOfCXXStructor(gd), gd);
352
353 cgf.emitCXXDestructorCall(gd, callee, thisAddr.getPointer(), thisTy, vtt,
354 vttTy, nullptr);
355}
356
357// The idea here is creating a separate block for the throw with an
358// `UnreachableOp` as the terminator. So, we branch from the current block
359// to the throw block and create a block for the remaining operations.
360static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc,
361 mlir::Value exceptionPtr = {},
362 mlir::FlatSymbolRefAttr typeInfo = {},
363 mlir::FlatSymbolRefAttr dtor = {}) {
364 mlir::Block *currentBlock = builder.getInsertionBlock();
365 mlir::Region *region = currentBlock->getParent();
366
367 if (currentBlock->empty()) {
368 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
369 cir::UnreachableOp::create(builder, loc);
370 } else {
371 mlir::Block *throwBlock = builder.createBlock(region);
372
373 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
374 cir::UnreachableOp::create(builder, loc);
375
376 builder.setInsertionPointToEnd(currentBlock);
377 cir::BrOp::create(builder, loc, throwBlock);
378 }
379
380 (void)builder.createBlock(region);
381}
382
383void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &cgf, bool isNoReturn) {
384 // void __cxa_rethrow();
385 if (isNoReturn) {
386 CIRGenBuilderTy &builder = cgf.getBuilder();
387 assert(cgf.currSrcLoc && "expected source location");
388 mlir::Location loc = *cgf.currSrcLoc;
389 insertThrowAndSplit(builder, loc);
390 } else {
391 cgm.errorNYI("emitRethrow with isNoReturn false");
392 }
393}
394
396 switch (cgm.getASTContext().getCXXABIKind()) {
397 case TargetCXXABI::GenericItanium:
398 case TargetCXXABI::GenericAArch64:
399 return new CIRGenItaniumCXXABI(cgm);
400
401 case TargetCXXABI::AppleARM64:
402 // The general Itanium ABI will do until we implement something that
403 // requires special handling.
405 return new CIRGenItaniumCXXABI(cgm);
406
407 default:
408 llvm_unreachable("bad or NYI ABI kind");
409 }
410}
411
412cir::GlobalOp CIRGenItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *rd,
413 CharUnits vptrOffset) {
414 assert(vptrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");
415 cir::GlobalOp &vtable = vtables[rd];
416 if (vtable)
417 return vtable;
418
419 // Queue up this vtable for possible deferred emission.
421
422 SmallString<256> name;
423 llvm::raw_svector_ostream out(name);
424 getMangleContext().mangleCXXVTable(rd, out);
425
426 const VTableLayout &vtLayout =
427 cgm.getItaniumVTableContext().getVTableLayout(rd);
428 mlir::Type vtableType = cgm.getVTables().getVTableType(vtLayout);
429
430 // Use pointer alignment for the vtable. Otherwise we would align them based
431 // on the size of the initializer which doesn't make sense as only single
432 // values are read.
433 unsigned ptrAlign = cgm.getItaniumVTableContext().isRelativeLayout()
434 ? 32
435 : cgm.getTarget().getPointerAlign(LangAS::Default);
436
437 vtable = cgm.createOrReplaceCXXRuntimeVariable(
438 cgm.getLoc(rd->getSourceRange()), name, vtableType,
439 cir::GlobalLinkageKind::ExternalLinkage,
440 cgm.getASTContext().toCharUnitsFromBits(ptrAlign));
441 // LLVM codegen handles unnamedAddr
443
444 // In MS C++ if you have a class with virtual functions in which you are using
445 // selective member import/export, then all virtual functions must be exported
446 // unless they are inline, otherwise a link error will result. To match this
447 // behavior, for such classes, we dllimport the vtable if it is defined
448 // externally and all the non-inline virtual methods are marked dllimport, and
449 // we dllexport the vtable if it is defined in this TU and all the non-inline
450 // virtual methods are marked dllexport.
451 if (cgm.getTarget().hasPS4DLLImportExport())
452 cgm.errorNYI(rd->getSourceRange(),
453 "getAddrOfVTable: PS4 DLL import/export");
454
455 cgm.setGVProperties(vtable, rd);
456 return vtable;
457}
458
459CIRGenCallee CIRGenItaniumCXXABI::getVirtualFunctionPointer(
460 CIRGenFunction &cgf, clang::GlobalDecl gd, Address thisAddr, mlir::Type ty,
461 SourceLocation srcLoc) {
462 CIRGenBuilderTy &builder = cgm.getBuilder();
463 mlir::Location loc = cgf.getLoc(srcLoc);
464 cir::PointerType tyPtr = builder.getPointerTo(ty);
465 auto *methodDecl = cast<CXXMethodDecl>(gd.getDecl());
466 mlir::Value vtable = cgf.getVTablePtr(loc, thisAddr, methodDecl->getParent());
467
468 uint64_t vtableIndex = cgm.getItaniumVTableContext().getMethodVTableIndex(gd);
469 mlir::Value vfunc{};
470 if (cgf.shouldEmitVTableTypeCheckedLoad(methodDecl->getParent())) {
471 cgm.errorNYI(loc, "getVirtualFunctionPointer: emitVTableTypeCheckedLoad");
472 } else {
474
475 mlir::Value vfuncLoad;
476 if (cgm.getItaniumVTableContext().isRelativeLayout()) {
478 cgm.errorNYI(loc, "getVirtualFunctionPointer: isRelativeLayout");
479 } else {
480 auto vtableSlotPtr = cir::VTableGetVirtualFnAddrOp::create(
481 builder, loc, builder.getPointerTo(tyPtr), vtable, vtableIndex);
482 vfuncLoad = builder.createAlignedLoad(
483 loc, vtableSlotPtr, cgf.getPointerAlign().getQuantity());
484 }
485
486 // Add !invariant.load md to virtual function load to indicate that
487 // function didn't change inside vtable.
488 // It's safe to add it without -fstrict-vtable-pointers, but it would not
489 // help in devirtualization because it will only matter if we will have 2
490 // the same virtual function loads from the same vtable load, which won't
491 // happen without enabled devirtualization with -fstrict-vtable-pointers.
492 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
493 cgm.getCodeGenOpts().StrictVTablePointers) {
494 cgm.errorNYI(loc, "getVirtualFunctionPointer: strictVTablePointers");
495 }
496 vfunc = vfuncLoad;
497 }
498
499 CIRGenCallee callee(gd, vfunc.getDefiningOp());
500 return callee;
501}
502
503mlir::Value
504CIRGenItaniumCXXABI::getVTableAddressPoint(BaseSubobject base,
505 const CXXRecordDecl *vtableClass) {
506 cir::GlobalOp vtable = getAddrOfVTable(vtableClass, CharUnits());
507
508 // Find the appropriate vtable within the vtable group, and the address point
509 // within that vtable.
511 cgm.getItaniumVTableContext()
512 .getVTableLayout(vtableClass)
513 .getAddressPoint(base);
514
515 mlir::OpBuilder &builder = cgm.getBuilder();
516 auto vtablePtrTy = cir::VPtrType::get(builder.getContext());
517
518 return builder.create<cir::VTableAddrPointOp>(
519 cgm.getLoc(vtableClass->getSourceRange()), vtablePtrTy,
520 mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()),
521 cir::AddressPointAttr::get(cgm.getBuilder().getContext(),
522 addressPoint.VTableIndex,
523 addressPoint.AddressPointIndex));
524}
525
526mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructor(
527 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,
528 clang::BaseSubobject base, const clang::CXXRecordDecl *nearestVBase) {
529
530 if ((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&
531 needsVTTParameter(cgf.curGD)) {
532 cgm.errorNYI(cgf.curFuncDecl->getLocation(),
533 "getVTableAddressPointInStructorWithVTT");
534 }
535 return getVTableAddressPoint(base, vtableClass);
536}
537
538bool CIRGenItaniumCXXABI::isVirtualOffsetNeededForVTableField(
540 if (vptr.nearestVBase == nullptr)
541 return false;
542 return needsVTTParameter(cgf.curGD);
543}
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 StructorCIRGen getCIRGenToUse(CIRGenModule &cgm, const CXXMethodDecl *md)
Defines the clang::Expr interface and subclasses for C++ expressions.
cir::PointerType getPointerTo(mlir::Type ty)
mlir::Value createAlignedLoad(mlir::Location loc, mlir::Value ptr, uint64_t alignment)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
CanQualType VoidPtrTy
Definition: ASTContext.h:1249
TargetCXXABI::Kind getCXXABIKind() const
Return the C++ ABI kind that should be used.
Definition: ASTContext.cpp:884
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
Definition: BaseSubobject.h:43
mlir::Value getPointer() const
Definition: Address.h:81
Implements C++ ABI-specific code generation functions.
Definition: CIRGenCXXABI.h:26
virtual void emitInstanceFunctionProlog(SourceLocation loc, CIRGenFunction &cgf)=0
Emit the ABI-specific prolog for the function.
virtual void emitCXXConstructors(const clang::CXXConstructorDecl *d)=0
Emit constructor variants required by this ABI.
virtual void emitCXXDestructors(const clang::CXXDestructorDecl *d)=0
Emit dtor variants required by this ABI.
virtual cir::GlobalOp getAddrOfVTable(const CXXRecordDecl *rd, CharUnits vptrOffset)=0
Get the address of the vtable for the given record decl which should be used for the vptr at the give...
virtual CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf, clang::GlobalDecl gd, Address thisAddr, mlir::Type ty, SourceLocation loc)=0
Build a virtual function pointer in the ABI-specific way.
virtual void emitVTableDefinitions(CIRGenVTables &cgvt, const CXXRecordDecl *rd)=0
Emits the VTable definitions required for the given record type.
virtual bool useThunkForDtorVariant(const CXXDestructorDecl *dtor, CXXDtorType dt) const =0
Returns true if the given destructor type should be emitted as a linkonce delegating thunk,...
virtual bool needsVTTParameter(clang::GlobalDecl gd)
Return whether the given global decl needs a VTT (virtual table table) parameter.
Definition: CIRGenCXXABI.h:72
virtual mlir::Value getVTableAddressPointInStructor(CIRGenFunction &cgf, const CXXRecordDecl *vtableClass, BaseSubobject base, const CXXRecordDecl *nearestVBase)=0
Get the address point of the vtable for the given base subobject while building a constructor or a de...
virtual mlir::Value getVTableAddressPoint(BaseSubobject base, const CXXRecordDecl *vtableClass)=0
Get the address point of the vtable for the given base subobject.
virtual void emitDestructorCall(CIRGenFunction &cgf, const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)=0
virtual void emitCXXStructor(clang::GlobalDecl gd)=0
Emit a single constructor/destructor with the gen type from a C++ constructor/destructor Decl.
virtual bool isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf, CIRGenFunction::VPtr vptr)=0
Checks if ABI requires extra virtual offset for vtable field.
virtual void emitRethrow(CIRGenFunction &cgf, bool isNoReturn)=0
virtual bool doStructorsInitializeVPtrs(const clang::CXXRecordDecl *vtableClass)=0
Checks if ABI requires to initialize vptrs for given dynamic class.
static CIRGenCallee forDirect(mlir::Operation *funcPtr, const CIRGenCalleeInfo &abstractInfo=CIRGenCalleeInfo())
Definition: CIRGenCall.h:90
clang::GlobalDecl curGD
The GlobalDecl for the current function being compiled or the global variable currently being initial...
const clang::Decl * curFuncDecl
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
mlir::Value getVTablePtr(mlir::Location loc, Address thisAddr, const clang::CXXRecordDecl *vtableClass)
Return the Value of the vtable pointer member pointed to by thisAddr.
bool shouldEmitVTableTypeCheckedLoad(const CXXRecordDecl *rd)
Returns whether we should perform a type checked load when loading a virtual function for virtual cal...
CIRGenBuilderTy & getBuilder()
void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type, bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy)
std::optional< mlir::Location > currSrcLoc
Use to track source locations across nested visitor traversals.
This class organizes the cross-function state that is used while generating CIR code.
Definition: CIRGenModule.h:56
llvm::StringRef getMangledName(clang::GlobalDecl gd)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
Definition: CIRGenModule.h:102
const clang::TargetInfo & getTarget() const
Definition: CIRGenModule.h:103
void emitAliasForGlobal(llvm::StringRef mangledName, mlir::Operation *op, GlobalDecl aliasGD, cir::FuncOp aliasee, cir::GlobalLinkageKind linkage)
cir::GlobalLinkageKind getFunctionLinkage(GlobalDecl gd)
const clang::CodeGenOptions & getCodeGenOpts() const
Definition: CIRGenModule.h:104
mlir::Operation * getGlobalValue(llvm::StringRef ref)
mlir::Operation * getAddrOfGlobal(clang::GlobalDecl gd, ForDefinition_t isForDefinition=NotForDefinition)
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.
Represents a C++ constructor within a class.
Definition: DeclCXX.h:2604
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2869
Represents a static or instance method of a struct/union/class.
Definition: DeclCXX.h:2129
bool isVirtual() const
Definition: DeclCXX.h:2184
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Definition: DeclCXX.h:2255
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
bool isAbstract() const
Determine whether this class has a pure virtual function.
Definition: DeclCXX.h:1221
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
Definition: DeclCXX.h:623
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition: CharUnits.h:122
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition: CharUnits.h:185
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition: DeclBase.h:1449
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:2109
bool isTranslationUnit() const
Definition: DeclBase.h:2185
SourceLocation getLocation() const
Definition: DeclBase.h:439
DeclContext * getDeclContext()
Definition: DeclBase.h:448
bool hasAttr() const
Definition: DeclBase.h:577
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4486
GlobalDecl - represents a global declaration.
Definition: GlobalDecl.h:57
GlobalDecl getWithCtorType(CXXCtorType Type)
Definition: GlobalDecl.h:178
CXXCtorType getCtorType() const
Definition: GlobalDecl.h:108
GlobalDecl getWithDtorType(CXXDtorType Type)
Definition: GlobalDecl.h:185
CXXDtorType getDtorType() const
Definition: GlobalDecl.h:113
const Decl * getDecl() const
Definition: GlobalDecl.h:106
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition: Decl.h:294
A (possibly-)qualified type.
Definition: TypeBase.h:937
Encodes a location in the source.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition: Decl.cpp:4830
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
Definition: TargetInfo.h:1288
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Decl.h:3540
static bool isLocalLinkage(GlobalLinkageKind linkage)
Definition: CIROpsEnums.h:51
static LLVM_ATTRIBUTE_UNUSED bool isDiscardableIfUnused(GlobalLinkageKind linkage)
Whether the definition of this global may be discarded if it is not used in its compilation unit.
Definition: CIROpsEnums.h:93
static LLVM_ATTRIBUTE_UNUSED bool isValidLinkage(GlobalLinkageKind gl)
Definition: CIROpsEnums.h:111
static LLVM_ATTRIBUTE_UNUSED bool isWeakForLinker(GlobalLinkageKind linkage)
Whether the definition of this global may be replaced at link time.
Definition: CIROpsEnums.h:102
CIRGenCXXABI * CreateCIRGenItaniumCXXABI(CIRGenModule &cgm)
Creates and Itanium-family ABI.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
The JSON file list parser is used to communicate input to InstallAPI.
@ Ctor_Base
Base object ctor.
Definition: ABI.h:26
@ Ctor_Complete
Complete object ctor.
Definition: ABI.h:25
CXXDtorType
C++ destructor types.
Definition: ABI.h:33
@ Dtor_Base
Base object dtor.
Definition: ABI.h:36
@ Dtor_Complete
Complete object dtor.
Definition: ABI.h:35
@ Dtor_Deleting
Deleting dtor.
Definition: ABI.h:34
static bool opGlobalUnnamedAddr()
static bool vtableEmitMetadata()
static bool emitTypeMetadataCodeForVCall()
static bool cxxabiStructorImplicitParam()
static bool cxxabiAppleARM64CXXABI()
static bool appleKext()
static bool deferredVtables()
static bool cxxabiUseARMGuardVarABI()
static bool cxxabiUseARMMethodPtrABI()
static bool vtableRelativeLayout()
const clang::CXXRecordDecl * nearestVBase
clang::CharUnits getPointerAlign() const