forked from OSchip/llvm-project
Handle virtual bases in return adjustment types.
llvm-svn: 96119
This commit is contained in:
parent
f3f67846c8
commit
cf5a882da1
|
@ -124,6 +124,9 @@ public:
|
||||||
/// BaseOffset - Represents an offset from a derived class to a direct or
|
/// BaseOffset - Represents an offset from a derived class to a direct or
|
||||||
/// indirect base class.
|
/// indirect base class.
|
||||||
struct BaseOffset {
|
struct BaseOffset {
|
||||||
|
/// DerivedClass - The derived class.
|
||||||
|
const CXXRecordDecl *DerivedClass;
|
||||||
|
|
||||||
/// VirtualBase - If the path from the derived class to the base class
|
/// VirtualBase - If the path from the derived class to the base class
|
||||||
/// involves a virtual base class, this holds its declaration.
|
/// involves a virtual base class, this holds its declaration.
|
||||||
const CXXRecordDecl *VirtualBase;
|
const CXXRecordDecl *VirtualBase;
|
||||||
|
@ -133,9 +136,11 @@ public:
|
||||||
/// from the derived class to the base class involves a virtual base class.
|
/// from the derived class to the base class involves a virtual base class.
|
||||||
uint64_t NonVirtualOffset;
|
uint64_t NonVirtualOffset;
|
||||||
|
|
||||||
BaseOffset() : VirtualBase(0), NonVirtualOffset(0) { }
|
BaseOffset() : DerivedClass(0), VirtualBase(0), NonVirtualOffset(0) { }
|
||||||
BaseOffset(const CXXRecordDecl *VirtualBase, uint64_t NonVirtualOffset)
|
BaseOffset(const CXXRecordDecl *DerivedClass,
|
||||||
: VirtualBase(VirtualBase), NonVirtualOffset(NonVirtualOffset) { }
|
const CXXRecordDecl *VirtualBase, uint64_t NonVirtualOffset)
|
||||||
|
: DerivedClass(DerivedClass), VirtualBase(VirtualBase),
|
||||||
|
NonVirtualOffset(NonVirtualOffset) { }
|
||||||
|
|
||||||
bool isEmpty() const { return !NonVirtualOffset && !VirtualBase; }
|
bool isEmpty() const { return !NonVirtualOffset && !VirtualBase; }
|
||||||
};
|
};
|
||||||
|
@ -333,7 +338,8 @@ ComputeBaseOffset(ASTContext &Context,
|
||||||
// FIXME: This should probably use CharUnits or something. Maybe we should
|
// FIXME: This should probably use CharUnits or something. Maybe we should
|
||||||
// even change the base offsets in ASTRecordLayout to be specified in
|
// even change the base offsets in ASTRecordLayout to be specified in
|
||||||
// CharUnits.
|
// CharUnits.
|
||||||
return FinalOverriders::BaseOffset(VirtualBase, NonVirtualOffset / 8);
|
return FinalOverriders::BaseOffset(DerivedRD, VirtualBase,
|
||||||
|
NonVirtualOffset / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FinalOverriders::BaseOffset
|
static FinalOverriders::BaseOffset
|
||||||
|
@ -663,6 +669,9 @@ public:
|
||||||
typedef llvm::SmallPtrSet<const CXXRecordDecl *, 8> PrimaryBasesSetTy;
|
typedef llvm::SmallPtrSet<const CXXRecordDecl *, 8> PrimaryBasesSetTy;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// VtableInfo - Global vtable information.
|
||||||
|
CGVtableInfo &VtableInfo;
|
||||||
|
|
||||||
/// MostDerivedClass - The most derived class for which we're building this
|
/// MostDerivedClass - The most derived class for which we're building this
|
||||||
/// vtable.
|
/// vtable.
|
||||||
const CXXRecordDecl *MostDerivedClass;
|
const CXXRecordDecl *MostDerivedClass;
|
||||||
|
@ -685,20 +694,20 @@ private:
|
||||||
/// nearest virtual base.
|
/// nearest virtual base.
|
||||||
int64_t NonVirtual;
|
int64_t NonVirtual;
|
||||||
|
|
||||||
/// VBaseOffsetIndex - The index relative to the address point of the
|
/// VBaseOffsetOffset - The offset, in bytes, relative to the address point
|
||||||
/// virtual base class offset.
|
/// of the virtual base class offset.
|
||||||
int64_t VBaseOffsetIndex;
|
int64_t VBaseOffsetOffset;
|
||||||
|
|
||||||
ReturnAdjustment() : NonVirtual(0), VBaseOffsetIndex(0) { }
|
ReturnAdjustment() : NonVirtual(0), VBaseOffsetOffset(0) { }
|
||||||
|
|
||||||
bool isEmpty() const { return !NonVirtual && !VBaseOffsetIndex; }
|
bool isEmpty() const { return !NonVirtual && !VBaseOffsetOffset; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// ReturnAdjustments - The return adjustments needed in this vtable.
|
/// ReturnAdjustments - The return adjustments needed in this vtable.
|
||||||
llvm::SmallVector<std::pair<uint64_t, ReturnAdjustment>, 16>
|
llvm::SmallVector<std::pair<uint64_t, ReturnAdjustment>, 16>
|
||||||
ReturnAdjustments;
|
ReturnAdjustments;
|
||||||
|
|
||||||
/// ComputeReturnAdjustment - Compute the return adjustment given return
|
/// ComputeReturnAdjustment - Compute the return adjustment given a return
|
||||||
/// adjustment base offset.
|
/// adjustment base offset.
|
||||||
ReturnAdjustment ComputeReturnAdjustment(FinalOverriders::BaseOffset Offset);
|
ReturnAdjustment ComputeReturnAdjustment(FinalOverriders::BaseOffset Offset);
|
||||||
|
|
||||||
|
@ -715,8 +724,8 @@ private:
|
||||||
void layoutSimpleVtable(BaseSubobject Base);
|
void layoutSimpleVtable(BaseSubobject Base);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VtableBuilder(const CXXRecordDecl *MostDerivedClass)
|
VtableBuilder(CGVtableInfo &VtableInfo, const CXXRecordDecl *MostDerivedClass)
|
||||||
: MostDerivedClass(MostDerivedClass),
|
: VtableInfo(VtableInfo), MostDerivedClass(MostDerivedClass),
|
||||||
Context(MostDerivedClass->getASTContext()), Overriders(MostDerivedClass) {
|
Context(MostDerivedClass->getASTContext()), Overriders(MostDerivedClass) {
|
||||||
|
|
||||||
layoutSimpleVtable(BaseSubobject(MostDerivedClass, 0));
|
layoutSimpleVtable(BaseSubobject(MostDerivedClass, 0));
|
||||||
|
@ -751,7 +760,16 @@ VtableBuilder::ComputeReturnAdjustment(FinalOverriders::BaseOffset Offset) {
|
||||||
ReturnAdjustment Adjustment;
|
ReturnAdjustment Adjustment;
|
||||||
|
|
||||||
if (!Offset.isEmpty()) {
|
if (!Offset.isEmpty()) {
|
||||||
assert(!Offset.VirtualBase && "FIXME: Handle virtual bases!");
|
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,
|
||||||
|
// we can get rid of this assert.
|
||||||
|
assert(Adjustment.VBaseOffsetOffset != 0 &&
|
||||||
|
"Invalid base offset offset!");
|
||||||
|
}
|
||||||
|
|
||||||
Adjustment.NonVirtual = Offset.NonVirtualOffset;
|
Adjustment.NonVirtual = Offset.NonVirtualOffset;
|
||||||
}
|
}
|
||||||
|
@ -967,10 +985,12 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
|
||||||
const ReturnAdjustment Adjustment =
|
const ReturnAdjustment Adjustment =
|
||||||
ReturnAdjustments[NextReturnAdjustmentIndex].second;
|
ReturnAdjustments[NextReturnAdjustmentIndex].second;
|
||||||
|
|
||||||
assert(!Adjustment.VBaseOffsetIndex && "FIXME: Handle virtual bases!");
|
|
||||||
|
|
||||||
Out << "\n [return adjustment: ";
|
Out << "\n [return adjustment: ";
|
||||||
Out << Adjustment.NonVirtual << " non-virtual]";
|
Out << Adjustment.NonVirtual << " non-virtual";
|
||||||
|
|
||||||
|
if (Adjustment.VBaseOffsetOffset)
|
||||||
|
Out << ", " << Adjustment.VBaseOffsetOffset << " vbase offset offset";
|
||||||
|
Out << ']';
|
||||||
|
|
||||||
NextReturnAdjustmentIndex++;
|
NextReturnAdjustmentIndex++;
|
||||||
}
|
}
|
||||||
|
@ -2291,7 +2311,7 @@ CGVtableInfo::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
|
||||||
const CXXRecordDecl *RD, uint64_t Offset,
|
const CXXRecordDecl *RD, uint64_t Offset,
|
||||||
AddressPointsMapTy& AddressPoints) {
|
AddressPointsMapTy& AddressPoints) {
|
||||||
if (GenerateDefinition && CGM.getLangOptions().DumpVtableLayouts) {
|
if (GenerateDefinition && CGM.getLangOptions().DumpVtableLayouts) {
|
||||||
VtableBuilder Builder(RD);
|
VtableBuilder Builder(*this, RD);
|
||||||
|
|
||||||
Builder.dumpLayout(llvm::errs());
|
Builder.dumpLayout(llvm::errs());
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ void D::f() { }
|
||||||
|
|
||||||
namespace Test4 {
|
namespace Test4 {
|
||||||
|
|
||||||
// Test simple non-virtual result adjustments.
|
// Test non-virtual result adjustments.
|
||||||
|
|
||||||
struct R1 { int r1; };
|
struct R1 { int r1; };
|
||||||
struct R2 { int r2; };
|
struct R2 { int r2; };
|
||||||
|
@ -142,9 +142,46 @@ struct A {
|
||||||
struct B : A {
|
struct B : A {
|
||||||
virtual R3 *f();
|
virtual R3 *f();
|
||||||
};
|
};
|
||||||
|
|
||||||
R3 *B::f() { return 0; }
|
R3 *B::f() { return 0; }
|
||||||
|
|
||||||
|
// Test virtual result adjustments.
|
||||||
|
struct V1 { int v1; };
|
||||||
|
struct V2 : virtual V1 { int v1; };
|
||||||
|
|
||||||
|
struct C {
|
||||||
|
virtual V1 *f();
|
||||||
|
};
|
||||||
|
|
||||||
|
// CHECK: Vtable for 'Test4::D' (4 entries).
|
||||||
|
// CHECK-NEXT: 0 | offset_to_top (0)
|
||||||
|
// CHECK-NEXT: 1 | Test4::D RTTI
|
||||||
|
// CHECK-NEXT: -- (Test4::C, 0) vtable address --
|
||||||
|
// CHECK-NEXT: -- (Test4::D, 0) vtable address --
|
||||||
|
// CHECK-NEXT: 2 | Test4::V2 *Test4::D::f()
|
||||||
|
// CHECK-NEXT: [return adjustment: 0 non-virtual, -24 vbase offset offset]
|
||||||
|
// CHECK-NEXT: 3 | Test4::V2 *Test4::D::f()
|
||||||
|
struct D : C {
|
||||||
|
virtual V2 *f();
|
||||||
|
};
|
||||||
|
V2 *D::f() { return 0; };
|
||||||
|
|
||||||
|
// Virtual result adjustments with an additional non-virtual adjustment.
|
||||||
|
struct V3 : virtual R3 { int r3; };
|
||||||
|
|
||||||
|
// CHECK: Vtable for 'Test4::E' (4 entries).
|
||||||
|
// CHECK-NEXT: 0 | offset_to_top (0)
|
||||||
|
// CHECK-NEXT: 1 | Test4::E RTTI
|
||||||
|
// CHECK-NEXT: -- (Test4::A, 0) vtable address --
|
||||||
|
// CHECK-NEXT: -- (Test4::E, 0) vtable address --
|
||||||
|
// CHECK-NEXT: 2 | Test4::V3 *Test4::E::f()
|
||||||
|
// CHECK-NEXT: [return adjustment: 4 non-virtual, -24 vbase offset offset]
|
||||||
|
// CHECK-NEXT: 3 | Test4::V3 *Test4::E::f()
|
||||||
|
|
||||||
|
struct E : A {
|
||||||
|
virtual V3 *f();
|
||||||
|
};
|
||||||
|
V3 *E::f() { return 0;}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now, just verify this doesn't crash.
|
// For now, just verify this doesn't crash.
|
||||||
|
|
Loading…
Reference in New Issue