27#include "llvm/Support/ErrorHandling.h"
37 llvm::DenseMap<const CXXRecordDecl *, cir::GlobalOp> vtables;
56 bool delegating,
Address thisAddr,
96void CIRGenItaniumCXXABI::emitInstanceFunctionProlog(
SourceLocation loc,
101 "emitInstanceFunctionProlog: Naked");
106 setCXXABIThisValue(cgf, loadIncomingCXXThis(cgf));
121 if (hasThisReturn(cgf.
curGD)) {
123 "emitInstanceFunctionProlog: hasThisReturn");
129enum class StructorCIRGen { Emit, RAUW, Alias, COMDAT };
135 return StructorCIRGen::Emit;
142 return StructorCIRGen::Emit;
146 if (
const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
149 const auto *cd = cast<CXXConstructorDecl>(md);
156 return StructorCIRGen::RAUW;
160 return StructorCIRGen::RAUW;
166 return StructorCIRGen::COMDAT;
167 return StructorCIRGen::Emit;
170 return StructorCIRGen::Alias;
180 auto globalValue = dyn_cast_or_null<cir::CIRGlobalValueInterface>(
182 if (globalValue && !globalValue.isDeclaration())
185 auto entry = cast_or_null<cir::FuncOp>(cgm.
getGlobalValue(mangledName));
194void CIRGenItaniumCXXABI::emitCXXStructor(
GlobalDecl gd) {
195 auto *md = cast<CXXMethodDecl>(gd.
getDecl());
197 const auto *cd = dyn_cast<CXXConstructorDecl>(md);
205 if (cirGenType == StructorCIRGen::Alias ||
206 cirGenType == StructorCIRGen::COMDAT) {
211 if (cirGenType == StructorCIRGen::RAUW) {
212 StringRef mangledName = cgm.getMangledName(gd);
213 mlir::Operation *aliasee = cgm.getAddrOfGlobal(baseDecl);
214 cgm.addReplacement(mangledName, aliasee);
219 auto fn = cgm.codegenCXXStructor(gd);
221 cgm.maybeSetTrivialComdat(*md, fn);
226 assert(cgm.getTarget().getCXXABI().hasConstructorVariants());
259bool CIRGenItaniumCXXABI::needsVTTParameter(
GlobalDecl gd) {
260 auto *md = cast<CXXMethodDecl>(gd.
getDecl());
263 if (!md->getParent()->getNumVBases())
277void CIRGenItaniumCXXABI::emitVTableDefinitions(
CIRGenVTables &cgvt,
279 cir::GlobalOp vtable = getAddrOfVTable(rd,
CharUnits());
280 if (vtable.hasInitializer())
285 cir::GlobalLinkageKind linkage = cgm.getVTableLinkage(rd);
286 mlir::Attribute rtti =
287 cgm.getAddrOfRTTIDescriptor(cgm.getLoc(rd->
getBeginLoc()),
288 cgm.getASTContext().getCanonicalTagType(rd));
297 vtable.setLinkage(linkage);
300 vtable.setComdat(
true);
303 cgm.setGVProperties(vtable, rd);
311 isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->getIdentifier() &&
312 cast<NamespaceDecl>(DC)->getIdentifier()->isStr(
"__cxxabiv1") &&
315 "emitVTableDefinitions: __fundamental_type_info");
318 auto vtableAsGlobalValue = dyn_cast<cir::CIRGlobalValueInterface>(*vtable);
319 assert(vtableAsGlobalValue &&
"VTable must support CIRGlobalValueInterface");
327 if (cgm.getCodeGenOpts().WholeProgramVTables) {
329 "emitVTableDefinitions: WholeProgramVTables");
338void CIRGenItaniumCXXABI::emitDestructorCall(
340 bool forVirtualBase,
bool delegating,
Address thisAddr,
QualType thisTy) {
342 if (needsVTTParameter(gd)) {
346 mlir::Value vtt =
nullptr;
361 mlir::Value exceptionPtr = {},
362 mlir::FlatSymbolRefAttr typeInfo = {},
363 mlir::FlatSymbolRefAttr dtor = {}) {
364 mlir::Block *currentBlock = builder.getInsertionBlock();
365 mlir::Region *region = currentBlock->getParent();
367 if (currentBlock->empty()) {
368 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
369 cir::UnreachableOp::create(builder, loc);
371 mlir::Block *throwBlock = builder.createBlock(region);
373 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
374 cir::UnreachableOp::create(builder, loc);
376 builder.setInsertionPointToEnd(currentBlock);
377 cir::BrOp::create(builder, loc, throwBlock);
380 (void)builder.createBlock(region);
383void CIRGenItaniumCXXABI::emitRethrow(
CIRGenFunction &cgf,
bool isNoReturn) {
387 assert(cgf.
currSrcLoc &&
"expected source location");
391 cgm.errorNYI(
"emitRethrow with isNoReturn false");
397 case TargetCXXABI::GenericItanium:
398 case TargetCXXABI::GenericAArch64:
399 return new CIRGenItaniumCXXABI(cgm);
401 case TargetCXXABI::AppleARM64:
405 return new CIRGenItaniumCXXABI(cgm);
408 llvm_unreachable(
"bad or NYI ABI kind");
412cir::GlobalOp CIRGenItaniumCXXABI::getAddrOfVTable(
const CXXRecordDecl *rd,
414 assert(vptrOffset.
isZero() &&
"Itanium ABI only supports zero vptr offsets");
415 cir::GlobalOp &vtable = vtables[rd];
423 llvm::raw_svector_ostream
out(name);
424 getMangleContext().mangleCXXVTable(rd,
out);
427 cgm.getItaniumVTableContext().getVTableLayout(rd);
428 mlir::Type vtableType = cgm.getVTables().getVTableType(vtLayout);
433 unsigned ptrAlign = cgm.getItaniumVTableContext().isRelativeLayout()
435 : cgm.getTarget().getPointerAlign(LangAS::Default);
437 vtable = cgm.createOrReplaceCXXRuntimeVariable(
439 cir::GlobalLinkageKind::ExternalLinkage,
440 cgm.getASTContext().toCharUnitsFromBits(ptrAlign));
451 if (cgm.getTarget().hasPS4DLLImportExport())
453 "getAddrOfVTable: PS4 DLL import/export");
455 cgm.setGVProperties(vtable, rd);
459CIRGenCallee CIRGenItaniumCXXABI::getVirtualFunctionPointer(
463 mlir::Location loc = cgf.
getLoc(srcLoc);
465 auto *methodDecl = cast<CXXMethodDecl>(gd.
getDecl());
466 mlir::Value vtable = cgf.
getVTablePtr(loc, thisAddr, methodDecl->getParent());
468 uint64_t vtableIndex = cgm.getItaniumVTableContext().getMethodVTableIndex(gd);
471 cgm.errorNYI(loc,
"getVirtualFunctionPointer: emitVTableTypeCheckedLoad");
475 mlir::Value vfuncLoad;
476 if (cgm.getItaniumVTableContext().isRelativeLayout()) {
478 cgm.errorNYI(loc,
"getVirtualFunctionPointer: isRelativeLayout");
480 auto vtableSlotPtr = cir::VTableGetVirtualFnAddrOp::create(
481 builder, loc, builder.
getPointerTo(tyPtr), vtable, vtableIndex);
492 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
493 cgm.getCodeGenOpts().StrictVTablePointers) {
494 cgm.errorNYI(loc,
"getVirtualFunctionPointer: strictVTablePointers");
504CIRGenItaniumCXXABI::getVTableAddressPoint(
BaseSubobject base,
506 cir::GlobalOp vtable = getAddrOfVTable(vtableClass,
CharUnits());
511 cgm.getItaniumVTableContext()
512 .getVTableLayout(vtableClass)
513 .getAddressPoint(base);
515 mlir::OpBuilder &builder = cgm.getBuilder();
516 auto vtablePtrTy = cir::VPtrType::get(builder.getContext());
518 return builder.create<cir::VTableAddrPointOp>(
520 mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()),
521 cir::AddressPointAttr::get(cgm.getBuilder().getContext(),
526mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructor(
531 needsVTTParameter(cgf.
curGD)) {
533 "getVTableAddressPointInStructorWithVTT");
535 return getVTableAddressPoint(base, vtableClass);
538bool CIRGenItaniumCXXABI::isVirtualOffsetNeededForVTableField(
542 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 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.
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