Move all vtable layout data into new VTableLayout class

llvm-svn: 140506
This commit is contained in:
Peter Collingbourne 2011-09-26 01:56:50 +00:00
parent cd3c3f4f3d
commit affe111ba5
5 changed files with 150 additions and 118 deletions

View File

@ -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");

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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);