17#include "mlir/IR/Types.h"
20#include "llvm/ADT/SmallVector.h"
27 : cgm(cgm), vtContext(cgm.getASTContext().getVTableContext()) {}
35mlir::Type CIRGenVTables::getVTableComponentType() {
41 mlir::Type componentType = getVTableComponentType();
43 tys.push_back(cir::ArrayType::get(componentType, layout.
getVTableSize(i)));
69mlir::Attribute CIRGenVTables::getVTableComponent(
70 const VTableLayout &layout,
unsigned componentIndex, mlir::Attribute rtti,
71 unsigned &nextVTableThunkIndex,
unsigned vtableAddressPoint,
72 bool vtableHasLocalLinkage) {
81 cgm.
errorNYI(
"getVTableComponent: CompleteDtorPointer");
82 return mlir::Attribute();
84 cgm.
errorNYI(
"getVTableComponent: DeletingDtorPointer");
85 return mlir::Attribute();
87 cgm.
errorNYI(
"getVTableComponent: UnusedFunctionPointer");
88 return mlir::Attribute();
103 assert((mlir::isa<cir::GlobalViewAttr>(rtti) ||
104 mlir::isa<cir::ConstPtrAttr>(rtti)) &&
105 "expected GlobalViewAttr or ConstPtrAttr");
114 if (cast<CXXMethodDecl>(gd.
getDecl())->isPureVirtual()) {
115 cgm.
errorNYI(
"getVTableComponent: CK_FunctionPointer: pure virtual");
116 return mlir::Attribute();
117 }
else if (cast<CXXMethodDecl>(gd.
getDecl())->isDeleted()) {
118 cgm.
errorNYI(
"getVTableComponent: CK_FunctionPointer: deleted virtual");
119 return mlir::Attribute();
120 }
else if (nextVTableThunkIndex < layout.
vtable_thunks().size() &&
123 cgm.
errorNYI(
"getVTableComponent: CK_FunctionPointer: thunk");
124 return mlir::Attribute();
131 return cir::GlobalViewAttr::get(
133 mlir::FlatSymbolRefAttr::get(fnPtr.getSymNameAttr()));
137 llvm_unreachable(
"Unexpected vtable component kind");
142 mlir::Attribute rtti,
143 bool vtableHasLocalLinkage) {
144 mlir::Type componentType = getVTableComponentType();
148 unsigned nextVTableThunkIndex = 0;
153 for (
auto [vtableIndex, addressPoint] : llvm::enumerate(addressPoints)) {
156 size_t vtableEnd = vtableStart + layout.
getVTableSize(vtableIndex);
158 components.reserve(vtableEnd - vtableStart);
159 for (
size_t componentIndex : llvm::seq(vtableStart, vtableEnd))
160 components.push_back(
161 getVTableComponent(layout, componentIndex, rtti, nextVTableThunkIndex,
162 addressPoint, vtableHasLocalLinkage));
164 auto arr = cir::ConstArrayAttr::get(
165 cir::ArrayType::get(componentType, components.size()),
166 mlir::ArrayAttr::get(mlirContext, components));
167 vtables.push_back(arr);
171 const auto members = mlir::ArrayAttr::get(mlirContext, vtables);
175 auto vtableAttr = cir::VTableAttr::get(record.getType(), record.getMembers());
183 cir::GlobalLinkageKind linkage, VTableAddressPointsMapTy &addressPoints) {
186 std::unique_ptr<VTableLayout> vtLayout(
191 addressPoints = vtLayout->getAddressPoints();
195 llvm::raw_svector_ostream
out(outName);
210 if (linkage == cir::GlobalLinkageKind::AvailableExternallyLinkage)
211 linkage = cir::GlobalLinkageKind::InternalLinkage;
232 assert(!vtable.isDeclaration() &&
"Shouldn't set properties on declaration");
246 return cir::GlobalLinkageKind::InternalLinkage;
251 if (keyFunction && !rd->
hasAttr<DLLImportAttr>()) {
256 keyFunction = cast<CXXMethodDecl>(def);
264 (def || codeGenOpts.OptimizationLevel > 0 ||
265 codeGenOpts.getDebugInfo() != llvm::codegenoptions::NoDebugInfo) &&
266 "Shouldn't query vtable linkage without key function, "
267 "optimizations, or debug info");
268 if (!def && codeGenOpts.OptimizationLevel > 0)
269 return cir::GlobalLinkageKind::AvailableExternallyLinkage;
273 ? cir::GlobalLinkageKind::LinkOnceODRLinkage
274 : cir::GlobalLinkageKind::InternalLinkage;
275 return cir::GlobalLinkageKind::ExternalLinkage;
278 return cir::GlobalLinkageKind::LinkOnceODRLinkage;
281 return cir::GlobalLinkageKind::WeakODRLinkage;
284 llvm_unreachable(
"Should not have been asked to emit this");
289 return cir::GlobalLinkageKind::ExternalLinkage;
293 assert(rd->
getNumVBases() &&
"Only classes with virtual bases need a VTT");
296 llvm::raw_svector_ostream
out(outName);
298 .mangleCXXVTT(rd,
out);
299 StringRef name = outName.str();
320 const VTTVTable &vtable, cir::GlobalLinkageKind linkage,
322 if (vtable.
getBase() == mostDerivedClass) {
324 "Most derived class vtable must have a zero offset!");
335 cir::GlobalLinkageKind linkage,
347 vtableAddressPoints.push_back(VTableAddressPointsMapTy());
349 vtableAddressPoints.back()));
355 cir::GlobalOp vtable = vtables[vttComponent.VTableIndex];
361 vttComponent.VTableBase);
363 addressPoint = vtableAddressPoints[vttComponent.VTableIndex].lookup(
364 vttComponent.VTableBase);
366 "Did not find ctor vtable address point!");
369 mlir::Attribute indices[2] = {
374 auto indicesAttr = mlir::ArrayAttr::get(mlirContext, indices);
378 vttComponents.push_back(init);
381 auto init = cir::ConstArrayAttr::get(
382 arrayType, mlir::ArrayAttr::get(mlirContext, vttComponents));
384 vttOp.setInitialValueAttr(init);
387 vttOp.setLinkage(linkage);
388 mlir::SymbolTable::setSymbolVisibility(
392 vttOp.setComdat(
true);
406 if (!thunkInfoVector)
static cir::GlobalOp getAddrOfVTTVTable(CIRGenVTables &cgvt, CIRGenModule &cgm, const CXXRecordDecl *mostDerivedClass, const VTTVTable &vtable, cir::GlobalLinkageKind linkage, VTableLayout::AddressPointsMapTy &addressPoints)
cir::GlobalViewAttr getGlobalViewAttr(cir::PointerType type, cir::GlobalOp globalOp, mlir::ArrayAttr indices={})
Get constant address of a global variable as an MLIR attribute.
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)
llvm::Align getABITypeAlign(mlir::Type ty) const
const CXXMethodDecl * getCurrentKeyFunction(const CXXRecordDecl *RD)
Get our current best idea for the key function of the given record decl, or nullptr if there isn't on...
const LangOptions & getLangOpts() const
CanQualType getCanonicalTagType(const TagDecl *TD) const
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
cir::ConstRecordAttr getAnonConstRecord(mlir::ArrayAttr arrayAttr, bool packed=false, bool padded=false, mlir::Type ty={})
cir::PointerType getUInt8PtrTy()
cir::RecordType getAnonRecordTy(llvm::ArrayRef< mlir::Type > members, bool packed=false, bool padded=false)
Get a CIR anonymous record type.
virtual void emitVirtualInheritanceTables(const CXXRecordDecl *rd)=0
Emit any tables needed to implement virtual inheritance.
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...
clang::MangleContext & getMangleContext()
Gets the mangle context.
virtual void emitVTableDefinitions(CIRGenVTables &cgvt, const CXXRecordDecl *rd)=0
Emits the VTable definitions required for the given record type.
This class organizes the cross-function state that is used while generating CIR code.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
clang::ASTContext & getASTContext() const
CIRGenBuilderTy & getBuilder()
void setGVProperties(mlir::Operation *op, const NamedDecl *d) const
Set visibility, dllimport/dllexport and dso_local.
mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc, QualType ty, bool forEH=false)
Get the address of the RTTI descriptor for the given type.
static mlir::SymbolTable::Visibility getMLIRVisibility(cir::GlobalOp op)
cir::GlobalOp createOrReplaceCXXRuntimeVariable(mlir::Location loc, llvm::StringRef name, mlir::Type ty, cir::GlobalLinkageKind linkage, clang::CharUnits alignment)
Will return a global variable of the given type.
mlir::Type getVTableComponentType()
cir::FuncOp getAddrOfFunction(clang::GlobalDecl gd, mlir::Type funcType=nullptr, bool forVTable=false, bool dontDefer=false, ForDefinition_t isForDefinition=NotForDefinition)
Return the address of the given function.
const cir::CIRDataLayout getDataLayout() const
static void setInitializer(cir::GlobalOp &op, mlir::Attribute value)
mlir::Location getLoc(clang::SourceLocation cLoc)
Helpers to convert the presumed location of Clang's SourceLocation to an MLIR Location.
bool supportsCOMDAT() const
mlir::MLIRContext & getMLIRContext()
CIRGenCXXABI & getCXXABI() const
void emitVTable(const CXXRecordDecl *rd)
This is a callback from Sema to tell us that a particular vtable is required to be emitted in this tr...
cir::GlobalLinkageKind getVTableLinkage(const CXXRecordDecl *rd)
Return the appropriate linkage for the vtable, VTT, and type information of the given class.
cir::FuncType getFunctionTypeForVTable(clang::GlobalDecl gd)
Get the CIR function type for use in a vtable, given a CXXMethodDecl.
cir::RecordType getVTableType(const clang::VTableLayout &layout)
Returns the type of a vtable with the given layout.
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.
cir::GlobalOp generateConstructionVTable(const CXXRecordDecl *rd, const BaseSubobject &base, bool baseIsVirtual, cir::GlobalLinkageKind linkage, VTableAddressPointsMapTy &addressPoints)
Generate a construction vtable for the given base subobject.
void emitThunks(GlobalDecl gd)
Emit the associated thunks for the given global decl.
void emitVTTDefinition(cir::GlobalOp vttOp, cir::GlobalLinkageKind linkage, const CXXRecordDecl *rd)
Emit the definition of the given vtable.
CIRGenVTables(CIRGenModule &cgm)
void generateClassData(const CXXRecordDecl *rd)
Generate all the class data required to be generated upon definition of a KeyFunction.
cir::GlobalOp getAddrOfVTT(const CXXRecordDecl *rd)
Get the address of the VTT for the given record decl.
clang::ItaniumVTableContext & getItaniumVTableContext()
Represents a static or instance method of a struct/union/class.
CXXMethodDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Represents a C++ struct/union/class.
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.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Represents a function declaration or definition.
bool isInlined() const
Determine whether this function should be inlined, because it is either marked "inline" or "constexpr...
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
TemplateSpecializationKind getTemplateSpecializationKind() const
Determine what kind of template instantiation this function represents.
bool hasBody(const FunctionDecl *&Definition) const
Returns true if the function has a body.
GlobalDecl - represents a global declaration.
CXXDtorType getDtorType() const
const Decl * getDecl() const
const VTableLayout & getVTableLayout(const CXXRecordDecl *RD)
bool isExternallyVisible() const
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Class for building VTT layout information.
const VTTComponentsVectorTy & getVTTComponents() const
const VTTVTablesVectorTy & getVTTVTables() const
CharUnits getBaseOffset() const
const CXXRecordDecl * getBase() const
BaseSubobject getBaseSubobject() const
Represents a single component in a vtable.
GlobalDecl getGlobalDecl() const
CharUnits getVBaseOffset() const
Kind getKind() const
Get the kind of this vtable component.
@ CK_DeletingDtorPointer
A pointer to the deleting destructor.
@ CK_UnusedFunctionPointer
An entry that is never used.
@ CK_CompleteDtorPointer
A pointer to the complete destructor.
CharUnits getOffsetToTop() const
CharUnits getVCallOffset() const
virtual const ThunkInfoVectorTy * getThunkInfo(GlobalDecl GD)
const AddressPointsIndexMapTy & getAddressPointIndices() const
size_t getVTableOffset(size_t i) const
llvm::DenseMap< BaseSubobject, AddressPointLocation > AddressPointsMapTy
AddressPointLocation getAddressPoint(BaseSubobject Base) const
ArrayRef< VTableComponent > vtable_components() const
size_t getNumVTables() const
ArrayRef< VTableThunkTy > vtable_thunks() const
size_t getVTableSize(size_t i) const
static bool isLocalLinkage(GlobalLinkageKind linkage)
const AstTypeMatcher< ArrayType > arrayType
Matches all kinds of arrays.
The JSON file list parser is used to communicate input to InstallAPI.
@ Dtor_Base
Base object dtor.
@ TSK_ExplicitInstantiationDefinition
This template specialization was instantiated from a template due to an explicit instantiation defini...
@ TSK_ExplicitInstantiationDeclaration
This template specialization was instantiated from a template due to an explicit instantiation declar...
@ TSK_ExplicitSpecialization
This template specialization was declared or defined by an explicit specialization (C++ [temp....
@ TSK_ImplicitInstantiation
This template specialization was implicitly instantiated from a template.
@ TSK_Undeclared
This template specialization was formed from a template-id but has not yet been declared,...
Diagnostic wrappers for TextAPI types for error reporting.
static bool opGlobalUnnamedAddr()
static bool vtableEmitMetadata()
static bool cudaSupport()
static bool generateDebugInfo()
static bool vtableRelativeLayout()
unsigned AddressPointIndex