27#include "llvm/Support/ErrorHandling.h"
37 llvm::DenseMap<const CXXRecordDecl *, cir::GlobalOp> vtables;
40 CIRGenItaniumCXXABI(CIRGenModule &cgm) : CIRGenCXXABI(cgm) {
45 AddedStructorArgs getImplicitConstructorArgs(CIRGenFunction &cgf,
46 const CXXConstructorDecl *d,
49 bool delegating)
override;
51 bool needsVTTParameter(clang::GlobalDecl gd)
override;
53 AddedStructorArgCounts
54 buildStructorSignature(GlobalDecl gd,
55 llvm::SmallVectorImpl<CanQualType> &argTys)
override;
57 void emitInstanceFunctionProlog(SourceLocation loc,
58 CIRGenFunction &cgf)
override;
60 void addImplicitStructorParams(CIRGenFunction &cgf, QualType &resTy,
61 FunctionArgList ¶ms)
override;
63 void emitCXXConstructors(
const clang::CXXConstructorDecl *d)
override;
64 void emitCXXDestructors(
const clang::CXXDestructorDecl *d)
override;
65 void emitCXXStructor(clang::GlobalDecl gd)
override;
67 void emitDestructorCall(CIRGenFunction &cgf,
const CXXDestructorDecl *dd,
69 bool delegating, Address thisAddr,
70 QualType thisTy)
override;
72 void emitRethrow(CIRGenFunction &cgf,
bool isNoReturn)
override;
74 bool useThunkForDtorVariant(
const CXXDestructorDecl *dtor,
82 bool isVirtualOffsetNeededForVTableField(CIRGenFunction &cgf,
83 CIRGenFunction::VPtr vptr)
override;
85 cir::GlobalOp getAddrOfVTable(
const CXXRecordDecl *rd,
86 CharUnits vptrOffset)
override;
87 CIRGenCallee getVirtualFunctionPointer(CIRGenFunction &cgf,
88 clang::GlobalDecl gd, Address thisAddr,
90 SourceLocation loc)
override;
92 mlir::Value getVTableAddressPoint(BaseSubobject base,
93 const CXXRecordDecl *vtableClass)
override;
94 mlir::Value getVTableAddressPointInStructorWithVTT(
95 CIRGenFunction &cgf,
const CXXRecordDecl *vtableClass, BaseSubobject base,
96 const CXXRecordDecl *nearestVBase);
98 mlir::Value getVTableAddressPointInStructor(
99 CIRGenFunction &cgf,
const clang::CXXRecordDecl *vtableClass,
100 clang::BaseSubobject base,
101 const clang::CXXRecordDecl *nearestVBase)
override;
102 void emitVTableDefinitions(CIRGenVTables &cgvt,
103 const CXXRecordDecl *rd)
override;
104 void emitVirtualInheritanceTables(
const CXXRecordDecl *rd)
override;
106 bool doStructorsInitializeVPtrs(
const CXXRecordDecl *vtableClass)
override {
111 getVirtualBaseClassOffset(mlir::Location loc, CIRGenFunction &cgf,
112 Address thisAddr,
const CXXRecordDecl *classDecl,
113 const CXXRecordDecl *baseClassDecl)
override;
118void CIRGenItaniumCXXABI::emitInstanceFunctionProlog(
SourceLocation loc,
123 "emitInstanceFunctionProlog: Naked");
128 setCXXABIThisValue(cgf, loadIncomingCXXThis(cgf));
131 if (getStructorImplicitParamDecl(cgf)) {
135 setStructorImplicitParamValue(cgf, val);
146 if (hasThisReturn(cgf.
curGD)) {
148 "emitInstanceFunctionProlog: hasThisReturn");
152CIRGenCXXABI::AddedStructorArgCounts
153CIRGenItaniumCXXABI::buildStructorSignature(
154 GlobalDecl gd, llvm::SmallVectorImpl<CanQualType> &argTys) {
155 clang::ASTContext &astContext = cgm.getASTContext();
165 argTys.insert(argTys.begin() + 1,
168 return AddedStructorArgCounts::withPrefix(1);
171 return AddedStructorArgCounts{};
176enum class StructorCIRGen { Emit, RAUW, Alias, COMDAT };
182 return StructorCIRGen::Emit;
187 return StructorCIRGen::Emit;
190 if (
const auto *dd = dyn_cast<CXXDestructorDecl>(md)) {
200 return StructorCIRGen::RAUW;
204 return StructorCIRGen::RAUW;
210 return StructorCIRGen::COMDAT;
211 return StructorCIRGen::Emit;
214 return StructorCIRGen::Alias;
224 auto globalValue = dyn_cast_or_null<cir::CIRGlobalValueInterface>(
226 if (globalValue && !globalValue.isDeclaration())
229 auto entry = cast_or_null<cir::FuncOp>(cgm.
getGlobalValue(mangledName));
238void CIRGenItaniumCXXABI::emitCXXStructor(GlobalDecl gd) {
241 const auto *cd = dyn_cast<CXXConstructorDecl>(md);
245 GlobalDecl baseDecl =
249 if (cirGenType == StructorCIRGen::Alias ||
250 cirGenType == StructorCIRGen::COMDAT) {
255 if (cirGenType == StructorCIRGen::RAUW) {
256 StringRef mangledName = cgm.getMangledName(gd);
257 mlir::Operation *aliasee = cgm.getAddrOfGlobal(baseDecl);
258 cgm.addReplacement(mangledName, aliasee);
263 auto fn = cgm.codegenCXXStructor(gd);
265 cgm.maybeSetTrivialComdat(*md, fn);
268void CIRGenItaniumCXXABI::addImplicitStructorParams(CIRGenFunction &cgf,
270 FunctionArgList ¶ms) {
275 if (needsVTTParameter(cgf.
curGD)) {
276 ASTContext &astContext = cgm.getASTContext();
282 astContext,
nullptr, md->getLocation(),
283 &astContext.
Idents.
get(
"vtt"), t, ImplicitParamKind::CXXVTT);
284 params.insert(params.begin() + 1, vttDecl);
285 getStructorImplicitParamDecl(cgf) = vttDecl;
289void CIRGenItaniumCXXABI::emitCXXConstructors(
const CXXConstructorDecl *d) {
291 assert(cgm.getTarget().getCXXABI().hasConstructorVariants());
295 cgm.emitGlobal(GlobalDecl(d,
Ctor_Base));
305void CIRGenItaniumCXXABI::emitCXXDestructors(
const CXXDestructorDecl *d) {
308 cgm.emitGlobal(GlobalDecl(d,
Dtor_Base));
321CIRGenCXXABI::AddedStructorArgs CIRGenItaniumCXXABI::getImplicitConstructorArgs(
323 bool forVirtualBase,
bool delegating) {
324 if (!needsVTTParameter(GlobalDecl(d,
type)))
325 return AddedStructorArgs{};
333 cgm.getASTContext().getPointerType(cgm.getASTContext().VoidPtrTy);
335 return AddedStructorArgs::withPrefix({{vtt, vttTy}});
341bool CIRGenItaniumCXXABI::needsVTTParameter(GlobalDecl gd) {
345 if (!md->getParent()->getNumVBases())
359void CIRGenItaniumCXXABI::emitVTableDefinitions(CIRGenVTables &cgvt,
360 const CXXRecordDecl *rd) {
361 cir::GlobalOp vtable = getAddrOfVTable(rd, CharUnits());
362 if (vtable.hasInitializer())
365 ItaniumVTableContext &vtContext = cgm.getItaniumVTableContext();
367 cir::GlobalLinkageKind linkage = cgm.getVTableLinkage(rd);
368 mlir::Attribute rtti =
369 cgm.getAddrOfRTTIDescriptor(cgm.getLoc(rd->
getBeginLoc()),
370 cgm.getASTContext().getCanonicalTagType(rd));
379 vtable.setLinkage(linkage);
382 vtable.setComdat(
true);
385 cgm.setGVProperties(vtable, rd);
397 "emitVTableDefinitions: __fundamental_type_info");
400 auto vtableAsGlobalValue = dyn_cast<cir::CIRGlobalValueInterface>(*vtable);
401 assert(vtableAsGlobalValue &&
"VTable must support CIRGlobalValueInterface");
409 if (cgm.getCodeGenOpts().WholeProgramVTables) {
411 "emitVTableDefinitions: WholeProgramVTables");
420void CIRGenItaniumCXXABI::emitVirtualInheritanceTables(
421 const CXXRecordDecl *rd) {
422 CIRGenVTables &vtables = cgm.getVTables();
427void CIRGenItaniumCXXABI::emitDestructorCall(
429 bool forVirtualBase,
bool delegating, Address thisAddr, QualType thisTy) {
430 GlobalDecl gd(dd,
type);
431 if (needsVTTParameter(gd)) {
435 mlir::Value vtt =
nullptr;
436 ASTContext &astContext = cgm.getASTContext();
439 CIRGenCallee callee =
450 mlir::Value exceptionPtr = {},
451 mlir::FlatSymbolRefAttr typeInfo = {},
452 mlir::FlatSymbolRefAttr dtor = {}) {
453 mlir::Block *currentBlock = builder.getInsertionBlock();
454 mlir::Region *region = currentBlock->getParent();
456 if (currentBlock->empty()) {
457 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
458 cir::UnreachableOp::create(builder, loc);
460 mlir::Block *throwBlock = builder.createBlock(region);
462 cir::ThrowOp::create(builder, loc, exceptionPtr, typeInfo, dtor);
463 cir::UnreachableOp::create(builder, loc);
465 builder.setInsertionPointToEnd(currentBlock);
466 cir::BrOp::create(builder, loc, throwBlock);
469 (void)builder.createBlock(region);
472void CIRGenItaniumCXXABI::emitRethrow(CIRGenFunction &cgf,
bool isNoReturn) {
476 assert(cgf.
currSrcLoc &&
"expected source location");
480 cgm.errorNYI(
"emitRethrow with isNoReturn false");
486 case TargetCXXABI::GenericItanium:
487 case TargetCXXABI::GenericAArch64:
488 return new CIRGenItaniumCXXABI(cgm);
490 case TargetCXXABI::AppleARM64:
494 return new CIRGenItaniumCXXABI(cgm);
497 llvm_unreachable(
"bad or NYI ABI kind");
501cir::GlobalOp CIRGenItaniumCXXABI::getAddrOfVTable(
const CXXRecordDecl *rd,
503 assert(vptrOffset.
isZero() &&
"Itanium ABI only supports zero vptr offsets");
504 cir::GlobalOp &vtable = vtables[rd];
512 llvm::raw_svector_ostream
out(name);
513 getMangleContext().mangleCXXVTable(rd,
out);
516 cgm.getItaniumVTableContext().getVTableLayout(rd);
517 mlir::Type vtableType = cgm.getVTables().getVTableType(vtLayout);
522 unsigned ptrAlign = cgm.getItaniumVTableContext().isRelativeLayout()
526 vtable = cgm.createOrReplaceCXXRuntimeVariable(
528 cir::GlobalLinkageKind::ExternalLinkage,
529 cgm.getASTContext().toCharUnitsFromBits(ptrAlign));
540 if (cgm.getTarget().hasPS4DLLImportExport())
542 "getAddrOfVTable: PS4 DLL import/export");
544 cgm.setGVProperties(vtable, rd);
548CIRGenCallee CIRGenItaniumCXXABI::getVirtualFunctionPointer(
552 mlir::Location loc = cgf.
getLoc(srcLoc);
555 mlir::Value vtable = cgf.
getVTablePtr(loc, thisAddr, methodDecl->getParent());
557 uint64_t vtableIndex = cgm.getItaniumVTableContext().getMethodVTableIndex(gd);
560 cgm.errorNYI(loc,
"getVirtualFunctionPointer: emitVTableTypeCheckedLoad");
564 mlir::Value vfuncLoad;
565 if (cgm.getItaniumVTableContext().isRelativeLayout()) {
567 cgm.errorNYI(loc,
"getVirtualFunctionPointer: isRelativeLayout");
569 auto vtableSlotPtr = cir::VTableGetVirtualFnAddrOp::create(
570 builder, loc, builder.
getPointerTo(tyPtr), vtable, vtableIndex);
581 if (cgm.getCodeGenOpts().OptimizationLevel > 0 &&
582 cgm.getCodeGenOpts().StrictVTablePointers) {
583 cgm.errorNYI(loc,
"getVirtualFunctionPointer: strictVTablePointers");
588 CIRGenCallee callee(gd, vfunc.getDefiningOp());
592mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
593 CIRGenFunction &cgf,
const CXXRecordDecl *vtableClass, BaseSubobject base,
594 const CXXRecordDecl *nearestVBase) {
596 needsVTTParameter(cgf.
curGD) &&
"This class doesn't have VTT");
600 cgm.getVTables().getSecondaryVirtualPointerIndex(vtableClass, base);
607 virtualPointerIndex);
609 auto vptrType = cir::VPtrType::get(cgf.
getBuilder().getContext());
615CIRGenItaniumCXXABI::getVTableAddressPoint(BaseSubobject base,
616 const CXXRecordDecl *vtableClass) {
617 cir::GlobalOp vtable = getAddrOfVTable(vtableClass, CharUnits());
621 VTableLayout::AddressPointLocation addressPoint =
622 cgm.getItaniumVTableContext()
623 .getVTableLayout(vtableClass)
624 .getAddressPoint(base);
626 mlir::OpBuilder &builder = cgm.getBuilder();
627 auto vtablePtrTy = cir::VPtrType::get(builder.getContext());
629 return builder.create<cir::VTableAddrPointOp>(
631 mlir::FlatSymbolRefAttr::get(vtable.getSymNameAttr()),
632 cir::AddressPointAttr::get(cgm.getBuilder().getContext(),
637mlir::Value CIRGenItaniumCXXABI::getVTableAddressPointInStructor(
638 CIRGenFunction &cgf,
const clang::CXXRecordDecl *vtableClass,
639 clang::BaseSubobject base,
const clang::CXXRecordDecl *nearestVBase) {
642 needsVTTParameter(cgf.
curGD)) {
643 return getVTableAddressPointInStructorWithVTT(cgf, vtableClass, base,
646 return getVTableAddressPoint(base, vtableClass);
649bool CIRGenItaniumCXXABI::isVirtualOffsetNeededForVTableField(
650 CIRGenFunction &cgf, CIRGenFunction::VPtr vptr) {
653 return needsVTTParameter(cgf.
curGD);
656mlir::Value CIRGenItaniumCXXABI::getVirtualBaseClassOffset(
657 mlir::Location loc, CIRGenFunction &cgf, Address thisAddr,
658 const CXXRecordDecl *classDecl,
const CXXRecordDecl *baseClassDecl) {
660 mlir::Value vtablePtr = cgf.
getVTablePtr(loc, thisAddr, classDecl);
661 mlir::Value vtableBytePtr = builder.
createBitcast(vtablePtr, cgm.UInt8PtrTy);
662 CharUnits vbaseOffsetOffset =
663 cgm.getItaniumVTableContext().getVirtualBaseOffsetOffset(classDecl,
665 mlir::Value offsetVal =
667 auto vbaseOffsetPtr = cir::PtrStrideOp::create(builder, loc, cgm.UInt8PtrTy,
668 vtableBytePtr, offsetVal);
670 mlir::Value vbaseOffset;
671 if (cgm.getItaniumVTableContext().isRelativeLayout()) {
673 cgm.errorNYI(loc,
"getVirtualBaseClassOffset: relative layout");
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 createBitcast(mlir::Value src, mlir::Type newTy)
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
cir::ConstantOp getSInt64(uint64_t c, mlir::Location loc)
cir::LoadOp createAlignedLoad(mlir::Location loc, mlir::Type ty, mlir::Value ptr, llvm::MaybeAlign align)
mlir::Value createVTTAddrPoint(mlir::Location loc, mlir::Type retTy, mlir::Value addr, uint64_t offset)
cir::LoadOp createLoad(mlir::Location loc, Address addr, bool isVolatile=false)
Implements C++ ABI-specific code generation functions.
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
Address getAddrOfLocalVar(const clang::VarDecl *vd)
Return the address of a local variable.
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()
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 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.
static CanQual< Type > CreateUnsafe(QualType Other)
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 * 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.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ImplicitParamDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, ImplicitParamKind ParamKind)
Create implicit parameter.
bool isRelativeLayout() const
const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
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.
CXXCtorType
C++ constructor types.
@ Ctor_Base
Base object ctor.
@ Ctor_Complete
Complete object ctor.
bool isa(CodeGen::Address addr)
CXXDtorType
C++ destructor types.
@ Dtor_Base
Base object dtor.
@ Dtor_Complete
Complete object dtor.
@ Dtor_Deleting
Deleting dtor.
U cast(CodeGen::Address addr)
static bool addressSpace()
static bool opGlobalUnnamedAddr()
static bool vtableEmitMetadata()
static bool emitTypeMetadataCodeForVCall()
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