17#include "mlir/IR/Types.h"
20#include "llvm/ADT/SmallVector.h"
27 : cgm(cgm), vtContext(cgm.getASTContext().getVTableContext()) {}
30 mlir::Type ptrTy = builder.getUInt8PtrTy();
35mlir::Type CIRGenVTables::getVTableComponentType() {
41 mlir::Type componentType = getVTableComponentType();
43 tys.push_back(cir::ArrayType::get(componentType, layout.
getVTableSize(i)));
47 return cgm.getBuilder().getAnonRecordTy(tys,
false);
57 vtables.generateClassData(rd);
64 cgm.getCXXABI().emitVirtualInheritanceTables(rd);
66 cgm.getCXXABI().emitVTableDefinitions(*
this, rd);
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");
115 cgm.
errorNYI(
"getVTableComponent: CK_FunctionPointer: pure virtual");
116 return mlir::Attribute();
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();
127 cir::FuncType fnTy = cgm.getTypes().getFunctionTypeForVTable(gd);
128 fnPtr = cgm.getAddrOfFunction(gd, fnTy,
true);
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;
150 mlir::MLIRContext *mlirContext = &cgm.getMLIRContext();
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);
172 cir::ConstRecordAttr record = cgm.getBuilder().getAnonConstRecord(members);
175 auto vtableAttr = cir::VTableAttr::get(record.getType(), record.getMembers());
178 cgm.setInitializer(vtableOp, vtableAttr);
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;
213 llvm::Align align = cgm.getDataLayout().getABITypeAlign(vtType);
217 cir::GlobalOp vtable = cgm.createOrReplaceCXXRuntimeVariable(
223 mlir::Attribute rtti = cgm.getAddrOfRTTIDescriptor(
224 loc, cgm.getASTContext().getCanonicalTagType(base.
getBase()));
232 assert(!vtable.isDeclaration() &&
"Shouldn't set properties on declaration");
233 cgm.setGVProperties(vtable, rd);
246 return cir::GlobalLinkageKind::InternalLinkage;
250 const CXXMethodDecl *keyFunction = astContext.getCurrentKeyFunction(rd);
251 if (keyFunction && !rd->
hasAttr<DLLImportAttr>()) {
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;
272 return !astContext.getLangOpts().AppleKext
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();
302 (void)cgm.getCXXABI().getAddrOfVTable(rd,
CharUnits());
304 VTTBuilder builder(cgm.getASTContext(), rd,
false);
306 auto arrayType = cir::ArrayType::get(cgm.getBuilder().getUInt8PtrTy(),
309 cgm.getDataLayout().getABITypeAlign(cgm.getBuilder().getUInt8PtrTy());
310 cir::GlobalOp vtt = cgm.createOrReplaceCXXRuntimeVariable(
313 cgm.setGVProperties(vtt, rd);
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,
337 VTTBuilder builder(cgm.getASTContext(), rd,
true);
339 mlir::MLIRContext *mlirContext = &cgm.getMLIRContext();
341 auto arrayType = cir::ArrayType::get(cgm.getBuilder().getUInt8PtrTy(),
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] = {
370 cgm.getBuilder().getI32IntegerAttr(addressPoint.
VTableIndex),
374 auto indicesAttr = mlir::ArrayAttr::get(mlirContext, indices);
375 cir::GlobalViewAttr init = cgm.getBuilder().getGlobalViewAttr(
376 cgm.getBuilder().getUInt8PtrTy(), vtable, indicesAttr);
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(
391 if (cgm.supportsCOMDAT() && vttOp.isWeakForLinker())
392 vttOp.setComdat(
true);
397 BaseSubobjectPairTy classSubobjectPair(rd, base);
399 SubVTTIndiciesMapTy::iterator it = subVTTIndicies.find(classSubobjectPair);
400 if (it != subVTTIndicies.end())
403 VTTBuilder builder(cgm.getASTContext(), rd,
false);
407 BaseSubobjectPairTy subclassSubobjectPair(rd, entry.first);
409 subVTTIndicies.insert(std::make_pair(subclassSubobjectPair, entry.second));
412 it = subVTTIndicies.find(classSubobjectPair);
413 assert(it != subVTTIndicies.end() &&
"Did not find index!");
420 auto it = secondaryVirtualPointerIndices.find(std::make_pair(rd, base));
422 if (it != secondaryVirtualPointerIndices.end())
425 VTTBuilder builder(cgm.getASTContext(), rd,
false);
429 std::pair<const CXXRecordDecl *, BaseSubobject> pair =
430 std::make_pair(rd, entry.first);
432 secondaryVirtualPointerIndices.insert(std::make_pair(pair, entry.second));
435 it = secondaryVirtualPointerIndices.find(std::make_pair(rd, base));
436 assert(it != secondaryVirtualPointerIndices.end() &&
"Did not find index!");
450 vtContext->getThunkInfo(gd);
452 if (!thunkInfoVector)
static cir::GlobalOp getAddrOfVTTVTable(CIRGenVTables &cgvt, CIRGenModule &cgm, const CXXRecordDecl *mostDerivedClass, const VTTVTable &vtable, cir::GlobalLinkageKind linkage, VTableLayout::AddressPointsMapTy &addressPoints)
mlir::TypedAttr getConstPtrAttr(mlir::Type type, int64_t value)
const CXXRecordDecl * getBase() const
getBase - Returns the base class declaration.
CharUnits getBaseOffset() const
getBaseOffset - Returns the base class offset.
cir::PointerType getUInt8PtrTy()
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...
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.
CIRGenBuilderTy & getBuilder()
static mlir::SymbolTable::Visibility getMLIRVisibility(cir::GlobalOp op)
mlir::Type getVTableComponentType()
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::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.
uint64_t getSubVTTIndex(const CXXRecordDecl *rd, BaseSubobject base)
Return the index of the sub-VTT for the base class of the given record decl.
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()
uint64_t getSecondaryVirtualPointerIndex(const CXXRecordDecl *rd, BaseSubobject base)
Return the index in the VTT where the virtual pointer for the given subobject is located.
Represents a static or instance method of a struct/union/class.
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 llvm::DenseMap< BaseSubobject, uint64_t > & getSecondaryVirtualPointerIndices() const
Returns a reference to the secondary virtual pointer indices.
const llvm::DenseMap< BaseSubobject, uint64_t > & getSubVTTIndices() const
Returns a reference to the sub-VTT indices.
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
SmallVector< ThunkInfo, 1 > ThunkInfoVectorTy
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
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
@ 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,...
U cast(CodeGen::Address addr)
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