LayoutVTable();
}
+ uint64_t getNumThunks() const {
+ return Thunks.size();
+ }
+
ThunksMapTy::const_iterator thunks_begin() const {
return Thunks.begin();
}
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 {
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
}
+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) {
}
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)
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;
-
- uint64_t *LayoutData = new uint64_t[NumVTableComponents + 1];
- if (IsAppleKext)
- LayoutData[NumVTableComponents] = 0;
- Entry = LayoutData;
-
- // Store the number of components.
- LayoutData[0] = NumVTableComponents;
+ llvm::SmallVector<VTableLayout::VTableThunkTy, 1>
+ VTableThunks(Builder.vtable_thunks_begin(), Builder.vtable_thunks_end());
+ std::sort(VTableThunks.begin(), VTableThunks.end());
- // 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.
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());
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;
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;
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,
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.
// 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;
CK_UnusedFunctionPointer
};
+ VTableComponent() { }
+
static VTableComponent MakeVCallOffset(CharUnits Offset) {
return VTableComponent(CK_VCallOffset, Offset);
}
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;
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;
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
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) {
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);
/// \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);