[cfe-commits] r80405 - in /cfe/trunk: lib/CodeGen/CGCXX.cpp test/CodeGenCXX/virt.cpp
Mike Stump
mrs at apple.com
Fri Aug 28 16:22:54 PDT 2009
Author: mrs
Date: Fri Aug 28 18:22:54 2009
New Revision: 80405
URL: http://llvm.org/viewvc/llvm-project?rev=80405&view=rev
Log:
iGenerate vcalls as we build up the methods. WIP.
Modified:
cfe/trunk/lib/CodeGen/CGCXX.cpp
cfe/trunk/test/CodeGenCXX/virt.cpp
Modified: cfe/trunk/lib/CodeGen/CGCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXX.cpp?rev=80405&r1=80404&r2=80405&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCXX.cpp Fri Aug 28 18:22:54 2009
@@ -856,6 +856,7 @@
typedef uint64_t Index_t;
private:
std::vector<llvm::Constant *> &methods;
+ std::vector<llvm::Constant *> submethods;
llvm::Type *Ptr8Ty;
/// Class - The most derived class that this vtable is being built for.
const CXXRecordDecl *Class;
@@ -870,6 +871,9 @@
/// Index - Maps a method decl into a vtable index. Useful for virtual
/// dispatch codegen.
llvm::DenseMap<const CXXMethodDecl *, Index_t> Index;
+ llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall;
+ llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset;
+ std::vector<Index_t> VCalls;
typedef CXXRecordDecl::method_iterator method_iter;
public:
VtableBuilder(std::vector<llvm::Constant *> &meth,
@@ -882,62 +886,15 @@
}
llvm::DenseMap<const CXXMethodDecl *, Index_t> &getIndex() { return Index; }
- llvm::Constant *GenerateVcall(const CXXMethodDecl *MD,
- const CXXRecordDecl *RD,
- bool VBoundary,
- bool SecondaryVirtual) {
- typedef CXXMethodDecl::method_iterator meth_iter;
- // No vcall for methods that don't override in primary vtables.
- llvm::Constant *m = 0;
-
- if (SecondaryVirtual || VBoundary)
- m = llvm::Constant::getNullValue(Ptr8Ty);
-
- int64_t Offset = 0;
- int64_t BaseOffset = 0;
- for (meth_iter mi = MD->begin_overridden_methods(),
- me = MD->end_overridden_methods();
- mi != me; ++mi) {
- const CXXRecordDecl *DefBase = (*mi)->getParent();
- // FIXME: vcall: offset for virtual base for this function
- // m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), 900);
- // m = llvm::Constant::getNullValue(Ptr8Ty);
- for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
- e = RD->bases_end(); i != e; ++i) {
- const CXXRecordDecl *Base =
- cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
- if (DefBase == Base) {
- if (!i->isVirtual())
- break;
-
- // FIXME: drop the 700-, just for debugging
- BaseOffset = 700- -(BLayout.getVBaseClassOffset(Base) / 8);
- m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
- BaseOffset);
- m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty);
- break;
- } else {
- // FIXME: more searching.
- (void)Offset;
- }
- }
- }
- return m;
- }
-
- void GenerateVcalls(const CXXRecordDecl *RD, bool VBoundary,
- bool SecondaryVirtual) {
+ llvm::Constant *wrap(Index_t i) {
llvm::Constant *m;
+ m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), i);
+ return llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty);
+ }
- for (method_iter mi = RD->method_begin(),
- me = RD->method_end(); mi != me; ++mi) {
- if (mi->isVirtual()) {
- m = GenerateVcall(*mi, RD, VBoundary, SecondaryVirtual);
- if (m)
- methods.push_back(m);
- }
- }
+ llvm::Constant *wrap(llvm::Constant *m) {
+ return llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
}
void GenerateVBaseOffsets(std::vector<llvm::Constant *> &offsets,
@@ -949,9 +906,8 @@
if (i->isVirtual() && !SeenVBase.count(Base)) {
SeenVBase.insert(Base);
int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
- llvm::Constant *m;
- m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),BaseOffset);
- m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty);
+ llvm::Constant *m = wrap(BaseOffset);
+ m = wrap((0?700:0) + BaseOffset);
offsets.push_back(m);
}
GenerateVBaseOffsets(offsets, Base, Offset);
@@ -962,12 +918,12 @@
SeenVBase.clear();
}
- void AddMethod(const CXXMethodDecl *MD, Index_t AddressPoint) {
+ void AddMethod(const CXXMethodDecl *MD, Index_t AddressPoint,
+ bool MorallyVirtual, Index_t Offset) {
typedef CXXMethodDecl::method_iterator meth_iter;
llvm::Constant *m;
- m = CGM.GetAddrOfFunction(GlobalDecl(MD), Ptr8Ty);
- m = llvm::ConstantExpr::getBitCast(m, Ptr8Ty);
+ m = wrap(CGM.GetAddrOfFunction(GlobalDecl(MD), Ptr8Ty));
// FIXME: Don't like the nested loops. For very large inheritance
// heirarchies we could have a table on the side with the final overridder
@@ -983,32 +939,50 @@
om = CGM.GetAddrOfFunction(GlobalDecl(OMD), Ptr8Ty);
om = llvm::ConstantExpr::getBitCast(om, Ptr8Ty);
- for (Index_t i = AddressPoint, e = methods.size();
+ for (Index_t i = 0, e = submethods.size();
i != e; ++i) {
// FIXME: begin_overridden_methods might be too lax, covariance */
- if (methods[i] == om) {
- methods[i] = m;
- Index[MD] = i - AddressPoint;
+ if (submethods[i] == om) {
+ // FIXME: thunks
+ submethods[i] = m;
+ Index[MD] = i;
+ if (MorallyVirtual) {
+ VCallOffset[MD] = Offset/8;
+ VCalls[VCall[OMD]] = Offset/8 - VCallOffset[OMD];
+ }
+ // submethods[VCall[OMD]] = wrap(Offset/8 - VCallOffset[OMD]);
return;
}
}
}
// else allocate a new slot.
- Index[MD] = methods.size() - AddressPoint;
- methods.push_back(m);
+ Index[MD] = submethods.size();
+ // VCall[MD] = Offset;
+ if (MorallyVirtual) {
+ VCallOffset[MD] = Offset/8;
+ Index_t &idx = VCall[MD];
+ // Allocate the first one, after that, we reuse the previous one.
+ if (idx == 0) {
+ idx = VCalls.size()+1;
+ VCallOffset[MD] = Offset/8;
+ VCalls.push_back(0);
+ }
+ }
+ submethods.push_back(m);
}
- void GenerateMethods(const CXXRecordDecl *RD, Index_t AddressPoint) {
+ void GenerateMethods(const CXXRecordDecl *RD, Index_t AddressPoint,
+ bool MorallyVirtual, Index_t Offset) {
for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
++mi)
if (mi->isVirtual())
- AddMethod(*mi, AddressPoint);
+ AddMethod(*mi, AddressPoint, MorallyVirtual, Offset);
}
int64_t GenerateVtableForBase(const CXXRecordDecl *RD,
- bool forPrimary,
- bool VBoundary,
+ bool forPrimary, bool Bottom,
+ bool MorallyVirtual,
int64_t Offset,
bool ForVirtualBase) {
llvm::Constant *m = llvm::Constant::getNullValue(Ptr8Ty);
@@ -1021,20 +995,11 @@
const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase();
const bool PrimaryBaseWasVirtual = Layout.getPrimaryBaseWasVirtual();
- if (VBoundary || forPrimary || ForVirtualBase) {
- // then comes the the vcall offsets for all our functions...
- GenerateVcalls(RD, VBoundary, !forPrimary && ForVirtualBase);
- }
-
- // The virtual base offsets come first...
+ std::vector<llvm::Constant *> offsets;
// FIXME: Audit, is this right?
- if (PrimaryBase == 0 || forPrimary || !PrimaryBaseWasVirtual) {
- std::vector<llvm::Constant *> offsets;
+ if (Bottom && (PrimaryBase == 0 || forPrimary || !PrimaryBaseWasVirtual
+ || Bottom))
GenerateVBaseOffsets(offsets, RD, Offset);
- for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
- e = offsets.rend(); i != e; ++i)
- methods.push_back(*i);
- }
bool Top = true;
@@ -1043,26 +1008,53 @@
if (PrimaryBaseWasVirtual)
IndirectPrimary.insert(PrimaryBase);
Top = false;
- AddressPoint = GenerateVtableForBase(PrimaryBase, true,
- PrimaryBaseWasVirtual|VBoundary,
+ AddressPoint = GenerateVtableForBase(PrimaryBase, true, false,
+ PrimaryBaseWasVirtual|MorallyVirtual,
Offset, PrimaryBaseWasVirtual);
}
- if (Top) {
- int64_t BaseOffset;
- if (ForVirtualBase) {
- BaseOffset = -(BLayout.getVBaseClassOffset(RD) / 8);
- } else
- BaseOffset = -Offset/8;
- m = llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), BaseOffset);
- m = llvm::ConstantExpr::getIntToPtr(m, Ptr8Ty);
- methods.push_back(m);
- methods.push_back(rtti);
- AddressPoint = methods.size();
+ // And add the virtuals for the class to the primary vtable.
+ GenerateMethods(RD, AddressPoint, MorallyVirtual, Offset);
+
+ if (!Bottom)
+ return AddressPoint;
+
+ StartNewTable();
+ // FIXME: Cleanup.
+ if (!ForVirtualBase) {
+ // then virtual base offsets...
+ for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
+ e = offsets.rend(); i != e; ++i)
+ methods.push_back(*i);
+ }
+
+ // The vcalls come first...
+ for (std::vector<Index_t>::iterator i=VCalls.begin(), e=VCalls.end();
+ i < e; ++i)
+ methods.push_back(wrap((0?600:0) + *i));
+ VCalls.clear();
+
+ if (ForVirtualBase) {
+ // then virtual base offsets...
+ for (std::vector<llvm::Constant *>::reverse_iterator i = offsets.rbegin(),
+ e = offsets.rend(); i != e; ++i)
+ methods.push_back(*i);
}
- // And add the virtuals for the class to the primary vtable.
- GenerateMethods(RD, AddressPoint);
+ int64_t BaseOffset;
+ if (ForVirtualBase) {
+ BaseOffset = -(BLayout.getVBaseClassOffset(RD) / 8);
+ // FIXME: The above is redundant with the other case.
+ assert(BaseOffset == -Offset/8);
+ } else
+ BaseOffset = -Offset/8;
+ m = wrap(BaseOffset);
+ methods.push_back(m);
+ methods.push_back(rtti);
+ AddressPoint = methods.size();
+
+ methods.insert(methods.end(), submethods.begin(), submethods.end());
+ submethods.clear();
// and then the non-virtual bases.
for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
@@ -1074,7 +1066,7 @@
if (Base != PrimaryBase || PrimaryBaseWasVirtual) {
uint64_t o = Offset + Layout.getBaseClassOffset(Base);
StartNewTable();
- GenerateVtableForBase(Base, true, false, o, false);
+ GenerateVtableForBase(Base, true, true, false, o, false);
}
}
return AddressPoint;
@@ -1091,7 +1083,7 @@
IndirectPrimary.insert(Base);
StartNewTable();
int64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
- GenerateVtableForBase(Base, false, true, BaseOffset, true);
+ GenerateVtableForBase(Base, false, true, true, BaseOffset, true);
}
if (Base->getNumVBases())
GenerateVtableForVBases(Base, Class);
@@ -1123,7 +1115,7 @@
if (I == IndexFor.end()) {
std::vector<llvm::Constant *> methods;
VtableBuilder b(methods, RD, CGM);
- b.GenerateVtableForBase(RD, true, false, 0, false);
+ b.GenerateVtableForBase(RD, true, true, false, 0, false);
b.GenerateVtableForVBases(RD, RD);
register_index(RD, b.getIndex());
I = IndexFor.find(RD);
@@ -1151,7 +1143,7 @@
VtableBuilder b(methods, RD, CGM);
// First comes the vtables for all the non-virtual bases...
- Offset = b.GenerateVtableForBase(RD, true, false, 0, false);
+ Offset = b.GenerateVtableForBase(RD, true, true, false, 0, false);
// then the vtables for all the virtual bases.
b.GenerateVtableForVBases(RD, RD);
Modified: cfe/trunk/test/CodeGenCXX/virt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/virt.cpp?rev=80405&r1=80404&r2=80405&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/virt.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/virt.cpp Fri Aug 28 18:22:54 2009
@@ -299,16 +299,16 @@
// CHECK-LP32-NEXT: .space 4
// CHECK-LP32-NEXT: .space 4
// CHECK-LP32-NEXT: .space 4
-// CHECK-LP32-NEXT .space 4 FIXME
+// CHECK-LP32-NEXT: .space 4
// CHECK-LP32-NEXT: .long 4294967292
// CHECK-LP32-NEXT: .long __ZTI7test5_D
// CHECK-LP32-NEXT: .long __ZN9test5_B237funcB23Ev
// CHECK-LP32-NEXT: .long __ZN9test5_B227funcB22Ev
// CHECK-LP32-NEXT: .long __ZN9test5_B217funcB21Ev
// CHECK-LP32 .space 4
-// CHECK-LP32 .long 8 FIXME
-// CHECK-LP32: .space 4
-// CHECK-LP32-NEXT: .space 4
+// CHECK-LP32: .long 8
+// CHECK-LP32 .space 4
+// CHECK-LP32 .space 4 FIXME
// CHECK-LP32: .long 4
// CHECK-LP32-NEXT: .space 4
// CHECK-LP32-NEXT: .space 4
@@ -351,20 +351,20 @@
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT .space 8 FIXME
+// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .quad 18446744073709551608
// CHECK-LP64-NEXT: .quad __ZTI7test5_D
// CHECK-LP64-NEXT: .quad __ZN9test5_B237funcB23Ev
// CHECK-LP64-NEXT: .quad __ZN9test5_B227funcB22Ev
// CHECK-LP64-NEXT: .quad __ZN9test5_B217funcB21Ev
// CHECK-LP64 .space 8
-// CHECK-LP64 .quad 16 FIXME
-// CHECK-LP64: .space 8
-// CHECK-LP64-NEXT: .space 8
+// CHECK-LP64: .quad 16
+// CHECK-LP64 .space 8
+// CHECK-LP64 .space 8
// CHECK-LP64: .quad 8
// CHECK-LP64-NEXT: .space 8
// CHECK-LP64-NEXT: .space 8
-// CHECK-LP64-NEXT: .quad 18446744073709551600
+// CHECK-LP64: .quad 18446744073709551600
// CHECK-LP64-NEXT: .quad __ZTI7test5_D
// CHECK-LP64-NEXT: .quad __ZN9test5_B337funcB33Ev
// CHECK-LP64-NEXT: .quad __ZN9test5_B327funcB32Ev
More information about the cfe-commits
mailing list