Move vtable component accessors to VTableContext

llvm-svn: 140504
This commit is contained in:
Peter Collingbourne 2011-09-26 01:56:41 +00:00
parent 71c26936a0
commit 5ee9ee490e
5 changed files with 110 additions and 97 deletions

View File

@ -337,7 +337,8 @@ CodeGenFunction::BuildAppleKextVirtualCall(const CXXMethodDecl *MD,
MD = MD->getCanonicalDecl(); MD = MD->getCanonicalDecl();
uint64_t VTableIndex = CGM.getVTableContext().getMethodVTableIndex(MD); uint64_t VTableIndex = CGM.getVTableContext().getMethodVTableIndex(MD);
uint64_t AddressPoint = uint64_t AddressPoint =
CGM.getVTables().getAddressPoint(BaseSubobject(RD, CharUnits::Zero()), RD); CGM.getVTableContext()
.getAddressPoint(BaseSubobject(RD, CharUnits::Zero()), RD);
VTableIndex += AddressPoint; VTableIndex += AddressPoint;
llvm::Value *VFuncPtr = llvm::Value *VFuncPtr =
Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");
@ -372,7 +373,8 @@ CodeGenFunction::BuildAppleKextVirtualDestructorCall(
uint64_t VTableIndex = uint64_t VTableIndex =
CGM.getVTableContext().getMethodVTableIndex(GlobalDecl(DD, Type)); CGM.getVTableContext().getMethodVTableIndex(GlobalDecl(DD, Type));
uint64_t AddressPoint = uint64_t AddressPoint =
CGM.getVTables().getAddressPoint(BaseSubobject(RD, CharUnits::Zero()), RD); CGM.getVTableContext()
.getAddressPoint(BaseSubobject(RD, CharUnits::Zero()), RD);
VTableIndex += AddressPoint; VTableIndex += AddressPoint;
llvm::Value *VFuncPtr = llvm::Value *VFuncPtr =
Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt"); Builder.CreateConstInBoundsGEP1_64(VTable, VTableIndex, "vfnkxt");

View File

@ -1452,7 +1452,8 @@ CodeGenFunction::InitializeVTablePointer(BaseSubobject Base,
// And load the address point from the VTT. // And load the address point from the VTT.
VTableAddressPoint = Builder.CreateLoad(VTT); VTableAddressPoint = Builder.CreateLoad(VTT);
} else { } else {
uint64_t AddressPoint = CGM.getVTables().getAddressPoint(Base, VTableClass); uint64_t AddressPoint =
CGM.getVTableContext().getAddressPoint(Base, VTableClass);
VTableAddressPoint = VTableAddressPoint =
Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint); Builder.CreateConstInBoundsGEP2_64(VTable, 0, AddressPoint);
} }

View File

@ -67,7 +67,7 @@ CodeGenVTables::EmitVTTDefinition(llvm::GlobalVariable *VTT,
uint64_t AddressPoint; uint64_t AddressPoint;
if (VTTVT.getBase() == RD) { if (VTTVT.getBase() == RD) {
// Just get the address point for the regular vtable. // Just get the address point for the regular vtable.
AddressPoint = getAddressPoint(i->VTableBase, RD); AddressPoint = VTContext.getAddressPoint(i->VTableBase, RD);
assert(AddressPoint != 0 && "Did not find vtable address point!"); assert(AddressPoint != 0 && "Did not find vtable address point!");
} else { } else {
AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase); AddressPoint = VTableAddressPoints[i->VTableIndex].lookup(i->VTableBase);

View File

@ -2507,17 +2507,6 @@ VTableContext::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
return I->second; return I->second;
} }
uint64_t
CodeGenVTables::getAddressPoint(BaseSubobject Base, const CXXRecordDecl *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;
}
llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD, llvm::Constant *CodeGenModule::GetAddrOfThunk(GlobalDecl GD,
const ThunkInfo &Thunk) { const ThunkInfo &Thunk) {
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl()); const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
@ -2953,36 +2942,30 @@ void CodeGenVTables::EmitThunks(GlobalDecl GD)
if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base) if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
return; return;
const CXXRecordDecl *RD = MD->getParent(); const VTableContext::ThunkInfoVectorTy *ThunkInfoVector =
VTContext.getThunkInfo(MD);
// Compute VTable related info for this class. if (!ThunkInfoVector)
ComputeVTableRelatedInformation(RD);
ThunksMapTy::const_iterator I = Thunks.find(MD);
if (I == Thunks.end()) {
// We did not find a thunk for this method.
return; return;
}
const ThunkInfoVectorTy &ThunkInfoVector = I->second; for (unsigned I = 0, E = ThunkInfoVector->size(); I != E; ++I)
for (unsigned I = 0, E = ThunkInfoVector.size(); I != E; ++I) EmitThunk(GD, (*ThunkInfoVector)[I],
EmitThunk(GD, ThunkInfoVector[I], /*UseAvailableExternallyLinkage=*/false); /*UseAvailableExternallyLinkage=*/false);
} }
void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) { void VTableContext::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) {
uint64_t *&Entry = VTableLayoutMap[RD]; uint64_t *&Entry = VTableLayoutMap[RD];
// Check if we've computed this information before. // Check if we've computed this information before.
if (Entry) if (Entry)
return; return;
VTableBuilder Builder(VTContext, RD, CharUnits::Zero(), VTableBuilder Builder(*this, RD, CharUnits::Zero(),
/*MostDerivedClassIsVirtual=*/0, RD); /*MostDerivedClassIsVirtual=*/0, RD);
// Add the VTable layout. // Add the VTable layout.
uint64_t NumVTableComponents = Builder.getNumVTableComponents(); uint64_t NumVTableComponents = Builder.getNumVTableComponents();
// -fapple-kext adds an extra entry at end of vtbl. // -fapple-kext adds an extra entry at end of vtbl.
bool IsAppleKext = CGM.getContext().getLangOptions().AppleKext; bool IsAppleKext = Context.getLangOptions().AppleKext;
if (IsAppleKext) if (IsAppleKext)
NumVTableComponents += 1; NumVTableComponents += 1;
@ -3036,17 +3019,16 @@ void CodeGenVTables::ComputeVTableRelatedInformation(const CXXRecordDecl *RD) {
RD->vbases_begin()->getType()->getAs<RecordType>(); RD->vbases_begin()->getType()->getAs<RecordType>();
const CXXRecordDecl *VBase = cast<CXXRecordDecl>(VBaseRT->getDecl()); const CXXRecordDecl *VBase = cast<CXXRecordDecl>(VBaseRT->getDecl());
if (VTContext.VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase))) if (VirtualBaseClassOffsetOffsets.count(std::make_pair(RD, VBase)))
return; return;
for (VTableBuilder::VBaseOffsetOffsetsMapTy::const_iterator I = for (VTableBuilder::VBaseOffsetOffsetsMapTy::const_iterator I =
Builder.getVBaseOffsetOffsets().begin(), Builder.getVBaseOffsetOffsets().begin(),
E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) { E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) {
// Insert all types. // Insert all types.
VTableContext::ClassPairTy ClassPair(RD, I->first); ClassPairTy ClassPair(RD, I->first);
VTContext.VirtualBaseClassOffsetOffsets.insert( VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second));
std::make_pair(ClassPair, I->second));
} }
} }
@ -3054,7 +3036,7 @@ llvm::Constant *
CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD, CodeGenVTables::CreateVTableInitializer(const CXXRecordDecl *RD,
const uint64_t *Components, const uint64_t *Components,
unsigned NumComponents, unsigned NumComponents,
const VTableThunksTy &VTableThunks) { const VTableContext::VTableThunksTy &VTableThunks) {
SmallVector<llvm::Constant *, 64> Inits; SmallVector<llvm::Constant *, 64> Inits;
llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
@ -3175,11 +3157,9 @@ llvm::GlobalVariable *CodeGenVTables::GetAddrOfVTable(const CXXRecordDecl *RD) {
Out.flush(); Out.flush();
StringRef Name = OutName.str(); StringRef Name = OutName.str();
ComputeVTableRelatedInformation(RD);
llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
llvm::ArrayType *ArrayType = llvm::ArrayType *ArrayType =
llvm::ArrayType::get(Int8PtrTy, getNumVTableComponents(RD)); llvm::ArrayType::get(Int8PtrTy, VTContext.getNumVTableComponents(RD));
VTable = VTable =
CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType, CGM.CreateOrReplaceCXXRuntimeVariable(Name, ArrayType,
@ -3200,15 +3180,12 @@ CodeGenVTables::EmitVTableDefinition(llvm::GlobalVariable *VTable,
Builder.dumpLayout(llvm::errs()); Builder.dumpLayout(llvm::errs());
} }
assert(VTableThunksMap.count(RD) && const VTableContext::VTableThunksTy& Thunks = VTContext.getVTableThunks(RD);
"No thunk status for this record decl!");
const VTableThunksTy& Thunks = VTableThunksMap[RD];
// Create and set the initializer. // Create and set the initializer.
llvm::Constant *Init = llvm::Constant *Init =
CreateVTableInitializer(RD, getVTableComponentsData(RD), CreateVTableInitializer(RD, VTContext.getVTableComponentsData(RD),
getNumVTableComponents(RD), Thunks); VTContext.getNumVTableComponents(RD), Thunks);
VTable->setInitializer(Init); VTable->setInitializer(Init);
// Set the correct linkage. // Set the correct linkage.
@ -3258,7 +3235,7 @@ CodeGenVTables::GenerateConstructionVTable(const CXXRecordDecl *RD,
VTable->setUnnamedAddr(true); VTable->setUnnamedAddr(true);
// Add the thunks. // Add the thunks.
VTableThunksTy VTableThunks; VTableContext::VTableThunksTy VTableThunks;
VTableThunks.append(Builder.vtable_thunks_begin(), VTableThunks.append(Builder.vtable_thunks_begin(),
Builder.vtable_thunks_end()); Builder.vtable_thunks_end());

View File

@ -26,11 +26,16 @@ namespace clang {
namespace CodeGen { namespace CodeGen {
class CodeGenModule; class CodeGenModule;
class CodeGenVTables;
class VTableContext { class VTableContext {
ASTContext &Context; ASTContext &Context;
public:
typedef SmallVector<std::pair<uint64_t, ThunkInfo>, 1>
VTableThunksTy;
typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
private:
/// MethodVTableIndices - Contains the index (relative to the vtable address /// MethodVTableIndices - Contains the index (relative to the vtable address
/// point) where the function pointer for a virtual function is stored. /// point) where the function pointer for a virtual function is stored.
typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy; typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy;
@ -50,11 +55,88 @@ class VTableContext {
VirtualBaseClassOffsetOffsetsMapTy; VirtualBaseClassOffsetOffsetsMapTy;
VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets; 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); void ComputeMethodVTableIndices(const CXXRecordDecl *RD);
/// ComputeVTableRelatedInformation - Compute and store all vtable related
/// information (vtable layout, vbase offset offsets, thunks etc) for the
/// given record decl.
void ComputeVTableRelatedInformation(const CXXRecordDecl *RD);
public: public:
VTableContext(ASTContext &Context) : Context(Context) {} VTableContext(ASTContext &Context) : Context(Context) {}
uint64_t getNumVTableComponents(const CXXRecordDecl *RD) {
ComputeVTableRelatedInformation(RD);
assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!");
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];
}
const ThunkInfoVectorTy *getThunkInfo(const CXXMethodDecl *MD) {
ComputeVTableRelatedInformation(MD->getParent());
ThunksMapTy::const_iterator I = Thunks.find(MD);
if (I == Thunks.end()) {
// We did not find a thunk for this method.
return 0;
}
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 /// getNumVirtualFunctionPointers - Return the number of virtual function
/// pointers in the vtable for a given record decl. /// pointers in the vtable for a given record decl.
uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD); uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
@ -71,8 +153,6 @@ public:
/// base. /// base.
CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
const CXXRecordDecl *VBase); const CXXRecordDecl *VBase);
friend class CodeGenVTables;
}; };
class CodeGenVTables { class CodeGenVTables {
@ -83,52 +163,10 @@ class CodeGenVTables {
/// VTables - All the vtables which have been defined. /// VTables - All the vtables which have been defined.
llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables; llvm::DenseMap<const CXXRecordDecl *, llvm::GlobalVariable *> VTables;
typedef SmallVector<ThunkInfo, 1> ThunkInfoVectorTy;
typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy;
/// Thunks - Contains all thunks that a given method decl will need.
ThunksMapTy Thunks;
// 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 std::pair<const CXXRecordDecl *, BaseSubobject> BaseSubobjectPairTy;
typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> AddressPointsMapTy;
/// Address points - Address points for all vtables.
AddressPointsMapTy AddressPoints;
/// VTableAddressPointsMapTy - Address points for a single vtable. /// VTableAddressPointsMapTy - Address points for a single vtable.
typedef llvm::DenseMap<BaseSubobject, uint64_t> VTableAddressPointsMapTy; typedef llvm::DenseMap<BaseSubobject, uint64_t> VTableAddressPointsMapTy;
typedef SmallVector<std::pair<uint64_t, ThunkInfo>, 1> typedef std::pair<const CXXRecordDecl *, BaseSubobject> BaseSubobjectPairTy;
VTableThunksTy;
typedef llvm::DenseMap<const CXXRecordDecl *, VTableThunksTy>
VTableThunksMapTy;
/// VTableThunksMap - Contains thunks needed by vtables.
VTableThunksMapTy VTableThunksMap;
uint64_t getNumVTableComponents(const CXXRecordDecl *RD) const {
assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!");
return VTableLayoutMap.lookup(RD)[0];
}
const uint64_t *getVTableComponentsData(const CXXRecordDecl *RD) const {
assert(VTableLayoutMap.count(RD) && "No vtable layout for this class!");
uint64_t *Components = VTableLayoutMap.lookup(RD);
return &Components[1];
}
typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> SubVTTIndiciesMapTy; typedef llvm::DenseMap<BaseSubobjectPairTy, uint64_t> SubVTTIndiciesMapTy;
/// SubVTTIndicies - Contains indices into the various sub-VTTs. /// SubVTTIndicies - Contains indices into the various sub-VTTs.
@ -151,11 +189,6 @@ class CodeGenVTables {
/// doesn't contain any incomplete types. /// doesn't contain any incomplete types.
void MaybeEmitThunkAvailableExternally(GlobalDecl GD, const ThunkInfo &Thunk); void MaybeEmitThunkAvailableExternally(GlobalDecl GD, const ThunkInfo &Thunk);
/// ComputeVTableRelatedInformation - Compute and store all vtable related
/// information (vtable layout, vbase offset offsets, thunks etc) for the
/// given record decl.
void ComputeVTableRelatedInformation(const CXXRecordDecl *RD);
/// CreateVTableInitializer - Create a vtable initializer for the given record /// CreateVTableInitializer - Create a vtable initializer for the given record
/// decl. /// decl.
/// \param Components - The vtable components; this is really an array of /// \param Components - The vtable components; this is really an array of
@ -163,7 +196,7 @@ class CodeGenVTables {
llvm::Constant *CreateVTableInitializer(const CXXRecordDecl *RD, llvm::Constant *CreateVTableInitializer(const CXXRecordDecl *RD,
const uint64_t *Components, const uint64_t *Components,
unsigned NumComponents, unsigned NumComponents,
const VTableThunksTy &VTableThunks); const VTableContext::VTableThunksTy &VTableThunks);
public: public:
CodeGenVTables(CodeGenModule &CGM); CodeGenVTables(CodeGenModule &CGM);