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 void emitVirtualInheritanceTables(const CXXRecordDecl *rd) override;
89
90 bool doStructorsInitializeVPtrs(const CXXRecordDecl *vtableClass) override {
91 return true;
92 }
93};
94
95} // namespace
96
97void CIRGenItaniumCXXABI::emitInstanceFunctionProlog(SourceLocation loc,
98 CIRGenFunction &cgf) {
99 // Naked functions have no prolog.
100 if (cgf.curFuncDecl && cgf.curFuncDecl->hasAttr<NakedAttr>()) {
102 "emitInstanceFunctionProlog: Naked");
103 }
104
105 /// Initialize the 'this' slot. In the Itanium C++ ABI, no prologue
106 /// adjustments are required, because they are all handled by thunks.
107 setCXXABIThisValue(cgf, loadIncomingCXXThis(cgf));
108
109 /// Classic codegen has code here to initialize the 'vtt' slot if
110 // getStructorImplicitParamDecl(cgf) returns a non-null value, but in the
111 // current implementation (of classic codegen) it never does.
113
114 /// If this is a function that the ABI specifies returns 'this', initialize
115 /// the return slot to this' at the start of the function.
116 ///
117 /// Unlike the setting of return types, this is done within the ABI
118 /// implementation instead of by clients of CIRGenCXXBI because:
119 /// 1) getThisValue is currently protected
120 /// 2) in theory, an ABI could implement 'this' returns some other way;
121 /// HasThisReturn only specifies a contract, not the implementation
122 if (hasThisReturn(cgf.curGD)) {
124 "emitInstanceFunctionProlog: hasThisReturn");
125 }
126}
127
128// Find out how to cirgen the complete destructor and constructor
129namespace {
130enum class StructorCIRGen { Emit, RAUW, Alias, COMDAT };
131}
132
133static StructorCIRGen getCIRGenToUse(CIRGenModule &cgm,
134 const CXXMethodDecl *md) {
135 if (!cgm.getCodeGenOpts().CXXCtorDtorAliases)
136 return StructorCIRGen::Emit;
137
138 // The complete and base structors are not equivalent if there are any virtual
139 // bases, so emit separate functions.
140 if (md->getParent()->getNumVBases()) {
141 // The return value is correct here, but other support for this is NYI.
142 cgm.errorNYI(md->getSourceRange(), "getCIRGenToUse: virtual bases");
143 return StructorCIRGen::Emit;
144 }
145
146 GlobalDecl aliasDecl;
147 if (const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
148 aliasDecl = GlobalDecl(dd, Dtor_Complete);
149 } else {
150 const auto *cd = cast<CXXConstructorDecl>(md);
151 aliasDecl = GlobalDecl(cd, Ctor_Complete);
152 }
153
154 cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);
155
156 if (cir::isDiscardableIfUnused(linkage))
157 return StructorCIRGen::RAUW;
158
159 // FIXME: Should we allow available_externally aliases?
160 if (!cir::isValidLinkage(linkage))
161 return StructorCIRGen::RAUW;
162
163 if (cir::isWeakForLinker(linkage)) {
164 // Only ELF and wasm support COMDATs with arbitrary names (C5/D5).
165 if (cgm.getTarget().getTriple().isOSBinFormatELF() ||
166 cgm.getTarget().getTriple().isOSBinFormatWasm())
167 return StructorCIRGen::COMDAT;
168 return StructorCIRGen::Emit;
169 }
170
171 return StructorCIRGen::Alias;
172}
173
175 GlobalDecl aliasDecl,
176 GlobalDecl targetDecl) {
177 cir::GlobalLinkageKind linkage = cgm.getFunctionLinkage(aliasDecl);
178
179 // Does this function alias already exists?
180 StringRef mangledName = cgm.getMangledName(aliasDecl);
181 auto globalValue = dyn_cast_or_null<cir::CIRGlobalValueInterface>(
182 cgm.getGlobalValue(mangledName));
183 if (globalValue && !globalValue.isDeclaration())
184 return;
185
186 auto entry = cast_or_null<cir::FuncOp>(cgm.getGlobalValue(mangledName));
187
188 // Retrieve aliasee info.
189 auto aliasee = cast<cir::FuncOp>(cgm.getAddrOfGlobal(targetDecl));
190
191 // Populate actual alias.
192 cgm.emitAliasForGlobal(mangledName, entry, aliasDecl, aliasee, linkage);
193}
194
195void CIRGenItaniumCXXABI::emitCXXStructor(GlobalDecl gd) {
196 auto *md = cast<CXXMethodDecl>(gd.getDecl());
197 StructorCIRGen cirGenType = getCIRGenToUse(cgm, md);
198 const auto *cd = dyn_cast<CXXConstructorDecl>(md);
199
200 if (cd ? gd.getCtorType() == Ctor_Complete
201 : gd.getDtorType() == Dtor_Complete) {
202 GlobalDecl baseDecl =
204 ;
205
206 if (cirGenType == StructorCIRGen::Alias ||
207 cirGenType == StructorCIRGen::COMDAT) {
208 emitConstructorDestructorAlias(cgm, gd, baseDecl);
209 return;
210 }
211
212 if (cirGenType == StructorCIRGen::RAUW) {
213 StringRef mangledName = cgm.getMangledName(gd);
214 mlir::Operation *aliasee = cgm.getAddrOfGlobal(baseDecl);
215 cgm.addReplacement(mangledName, aliasee);
216 return;
217 }
218 }
219
220 auto fn = cgm.codegenCXXStructor(gd);
221
222 cgm.maybeSetTrivialComdat(*md, fn);
223}
224
225void CIRGenItaniumCXXABI::emitCXXConstructors(const CXXConstructorDecl *d) {
226 // Just make sure we're in sync with TargetCXXABI.
227 assert(cgm.getTarget().getCXXABI().hasConstructorVariants());
228
229 // The constructor used for constructing this as a base class;
230 // ignores virtual bases.
231 cgm.emitGlobal(GlobalDecl(d, Ctor_Base));
232
233 // The constructor used for constructing this as a complete class;
234 // constructs the virtual bases, then calls the base constructor.
235 if (!d->getParent()->isAbstract()) {
236 // We don't need to emit the complete ctro if the class is abstract.
237 cgm.emitGlobal(GlobalDecl(d, Ctor_Complete));
238 }
239}
240
241void CIRGenItaniumCXXABI::emitCXXDestructors(const CXXDestructorDecl *d) {
242 // The destructor used for destructing this as a base class; ignores
243 // virtual bases.
244 cgm.emitGlobal(GlobalDecl(d, Dtor_Base));
245
246 // The destructor used for destructing this as a most-derived class;
247 // call the base destructor and then destructs any virtual bases.
248 cgm.emitGlobal(GlobalDecl(d, Dtor_Complete));
249
250 // The destructor in a virtual table is always a 'deleting'
251 // destructor, which calls the complete destructor and then uses the
252 // appropriate operator delete.
253 if (d->isVirtual())
254 cgm.emitGlobal(GlobalDecl(d, Dtor_Deleting));
255}
256
257/// Return whether the given global decl needs a VTT (virtual table table)
258/// parameter, which it does if it's a base constructor or destructor with
259/// virtual bases.
260bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) {
261 auto *md = cast<CXXMethodDecl>(gd.getDecl());
262
263 // We don't have any virtual bases, just return early.
264 if (!md->getParent()->getNumVBases())
265 return false;
266
267 // Check if we have a base constructor.
268 if (isa<CXXConstructorDecl>(md) && gd.getCtorType() == Ctor_Base)
269 return true;
270
271 // Check if we have a base destructor.
272 if (isa<CXXDestructorDecl>(md) && gd.getDtorType() == Dtor_Base)
273 return true;
274
275 return false;
276}
277
278void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,
279 const CXXRecordDecl *rd) {
280 cir::GlobalOp vtable = getAddrOfVTable(rd, CharUnits());
281 if (vtable.hasInitializer())
282 return;
283
284 ItaniumVTableContext &vtContext = cgm.getItaniumVTableContext();
285 const VTableLayout &vtLayout = vtContext.getVTableLayout(rd);
286 cir::GlobalLinkageKind linkage = cgm.getVTableLinkage(rd);
287 mlir::Attribute rtti =
288 cgm.getAddrOfRTTIDescriptor(cgm.getLoc(rd->getBeginLoc()),
289 cgm.getASTContext().getCanonicalTagType(rd));
290
291 // Classic codegen uses ConstantInitBuilder here, which is a very general
292 // and feature-rich class to generate initializers for global values.
293 // For now, this is using a simpler approach to create the initializer in CIR.
294 cgvt.createVTableInitializer(vtable, vtLayout, rtti,
295 cir::isLocalLinkage(linkage));
296
297 // Set the correct linkage.
298 vtable.setLinkage(linkage);
299
300 if (cgm.supportsCOMDAT() && cir::isWeakForLinker(linkage))
301 vtable.setComdat(true);
302
303 // Set the right visibility.
304 cgm.setGVProperties(vtable, rd);
305
306 // If this is the magic class __cxxabiv1::__fundamental_type_info,
307 // we will emit the typeinfo for the fundamental types. This is the
308 // same behaviour as GCC.
309 const DeclContext *DC = rd->getDeclContext();
310 if (rd->getIdentifier() &&
311 rd->getIdentifier()->isStr("__fundamental_type_info") &&
312 isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
313 cast<NamespaceDecl>(DC)->getIdentifier()->isStr("__cxxabiv1") &&
314 DC->getParent()->isTranslationUnit()) {
315 cgm.errorNYI(rd->getSourceRange(),
316 "emitVTableDefinitions: __fundamental_type_info");
317 }
318
319 auto vtableAsGlobalValue = dyn_cast<cir::CIRGlobalValueInterface>(*vtable);
320 assert(vtableAsGlobalValue && "VTable must support CIRGlobalValueInterface");
321 // Always emit type metadata on non-available_externally definitions, and on
322 // available_externally definitions if we are performing whole program
323 // devirtualization. For WPD we need the type metadata on all vtable
324 // definitions to ensure we associate derived classes with base classes
325 // defined in headers but with a strong definition only in a shared
326 // library.
328 if (cgm.getCodeGenOpts().WholeProgramVTables) {
329 cgm.errorNYI(rd->getSourceRange(),
330 "emitVTableDefinitions: WholeProgramVTables");
331 }
332
334 if (vtContext.isRelativeLayout()) {
335 cgm.errorNYI(rd->getSourceRange(), "vtableRelativeLayout");
336 }
337}
338
339void CIRGenItaniumCXXABI::emitVirtualInheritanceTables(
340 const CXXRecordDecl *rd) {
341 CIRGenVTables &vtables = cgm.getVTables();
342 cir::GlobalOp vtt = vtables.getAddrOfVTT(rd);
343 vtables.emitVTTDefinition(vtt, cgm.getVTableLinkage(rd), rd);
344}
345
346void CIRGenItaniumCXXABI::emitDestructorCall(
348 bool forVirtualBase, bool delegating, Address thisAddr, QualType thisTy) {
349 GlobalDecl gd(dd, type);
350 if (needsVTTParameter(gd)) {
351 cgm.errorNYI(dd->getSourceRange(), "emitDestructorCall: VTT");
352 }
353
354 mlir::Value vtt = nullptr;
355 ASTContext &astContext = cgm.getASTContext();
356 QualType vttTy = astContext.getPointerType(astContext.VoidPtrTy);
358 CIRGenCallee callee =
359 CIRGenCallee::forDirect(cgm.getAddrOfCXXStructor(gd), gd);
360
361 cgf.emitCXXDestructorCall(gd, callee, thisAddr.getPointer(), thisTy, vtt,
362 vttTy, nullptr);
363}
364
365// The idea here is creating a separate block for the throw with an
366// `UnreachableOp` as the terminator. So, we branch from the current block
367// to the throw block and create a block for the remaining operations.
368static void insertThrowAndSplit(mlir::OpBuilder &builder, mlir::Location loc,
369 mlir::Value exceptionPtr = {},
370 mlir::FlatSymbolRefAttr typeInfo = {},
371 mlir::FlatSymbolRefAttr dtor = {}) {
372 mlir::Block *currentBlock = builder.getInsertionBlock();
373 mlir::Region *region = currentBlock->getParent();
374
375 if (currentBlock->empty()) {
376 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
377 cir::UnreachableOp::create(builder, loc);
378 } else {
379 mlir::Block *throwBlock = builder.createBlock(region);
380
381 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
382 cir::UnreachableOp::create(builder, loc);
383
384 builder.setInsertionPointToEnd(currentBlock);
385 cir::BrOp::create(builder, loc, throwBlock);
386 }
387
388 (void)builder.createBlock(region);
389}
390
391void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &cgf, bool isNoReturn) {
392 // void __cxa_rethrow();
393 if (isNoReturn) {
394 CIRGenBuilderTy &builder = cgf.getBuilder();
395 assert(cgf.currSrcLoc && "expected source location");
396 mlir::Location loc = *cgf.currSrcLoc;
397 insertThrowAndSplit(builder, loc);
398 } else {
399 cgm.errorNYI("emitRethrow with isNoReturn false");
400 }
401}
402
404 switch (cgm.getASTContext().getCXXABIKind()) {
405 case TargetCXXABI::GenericItanium:
406 case TargetCXXABI::GenericAArch64:
407 return new CIRGenItaniumCXXABI(cgm);
408
409 case TargetCXXABI::AppleARM64:
410 // The general Itanium ABI will do until we implement something that
411 // requires special handling.
413 return new CIRGenItaniumCXXABI(cgm);
414
415 default:
416 llvm_unreachable("bad or NYI ABI kind");
417 }
418}
419
420cir::GlobalOp CIRGenItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *rd,
421 CharUnits vptrOffset) {
422 assert(vptrOffset.isZero() && "Itanium ABI only supports zero vptr offsets");
423 cir::GlobalOp &vtable = vtables[rd];
424 if (vtable)
425 return vtable;
426
427 // Queue up this vtable for possible deferred emission.
429
430 SmallString<256> name;
431 llvm::raw_svector_ostream out(name);
432 getMangleContext().mangleCXXVTable(rd, out);
433
434 const VTableLayout &vtLayout =
435 cgm.getItaniumVTableContext().getVTableLayout(rd);
436 mlir::Type vtableType = cgm.getVTables().getVTableType(vtLayout);
437
438 // Use pointer alignment for the vtable. Otherwise we would align them based
439 // on the size of the initializer which doesn't make sense as only single
440 // values are read.
441 unsigned ptrAlign = cgm.getItaniumVTableContext().isRelativeLayout()
442 ? 32
443 : cgm.getTarget().getPointerAlign(LangAS::Default);
444
445 vtable = cgm.createOrReplaceCXXRuntimeVariable(
446 cgm.getLoc(rd->getSourceRange()), name, vtableType,
447 cir::GlobalLinkageKind::ExternalLinkage,
448 cgm.getASTContext().toCharUnitsFromBits(ptrAlign));
449 // LLVM codegen handles unnamedAddr
451
452 // In MS C++ if you have a class with virtual functions in which you are using
453 // selective member import/export, then all virtual functions must be exported
454 // unless they are inline, otherwise a link error will result. To match this
455 // behavior, for such classes, we dllimport the vtable if it is defined
456 // externally and all the non-inline virtual methods are marked dllimport, and
457 // we dllexport the vtable if it is defined in this TU and all the non-inline
458 // virtual methods are marked dllexport.
459 if (cgm.getTarget().hasPS4DLLImportExport())
460 cgm.errorNYI(rd->getSourceRange(),
461 "getAddrOfVTable: PS4 DLL import/export");
462
463 cgm.setGVProperties(vtable, rd);
464 return vtable;
465}
466
467CIRGenCallee CIRGenItaniumCXXABI::getVirtualFunctionPointer(
468 CIRGenFunction &cgf, clang::GlobalDecl gd, Address thisAddr, mlir::Type ty,
469 SourceLocation srcLoc) {
470 CIRGenBuilderTy &builder = cgm.getBuilder();
471 mlir::Location loc = cgf.getLoc(srcLoc);
472 cir::PointerType tyPtr = builder.getPointerTo(ty);
473 auto *methodDecl = cast<CXXMethodDecl>(gd.getDecl());
474 mlir::Value vtable = cgf.getVTablePtr(loc, thisAddr, methodDecl->getParent());
475
476 uint64_t vtableIndex = cgm.getItaniumVTableContext().getMethodVTableIndex(gd);
477 mlir::Value vfunc{};
478 if (cgf.shouldEmitVTableTypeCheckedLoad(methodDecl->getParent())) {
479 cgm.errorNYI(loc, "getVirtualFunctionPointer: emitVTableTypeCheckedLoad");
480 } else {
482
483 mlir::Value vfuncLoad;
484 if (cgm.getItaniumVTableContext().isRelativeLayout()) {
486 cgm.errorNYI(loc, "getVirtualFunctionPointer: isRelativeLayout");
487 } else {
488 auto vtableSlotPtr = cir::VTableGetVirtualFnAddrOp::create(
489 builder, loc, builder.getPointerTo(tyPtr), vtable, vtableIndex);
490 vfuncLoad = builder.createAlignedLoad(
491 loc, vtableSlotPtr, cgf.getPointerAlign().getQuantity());
492 }
493
494 // Add !invariant.load md to virtual function load to indicate that
495 // function didn't change inside vtable.
496 // It's safe to add it without -fstrict-vtable-pointers, but it would not
497 // help in devirtualization because it will only matter if we will have 2
498 // the same virtual function loads from the same vtable load, which won't
499 // happen without enabled devirtualization with -fstrict-vtable-pointers.
500 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
501 cgm.getCodeGenOpts().StrictVTablePointers) {
502 cgm.errorNYI(loc, "getVirtualFunctionPointer: strictVTablePointers");
503 }
504 vfunc = vfuncLoad;
505 }
506
507 CIRGenCallee callee(gd, vfunc.getDefiningOp());
508 return callee;
509}
510
511mlir::Value
512CIRGenItaniumCXXABI::getVTableAddressPoint(BaseSubobject base,
513 const CXXRecordDecl *vtableClass) {
514 cir::GlobalOp vtable = getAddrOfVTable(vtableClass, CharUnits());
515
516 // Find the appropriate vtable within the vtable group, and the address point
517 // within that vtable.
519 cgm.getItaniumVTableContext()
520 .getVTableLayout(vtableClass)
521 .getAddressPoint(base);
522
523 mlir::OpBuilder &builder = cgm.getBuilder();
524 auto vtablePtrTy = cir::VPtrType::get(builder.getContext());
525
526 return builder.create<cir::VTableAddrPointOp>(
527 cgm.getLoc(vtableClass->getSourceRange()), vtablePtrTy,
528 mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()),
529 cir::AddressPointAttr::get(cgm.getBuilder().getContext(),
530 addressPoint.VTableIndex,
531 addressPoint.AddressPointIndex));
532}
533
534mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructor(
535 CIRGenFunction &cgf, const clang::CXXRecordDecl *vtableClass,
536 clang::BaseSubobject base, const clang::CXXRecordDecl *nearestVBase) {
537
538 if ((base.getBase()->getNumVBases() || nearestVBase != nullptr) &&
539 needsVTTParameter(cgf.curGD)) {
540 cgm.errorNYI(cgf.curFuncDecl->getLocation(),
541 "getVTableAddressPointInStructorWithVTT");
542 }
543 return getVTableAddressPoint(base, vtableClass);
544}
545
546bool CIRGenItaniumCXXABI::isVirtualOffsetNeededForVTableField(
548 if (vptr.nearestVBase == nullptr)
549 return false;
550 return needsVTTParameter(cgf.curGD);
551}
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 emitVirtualInheritanceTables(const CXXRecordDecl *rd)=0
Emit any tables needed to implement virtual inheritance.
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.
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.
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:4490
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:4834
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:3544
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