Use the new CovariantThunkAdjustment in the vtable builder.
Make the pure virtual methods map a set instead. llvm-svn: 89961
This commit is contained in:
parent
5fe97e7aca
commit
d420a31fe9
|
|
@ -15,6 +15,7 @@
|
||||||
#include "CodeGenFunction.h"
|
#include "CodeGenFunction.h"
|
||||||
|
|
||||||
#include "clang/AST/RecordLayout.h"
|
#include "clang/AST/RecordLayout.h"
|
||||||
|
#include "llvm/ADT/DenseSet.h"
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
@ -63,21 +64,43 @@ private:
|
||||||
/// Index - The index in the vtable.
|
/// Index - The index in the vtable.
|
||||||
uint64_t Index;
|
uint64_t Index;
|
||||||
|
|
||||||
/// ThisAdjustment - The thunk adjustment.
|
/// Adjustment - The thunk adjustment.
|
||||||
ThunkAdjustment Adjustment;
|
ThunkAdjustment Adjustment;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef llvm::DenseMap<GlobalDecl, int> Pures_t;
|
/// Thunks - The thunks in a vtable.
|
||||||
Pures_t Pures;
|
|
||||||
typedef std::pair<Index_t, Index_t> CallOffset;
|
|
||||||
|
|
||||||
typedef llvm::DenseMap<GlobalDecl, Thunk> ThunksMapTy;
|
typedef llvm::DenseMap<GlobalDecl, Thunk> ThunksMapTy;
|
||||||
ThunksMapTy Thunks;
|
ThunksMapTy Thunks;
|
||||||
|
|
||||||
typedef llvm::DenseMap<GlobalDecl,
|
/// CovariantThunk - Represents a single covariant thunk.
|
||||||
std::pair<std::pair<CallOffset, CallOffset>,
|
struct CovariantThunk {
|
||||||
CanQualType> > CovariantThunks_t;
|
CovariantThunk()
|
||||||
CovariantThunks_t CovariantThunks;
|
: Index(0) { }
|
||||||
|
|
||||||
|
CovariantThunk(uint64_t Index, const ThunkAdjustment &ThisAdjustment,
|
||||||
|
const ThunkAdjustment &ReturnAdjustment,
|
||||||
|
CanQualType ReturnType)
|
||||||
|
: Index(Index), Adjustment(ThisAdjustment, ReturnAdjustment),
|
||||||
|
ReturnType(ReturnType) { }
|
||||||
|
|
||||||
|
// Index - The index in the vtable.
|
||||||
|
uint64_t Index;
|
||||||
|
|
||||||
|
/// Adjustment - The covariant thunk adjustment.
|
||||||
|
CovariantThunkAdjustment Adjustment;
|
||||||
|
|
||||||
|
/// ReturnType - The return type of the function.
|
||||||
|
CanQualType ReturnType;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// CovariantThunks - The covariant thunks in a vtable.
|
||||||
|
typedef llvm::DenseMap<GlobalDecl, CovariantThunk> CovariantThunksMapTy;
|
||||||
|
CovariantThunksMapTy CovariantThunks;
|
||||||
|
|
||||||
|
/// PureVirtualMethods - Pure virtual methods.
|
||||||
|
typedef llvm::DenseSet<GlobalDecl> PureVirtualMethodsSetTy;
|
||||||
|
PureVirtualMethodsSetTy PureVirtualMethods;
|
||||||
|
|
||||||
std::vector<Index_t> VCalls;
|
std::vector<Index_t> VCalls;
|
||||||
|
|
||||||
typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
|
typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
|
||||||
|
|
@ -268,22 +291,23 @@ public:
|
||||||
CanQualType oret = CGM.getContext().getCanonicalType(nc_oret);
|
CanQualType oret = CGM.getContext().getCanonicalType(nc_oret);
|
||||||
QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType();
|
QualType nc_ret = MD->getType()->getAs<FunctionType>()->getResultType();
|
||||||
CanQualType ret = CGM.getContext().getCanonicalType(nc_ret);
|
CanQualType ret = CGM.getContext().getCanonicalType(nc_ret);
|
||||||
CallOffset ReturnOffset = std::make_pair(0, 0);
|
ThunkAdjustment ReturnAdjustment;
|
||||||
if (oret != ret) {
|
if (oret != ret) {
|
||||||
// FIXME: calculate offsets for covariance
|
// FIXME: calculate offsets for covariance
|
||||||
if (CovariantThunks.count(OMD)) {
|
CovariantThunksMapTy::iterator i = CovariantThunks.find(OMD);
|
||||||
oret = CovariantThunks[OMD].second;
|
if (i != CovariantThunks.end()) {
|
||||||
CovariantThunks.erase(OMD);
|
oret = i->second.ReturnType;
|
||||||
|
CovariantThunks.erase(i);
|
||||||
}
|
}
|
||||||
// FIXME: Double check oret
|
// FIXME: Double check oret
|
||||||
Index_t nv = getNVOffset(oret, ret)/8;
|
Index_t nv = getNVOffset(oret, ret)/8;
|
||||||
ReturnOffset = std::make_pair(nv, getVbaseOffset(oret, ret));
|
ReturnAdjustment = ThunkAdjustment(nv, getVbaseOffset(oret, ret));
|
||||||
}
|
}
|
||||||
Index[GD] = i;
|
Index[GD] = i;
|
||||||
submethods[i] = m;
|
submethods[i] = m;
|
||||||
if (isPure)
|
if (isPure)
|
||||||
Pures[GD] = 1;
|
PureVirtualMethods.insert(GD);
|
||||||
Pures.erase(OGD);
|
PureVirtualMethods.erase(OGD);
|
||||||
Thunks.erase(OGD);
|
Thunks.erase(OGD);
|
||||||
if (MorallyVirtual || VCall.count(OGD)) {
|
if (MorallyVirtual || VCall.count(OGD)) {
|
||||||
Index_t &idx = VCall[OGD];
|
Index_t &idx = VCall[OGD];
|
||||||
|
|
@ -312,18 +336,15 @@ public:
|
||||||
if (VCalls[idx-1] == 0)
|
if (VCalls[idx-1] == 0)
|
||||||
VirtualAdjustment = 0;
|
VirtualAdjustment = 0;
|
||||||
|
|
||||||
CallOffset ThisOffset = std::make_pair(NonVirtualAdjustment,
|
|
||||||
VirtualAdjustment);
|
|
||||||
ThunkAdjustment ThisAdjustment(NonVirtualAdjustment,
|
ThunkAdjustment ThisAdjustment(NonVirtualAdjustment,
|
||||||
VirtualAdjustment);
|
VirtualAdjustment);
|
||||||
|
|
||||||
// FIXME: Do we always have to build a covariant thunk to save oret,
|
// FIXME: Do we always have to build a covariant thunk to save oret,
|
||||||
// which is the containing virtual base class?
|
// which is the containing virtual base class?
|
||||||
if (ReturnOffset.first || ReturnOffset.second)
|
if (!ReturnAdjustment.isEmpty()) {
|
||||||
CovariantThunks[GD] = std::make_pair(std::make_pair(ThisOffset,
|
CovariantThunks[GD] =
|
||||||
ReturnOffset),
|
CovariantThunk(i, ThisAdjustment, ReturnAdjustment, oret);
|
||||||
oret);
|
} else if (!isPure && !ThisAdjustment.isEmpty())
|
||||||
else if (!isPure && !ThisAdjustment.isEmpty())
|
|
||||||
Thunks[GD] = Thunk(i, ThisAdjustment);
|
Thunks[GD] = Thunk(i, ThisAdjustment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -331,15 +352,13 @@ public:
|
||||||
// FIXME: finish off
|
// FIXME: finish off
|
||||||
int64_t NonVirtualAdjustment = VCallOffset[OGD] - OverrideOffset/8;
|
int64_t NonVirtualAdjustment = VCallOffset[OGD] - OverrideOffset/8;
|
||||||
|
|
||||||
if (NonVirtualAdjustment || ReturnOffset.first || ReturnOffset.second) {
|
if (NonVirtualAdjustment || !ReturnAdjustment.isEmpty()) {
|
||||||
CallOffset ThisOffset = std::make_pair(NonVirtualAdjustment, 0);
|
|
||||||
ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0);
|
ThunkAdjustment ThisAdjustment(NonVirtualAdjustment, 0);
|
||||||
|
|
||||||
if (ReturnOffset.first || ReturnOffset.second)
|
if (!ReturnAdjustment.isEmpty()) {
|
||||||
CovariantThunks[GD] = std::make_pair(std::make_pair(ThisOffset,
|
CovariantThunks[GD] =
|
||||||
ReturnOffset),
|
CovariantThunk(i, ThisAdjustment, ReturnAdjustment, oret);
|
||||||
oret);
|
} else if (!isPure)
|
||||||
else if (!isPure)
|
|
||||||
Thunks[GD] = Thunk(i, ThisAdjustment);
|
Thunks[GD] = Thunk(i, ThisAdjustment);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -363,31 +382,26 @@ public:
|
||||||
}
|
}
|
||||||
Thunks.clear();
|
Thunks.clear();
|
||||||
|
|
||||||
for (CovariantThunks_t::iterator i = CovariantThunks.begin(),
|
for (CovariantThunksMapTy::const_iterator i = CovariantThunks.begin(),
|
||||||
e = CovariantThunks.end();
|
e = CovariantThunks.end(); i != e; ++i) {
|
||||||
i != e; ++i) {
|
|
||||||
GlobalDecl GD = i->first;
|
GlobalDecl GD = i->first;
|
||||||
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
|
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
|
||||||
if (MD->isPure())
|
if (MD->isPure())
|
||||||
continue;
|
continue;
|
||||||
Index_t idx = Index[GD];
|
|
||||||
Index_t nv_t = i->second.first.first.first;
|
|
||||||
Index_t v_t = i->second.first.first.second;
|
|
||||||
Index_t nv_r = i->second.first.second.first;
|
|
||||||
Index_t v_r = i->second.first.second.second;
|
|
||||||
|
|
||||||
CovariantThunkAdjustment Adjustment(ThunkAdjustment(nv_t, v_t),
|
const CovariantThunk &Thunk = i->second;
|
||||||
ThunkAdjustment(nv_r, v_r));
|
assert(Thunk.Index == Index[GD] && "Thunk index mismatch!");
|
||||||
submethods[idx] = CGM.BuildCovariantThunk(MD, Extern, Adjustment);
|
submethods[Thunk.Index] =
|
||||||
|
CGM.BuildCovariantThunk(MD, Extern, Thunk.Adjustment);
|
||||||
}
|
}
|
||||||
CovariantThunks.clear();
|
CovariantThunks.clear();
|
||||||
for (Pures_t::iterator i = Pures.begin(), e = Pures.end();
|
|
||||||
i != e; ++i) {
|
for (PureVirtualMethodsSetTy::iterator i = PureVirtualMethods.begin(),
|
||||||
GlobalDecl GD = i->first;
|
e = PureVirtualMethods.end(); i != e; ++i) {
|
||||||
Index_t idx = Index[GD];
|
GlobalDecl GD = *i;
|
||||||
submethods[idx] = cxa_pure;
|
submethods[Index[GD]] = cxa_pure;
|
||||||
}
|
}
|
||||||
Pures.clear();
|
PureVirtualMethods.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Constant *WrapAddrOf(GlobalDecl GD) {
|
llvm::Constant *WrapAddrOf(GlobalDecl GD) {
|
||||||
|
|
@ -448,7 +462,7 @@ public:
|
||||||
D1(printf(" vfn for %s at %d\n", MD->getNameAsString().c_str(),
|
D1(printf(" vfn for %s at %d\n", MD->getNameAsString().c_str(),
|
||||||
(int)Index[GD]));
|
(int)Index[GD]));
|
||||||
if (MD->isPure())
|
if (MD->isPure())
|
||||||
Pures[GD] = 1;
|
PureVirtualMethods.insert(GD);
|
||||||
if (MorallyVirtual) {
|
if (MorallyVirtual) {
|
||||||
VCallOffset[GD] = Offset/8;
|
VCallOffset[GD] = Offset/8;
|
||||||
Index_t &idx = VCall[GD];
|
Index_t &idx = VCall[GD];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue