forked from OSchip/llvm-project
More improvements to construction vtables; we know handle vbase offsets correctly (I hope).
llvm-svn: 97361
This commit is contained in:
parent
34021b7445
commit
e3385f566b
|
@ -420,7 +420,7 @@
|
|||
1A81AA5D108278A20094E50B /* CGVtable.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGVtable.h; path = lib/CodeGen/CGVtable.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = "<group>"; };
|
||||
1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
|
||||
1A97825A1108BA18002B98FC /* CGVTT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGVTT.cpp; path = lib/CodeGen/CGVTT.cpp; sourceTree = "<group>"; };
|
||||
1A97825A1108BA18002B98FC /* CGVTT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGVTT.cpp; path = lib/CodeGen/CGVTT.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A986AB610D0746D00A8EA9E /* CGDeclCXX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGDeclCXX.cpp; path = lib/CodeGen/CGDeclCXX.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = RecordLayoutBuilder.cpp; path = lib/AST/RecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = RecordLayoutBuilder.h; path = lib/AST/RecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
|
|
|
@ -824,14 +824,10 @@ int64_t VCallOffsetMap::getVCallOffsetOffset(const CXXMethodDecl *MD) {
|
|||
|
||||
/// VCallAndVBaseOffsetBuilder - Class for building vcall and vbase offsets.
|
||||
class VCallAndVBaseOffsetBuilder {
|
||||
/// MostDerivedClass - The most derived class for which we're building this
|
||||
/// vtable.
|
||||
/// MostDerivedClass - The most derived class for which we're building vcall
|
||||
/// and vbase offsets.
|
||||
const CXXRecordDecl *MostDerivedClass;
|
||||
|
||||
/// MostDerivedClassOffset - If we're building a construction vtable, this
|
||||
/// holds the offset from the layout class to the most derived class.
|
||||
const uint64_t MostDerivedClassOffset;
|
||||
|
||||
/// LayoutClass - The class we're using for layout information. Will be
|
||||
/// different than the most derived class if we're building a construction
|
||||
/// vtable.
|
||||
|
@ -867,16 +863,15 @@ class VCallAndVBaseOffsetBuilder {
|
|||
|
||||
public:
|
||||
VCallAndVBaseOffsetBuilder(const CXXRecordDecl *MostDerivedClass,
|
||||
uint64_t MostDerivedClassOffset,
|
||||
const CXXRecordDecl *LayoutClass,
|
||||
const FinalOverriders *Overriders,
|
||||
BaseSubobject Base, bool BaseIsVirtual)
|
||||
: MostDerivedClass(MostDerivedClass),
|
||||
MostDerivedClassOffset(MostDerivedClassOffset), LayoutClass(LayoutClass),
|
||||
BaseSubobject Base, bool BaseIsVirtual,
|
||||
uint64_t OffsetInLayoutClass)
|
||||
: MostDerivedClass(MostDerivedClass), LayoutClass(LayoutClass),
|
||||
Context(MostDerivedClass->getASTContext()), Overriders(Overriders) {
|
||||
|
||||
// Add vcall and vbase offsets.
|
||||
AddVCallAndVBaseOffsets(Base, BaseIsVirtual, Base.getBaseOffset());
|
||||
AddVCallAndVBaseOffsets(Base, BaseIsVirtual, OffsetInLayoutClass);
|
||||
}
|
||||
|
||||
/// Methods for iterating over the components.
|
||||
|
@ -1045,9 +1040,6 @@ void VCallAndVBaseOffsetBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
|
|||
uint64_t Offset =
|
||||
OffsetToTop + LayoutClassLayout.getVBaseClassOffset(BaseDecl) / 8;
|
||||
|
||||
// The offset should be relative to the most derived class offset.
|
||||
Offset -= MostDerivedClassOffset / 8;
|
||||
|
||||
Components.push_back(VtableComponent::MakeVBaseOffset(Offset));
|
||||
}
|
||||
|
||||
|
@ -1222,14 +1214,15 @@ private:
|
|||
// secondary vtables and any vtables for virtual bases.
|
||||
void LayoutVtable();
|
||||
|
||||
/// LayoutPrimaryAndAndSecondaryVtables - Layout the primary vtable for the
|
||||
/// LayoutPrimaryAndSecondaryVtables - Layout the primary vtable for the
|
||||
/// given base subobject, as well as all its secondary vtables.
|
||||
void LayoutPrimaryAndAndSecondaryVtables(BaseSubobject Base,
|
||||
bool BaseIsVirtual);
|
||||
void LayoutPrimaryAndSecondaryVtables(BaseSubobject Base,
|
||||
bool BaseIsVirtual,
|
||||
uint64_t OffsetInLayoutClass);
|
||||
|
||||
/// LayoutSecondaryVtables - Layout the secondary vtables for the given base
|
||||
/// subobject.
|
||||
void LayoutSecondaryVtables(BaseSubobject Base);
|
||||
void LayoutSecondaryVtables(BaseSubobject Base, uint64_t OffsetInLayoutClass);
|
||||
|
||||
/// DeterminePrimaryVirtualBases - Determine the primary virtual bases in this
|
||||
/// class hierarchy.
|
||||
|
@ -1434,10 +1427,11 @@ VtableBuilder::ComputeThisAdjustment(const CXXMethodDecl *MD,
|
|||
if (VCallOffsets.empty()) {
|
||||
// We don't have vcall offsets for this virtual base, go ahead and
|
||||
// build them.
|
||||
VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, 0,
|
||||
MostDerivedClass, 0,
|
||||
BaseSubobject(Offset.VirtualBase, 0),
|
||||
/*BaseIsVirtual=*/true);
|
||||
VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClass,
|
||||
/*FinalOverriders=*/0,
|
||||
BaseSubobject(Offset.VirtualBase, 0),
|
||||
/*BaseIsVirtual=*/true,
|
||||
/*OffsetInLayoutClass=*/0);
|
||||
|
||||
VCallOffsets = Builder.getVCallOffsets();
|
||||
}
|
||||
|
@ -1683,8 +1677,9 @@ VtableBuilder::AddMethods(BaseSubobject Base,
|
|||
}
|
||||
|
||||
void VtableBuilder::LayoutVtable() {
|
||||
LayoutPrimaryAndAndSecondaryVtables(BaseSubobject(MostDerivedClass, 0),
|
||||
MostDerivedClassIsVirtual);
|
||||
LayoutPrimaryAndSecondaryVtables(BaseSubobject(MostDerivedClass, 0),
|
||||
MostDerivedClassIsVirtual,
|
||||
MostDerivedClassOffset);
|
||||
|
||||
VisitedVirtualBasesSetTy VBases;
|
||||
|
||||
|
@ -1695,14 +1690,15 @@ void VtableBuilder::LayoutVtable() {
|
|||
LayoutVtablesForVirtualBases(MostDerivedClass, VBases);
|
||||
}
|
||||
|
||||
void VtableBuilder::LayoutPrimaryAndAndSecondaryVtables(BaseSubobject Base,
|
||||
bool BaseIsVirtual) {
|
||||
void
|
||||
VtableBuilder::LayoutPrimaryAndSecondaryVtables(BaseSubobject Base,
|
||||
bool BaseIsVirtual,
|
||||
uint64_t OffsetInLayoutClass) {
|
||||
assert(Base.getBase()->isDynamicClass() && "class does not have a vtable!");
|
||||
|
||||
// Add vcall and vbase offsets for this vtable.
|
||||
VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, MostDerivedClassOffset,
|
||||
LayoutClass, &Overriders,
|
||||
Base, BaseIsVirtual);
|
||||
VCallAndVBaseOffsetBuilder Builder(MostDerivedClass, LayoutClass, &Overriders,
|
||||
Base, BaseIsVirtual, OffsetInLayoutClass);
|
||||
Components.append(Builder.components_begin(), Builder.components_end());
|
||||
|
||||
// Check if we need to add these vcall offsets.
|
||||
|
@ -1714,9 +1710,9 @@ void VtableBuilder::LayoutPrimaryAndAndSecondaryVtables(BaseSubobject Base,
|
|||
}
|
||||
|
||||
// Add the offset to top.
|
||||
// FIXME: This is not going to be right for construction vtables.
|
||||
// FIXME: We should not use / 8 here.
|
||||
int64_t OffsetToTop = -(int64_t)Base.getBaseOffset() / 8;
|
||||
int64_t OffsetToTop = -(int64_t)(OffsetInLayoutClass -
|
||||
MostDerivedClassOffset) / 8;
|
||||
Components.push_back(VtableComponent::MakeOffsetToTop(OffsetToTop));
|
||||
|
||||
// Next, add the RTTI.
|
||||
|
@ -1732,7 +1728,9 @@ void VtableBuilder::LayoutPrimaryAndAndSecondaryVtables(BaseSubobject Base,
|
|||
ComputeThisAdjustments();
|
||||
|
||||
// Record the address point.
|
||||
AddressPoints.insert(std::make_pair(Base, AddressPoint));
|
||||
AddressPoints.insert(std::make_pair(BaseSubobject(Base.getBase(),
|
||||
OffsetInLayoutClass),
|
||||
AddressPoint));
|
||||
|
||||
// Record the address points for all primary bases.
|
||||
for (PrimaryBasesSetVectorTy::const_iterator I = PrimaryBases.begin(),
|
||||
|
@ -1741,15 +1739,16 @@ void VtableBuilder::LayoutPrimaryAndAndSecondaryVtables(BaseSubobject Base,
|
|||
|
||||
// We know that all the primary bases have the same offset as the base
|
||||
// subobject.
|
||||
BaseSubobject PrimaryBase(BaseDecl, Base.getBaseOffset());
|
||||
BaseSubobject PrimaryBase(BaseDecl, OffsetInLayoutClass);
|
||||
AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint));
|
||||
}
|
||||
|
||||
// Layout secondary vtables.
|
||||
LayoutSecondaryVtables(Base);
|
||||
LayoutSecondaryVtables(Base, OffsetInLayoutClass);
|
||||
}
|
||||
|
||||
void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base) {
|
||||
void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base,
|
||||
uint64_t OffsetInLayoutClass) {
|
||||
// Itanium C++ ABI 2.5.2:
|
||||
// Following the primary virtual table of a derived class are secondary
|
||||
// virtual tables for each of its proper base classes, except any primary
|
||||
|
@ -1773,19 +1772,23 @@ void VtableBuilder::LayoutSecondaryVtables(BaseSubobject Base) {
|
|||
continue;
|
||||
|
||||
// Get the base offset of this base.
|
||||
uint64_t BaseOffset = Base.getBaseOffset() +
|
||||
Layout.getBaseClassOffset(BaseDecl);
|
||||
uint64_t RelativeBaseOffset = Layout.getBaseClassOffset(BaseDecl);
|
||||
uint64_t BaseOffset = Base.getBaseOffset() + RelativeBaseOffset;
|
||||
|
||||
uint64_t BaseOffsetInLayoutClass = OffsetInLayoutClass + RelativeBaseOffset;
|
||||
|
||||
// Don't emit a secondary vtable for a primary base. We might however want
|
||||
// to emit secondary vtables for other bases of this base.
|
||||
if (BaseDecl == PrimaryBase) {
|
||||
LayoutSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset));
|
||||
LayoutSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset),
|
||||
BaseOffsetInLayoutClass);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Layout the primary vtable (and any secondary vtables) for this base.
|
||||
LayoutPrimaryAndAndSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset),
|
||||
/*BaseIsVirtual=*/false);
|
||||
LayoutPrimaryAndSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset),
|
||||
/*BaseIsVirtual=*/false,
|
||||
BaseOffsetInLayoutClass);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1835,8 +1838,14 @@ VtableBuilder::LayoutVtablesForVirtualBases(const CXXRecordDecl *RD,
|
|||
uint64_t BaseOffset =
|
||||
MostDerivedClassLayout.getVBaseClassOffset(BaseDecl);
|
||||
|
||||
LayoutPrimaryAndAndSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset),
|
||||
/*BaseIsVirtual=*/true);
|
||||
const ASTRecordLayout &LayoutClassLayout =
|
||||
Context.getASTRecordLayout(LayoutClass);
|
||||
uint64_t BaseOffsetInLayoutClass =
|
||||
LayoutClassLayout.getVBaseClassOffset(BaseDecl);
|
||||
|
||||
LayoutPrimaryAndSecondaryVtables(BaseSubobject(BaseDecl, BaseOffset),
|
||||
/*BaseIsVirtual=*/true,
|
||||
BaseOffsetInLayoutClass);
|
||||
}
|
||||
|
||||
// We only need to check the base for virtual base vtables if it actually
|
||||
|
|
|
@ -855,6 +855,7 @@ struct V2 : virtual V1 {
|
|||
// CHECK-NEXT: 5 | vbase_offset (-4)
|
||||
// CHECK-NEXT: 6 | offset_to_top (-16)
|
||||
// CHECK-NEXT: 7 | Test22::C RTTI
|
||||
// CHECK-NEXT: -- (Test22::V2, 16) vtable address --
|
||||
|
||||
// CHECK: Construction vtable for ('Test22::V2', 16) in 'Test22::C' (3 entries).
|
||||
// CHECK-NEXT: 0 | vbase_offset (-4)
|
||||
|
@ -868,3 +869,55 @@ struct C : virtual V1, virtual V2 {
|
|||
void C::f() { }
|
||||
|
||||
}
|
||||
|
||||
namespace Test23 {
|
||||
|
||||
struct A {
|
||||
int a;
|
||||
};
|
||||
|
||||
struct B : virtual A {
|
||||
int b;
|
||||
};
|
||||
|
||||
struct C : A, virtual B {
|
||||
int c;
|
||||
};
|
||||
|
||||
// CHECK: Vtable for 'Test23::D' (7 entries).
|
||||
// CHECK-NEXT: 0 | vbase_offset (20)
|
||||
// CHECK-NEXT: 1 | vbase_offset (24)
|
||||
// CHECK-NEXT: 2 | offset_to_top (0)
|
||||
// CHECK-NEXT: 3 | Test23::D RTTI
|
||||
// CHECK-NEXT: -- (Test23::C, 0) vtable address --
|
||||
// CHECK-NEXT: -- (Test23::D, 0) vtable address --
|
||||
// CHECK-NEXT: 4 | vbase_offset (-4)
|
||||
// CHECK-NEXT: 5 | offset_to_top (-24)
|
||||
// CHECK-NEXT: 6 | Test23::D RTTI
|
||||
// CHECK-NEXT: -- (Test23::B, 24) vtable address --
|
||||
|
||||
// CHECK: Construction vtable for ('Test23::C', 0) in 'Test23::D' (7 entries).
|
||||
// CHECK-NEXT: 0 | vbase_offset (20)
|
||||
// CHECK-NEXT: 1 | vbase_offset (24)
|
||||
// CHECK-NEXT: 2 | offset_to_top (0)
|
||||
// CHECK-NEXT: 3 | Test23::C RTTI
|
||||
// CHECK-NEXT: -- (Test23::C, 0) vtable address --
|
||||
// CHECK-NEXT: 4 | vbase_offset (-4)
|
||||
// CHECK-NEXT: 5 | offset_to_top (-24)
|
||||
// CHECK-NEXT: 6 | Test23::C RTTI
|
||||
// CHECK-NEXT: -- (Test23::B, 24) vtable address --
|
||||
|
||||
// CHECK: Construction vtable for ('Test23::B', 24) in 'Test23::D' (3 entries).
|
||||
// CHECK-NEXT: 0 | vbase_offset (-4)
|
||||
// CHECK-NEXT: 1 | offset_to_top (0)
|
||||
// CHECK-NEXT: 2 | Test23::B RTTI
|
||||
// CHECK-NEXT: -- (Test23::B, 24) vtable address --
|
||||
|
||||
struct D : virtual A, virtual B, C {
|
||||
int d;
|
||||
|
||||
void f();
|
||||
};
|
||||
void D::f() { }
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue