diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-03-16 16:52:15 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-03-16 16:52:15 +0000 |
commit | 1033b7c1e32962948b01a25145829f17bc70a8de (patch) | |
tree | 52aebaff3a47b97dbac434530524c30967468412 /lib/CodeGen/CGVtable.cpp | |
parent | 27c39af73c0d7d0b97e57b3a905040d4cefc9708 (diff) | |
download | FreeBSD-src-1033b7c1e32962948b01a25145829f17bc70a8de.zip FreeBSD-src-1033b7c1e32962948b01a25145829f17bc70a8de.tar.gz |
Update clang to r98631.
Diffstat (limited to 'lib/CodeGen/CGVtable.cpp')
-rw-r--r-- | lib/CodeGen/CGVtable.cpp | 479 |
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; |