Generate more of the vbase virtual offset for covariant thunks. WIP.

llvm-svn: 82253
This commit is contained in:
Mike Stump 2009-09-18 19:06:35 +00:00
parent 7e90c6db18
commit f9c95be2f6
1 changed files with 72 additions and 8 deletions

View File

@ -768,6 +768,7 @@ private:
llvm::DenseMap<const CXXMethodDecl *, Index_t> Index; llvm::DenseMap<const CXXMethodDecl *, Index_t> Index;
llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall; llvm::DenseMap<const CXXMethodDecl *, Index_t> VCall;
llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset; llvm::DenseMap<const CXXMethodDecl *, Index_t> VCallOffset;
llvm::DenseMap<const CXXRecordDecl *, Index_t> VBIndex;
typedef std::pair<Index_t, Index_t> CallOffset; typedef std::pair<Index_t, Index_t> CallOffset;
typedef llvm::DenseMap<const CXXMethodDecl *, CallOffset> Thunks_t; typedef llvm::DenseMap<const CXXMethodDecl *, CallOffset> Thunks_t;
Thunks_t Thunks; Thunks_t Thunks;
@ -792,6 +793,8 @@ public:
} }
llvm::DenseMap<const CXXMethodDecl *, Index_t> &getIndex() { return Index; } llvm::DenseMap<const CXXMethodDecl *, Index_t> &getIndex() { return Index; }
llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex()
{ return VBIndex; }
llvm::Constant *wrap(Index_t i) { llvm::Constant *wrap(Index_t i) {
llvm::Constant *m; llvm::Constant *m;
@ -805,7 +808,7 @@ public:
void GenerateVBaseOffsets(std::vector<llvm::Constant *> &offsets, void GenerateVBaseOffsets(std::vector<llvm::Constant *> &offsets,
const CXXRecordDecl *RD, uint64_t Offset) { const CXXRecordDecl *RD, uint64_t Offset) {
for (CXXRecordDecl::base_class_const_iterator i =RD->bases_begin(), for (CXXRecordDecl::base_class_const_iterator i = RD->bases_begin(),
e = RD->bases_end(); i != e; ++i) { e = RD->bases_end(); i != e; ++i) {
const CXXRecordDecl *Base = const CXXRecordDecl *Base =
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
@ -814,6 +817,8 @@ public:
int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8; int64_t BaseOffset = -(Offset/8) + BLayout.getVBaseClassOffset(Base)/8;
llvm::Constant *m = wrap(BaseOffset); llvm::Constant *m = wrap(BaseOffset);
m = wrap((0?700:0) + BaseOffset); m = wrap((0?700:0) + BaseOffset);
VBIndex[Base] = -(offsets.size()*LLVMPointerWidth/8)
- 3*LLVMPointerWidth/8;
offsets.push_back(m); offsets.push_back(m);
} }
GenerateVBaseOffsets(offsets, Base, Offset); GenerateVBaseOffsets(offsets, Base, Offset);
@ -824,6 +829,27 @@ public:
SeenVBase.clear(); SeenVBase.clear();
} }
Index_t VBlookup(CXXRecordDecl *D, CXXRecordDecl *B);
/// getVbaseOffset - Returns the index into the vtable for the virtual base
/// offset for the given (B) virtual base of the derived class D.
Index_t getVbaseOffset(QualType qB, QualType qD) {
qD = qD->getAs<PointerType>()->getPointeeType();
qB = qB->getAs<PointerType>()->getPointeeType();
CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl());
CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl());
if (D != Class)
return VBlookup(D, B);
llvm::DenseMap<const CXXRecordDecl *, Index_t>::iterator i;
i = VBIndex.find(B);
if (i != VBIndex.end())
return i->second;
// FIXME: temporal botch, is this data here, by the time we need it?
// FIXME: Locate the containing virtual base first.
return 42;
}
bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m, bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m,
bool MorallyVirtual, Index_t Offset) { bool MorallyVirtual, Index_t Offset) {
typedef CXXMethodDecl::method_iterator meth_iter; typedef CXXMethodDecl::method_iterator meth_iter;
@ -853,7 +879,7 @@ public:
CallOffset ReturnOffset = std::make_pair(0, 0); CallOffset ReturnOffset = std::make_pair(0, 0);
if (oret != ret) { if (oret != ret) {
// FIXME: calculate offsets for covariance // FIXME: calculate offsets for covariance
ReturnOffset = std::make_pair(42,42); ReturnOffset = std::make_pair(42,getVbaseOffset(oret, ret));
} }
Index[MD] = i; Index[MD] = i;
submethods[i] = m; submethods[i] = m;
@ -1132,33 +1158,74 @@ private:
typedef llvm::DenseMap<const CXXRecordDecl *, ElTy *> MapTy; typedef llvm::DenseMap<const CXXRecordDecl *, ElTy *> MapTy;
// FIXME: Move to Context. // FIXME: Move to Context.
static MapTy IndexFor; static MapTy IndexFor;
typedef llvm::DenseMap<const CXXRecordDecl *, Index_t> VBElTy;
typedef llvm::DenseMap<const CXXRecordDecl *, VBElTy *> VBMapTy;
// FIXME: Move to Context.
static VBMapTy VBIndexFor;
public: public:
VtableInfo(CodeGenModule &cgm) : CGM(cgm) { } VtableInfo(CodeGenModule &cgm) : CGM(cgm) { }
void register_index(const CXXRecordDecl *RD, const ElTy &e) { void RegisterIndex(const CXXRecordDecl *RD, const ElTy &e) {
assert(IndexFor.find(RD) == IndexFor.end() && "Don't compute vtbl twice"); assert(IndexFor.find(RD) == IndexFor.end() && "Don't compute vtbl twice");
// We own a copy of this, it will go away shortly. // We own a copy of this, it will go away shortly.
new ElTy (e);
IndexFor[RD] = new ElTy (e); IndexFor[RD] = new ElTy (e);
} }
void RegisterVBIndex(const CXXRecordDecl *RD, const VBElTy &e) {
assert(VBIndexFor.find(RD) == VBIndexFor.end() && "Don't compute vtbl twice");
// We own a copy of this, it will go away shortly.
VBIndexFor[RD] = new VBElTy (e);
}
Index_t lookup(const CXXMethodDecl *MD) { Index_t lookup(const CXXMethodDecl *MD) {
const CXXRecordDecl *RD = MD->getParent(); const CXXRecordDecl *RD = MD->getParent();
MapTy::iterator I = IndexFor.find(RD); MapTy::iterator I = IndexFor.find(RD);
if (I == IndexFor.end()) { if (I == IndexFor.end()) {
std::vector<llvm::Constant *> methods; std::vector<llvm::Constant *> methods;
// FIXME: This seems expensive. Can we do a partial job to get
// just this data.
VtableBuilder b(methods, RD, CGM); VtableBuilder b(methods, RD, CGM);
b.GenerateVtableForBase(RD); b.GenerateVtableForBase(RD);
b.GenerateVtableForVBases(RD); b.GenerateVtableForVBases(RD);
register_index(RD, b.getIndex()); RegisterIndex(RD, b.getIndex());
I = IndexFor.find(RD); I = IndexFor.find(RD);
} }
assert(I->second->find(MD)!=I->second->end() && "Can't find vtable index"); assert(I->second->find(MD)!=I->second->end() && "Can't find vtable index");
return (*I->second)[MD]; return (*I->second)[MD];
} }
Index_t VBlookup(const CXXRecordDecl *RD, const CXXRecordDecl *BD) {
VBMapTy::iterator I = VBIndexFor.find(RD);
if (I == VBIndexFor.end()) {
std::vector<llvm::Constant *> methods;
// FIXME: This seems expensive. Can we do a partial job to get
// just this data.
VtableBuilder b(methods, RD, CGM);
b.GenerateVtableForBase(RD);
b.GenerateVtableForVBases(RD);
RegisterVBIndex(RD, b.getVBIndex());
I = VBIndexFor.find(RD);
}
assert(I->second->find(BD)!=I->second->end() && "Can't find vtable index");
return (*I->second)[BD];
}
}; };
// FIXME: move to Context
static VtableInfo *vtableinfo;
VtableBuilder::Index_t VtableBuilder::VBlookup(CXXRecordDecl *D,
CXXRecordDecl *B) {
if (vtableinfo == 0)
vtableinfo = new VtableInfo(CGM);
return vtableinfo->VBlookup(D, B);
}
// FIXME: Move to Context. // FIXME: Move to Context.
VtableInfo::MapTy VtableInfo::IndexFor; VtableInfo::MapTy VtableInfo::IndexFor;
// FIXME: Move to Context.
VtableInfo::VBMapTy VtableInfo::VBIndexFor;
llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) { llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) {
llvm::SmallString<256> OutName; llvm::SmallString<256> OutName;
llvm::raw_svector_ostream Out(OutName); llvm::raw_svector_ostream Out(OutName);
@ -1191,9 +1258,6 @@ llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) {
return vtable; return vtable;
} }
// FIXME: move to Context
static VtableInfo *vtableinfo;
llvm::Constant *CodeGenFunction::GenerateThunk(llvm::Function *Fn, llvm::Constant *CodeGenFunction::GenerateThunk(llvm::Function *Fn,
const CXXMethodDecl *MD, const CXXMethodDecl *MD,
bool Extern, int64_t nv, bool Extern, int64_t nv,