summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGVtable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/CGVtable.cpp')
-rw-r--r--lib/CodeGen/CGVtable.cpp479
1 files changed, 286 insertions, 193 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index 4500ec0..9bcf986 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -63,10 +63,7 @@ public:
/// Offset - the base offset of the overrider in the layout class.
uint64_t Offset;
- /// OldOffset - FIXME: Remove this.
- int64_t OldOffset;
-
- OverriderInfo() : Method(0), Offset(0), OldOffset(0) { }
+ OverriderInfo() : Method(0), Offset(0) { }
};
private:
@@ -251,7 +248,6 @@ void FinalOverriders::AddOverriders(BaseSubobject Base,
OverriderInfo& Overrider = OverridersMap[std::make_pair(Base, MD)];
assert(!Overrider.Method && "Overrider should not exist yet!");
- Overrider.OldOffset = Base.getBaseOffset();
Overrider.Offset = OffsetInLayoutClass;
Overrider.Method = MD;
}
@@ -415,7 +411,6 @@ void FinalOverriders::PropagateOverrider(const CXXMethodDecl *OldMD,
// Set the new overrider.
Overrider.Offset = OverriderOffsetInLayoutClass;
- Overrider.OldOffset = NewBase.getBaseOffset();
Overrider.Method = NewMD;
// And propagate it further.
@@ -559,7 +554,7 @@ void FinalOverriders::dump(llvm::raw_ostream &Out, BaseSubobject Base) {
Out << " " << MD->getQualifiedNameAsString() << " - (";
Out << Overrider.Method->getQualifiedNameAsString();
- Out << ", " << Overrider.OldOffset / 8 << ", " << Overrider.Offset / 8 << ')';
+ Out << ", " << ", " << Overrider.Offset / 8 << ')';
AdjustmentOffsetsMapTy::const_iterator AI =
ReturnAdjustments.find(std::make_pair(Base, MD));
@@ -834,6 +829,11 @@ int64_t VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
/// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
class VCallAndVBaseOffsetBuilder {
+public:
+ typedef llvm::DenseMap<const CXXRecordDecl *, int64_t>
+ VBaseOffsetOffsetsMapTy;
+
+private:
/// MostDerivedClass - The most derived class for which we're building vcall
/// and vbase offsets.
const CXXRecordDecl *MostDerivedClass;
@@ -856,6 +856,11 @@ class VCallAndVBaseOffsetBuilder {
/// VCallOffsets - Keeps track of vcall offsets.
VCallOffsetMap VCallOffsets;
+
+ /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets,
+ /// relative to the address point.
+ VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
+
/// FinalOverriders - The final overriders of the most derived class.
/// (Can be null when we're not building a vtable of the most derived class).
const FinalOverriders *Overriders;
@@ -871,6 +876,10 @@ class VCallAndVBaseOffsetBuilder {
/// AddVBaseOffsets - Add vbase offsets for the given class.
void AddVBaseOffsets(const CXXRecordDecl *Base, uint64_t OffsetInLayoutClass);
+ /// getCurrentOffsetOffset - Get the current vcall or vbase offset offset in
+ /// bytes, relative to the vtable address point.
+ int64_t getCurrentOffsetOffset() const;
+
public:
VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass,
const CXXRecordDecl *LayoutClass,
@@ -889,7 +898,10 @@ public:
const_iterator components_begin() const { return Components.rbegin(); }
const_iterator components_end() const { return Components.rend(); }
- const VCallOffsetMap& getVCallOffsets() const { return VCallOffsets; }
+ const VCallOffsetMap &getVCallOffsets() const { return VCallOffsets; }
+ const VBaseOffsetOffsetsMapTy &getVBaseOffsetOffsets() const {
+ return VBaseOffsetOffsets;
+ }
};
void
@@ -940,6 +952,20 @@ VCallAndVBaseOffsetBuilder::AddVCallAndVBaseOffsets(BaseSubobject Base,
AddVCallOffsets(Base, RealBaseOffset);
}
+int64_t VCallAndVBaseOffsetBuilder::getCurrentOffsetOffset() const {
+ // OffsetIndex is the index of this vcall or vbase offset, relative to the
+ // vtable address point. (We subtract 3 to account for the information just
+ // above the address point, the RTTI info, the offset to top, and the
+ // vcall offset itself).
+ int64_t OffsetIndex = -(int64_t)(3 + Components.size());
+
+ // FIXME: We shouldn't use / 8 here.
+ int64_t OffsetOffset = OffsetIndex *
+ (int64_t)Context.Target.getPointerWidth(0) / 8;
+
+ return OffsetOffset;
+}
+
void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
uint64_t VBaseOffset) {
const CXXRecordDecl *RD = Base.getBase();
@@ -980,15 +1006,7 @@ void VCallAndVBaseOffsetBuilder::AddVCallOffsets(BaseSubobject Base,
if (!MD->isVirtual())
continue;
- // OffsetIndex is the index of this vcall offset, relative to the vtable
- // address point. (We subtract 3 to account for the information just
- // above the address point, the RTTI info, the offset to top, and the
- // vcall offset itself).
- int64_t OffsetIndex = -(int64_t)(3 + Components.size());
-
- // FIXME: We shouldn't use / 8 here.
- int64_t OffsetOffset = OffsetIndex *
- (int64_t)Context.Target.getPointerWidth(0) / 8;
+ int64_t OffsetOffset = getCurrentOffsetOffset();
// Don't add a vcall offset if we already have one for this member function
// signature.
@@ -1048,10 +1066,17 @@ void VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
int64_t Offset =
(int64_t)(LayoutClassLayout.getVBaseClassOffset(BaseDecl) -
OffsetInLayoutClass) / 8;
-
+
+ // Add the vbase offset offset.
+ assert(!VBaseOffsetOffsets.count(BaseDecl) &&
+ "vbase offset offset already exists!");
+
+ int64_t VBaseOffsetOffset = getCurrentOffsetOffset();
+ VBaseOffsetOffsets.insert(std::make_pair(BaseDecl, VBaseOffsetOffset));
+
Components.push_back(VtableComponent::MakeVBaseOffset(Offset));
}
-
+
// Check the base class looking for more vbase offsets.
AddVBaseOffsets(BaseDecl, OffsetInLayoutClass);
}
@@ -1096,6 +1121,13 @@ private:
/// bases in this vtable.
llvm::DenseMap<const CXXRecordDecl *, VCallOffsetMap> VCallOffsetsForVBases;
+ typedef llvm::DenseMap<const CXXRecordDecl *, int64_t>
+ VBaseOffsetOffsetsMapTy;
+
+ /// VBaseOffsetOffsets - Contains the offsets of the virtual base offsets for
+ /// the most derived class.
+ VBaseOffsetOffsetsMapTy VBaseOffsetOffsets;
+
/// Components - The components of the vtable being built.
llvm::SmallVector<VtableComponent, 64> Components;
@@ -1117,24 +1149,27 @@ private:
bool isEmpty() const { return !NonVirtual && !VBaseOffsetOffset; }
};
- /// ReturnAdjustments - The return adjustments needed in this vtable.
- llvm::SmallVector<std::pair<uint64_t, ReturnAdjustment>, 16>
- ReturnAdjustments;
-
/// MethodInfo - Contains information about a method in a vtable.
/// (Used for computing 'this' pointer adjustment thunks.
struct MethodInfo {
/// BaseOffset - The base offset of this method.
const uint64_t BaseOffset;
+ /// BaseOffsetInLayoutClass - The base offset in the layout class of this
+ /// method.
+ const uint64_t BaseOffsetInLayoutClass;
+
/// VtableIndex - The index in the vtable that this method has.
/// (For destructors, this is the index of the complete destructor).
const uint64_t VtableIndex;
- MethodInfo(uint64_t BaseOffset, uint64_t VtableIndex)
- : BaseOffset(BaseOffset), VtableIndex(VtableIndex) { }
+ MethodInfo(uint64_t BaseOffset, uint64_t BaseOffsetInLayoutClass,
+ uint64_t VtableIndex)
+ : BaseOffset(BaseOffset),
+ BaseOffsetInLayoutClass(BaseOffsetInLayoutClass),
+ VtableIndex(VtableIndex) { }
- MethodInfo() : BaseOffset(0), VtableIndex(0) { }
+ MethodInfo() : BaseOffset(0), BaseOffsetInLayoutClass(0), VtableIndex(0) { }
};
typedef llvm::DenseMap<const CXXMethodDecl *, MethodInfo> MethodInfoMapTy;
@@ -1158,9 +1193,27 @@ private:
bool isEmpty() const { return !NonVirtual && !VCallOffsetOffset; }
};
- /// ThisAdjustments - The 'this' pointer adjustments needed in this vtable.
- llvm::SmallVector<std::pair<uint64_t, ThisAdjustment>, 16>
- ThisAdjustments;
+ /// ThunkInfo - The 'this' pointer adjustment as well as an optional return
+ /// adjustment for a thunk.
+ struct ThunkInfo {
+ /// This - The 'this' pointer adjustment.
+ ThisAdjustment This;
+
+ /// Return - The return adjustment.
+ ReturnAdjustment Return;
+
+ ThunkInfo() { }
+
+ ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return)
+ : This(This), Return(Return) { }
+
+ bool isEmpty() const { return This.isEmpty() && Return.isEmpty(); }
+ };
+
+ typedef llvm::DenseMap<uint64_t, ThunkInfo> ThunksInfoMapTy;
+
+ /// Thunks - The thunks by vtable index in the vtable currently being built.
+ ThunksInfoMapTy Thunks;
/// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the
/// part of the vtable we're currently building.
@@ -1182,11 +1235,13 @@ private:
BaseSubobject Derived) const;
/// ComputeThisAdjustment - Compute the 'this' pointer adjustment for the
- /// given virtual member function and the 'this' pointer adjustment base
- /// offset.
- ThisAdjustment ComputeThisAdjustment(const CXXMethodDecl *MD,
- BaseOffset Offset);
-
+ /// given virtual member function, its offset in the layout class and its
+ /// final overrider.
+ ThisAdjustment
+ ComputeThisAdjustment(const CXXMethodDecl *MD,
+ uint64_t BaseOffsetInLayoutClass,
+ FinalOverriders::OverriderInfo Overrider);
+
/// AddMethod - Add a single virtual member function to the vtable
/// components vector.
void AddMethod(const CXXMethodDecl *MD, ReturnAdjustment ReturnAdjustment);
@@ -1235,7 +1290,11 @@ private:
/// LayoutSecondaryVtables - Layout the secondary vtables for the given base
/// subobject.
- void LayoutSecondaryVtables(BaseSubobject Base, uint64_t OffsetInLayoutClass);
+ ///
+ /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base
+ /// or a direct or indirect base of a virtual base.
+ void LayoutSecondaryVtables(BaseSubobject Base, bool BaseIsMorallyVirtual,
+ uint64_t OffsetInLayoutClass);
/// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
/// class hierarchy.
@@ -1292,8 +1351,6 @@ OverridesMethodInBases(const CXXMethodDecl *MD,
}
void VtableBuilder::ComputeThisAdjustments() {
- std::map<uint64_t, ThisAdjustment> SortedThisAdjustments;
-
// Now go through the method info map and see if any of the methods need
// 'this' pointer adjustments.
for (MethodInfoMapTy::const_iterator I = MethodInfoMap.begin(),
@@ -1301,56 +1358,34 @@ void VtableBuilder::ComputeThisAdjustments() {
const CXXMethodDecl *MD = I->first;
const MethodInfo &MethodInfo = I->second;
- BaseSubobject OverriddenBaseSubobject(MD->getParent(),
- MethodInfo.BaseOffset);
-
- // Get the final overrider for this method.
- FinalOverriders::OverriderInfo Overrider =
- Overriders.getOverrider(OverriddenBaseSubobject, MD);
-
- // Check if we need an adjustment.
- if (Overrider.OldOffset == (int64_t)MethodInfo.BaseOffset)
- continue;
-
- uint64_t VtableIndex = MethodInfo.VtableIndex;
-
- // Ignore adjustments for pure virtual member functions.
- if (Overrider.Method->isPure())
- continue;
-
// Ignore adjustments for unused function pointers.
+ uint64_t VtableIndex = MethodInfo.VtableIndex;
if (Components[VtableIndex].getKind() ==
VtableComponent::CK_UnusedFunctionPointer)
continue;
+
+ // Get the final overrider for this method.
+ FinalOverriders::OverriderInfo Overrider =
+ Overriders.getOverrider(BaseSubobject(MD->getParent(),
+ MethodInfo.BaseOffset), MD);
+
+ ThisAdjustment ThisAdjustment =
+ ComputeThisAdjustment(MD, MethodInfo.BaseOffsetInLayoutClass, Overrider);
- BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
- Overrider.OldOffset);
-
- // Compute the adjustment offset.
- BaseOffset ThisAdjustmentOffset =
- ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
- OverriderBaseSubobject);
-
- // Then compute the adjustment itself.
- ThisAdjustment ThisAdjustment = ComputeThisAdjustment(Overrider.Method,
- ThisAdjustmentOffset);
+ if (ThisAdjustment.isEmpty())
+ continue;
// Add it.
- SortedThisAdjustments.insert(std::make_pair(VtableIndex, ThisAdjustment));
-
+ Thunks[VtableIndex].This = ThisAdjustment;
+
if (isa<CXXDestructorDecl>(MD)) {
// Add an adjustment for the deleting destructor as well.
- SortedThisAdjustments.insert(std::make_pair(VtableIndex + 1,
- ThisAdjustment));
+ Thunks[VtableIndex + 1].This = ThisAdjustment;
}
}
/// Clear the method info map.
MethodInfoMap.clear();
-
- // Add the sorted elements.
- ThisAdjustments.append(SortedThisAdjustments.begin(),
- SortedThisAdjustments.end());
}
VtableBuilder::ReturnAdjustment
@@ -1360,13 +1395,20 @@ VtableBuilder::ComputeReturnAdjustment(BaseOffset Offset) {
if (!Offset.isEmpty()) {
if (Offset.VirtualBase) {
// Get the virtual base offset offset.
- Adjustment.VBaseOffsetOffset =
- VtableInfo.getVirtualBaseOffsetIndex(Offset.DerivedClass,
- Offset.VirtualBase);
- // FIXME: Once the assert in getVirtualBaseOffsetIndex is back again,
+ if (Offset.DerivedClass == MostDerivedClass) {
+ // We can get the offset offset directly from our map.
+ Adjustment.VBaseOffsetOffset =
+ VBaseOffsetOffsets.lookup(Offset.VirtualBase);
+ } else {
+ Adjustment.VBaseOffsetOffset =
+ VtableInfo.getVirtualBaseOffsetOffset(Offset.DerivedClass,
+ Offset.VirtualBase);
+ }
+
+ // FIXME: Once the assert in getVirtualBaseOffsetOffset is back again,
// we can get rid of this assert.
assert(Adjustment.VBaseOffsetOffset != 0 &&
- "Invalid base offset offset!");
+ "Invalid vbase offset offset!");
}
Adjustment.NonVirtual = Offset.NonVirtualOffset;
@@ -1402,13 +1444,13 @@ VtableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
if (Offset.VirtualBase) {
// If we have a virtual base class, the non-virtual offset is relative
// to the virtual base class offset.
- const ASTRecordLayout &MostDerivedClassLayout =
- Context.getASTRecordLayout(MostDerivedClass);
+ const ASTRecordLayout &LayoutClassLayout =
+ Context.getASTRecordLayout(LayoutClass);
/// Get the virtual base offset, relative to the most derived class
/// layout.
OffsetToBaseSubobject +=
- MostDerivedClassLayout.getVBaseClassOffset(Offset.VirtualBase);
+ LayoutClassLayout.getVBaseClassOffset(Offset.VirtualBase);
} else {
// Otherwise, the non-virtual offset is relative to the derived class
// offset.
@@ -1427,38 +1469,57 @@ VtableBuilder::ComputeThisAdjustmentBaseOffset(BaseSubobject Base,
return BaseOffset();
}
+VtableBuilder::ThisAdjustment
+VtableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD,
+ uint64_t BaseOffsetInLayoutClass,
+ FinalOverriders::OverriderInfo Overrider) {
+ // Check if we need an adjustment at all.
+ if (BaseOffsetInLayoutClass == Overrider.Offset)
+ return ThisAdjustment();
+
+ // Ignore adjustments for pure virtual member functions.
+ if (Overrider.Method->isPure())
+ return ThisAdjustment();
+
+ BaseSubobject OverriddenBaseSubobject(MD->getParent(),
+ BaseOffsetInLayoutClass);
+
+ BaseSubobject OverriderBaseSubobject(Overrider.Method->getParent(),
+ Overrider.Offset);
+
+ // Compute the adjustment offset.
+ BaseOffset Offset = ComputeThisAdjustmentBaseOffset(OverriddenBaseSubobject,
+ OverriderBaseSubobject);
+ if (Offset.isEmpty())
+ return ThisAdjustment();
-VtableBuilder::ThisAdjustment
-VtableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD,
- BaseOffset Offset) {
ThisAdjustment Adjustment;
- if (!Offset.isEmpty()) {
- if (Offset.VirtualBase) {
- // Get the vcall offset map for this virtual base.
- VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
-
- if (VCallOffsets.empty()) {
- // We don't have vcall offsets for this virtual base, go ahead and
- // build them.
- VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
- /*FinalOverriders=*/0,
- BaseSubobject(Offset.VirtualBase, 0),
- /*BaseIsVirtual=*/true,
- /*OffsetInLayoutClass=*/0);
+ if (Offset.VirtualBase) {
+ // Get the vcall offset map for this virtual base.
+ VCallOffsetMap &VCallOffsets = VCallOffsetsForVBases[Offset.VirtualBase];
+
+ if (VCallOffsets.empty()) {
+ // We don't have vcall offsets for this virtual base, go ahead and
+ // build them.
+ VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
+ /*FinalOverriders=*/0,
+ BaseSubobject(Offset.VirtualBase, 0),
+ /*BaseIsVirtual=*/true,
+ /*OffsetInLayoutClass=*/0);
- VCallOffsets = Builder.getVCallOffsets();
- }
-
- Adjustment.VCallOffsetOffset = VCallOffsets.getVCallOffsetOffset(MD);
+ VCallOffsets = Builder.getVCallOffsets();
}
-
- Adjustment.NonVirtual = Offset.NonVirtualOffset;
+
+ Adjustment.VCallOffsetOffset = VCallOffsets.getVCallOffsetOffset(MD);
}
+
+ // Set the non-virtual part of the adjustment.
+ Adjustment.NonVirtual = Offset.NonVirtualOffset;
return Adjustment;
}
-
+
void
VtableBuilder::AddMethod(const CXXMethodDecl *MD,
ReturnAdjustment ReturnAdjustment) {
@@ -1472,8 +1533,7 @@ VtableBuilder::AddMethod(const CXXMethodDecl *MD,
} else {
// Add the return adjustment if necessary.
if (!ReturnAdjustment.isEmpty())
- ReturnAdjustments.push_back(std::make_pair(Components.size(),
- ReturnAdjustment));
+ Thunks[Components.size()].Return = ReturnAdjustment;
// Add the function.
Components.push_back(VtableComponent::MakeFunction(MD));
@@ -1665,6 +1725,7 @@ VtableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass,
MethodInfo &OverriddenMethodInfo = MethodInfoMap[OverriddenMD];
MethodInfo MethodInfo(Base.getBaseOffset(),
+ BaseOffsetInLayoutClass,
OverriddenMethodInfo.VtableIndex);
assert(!MethodInfoMap.count(MD) &&
@@ -1677,7 +1738,8 @@ VtableBuilder::AddMethods(BaseSubobject Base, uint64_t BaseOffsetInLayoutClass,
}
// Insert the method info for this method.
- MethodInfo MethodInfo(Base.getBaseOffset(), Components.size());
+ MethodInfo MethodInfo(Base.getBaseOffset(), BaseOffsetInLayoutClass,
+ Components.size());
assert(!MethodInfoMap.count(MD) &&
"Should not have method info for this method yet!");
@@ -1737,6 +1799,11 @@ VtableBuilder::LayoutPrimaryAndSecondaryVtables(BaseSubobject Base,
VCallOffsets = Builder.getVCallOffsets();
}
+ // If we're laying out the most derived class we want to keep track of the
+ // virtual base class offset offsets.
+ if (Base.getBase() == MostDerivedClass)
+ VBaseOffsetOffsets = Builder.getVBaseOffsetOffsets();
+
// Add the offset to top.
// FIXME: We should not use / 8 here.
int64_t OffsetToTop = -(int64_t)(OffsetInLayoutClass -
@@ -1772,11 +1839,16 @@ VtableBuilder::LayoutPrimaryAndSecondaryVtables(BaseSubobject Base,
AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint));
}
+ bool BaseIsMorallyVirtual = BaseIsVirtual;
+ if (isBuildingConstructorVtable() && Base.getBase() == MostDerivedClass)
+ BaseIsMorallyVirtual = false;
+
// Layout secondary vtables.
- LayoutSecondaryVtables(Base, OffsetInLayoutClass);
+ LayoutSecondaryVtables(Base, BaseIsMorallyVirtual, OffsetInLayoutClass);
}
void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
+ bool BaseIsMorallyVirtual,
uint64_t OffsetInLayoutClass) {
// Itanium C++ ABI 2.5.2:
// Following the primary virtual table of a derived class are secondary
@@ -1800,6 +1872,16 @@ void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
if (!BaseDecl->isDynamicClass())
continue;
+ if (isBuildingConstructorVtable()) {
+ // Itanium C++ ABI 2.6.4:
+ // Some of the base class subobjects may not need construction virtual
+ // tables, which will therefore not be present in the construction
+ // virtual table group, even though the subobject virtual tables are
+ // present in the main virtual table group for the complete object.
+ if (!BaseIsMorallyVirtual && !BaseDecl->getNumVBases())
+ continue;
+ }
+
// Get the base offset of this base.
uint64_t RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl);
uint64_t BaseOffset = Base.getBaseOffset() + RelativeBaseOffset;
@@ -1810,7 +1892,7 @@ void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
// to emit secondary vtables for other bases of this base.
if (BaseDecl == PrimaryBase) {
LayoutSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset),
- BaseOffsetInLayoutClass);
+ BaseIsMorallyVirtual, BaseOffsetInLayoutClass);
continue;
}
@@ -1920,15 +2002,15 @@ VtableBuilder::LayoutVtablesForVirtualBases(const CXXRecordDecl *RD,
/// dumpLayout - Dump the vtable layout.
void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
- if (MostDerivedClass == LayoutClass) {
- Out << "Vtable for '";
- Out << MostDerivedClass->getQualifiedNameAsString();
- } else {
+ if (isBuildingConstructorVtable()) {
Out << "Construction vtable for ('";
Out << MostDerivedClass->getQualifiedNameAsString() << "', ";
// FIXME: Don't use / 8 .
Out << MostDerivedClassOffset / 8 << ") in '";
Out << LayoutClass->getQualifiedNameAsString();
+ } else {
+ Out << "Vtable for '";
+ Out << MostDerivedClass->getQualifiedNameAsString();
}
Out << "' (" << Components.size() << " entries).\n";
@@ -1945,8 +2027,6 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
AddressPointsByIndex.insert(std::make_pair(Index, Base));
}
- unsigned NextReturnAdjustmentIndex = 0;
- unsigned NextThisAdjustmentIndex = 0;
for (unsigned I = 0, E = Components.size(); I != E; ++I) {
uint64_t Index = I;
@@ -1983,38 +2063,33 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
if (MD->isPure())
Out << " [pure]";
- // If this function pointer has a return adjustment, dump it.
- if (NextReturnAdjustmentIndex < ReturnAdjustments.size() &&
- ReturnAdjustments[NextReturnAdjustmentIndex].first == I) {
- const ReturnAdjustment Adjustment =
- ReturnAdjustments[NextReturnAdjustmentIndex].second;
-
- Out << "\n [return adjustment: ";
- Out << Adjustment.NonVirtual << " non-virtual";
-
- if (Adjustment.VBaseOffsetOffset)
- Out << ", " << Adjustment.VBaseOffsetOffset << " vbase offset offset";
-
- Out << ']';
+ ThunkInfo Thunk = Thunks.lookup(I);
+ if (!Thunk.isEmpty()) {
+ // If this function pointer has a return adjustment, dump it.
+ if (!Thunk.Return.isEmpty()) {
+ Out << "\n [return adjustment: ";
+ Out << Thunk.Return.NonVirtual << " non-virtual";
+
+ if (Thunk.Return.VBaseOffsetOffset) {
+ Out << ", " << Thunk.Return.VBaseOffsetOffset;
+ Out << " vbase offset offset";
+ }
- NextReturnAdjustmentIndex++;
- }
-
- // If this function pointer has a 'this' pointer adjustment, dump it.
- if (NextThisAdjustmentIndex < ThisAdjustments.size() &&
- ThisAdjustments[NextThisAdjustmentIndex].first == I) {
- const ThisAdjustment Adjustment =
- ThisAdjustments[NextThisAdjustmentIndex].second;
-
- Out << "\n [this adjustment: ";
- Out << Adjustment.NonVirtual << " non-virtual";
+ Out << ']';
+ }
- if (Adjustment.VCallOffsetOffset)
- Out << ", " << Adjustment.VCallOffsetOffset << " vcall offset offset";
+ // If this function pointer has a 'this' pointer adjustment, dump it.
+ if (!Thunk.This.isEmpty()) {
+ Out << "\n [this adjustment: ";
+ Out << Thunk.This.NonVirtual << " non-virtual";
+
+ if (Thunk.This.VCallOffsetOffset) {
+ Out << ", " << Thunk.This.VCallOffsetOffset;
+ Out << " vcall offset offset";
+ }
- Out << ']';
-
- NextThisAdjustmentIndex++;
+ Out << ']';
+ }
}
break;
@@ -2036,23 +2111,21 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
if (DD->isPure())
Out << " [pure]";
- // If this destructor has a 'this' pointer adjustment, dump it.
- if (NextThisAdjustmentIndex < ThisAdjustments.size() &&
- ThisAdjustments[NextThisAdjustmentIndex].first == I) {
- const ThisAdjustment Adjustment =
- ThisAdjustments[NextThisAdjustmentIndex].second;
-
- Out << "\n [this adjustment: ";
- Out << Adjustment.NonVirtual << " non-virtual";
-
- if (Adjustment.VCallOffsetOffset)
- Out << ", " << Adjustment.VCallOffsetOffset << " vcall offset offset";
-
- Out << ']';
-
- NextThisAdjustmentIndex++;
- }
-
+ ThunkInfo Thunk = Thunks.lookup(I);
+ if (!Thunk.isEmpty()) {
+ // If this destructor has a 'this' pointer adjustment, dump it.
+ if (!Thunk.This.isEmpty()) {
+ Out << "\n [this adjustment: ";
+ Out << Thunk.This.NonVirtual << " non-virtual";
+
+ if (Thunk.This.VCallOffsetOffset) {
+ Out << ", " << Thunk.This.VCallOffsetOffset;
+ Out << " vcall offset offset";
+ }
+
+ Out << ']';
+ }
+ }
break;
}
@@ -2108,6 +2181,29 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
}
Out << '\n';
+
+ if (!isBuildingConstructorVtable() && MostDerivedClass->getNumVBases()) {
+ Out << "Virtual base offset offsets for '";
+ Out << MostDerivedClass->getQualifiedNameAsString() << "'.\n";
+
+ // We store the virtual base class names and their offsets in a map to get
+ // a stable order.
+ std::map<std::string, int64_t> ClassNamesAndOffsets;
+
+ for (VBaseOffsetOffsetsMapTy::const_iterator I = VBaseOffsetOffsets.begin(),
+ E = VBaseOffsetOffsets.end(); I != E; ++I) {
+ std::string ClassName = I->first->getQualifiedNameAsString();
+ int64_t OffsetOffset = I->second;
+ ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset));
+ }
+
+ for (std::map<std::string, int64_t>::const_iterator I =
+ ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end();
+ I != E; ++I)
+ Out << " " << I->first << " | " << I->second << '\n';
+
+ Out << "\n";
+ }
}
}
@@ -2598,7 +2694,7 @@ public:
CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
if (D != MostDerivedClass)
- return CGM.getVtableInfo().getVirtualBaseOffsetIndex(D, B);
+ return CGM.getVtableInfo().getVirtualBaseOffsetOffset(D, B);
llvm::DenseMap<const CXXRecordDecl *, Index_t>::iterator i;
i = VBIndex.find(B);
if (i != VBIndex.end())
@@ -3346,39 +3442,39 @@ CGVtableInfo::getAdjustments(GlobalDecl GD) {
return 0;
}
-int64_t CGVtableInfo::getVirtualBaseOffsetIndex(const CXXRecordDecl *RD,
- const CXXRecordDecl *VBase) {
+int64_t CGVtableInfo::getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
+ const CXXRecordDecl *VBase) {
ClassPairTy ClassPair(RD, VBase);
- VirtualBaseClassIndiciesTy::iterator I =
- VirtualBaseClassIndicies.find(ClassPair);
- if (I != VirtualBaseClassIndicies.end())
+ VirtualBaseClassOffsetOffsetsMapTy::iterator I =
+ VirtualBaseClassOffsetOffsets.find(ClassPair);
+ if (I != VirtualBaseClassOffsetOffsets.end())
return I->second;
- // FIXME: This seems expensive. Can we do a partial job to get
- // just this data.
- AddressPointsMapTy AddressPoints;
- OldVtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
- D1(printf("vtable %s\n", RD->getNameAsCString()));
- b.GenerateVtableForBase(RD);
- b.GenerateVtableForVBases(RD);
+ VCallAndVBaseOffsetBuilder Builder(RD, RD, /*FinalOverriders=*/0,
+ BaseSubobject(RD, 0),
+ /*BaseIsVirtual=*/false,
+ /*OffsetInLayoutClass=*/0);
- for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
- b.getVBIndex().begin(), E = b.getVBIndex().end(); I != E; ++I) {
+
+ for (VCallAndVBaseOffsetBuilder::VBaseOffsetOffsetsMapTy::const_iterator I =
+ Builder.getVBaseOffsetOffsets().begin(),
+ E = Builder.getVBaseOffsetOffsets().end(); I != E; ++I) {
// Insert all types.
ClassPairTy ClassPair(RD, I->first);
- VirtualBaseClassIndicies.insert(std::make_pair(ClassPair, I->second));
+ VirtualBaseClassOffsetOffsets.insert(std::make_pair(ClassPair, I->second));
}
- I = VirtualBaseClassIndicies.find(ClassPair);
+ I = VirtualBaseClassOffsetOffsets.find(ClassPair);
+
// FIXME: The assertion below assertion currently fails with the old vtable
/// layout code if there is a non-virtual thunk adjustment in a vtable.
// Once the new layout is in place, this return should be removed.
- if (I == VirtualBaseClassIndicies.end())
+ if (I == VirtualBaseClassOffsetOffsets.end())
return 0;
- assert(I != VirtualBaseClassIndicies.end() && "Did not find index!");
+ assert(I != VirtualBaseClassOffsetOffsets.end() && "Did not find index!");
return I->second;
}
@@ -3400,20 +3496,17 @@ CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
if (GenerateDefinition) {
if (LayoutClass == RD) {
assert(!IsVirtual &&
- "Can't only have a virtual base in construction vtables!");
- VtableBuilder Builder(*this, RD, Offset,
- /*MostDerivedClassIsVirtual=*/false,
- LayoutClass);
-
- if (CGM.getLangOptions().DumpVtableLayouts)
- Builder.dumpLayout(llvm::errs());
- } else if (CGM.getLangOptions().DumpVtableLayouts) {
- // We only build construction vtables when dumping vtable layouts for now.
- VtableBuilder Builder(*this, RD, Offset,
- /*MostDerivedClassIsVirtual=*/IsVirtual,
- LayoutClass);
- Builder.dumpLayout(llvm::errs());
+ "Can only have a virtual base in construction vtables!");
+ assert(!Offset &&
+ "Can only have a base offset in construction vtables!");
}
+
+ VtableBuilder Builder(*this, RD, Offset,
+ /*MostDerivedClassIsVirtual=*/IsVirtual,
+ LayoutClass);
+
+ if (CGM.getLangOptions().DumpVtableLayouts)
+ Builder.dumpLayout(llvm::errs());
}
llvm::SmallString<256> OutName;
OpenPOWER on IntegriCloud