Move all vtable layout data into new VTableLayout class
llvm-svn: 140506
This commit is contained in:
parent
cd3c3f4f3d
commit
affe111ba5
|
@ -337,8 +337,8 @@ CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
|
|||
MD = MD->getCanonicalDecl();
|
||||
uint64_t VTableIndex = CGM.getVTableContext().getMethodVTableIndex(MD);
|
||||
uint64_t AddressPoint =
|
||||
CGM.getVTableContext()
|
||||
.getAddressPoint(BaseSubobject(RD, CharUnits::Zero()), RD);
|
||||
CGM.getVTableContext().getVTableLayout(RD)
|
||||
.getAddressPoint(BaseSubobject(RD, CharUnits::Zero()));
|
||||
VTableIndex += AddressPoint;
|
||||
llvm::Value *VFuncPtr =
|
||||
Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
|
||||
|
@ -373,8 +373,8 @@ CodeGenFunction::BuildAppleKextVirtualDestructorCall(
|
|||
uint64_t VTableIndex =
|
||||
CGM.getVTableContext().getMethodVTableIndex(GlobalDecl(DD, Type));
|
||||
uint64_t AddressPoint =
|
||||
CGM.getVTableContext()
|
||||
.getAddressPoint(BaseSubobject(RD, CharUnits::Zero()), RD);
|
||||
CGM.getVTableContext().getVTableLayout(RD)
|
||||
.getAddressPoint(BaseSubobject(RD, CharUnits::Zero()));
|
||||
VTableIndex += AddressPoint;
|
||||
llvm::Value *VFuncPtr =
|
||||
Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
|
||||
|
|
|
@ -1453,7 +1453,7 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
|
|||
VTableAddressPoint = Builder.CreateLoad(VTT);
|
||||
} else {
|
||||
uint64_t AddressPoint =
|
||||
CGM.getVTableContext().getAddressPoint(Base, VTableClass);
|
||||
CGM.getVTableContext().getVTableLayout(VTableClass).getAddressPoint(Base);
|
||||
VTableAddressPoint =
|
||||
Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint);
|
||||
}
|
||||
|
|
|
@ -67,7 +67,8 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
|
|||
uint64_t AddressPoint;
|
||||
if (VTTVT.getBase() == RD) {
|
||||
// Just get the address point for the regular vtable.
|
||||
AddressPoint = VTContext.getAddressPoint(i->VTableBase, RD);
|
||||
AddressPoint = VTContext.getVTableLayout(RD)
|
||||
.getAddressPoint(i->VTableBase);
|
||||
assert(AddressPoint != 0 && "Did not find vtable address point!");
|
||||
} else {
|
||||
AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase);
|
||||
|
|
|
@ -1002,6 +1002,10 @@ public:
|
|||
LayoutVTable();
|
||||
}
|
||||
|
||||
uint64_t getNumThunks() const {
|
||||
return Thunks.size();
|
||||
}
|
||||
|
||||
ThunksMapTy::const_iterator thunks_begin() const {
|
||||
return Thunks.begin();
|
||||
}
|
||||
|
@ -1014,18 +1018,22 @@ public:
|
|||
return VBaseOffsetOffsets;
|
||||
}
|
||||
|
||||
const AddressPointsMapTy &getAddressPoints() const {
|
||||
return AddressPoints;
|
||||
}
|
||||
|
||||
/// getNumVTableComponents - Return the number of components in the vtable
|
||||
/// currently built.
|
||||
uint64_t getNumVTableComponents() const {
|
||||
return Components.size();
|
||||
}
|
||||
|
||||
const uint64_t *vtable_components_data_begin() const {
|
||||
return reinterpret_cast<const uint64_t *>(Components.begin());
|
||||
const VTableComponent *vtable_component_begin() const {
|
||||
return Components.begin();
|
||||
}
|
||||
|
||||
const uint64_t *vtable_components_data_end() const {
|
||||
return reinterpret_cast<const uint64_t *>(Components.end());
|
||||
const VTableComponent *vtable_component_end() const {
|
||||
return Components.end();
|
||||
}
|
||||
|
||||
AddressPointsMapTy::const_iterator address_points_begin() const {
|
||||
|
@ -1572,6 +1580,11 @@ void VTableBuilder::LayoutVTable() {
|
|||
VBases.clear();
|
||||
|
||||
LayoutVTablesForVirtualBases(MostDerivedClass, VBases);
|
||||
|
||||
// -fapple-kext adds an extra entry at end of vtbl.
|
||||
bool IsAppleKext = Context.getLangOptions().AppleKext;
|
||||
if (IsAppleKext)
|
||||
Components.push_back(VTableComponent::MakeVCallOffset(CharUnits::Zero()));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2134,6 +2147,29 @@ void VTableBuilder::dumpLayout(raw_ostream& Out) {
|
|||
|
||||
}
|
||||
|
||||
VTableLayout::VTableLayout(uint64_t NumVTableComponents,
|
||||
const VTableComponent *VTableComponents,
|
||||
uint64_t NumVTableThunks,
|
||||
const VTableThunkTy *VTableThunks,
|
||||
const AddressPointsMapTy &AddressPoints)
|
||||
: NumVTableComponents(NumVTableComponents),
|
||||
VTableComponents(new VTableComponent[NumVTableComponents]),
|
||||
NumVTableThunks(NumVTableThunks),
|
||||
VTableThunks(new VTableThunkTy[NumVTableThunks]),
|
||||
AddressPoints(AddressPoints) {
|
||||
std::copy(VTableComponents, VTableComponents+NumVTableComponents,
|
||||
this->VTableComponents);
|
||||
std::copy(VTableThunks, VTableThunks+NumVTableThunks, this->VTableThunks);
|
||||
}
|
||||
|
||||
VTableLayout::~VTableLayout() {
|
||||
delete[] VTableComponents;
|
||||
}
|
||||
|
||||
VTableContext::~VTableContext() {
|
||||
llvm::DeleteContainerSeconds(VTableLayouts);
|
||||
}
|
||||
|
||||
static void
|
||||
CollectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context,
|
||||
VTableBuilder::PrimaryBasesSetVectorTy &PrimaryBases) {
|
||||
|
@ -2786,7 +2822,7 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
|
|||
}
|
||||
|
||||
void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) {
|
||||
uint64_t *&Entry = VTableLayoutMap[RD];
|
||||
const VTableLayout *&Entry = VTableLayouts[RD];
|
||||
|
||||
// Check if we've computed this information before.
|
||||
if (Entry)
|
||||
|
@ -2795,53 +2831,19 @@ void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) {
|
|||
VTableBuilder Builder(*this, RD, CharUnits::Zero(),
|
||||
/*MostDerivedClassIsVirtual=*/0, RD);
|
||||
|
||||
// Add the VTable layout.
|
||||
uint64_t NumVTableComponents = Builder.getNumVTableComponents();
|
||||
// -fapple-kext adds an extra entry at end of vtbl.
|
||||
bool IsAppleKext = Context.getLangOptions().AppleKext;
|
||||
if (IsAppleKext)
|
||||
NumVTableComponents += 1;
|
||||
llvm::SmallVector<VTableLayout::VTableThunkTy, 1>
|
||||
VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
|
||||
std::sort(VTableThunks.begin(), VTableThunks.end());
|
||||
|
||||
uint64_t *LayoutData = new uint64_t[NumVTableComponents + 1];
|
||||
if (IsAppleKext)
|
||||
LayoutData[NumVTableComponents] = 0;
|
||||
Entry = LayoutData;
|
||||
|
||||
// Store the number of components.
|
||||
LayoutData[0] = NumVTableComponents;
|
||||
|
||||
// Store the components.
|
||||
std::copy(Builder.vtable_components_data_begin(),
|
||||
Builder.vtable_components_data_end(),
|
||||
&LayoutData[1]);
|
||||
Entry = new VTableLayout(Builder.getNumVTableComponents(),
|
||||
Builder.vtable_component_begin(),
|
||||
VTableThunks.size(),
|
||||
VTableThunks.data(),
|
||||
Builder.getAddressPoints());
|
||||
|
||||
// Add the known thunks.
|
||||
Thunks.insert(Builder.thunks_begin(), Builder.thunks_end());
|
||||
|
||||
// Add the thunks needed in this vtable.
|
||||
assert(!VTableThunksMap.count(RD) &&
|
||||
"Thunks already exists for this vtable!");
|
||||
|
||||
VTableThunksTy &VTableThunks = VTableThunksMap[RD];
|
||||
VTableThunks.append(Builder.vtable_thunks_begin(),
|
||||
Builder.vtable_thunks_end());
|
||||
|
||||
// Sort them.
|
||||
std::sort(VTableThunks.begin(), VTableThunks.end());
|
||||
|
||||
// Add the address points.
|
||||
for (VTableBuilder::AddressPointsMapTy::const_iterator I =
|
||||
Builder.address_points_begin(), E = Builder.address_points_end();
|
||||
I != E; ++I) {
|
||||
|
||||
uint64_t &AddressPoint = AddressPoints[std::make_pair(RD, I->first)];
|
||||
|
||||
// Check if we already have the address points for this base.
|
||||
assert(!AddressPoint && "Address point already exists for this base!");
|
||||
|
||||
AddressPoint = I->second;
|
||||
}
|
||||
|
||||
// If we don't have the vbase information for this class, insert it.
|
||||
// getVirtualBaseOffsetOffset will compute it separately without computing
|
||||
// the rest of the vtable related information.
|
||||
|
@ -2867,9 +2869,10 @@ void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) {
|
|||
|
||||
llvm::Constant *
|
||||
CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
|
||||
const uint64_t *Components,
|
||||
const VTableComponent *Components,
|
||||
unsigned NumComponents,
|
||||
const VTableContext::VTableThunksTy &VTableThunks) {
|
||||
const VTableLayout::VTableThunkTy *VTableThunks,
|
||||
unsigned NumVTableThunks) {
|
||||
SmallVector<llvm::Constant *, 64> Inits;
|
||||
|
||||
llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
|
||||
|
@ -2885,8 +2888,7 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
|
|||
llvm::Constant* PureVirtualFn = 0;
|
||||
|
||||
for (unsigned I = 0; I != NumComponents; ++I) {
|
||||
VTableComponent Component =
|
||||
VTableComponent::getFromOpaqueInteger(Components[I]);
|
||||
VTableComponent Component = Components[I];
|
||||
|
||||
llvm::Constant *Init = 0;
|
||||
|
||||
|
@ -2944,7 +2946,7 @@ CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
|
|||
Init = PureVirtualFn;
|
||||
} else {
|
||||
// Check if we should use a thunk.
|
||||
if (NextVTableThunkIndex < VTableThunks.size() &&
|
||||
if (NextVTableThunkIndex < NumVTableThunks &&
|
||||
VTableThunks[NextVTableThunkIndex].first == I) {
|
||||
const ThunkInfo &Thunk = VTableThunks[NextVTableThunkIndex].second;
|
||||
|
||||
|
@ -2992,7 +2994,8 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) {
|
|||
|
||||
llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
|
||||
llvm::ArrayType *ArrayType =
|
||||
llvm::ArrayType::get(Int8PtrTy, VTContext.getNumVTableComponents(RD));
|
||||
llvm::ArrayType::get(Int8PtrTy,
|
||||
VTContext.getVTableLayout(RD).getNumVTableComponents());
|
||||
|
||||
VTable =
|
||||
CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
|
||||
|
@ -3013,12 +3016,15 @@ CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable,
|
|||
Builder.dumpLayout(llvm::errs());
|
||||
}
|
||||
|
||||
const VTableContext::VTableThunksTy& Thunks = VTContext.getVTableThunks(RD);
|
||||
|
||||
const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);
|
||||
|
||||
// Create and set the initializer.
|
||||
llvm::Constant *Init =
|
||||
CreateVTableInitializer(RD, VTContext.getVTableComponentsData(RD),
|
||||
VTContext.getNumVTableComponents(RD), Thunks);
|
||||
CreateVTableInitializer(RD,
|
||||
VTLayout.vtable_component_begin(),
|
||||
VTLayout.getNumVTableComponents(),
|
||||
VTLayout.vtable_thunk_begin(),
|
||||
VTLayout.getNumVTableThunks());
|
||||
VTable->setInitializer(Init);
|
||||
|
||||
// Set the correct linkage.
|
||||
|
@ -3078,8 +3084,10 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
|
|||
// Create and set the initializer.
|
||||
llvm::Constant *Init =
|
||||
CreateVTableInitializer(Base.getBase(),
|
||||
Builder.vtable_components_data_begin(),
|
||||
Builder.getNumVTableComponents(), VTableThunks);
|
||||
Builder.vtable_component_begin(),
|
||||
Builder.getNumVTableComponents(),
|
||||
VTableThunks.begin(),
|
||||
VTableThunks.size());
|
||||
VTable->setInitializer(Init);
|
||||
|
||||
return VTable;
|
||||
|
|
|
@ -49,6 +49,8 @@ public:
|
|||
CK_UnusedFunctionPointer
|
||||
};
|
||||
|
||||
VTableComponent() { }
|
||||
|
||||
static VTableComponent MakeVCallOffset(CharUnits Offset) {
|
||||
return VTableComponent(CK_VCallOffset, Offset);
|
||||
}
|
||||
|
@ -194,6 +196,69 @@ private:
|
|||
int64_t Value;
|
||||
};
|
||||
|
||||
class VTableLayout {
|
||||
public:
|
||||
typedef std::pair<uint64_t, ThunkInfo> VTableThunkTy;
|
||||
typedef llvm::SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
|
||||
|
||||
typedef const VTableComponent *vtable_component_iterator;
|
||||
typedef const VTableThunkTy *vtable_thunk_iterator;
|
||||
|
||||
typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
|
||||
private:
|
||||
uint64_t NumVTableComponents;
|
||||
VTableComponent *VTableComponents;
|
||||
|
||||
/// VTableThunks - Contains thunks needed by vtables.
|
||||
uint64_t NumVTableThunks;
|
||||
VTableThunkTy *VTableThunks;
|
||||
|
||||
/// Address points - Address points for all vtables.
|
||||
AddressPointsMapTy AddressPoints;
|
||||
|
||||
public:
|
||||
VTableLayout(uint64_t NumVTableComponents,
|
||||
const VTableComponent *VTableComponents,
|
||||
uint64_t NumVTableThunks,
|
||||
const VTableThunkTy *VTableThunks,
|
||||
const AddressPointsMapTy &AddressPoints);
|
||||
~VTableLayout();
|
||||
|
||||
uint64_t getNumVTableComponents() const {
|
||||
return NumVTableComponents;
|
||||
}
|
||||
|
||||
vtable_component_iterator vtable_component_begin() const {
|
||||
return VTableComponents;
|
||||
}
|
||||
|
||||
vtable_component_iterator vtable_component_end() const {
|
||||
return VTableComponents+NumVTableComponents;
|
||||
}
|
||||
|
||||
uint64_t getNumVTableThunks() const {
|
||||
return NumVTableThunks;
|
||||
}
|
||||
|
||||
vtable_thunk_iterator vtable_thunk_begin() const {
|
||||
return VTableThunks;
|
||||
}
|
||||
|
||||
vtable_thunk_iterator vtable_thunk_end() const {
|
||||
return VTableThunks+NumVTableThunks;
|
||||
}
|
||||
|
||||
uint64_t getAddressPoint(BaseSubobject Base) const {
|
||||
assert(AddressPoints.count(Base) &&
|
||||
"Did not find address point!");
|
||||
|
||||
uint64_t AddressPoint = AddressPoints.lookup(Base);
|
||||
assert(AddressPoint && "Address point must not be zero!");
|
||||
|
||||
return AddressPoint;
|
||||
}
|
||||
};
|
||||
|
||||
class VTableContext {
|
||||
ASTContext &Context;
|
||||
|
||||
|
@ -208,6 +273,10 @@ private:
|
|||
typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
|
||||
MethodVTableIndicesTy MethodVTableIndices;
|
||||
|
||||
typedef llvm::DenseMap<const CXXRecordDecl *, const VTableLayout *>
|
||||
VTableLayoutMapTy;
|
||||
VTableLayoutMapTy VTableLayouts;
|
||||
|
||||
/// NumVirtualFunctionPointers - Contains the number of virtual function
|
||||
/// pointers in the vtable for a given record decl.
|
||||
llvm::DenseMap<const CXXRecordDecl *, uint64_t> NumVirtualFunctionPointers;
|
||||
|
@ -222,32 +291,11 @@ private:
|
|||
VirtualBaseClassOffsetOffsetsMapTy;
|
||||
VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets;
|
||||
|
||||
// The layout entry.
|
||||
typedef llvm::DenseMap<const CXXRecordDecl *, uint64_t *> VTableLayoutMapTy;
|
||||
|
||||
/// VTableLayoutMap - Stores the vtable layout for all record decls.
|
||||
/// The layout is stored as an array of 64-bit integers, where the first
|
||||
/// integer is the number of vtable entries in the layout, and the subsequent
|
||||
/// integers are the vtable components.
|
||||
VTableLayoutMapTy VTableLayoutMap;
|
||||
|
||||
typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
|
||||
|
||||
/// Thunks - Contains all thunks that a given method decl will need.
|
||||
ThunksMapTy Thunks;
|
||||
|
||||
typedef llvm::DenseMap<const CXXRecordDecl *, VTableThunksTy>
|
||||
VTableThunksMapTy;
|
||||
|
||||
/// VTableThunksMap - Contains thunks needed by vtables.
|
||||
VTableThunksMapTy VTableThunksMap;
|
||||
|
||||
typedef std::pair<const CXXRecordDecl *, BaseSubobject> BaseSubobjectPairTy;
|
||||
typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> AddressPointsMapTy;
|
||||
|
||||
/// Address points - Address points for all vtables.
|
||||
AddressPointsMapTy AddressPoints;
|
||||
|
||||
void ComputeMethodVTableIndices(const CXXRecordDecl *RD);
|
||||
|
||||
/// ComputeVTableRelatedInformation - Compute and store all vtable related
|
||||
|
@ -257,20 +305,13 @@ private:
|
|||
|
||||
public:
|
||||
VTableContext(ASTContext &Context) : Context(Context) {}
|
||||
~VTableContext();
|
||||
|
||||
uint64_t getNumVTableComponents(const CXXRecordDecl *RD) {
|
||||
const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) {
|
||||
ComputeVTableRelatedInformation(RD);
|
||||
assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!");
|
||||
assert(VTableLayouts.count(RD) && "No layout for this record decl!");
|
||||
|
||||
return VTableLayoutMap.lookup(RD)[0];
|
||||
}
|
||||
|
||||
const uint64_t *getVTableComponentsData(const CXXRecordDecl *RD) {
|
||||
ComputeVTableRelatedInformation(RD);
|
||||
assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!");
|
||||
|
||||
uint64_t *Components = VTableLayoutMap.lookup(RD);
|
||||
return &Components[1];
|
||||
return *VTableLayouts[RD];
|
||||
}
|
||||
|
||||
const ThunkInfoVectorTy *getThunkInfo(const CXXMethodDecl *MD) {
|
||||
|
@ -285,25 +326,6 @@ public:
|
|||
return &I->second;
|
||||
}
|
||||
|
||||
const VTableThunksTy &getVTableThunks(const CXXRecordDecl *RD) {
|
||||
ComputeVTableRelatedInformation(RD);
|
||||
assert(VTableThunksMap.count(RD) &&
|
||||
"No thunk status for this record decl!");
|
||||
|
||||
return VTableThunksMap[RD];
|
||||
}
|
||||
|
||||
uint64_t getAddressPoint(BaseSubobject Base, const CXXRecordDecl *RD) {
|
||||
ComputeVTableRelatedInformation(RD);
|
||||
assert(AddressPoints.count(std::make_pair(RD, Base)) &&
|
||||
"Did not find address point!");
|
||||
|
||||
uint64_t AddressPoint = AddressPoints.lookup(std::make_pair(RD, Base));
|
||||
assert(AddressPoint && "Address point must not be zero!");
|
||||
|
||||
return AddressPoint;
|
||||
}
|
||||
|
||||
/// getNumVirtualFunctionPointers - Return the number of virtual function
|
||||
/// pointers in the vtable for a given record decl.
|
||||
uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
|
||||
|
@ -361,9 +383,10 @@ class CodeGenVTables {
|
|||
/// \param Components - The vtable components; this is really an array of
|
||||
/// VTableComponents.
|
||||
llvm::Constant *CreateVTableInitializer(const CXXRecordDecl *RD,
|
||||
const uint64_t *Components,
|
||||
const VTableComponent *Components,
|
||||
unsigned NumComponents,
|
||||
const VTableContext::VTableThunksTy &VTableThunks);
|
||||
const VTableLayout::VTableThunkTy *VTableThunks,
|
||||
unsigned NumVTableThunks);
|
||||
|
||||
public:
|
||||
CodeGenVTables(CodeGenModule &CGM);
|
||||
|
|
Loading…
Reference in New Issue