27#include "llvm/Support/ErrorHandling.h"
37 llvm::DenseMap<const CXXRecordDecl *, cir::GlobalOp> vtables;
56 bool delegating,
Address thisAddr,
97void CIRGenItaniumCXXABI::emitInstanceFunctionProlog(
SourceLocation loc,
102 "emitInstanceFunctionProlog: Naked");
107 setCXXABIThisValue(cgf, loadIncomingCXXThis(cgf));
122 if (hasThisReturn(cgf.
curGD)) {
124 "emitInstanceFunctionProlog: hasThisReturn");
130enum class StructorCIRGen { Emit, RAUW, Alias, COMDAT };
136 return StructorCIRGen::Emit;
143 return StructorCIRGen::Emit;
147 if (
const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
150 const auto *cd = cast<CXXConstructorDecl>(md);
157 return StructorCIRGen::RAUW;
161 return StructorCIRGen::RAUW;
167 return StructorCIRGen::COMDAT;
168 return StructorCIRGen::Emit;
171 return StructorCIRGen::Alias;
181 auto globalValue = dyn_cast_or_null<cir::CIRGlobalValueInterface>(
183 if (globalValue && !globalValue.isDeclaration())
186 auto entry = cast_or_null<cir::FuncOp>(cgm.
getGlobalValue(mangledName));
195void CIRGenItaniumCXXABI::emitCXXStructor(
GlobalDecl gd) {
196 auto *md = cast<CXXMethodDecl>(gd.
getDecl());
198 const auto *cd = dyn_cast<CXXConstructorDecl>(md);
206 if (cirGenType == StructorCIRGen::Alias ||
207 cirGenType == StructorCIRGen::COMDAT) {
212 if (cirGenType == StructorCIRGen::RAUW) {
213 StringRef mangledName = cgm.getMangledName(gd);
214 mlir::Operation *aliasee = cgm.getAddrOfGlobal(baseDecl);
215 cgm.addReplacement(mangledName, aliasee);
220 auto fn = cgm.codegenCXXStructor(gd);
222 cgm.maybeSetTrivialComdat(*md, fn);
227 assert(cgm.getTarget().getCXXABI().hasConstructorVariants());
260bool CIRGenItaniumCXXABI::needsVTTParameter(
GlobalDecl gd) {
261 auto *md = cast<CXXMethodDecl>(gd.
getDecl());
264 if (!md->getParent()->getNumVBases())
278void CIRGenItaniumCXXABI::emitVTableDefinitions(
CIRGenVTables &cgvt,
280 cir::GlobalOp vtable = getAddrOfVTable(rd,
CharUnits());
281 if (vtable.hasInitializer())
286 cir::GlobalLinkageKind linkage = cgm.getVTableLinkage(rd);
287 mlir::Attribute rtti =
288 cgm.getAddrOfRTTIDescriptor(cgm.getLoc(rd->
getBeginLoc()),
289 cgm.getASTContext().getCanonicalTagType(rd));
298 vtable.setLinkage(linkage);
301 vtable.setComdat(
true);
304 cgm.setGVProperties(vtable, rd);
312 isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
313 cast<NamespaceDecl>(DC)->getIdentifier()->isStr(
"__cxxabiv1") &&
316 "emitVTableDefinitions: __fundamental_type_info");
319 auto vtableAsGlobalValue = dyn_cast<cir::CIRGlobalValueInterface>(*vtable);
320 assert(vtableAsGlobalValue &&
"VTable must support CIRGlobalValueInterface");
328 if (cgm.getCodeGenOpts().WholeProgramVTables) {
330 "emitVTableDefinitions: WholeProgramVTables");
339void CIRGenItaniumCXXABI::emitVirtualInheritanceTables(
346void CIRGenItaniumCXXABI::emitDestructorCall(
348 bool forVirtualBase,
bool delegating,
Address thisAddr,
QualType thisTy) {
350 if (needsVTTParameter(gd)) {
354 mlir::Value vtt =
nullptr;
369 mlir::Value exceptionPtr = {},
370 mlir::FlatSymbolRefAttr typeInfo = {},
371 mlir::FlatSymbolRefAttr dtor = {}) {
372 mlir::Block *currentBlock = builder.getInsertionBlock();
373 mlir::Region *region = currentBlock->getParent();
375 if (currentBlock->empty()) {
376 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
377 cir::UnreachableOp::create(builder, loc);
379 mlir::Block *throwBlock = builder.createBlock(region);
381 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
382 cir::UnreachableOp::create(builder, loc);
384 builder.setInsertionPointToEnd(currentBlock);
385 cir::BrOp::create(builder, loc, throwBlock);
388 (void)builder.createBlock(region);
391void CIRGenItaniumCXXABI::emitRethrow(
CIRGenFunction &cgf,
bool isNoReturn) {
395 assert(cgf.
currSrcLoc &&
"expected source location");
399 cgm.errorNYI(
"emitRethrow with isNoReturn false");
405 case TargetCXXABI::GenericItanium:
406 case TargetCXXABI::GenericAArch64:
407 return new CIRGenItaniumCXXABI(cgm);
409 case TargetCXXABI::AppleARM64:
413 return new CIRGenItaniumCXXABI(cgm);
416 llvm_unreachable(
"bad or NYI ABI kind");
420cir::GlobalOp CIRGenItaniumCXXABI::getAddrOfVTable(
const CXXRecordDecl *rd,
422 assert(vptrOffset.
isZero() &&
"Itanium ABI only supports zero vptr offsets");
423 cir::GlobalOp &vtable = vtables[rd];
431 llvm::raw_svector_ostream
out(name);
432 getMangleContext().mangleCXXVTable(rd,
out);
435 cgm.getItaniumVTableContext().getVTableLayout(rd);
436 mlir::Type vtableType = cgm.getVTables().getVTableType(vtLayout);
441 unsigned ptrAlign = cgm.getItaniumVTableContext().isRelativeLayout()
443 : cgm.getTarget().getPointerAlign(LangAS::Default);
445 vtable = cgm.createOrReplaceCXXRuntimeVariable(
447 cir::GlobalLinkageKind::ExternalLinkage,
448 cgm.getASTContext().toCharUnitsFromBits(ptrAlign));
459 if (cgm.getTarget().hasPS4DLLImportExport())
461 "getAddrOfVTable: PS4 DLL import/export");
463 cgm.setGVProperties(vtable, rd);
467CIRGenCallee CIRGenItaniumCXXABI::getVirtualFunctionPointer(
471 mlir::Location loc = cgf.
getLoc(srcLoc);
473 auto *methodDecl = cast<CXXMethodDecl>(gd.
getDecl());
474 mlir::Value vtable = cgf.
getVTablePtr(loc, thisAddr, methodDecl->getParent());
476 uint64_t vtableIndex = cgm.getItaniumVTableContext().getMethodVTableIndex(gd);
479 cgm.errorNYI(loc,
"getVirtualFunctionPointer: emitVTableTypeCheckedLoad");
483 mlir::Value vfuncLoad;
484 if (cgm.getItaniumVTableContext().isRelativeLayout()) {
486 cgm.errorNYI(loc,
"getVirtualFunctionPointer: isRelativeLayout");
488 auto vtableSlotPtr = cir::VTableGetVirtualFnAddrOp::create(
489 builder, loc, builder.
getPointerTo(tyPtr), vtable, vtableIndex);
500 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
501 cgm.getCodeGenOpts().StrictVTablePointers) {
502 cgm.errorNYI(loc,
"getVirtualFunctionPointer: strictVTablePointers");
512CIRGenItaniumCXXABI::getVTableAddressPoint(
BaseSubobject base,
514 cir::GlobalOp vtable = getAddrOfVTable(vtableClass,
CharUnits());
519 cgm.getItaniumVTableContext()
520 .getVTableLayout(vtableClass)
521 .getAddressPoint(base);
523 mlir::OpBuilder &builder = cgm.getBuilder();
524 auto vtablePtrTy = cir::VPtrType::get(builder.getContext());
526 return builder.create<cir::VTableAddrPointOp>(
528 mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()),
529 cir::AddressPointAttr::get(cgm.getBuilder().getContext(),
534mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructor(
539 needsVTTParameter(cgf.
curGD)) {
541 "getVTableAddressPointInStructorWithVTT");
543 return getVTableAddressPoint(base, vtableClass);
546bool CIRGenItaniumCXXABI::isVirtualOffsetNeededForVTableField(
550 return needsVTTParameter(cgf.
curGD);
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 ...
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
TargetCXXABI::Kind getCXXABIKind() const
Return the C++ ABI kind that should be used.
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
mlir::Value getPointer() const
Implements C++ ABI-specific code generation functions.
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.
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())
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.
llvm::StringRef getMangledName(clang::GlobalDecl gd)
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
const clang::TargetInfo & getTarget() const
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
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.
Represents a C++ destructor within a class.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
bool isAbstract() const
Determine whether this class has a pure virtual function.
unsigned getNumVBases() const
Retrieves the number of virtual base classes of this class.
CharUnits - This is an opaque type for sizes expressed in character units.
bool isZero() const
isZero - Test whether the quantity equals zero.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isTranslationUnit() const
SourceLocation getLocation() const
DeclContext * getDeclContext()
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
GlobalDecl - represents a global declaration.
GlobalDecl getWithCtorType(CXXCtorType Type)
CXXCtorType getCtorType() const
GlobalDecl getWithDtorType(CXXDtorType Type)
CXXDtorType getDtorType() const
const Decl * getDecl() const
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
bool isRelativeLayout() const
const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
A (possibly-)qualified type.
Encodes a location in the source.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
SourceLocation getBeginLoc() const LLVM_READONLY
static bool isLocalLinkage(GlobalLinkageKind linkage)
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.
static LLVM_ATTRIBUTE_UNUSED bool isValidLinkage(GlobalLinkageKind gl)
static LLVM_ATTRIBUTE_UNUSED bool isWeakForLinker(GlobalLinkageKind linkage)
Whether the definition of this global may be replaced at link time.
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.
@ Ctor_Complete
Complete object ctor.
CXXDtorType
C++ destructor types.
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
static bool opGlobalUnnamedAddr()
static bool vtableEmitMetadata()
static bool emitTypeMetadataCodeForVCall()
static bool cxxabiStructorImplicitParam()
static bool cxxabiAppleARM64CXXABI()
static bool deferredVtables()
static bool cxxabiUseARMGuardVarABI()
static bool cxxabiUseARMMethodPtrABI()
static bool vtableRelativeLayout()
const clang::CXXRecordDecl * nearestVBase
clang::CharUnits getPointerAlign() const
unsigned AddressPointIndex