зеркало из https://github.com/microsoft/clang-1.git
Correctly pass VTT parameters to constructors and destructors. The VTTs aren't yet used in the ctors/dtors, but that will follow.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92409 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
3b5ad2283c
Коммит
c997d4278d
|
@ -431,6 +431,37 @@ void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest,
|
||||||
EmitBlock(AfterFor, true);
|
EmitBlock(AfterFor, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// GetVTTParameter - Return the VTT parameter that should be passed to a
|
||||||
|
/// base constructor/destructor with virtual bases.
|
||||||
|
static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD) {
|
||||||
|
if (!CGVtableInfo::needsVTTParameter(GD)) {
|
||||||
|
// This constructor/destructor does not need a VTT parameter.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CXXRecordDecl *RD = cast<CXXMethodDecl>(CGF.CurFuncDecl)->getParent();
|
||||||
|
const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl())->getParent();
|
||||||
|
|
||||||
|
llvm::Value *VTT;
|
||||||
|
|
||||||
|
uint64_t SubVTTIndex =
|
||||||
|
CGF.CGM.getVtableInfo().getSubVTTIndex(RD, Base);
|
||||||
|
assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!");
|
||||||
|
|
||||||
|
if (CGVtableInfo::needsVTTParameter(CGF.CurGD)) {
|
||||||
|
// A VTT parameter was passed to the constructor, use it.
|
||||||
|
VTT = CGF.LoadCXXVTT();
|
||||||
|
VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, SubVTTIndex);
|
||||||
|
} else {
|
||||||
|
// We're the complete constructor, so get the VTT by name.
|
||||||
|
VTT = CGF.CGM.getVtableInfo().getVTT(RD);
|
||||||
|
VTT = CGF.Builder.CreateConstInBoundsGEP2_64(VTT, 0, SubVTTIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return VTT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// EmitClassMemberwiseCopy - This routine generates code to copy a class
|
/// EmitClassMemberwiseCopy - This routine generates code to copy a class
|
||||||
/// object from SrcValue to DestValue. Copying can be either a bitwise copy
|
/// object from SrcValue to DestValue. Copying can be either a bitwise copy
|
||||||
/// or via a copy constructor call.
|
/// or via a copy constructor call.
|
||||||
|
@ -438,11 +469,16 @@ void CodeGenFunction::EmitClassMemberwiseCopy(
|
||||||
llvm::Value *Dest, llvm::Value *Src,
|
llvm::Value *Dest, llvm::Value *Src,
|
||||||
const CXXRecordDecl *ClassDecl,
|
const CXXRecordDecl *ClassDecl,
|
||||||
const CXXRecordDecl *BaseClassDecl, QualType Ty) {
|
const CXXRecordDecl *BaseClassDecl, QualType Ty) {
|
||||||
|
CXXCtorType CtorType = Ctor_Complete;
|
||||||
|
|
||||||
if (ClassDecl) {
|
if (ClassDecl) {
|
||||||
Dest = GetAddressOfBaseClass(Dest, ClassDecl, BaseClassDecl,
|
Dest = GetAddressOfBaseClass(Dest, ClassDecl, BaseClassDecl,
|
||||||
/*NullCheckValue=*/false);
|
/*NullCheckValue=*/false);
|
||||||
Src = GetAddressOfBaseClass(Src, ClassDecl, BaseClassDecl,
|
Src = GetAddressOfBaseClass(Src, ClassDecl, BaseClassDecl,
|
||||||
/*NullCheckValue=*/false);
|
/*NullCheckValue=*/false);
|
||||||
|
|
||||||
|
// We want to call the base constructor.
|
||||||
|
CtorType = Ctor_Base;
|
||||||
}
|
}
|
||||||
if (BaseClassDecl->hasTrivialCopyConstructor()) {
|
if (BaseClassDecl->hasTrivialCopyConstructor()) {
|
||||||
EmitAggregateCopy(Dest, Src, Ty);
|
EmitAggregateCopy(Dest, Src, Ty);
|
||||||
|
@ -451,13 +487,19 @@ void CodeGenFunction::EmitClassMemberwiseCopy(
|
||||||
|
|
||||||
if (CXXConstructorDecl *BaseCopyCtor =
|
if (CXXConstructorDecl *BaseCopyCtor =
|
||||||
BaseClassDecl->getCopyConstructor(getContext(), 0)) {
|
BaseClassDecl->getCopyConstructor(getContext(), 0)) {
|
||||||
llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor,
|
llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, CtorType);
|
||||||
Ctor_Complete);
|
|
||||||
CallArgList CallArgs;
|
CallArgList CallArgs;
|
||||||
// Push the this (Dest) ptr.
|
// Push the this (Dest) ptr.
|
||||||
CallArgs.push_back(std::make_pair(RValue::get(Dest),
|
CallArgs.push_back(std::make_pair(RValue::get(Dest),
|
||||||
BaseCopyCtor->getThisType(getContext())));
|
BaseCopyCtor->getThisType(getContext())));
|
||||||
|
|
||||||
|
// Push the VTT parameter, if necessary.
|
||||||
|
if (llvm::Value *VTT =
|
||||||
|
GetVTTParameter(*this, GlobalDecl(BaseCopyCtor, CtorType))) {
|
||||||
|
QualType T = getContext().getPointerType(getContext().VoidPtrTy);
|
||||||
|
CallArgs.push_back(std::make_pair(RValue::get(VTT), T));
|
||||||
|
}
|
||||||
|
|
||||||
// Push the Src ptr.
|
// Push the Src ptr.
|
||||||
CallArgs.push_back(std::make_pair(RValue::get(Src),
|
CallArgs.push_back(std::make_pair(RValue::get(Src),
|
||||||
BaseCopyCtor->getParamDecl(0)->getType()));
|
BaseCopyCtor->getParamDecl(0)->getType()));
|
||||||
|
@ -787,10 +829,8 @@ static void EmitBaseInitializer(CodeGenFunction &CGF,
|
||||||
V = CGF.Builder.CreateConstInBoundsGEP1_64(V, Offset/8);
|
V = CGF.Builder.CreateConstInBoundsGEP1_64(V, Offset/8);
|
||||||
V = CGF.Builder.CreateBitCast(V, BaseClassType->getPointerTo());
|
V = CGF.Builder.CreateBitCast(V, BaseClassType->getPointerTo());
|
||||||
|
|
||||||
// FIXME: This should always use Ctor_Base as the ctor type! (But that
|
|
||||||
// causes crashes in tests.)
|
|
||||||
CGF.EmitCXXConstructorCall(BaseInit->getConstructor(),
|
CGF.EmitCXXConstructorCall(BaseInit->getConstructor(),
|
||||||
CtorType, V,
|
Ctor_Base, V,
|
||||||
BaseInit->const_arg_begin(),
|
BaseInit->const_arg_begin(),
|
||||||
BaseInit->const_arg_end());
|
BaseInit->const_arg_end());
|
||||||
}
|
}
|
||||||
|
@ -1248,6 +1288,7 @@ CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D,
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
|
CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
|
||||||
CXXCtorType Type,
|
CXXCtorType Type,
|
||||||
|
@ -1271,35 +1312,19 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(D, Type));
|
||||||
llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type);
|
llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type);
|
||||||
|
|
||||||
EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, ArgBeg, ArgEnd);
|
EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, VTT, ArgBeg, ArgEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
|
void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
|
||||||
CXXDtorType Type,
|
CXXDtorType Type,
|
||||||
llvm::Value *This) {
|
llvm::Value *This) {
|
||||||
|
llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(DD, Type));
|
||||||
llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(DD, Type);
|
llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(DD, Type);
|
||||||
|
|
||||||
CallArgList Args;
|
EmitCXXMemberCall(DD, Callee, ReturnValueSlot(), This, VTT, 0, 0);
|
||||||
|
|
||||||
// Push the this ptr.
|
|
||||||
Args.push_back(std::make_pair(RValue::get(This),
|
|
||||||
DD->getThisType(getContext())));
|
|
||||||
|
|
||||||
// Add a VTT parameter if necessary.
|
|
||||||
// FIXME: This should not be a dummy null parameter!
|
|
||||||
if (Type == Dtor_Base && DD->getParent()->getNumVBases() != 0) {
|
|
||||||
QualType T = getContext().getPointerType(getContext().VoidPtrTy);
|
|
||||||
|
|
||||||
Args.push_back(std::make_pair(RValue::get(CGM.EmitNullConstant(T)), T));
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: We should try to share this code with EmitCXXMemberCall.
|
|
||||||
|
|
||||||
QualType ResultType = DD->getType()->getAs<FunctionType>()->getResultType();
|
|
||||||
EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee,
|
|
||||||
ReturnValueSlot(), Args, DD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Value *
|
llvm::Value *
|
||||||
|
@ -1395,3 +1420,11 @@ void CodeGenFunction::InitializeVtablePtrsRecursive(
|
||||||
// Store address point
|
// Store address point
|
||||||
Builder.CreateStore(VtableAddressPoint, VtableField);
|
Builder.CreateStore(VtableAddressPoint, VtableField);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::Value *CodeGenFunction::LoadCXXVTT() {
|
||||||
|
assert((isa<CXXConstructorDecl>(CurFuncDecl) ||
|
||||||
|
isa<CXXDestructorDecl>(CurFuncDecl)) &&
|
||||||
|
"Must be in a C++ ctor or dtor to load the vtt parameter");
|
||||||
|
|
||||||
|
return Builder.CreateLoad(LocalDeclMap[CXXVTTDecl], "vtt");
|
||||||
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD,
|
||||||
llvm::Value *Callee,
|
llvm::Value *Callee,
|
||||||
ReturnValueSlot ReturnValue,
|
ReturnValueSlot ReturnValue,
|
||||||
llvm::Value *This,
|
llvm::Value *This,
|
||||||
|
llvm::Value *VTT,
|
||||||
CallExpr::const_arg_iterator ArgBeg,
|
CallExpr::const_arg_iterator ArgBeg,
|
||||||
CallExpr::const_arg_iterator ArgEnd) {
|
CallExpr::const_arg_iterator ArgEnd) {
|
||||||
assert(MD->isInstance() &&
|
assert(MD->isInstance() &&
|
||||||
|
@ -32,6 +33,12 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD,
|
||||||
Args.push_back(std::make_pair(RValue::get(This),
|
Args.push_back(std::make_pair(RValue::get(This),
|
||||||
MD->getThisType(getContext())));
|
MD->getThisType(getContext())));
|
||||||
|
|
||||||
|
// If there is a VTT parameter, emit it.
|
||||||
|
if (VTT) {
|
||||||
|
QualType T = getContext().getPointerType(getContext().VoidPtrTy);
|
||||||
|
Args.push_back(std::make_pair(RValue::get(VTT), T));
|
||||||
|
}
|
||||||
|
|
||||||
// And the rest of the call args
|
// And the rest of the call args
|
||||||
EmitCallArgs(Args, FPT, ArgBeg, ArgEnd);
|
EmitCallArgs(Args, FPT, ArgBeg, ArgEnd);
|
||||||
|
|
||||||
|
@ -129,7 +136,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,
|
||||||
Callee = CGM.GetAddrOfFunction(MD, Ty);
|
Callee = CGM.GetAddrOfFunction(MD, Ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EmitCXXMemberCall(MD, Callee, ReturnValue, This,
|
return EmitCXXMemberCall(MD, Callee, ReturnValue, This, /*VTT=*/0,
|
||||||
CE->arg_begin(), CE->arg_end());
|
CE->arg_begin(), CE->arg_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +282,7 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E,
|
||||||
else
|
else
|
||||||
Callee = CGM.GetAddrOfFunction(MD, Ty);
|
Callee = CGM.GetAddrOfFunction(MD, Ty);
|
||||||
|
|
||||||
return EmitCXXMemberCall(MD, Callee, ReturnValue, This,
|
return EmitCXXMemberCall(MD, Callee, ReturnValue, This, /*VTT=*/0,
|
||||||
E->arg_begin() + 1, E->arg_end());
|
E->arg_begin() + 1, E->arg_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -726,7 +733,8 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
|
||||||
/*isVariadic=*/false);
|
/*isVariadic=*/false);
|
||||||
|
|
||||||
llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty);
|
llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty);
|
||||||
EmitCXXMemberCall(Dtor, Callee, ReturnValueSlot(), Ptr, 0, 0);
|
EmitCXXMemberCall(Dtor, Callee, ReturnValueSlot(), Ptr, /*VTT=*/0,
|
||||||
|
0, 0);
|
||||||
|
|
||||||
// The dtor took care of deleting the object.
|
// The dtor took care of deleting the object.
|
||||||
ShouldCallDelete = false;
|
ShouldCallDelete = false;
|
||||||
|
|
|
@ -211,7 +211,7 @@ public:
|
||||||
return VtableComponents;
|
return VtableComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::DenseMap<const CXXRecordDecl *, Index_t> &getVBIndex()
|
llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getVBIndex()
|
||||||
{ return VBIndex; }
|
{ return VBIndex; }
|
||||||
|
|
||||||
SavedAdjustmentsVectorTy &getSavedAdjustments()
|
SavedAdjustmentsVectorTy &getSavedAdjustments()
|
||||||
|
@ -1209,6 +1209,10 @@ class VTTBuilder {
|
||||||
llvm::Constant *ClassVtbl;
|
llvm::Constant *ClassVtbl;
|
||||||
llvm::LLVMContext &VMContext;
|
llvm::LLVMContext &VMContext;
|
||||||
|
|
||||||
|
llvm::DenseMap<const CXXRecordDecl *, uint64_t> SubVTTIndicies;
|
||||||
|
|
||||||
|
bool GenerateDefinition;
|
||||||
|
|
||||||
/// BuildVtablePtr - Build up a referene to the given secondary vtable
|
/// BuildVtablePtr - Build up a referene to the given secondary vtable
|
||||||
llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable,
|
llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable,
|
||||||
const CXXRecordDecl *VtableClass,
|
const CXXRecordDecl *VtableClass,
|
||||||
|
@ -1268,14 +1272,17 @@ class VTTBuilder {
|
||||||
// FIXME: Slightly too many of these for __ZTT8test8_B2
|
// FIXME: Slightly too many of these for __ZTT8test8_B2
|
||||||
llvm::Constant *init;
|
llvm::Constant *init;
|
||||||
if (BaseMorallyVirtual)
|
if (BaseMorallyVirtual)
|
||||||
init = BuildVtablePtr(vtbl, VtblClass, RD, Offset);
|
init = GenerateDefinition ?
|
||||||
|
BuildVtablePtr(vtbl, VtblClass, RD, Offset) : 0;
|
||||||
else {
|
else {
|
||||||
init = CGM.getVtableInfo().getCtorVtable(Class, Base, BaseOffset);
|
init = GenerateDefinition ?
|
||||||
|
CGM.getVtableInfo().getCtorVtable(Class, Base, BaseOffset) : 0;
|
||||||
|
|
||||||
subvtbl = init;
|
subvtbl = init;
|
||||||
subVtblClass = Base;
|
subVtblClass = Base;
|
||||||
|
|
||||||
init = BuildVtablePtr(init, Class, Base, BaseOffset);
|
init = GenerateDefinition ?
|
||||||
|
BuildVtablePtr(init, Class, Base, BaseOffset) : 0;
|
||||||
}
|
}
|
||||||
Inits.push_back(init);
|
Inits.push_back(init);
|
||||||
}
|
}
|
||||||
|
@ -1294,14 +1301,16 @@ class VTTBuilder {
|
||||||
|
|
||||||
// First comes the primary virtual table pointer...
|
// First comes the primary virtual table pointer...
|
||||||
if (MorallyVirtual) {
|
if (MorallyVirtual) {
|
||||||
Vtable = ClassVtbl;
|
Vtable = GenerateDefinition ? ClassVtbl : 0;
|
||||||
VtableClass = Class;
|
VtableClass = Class;
|
||||||
} else {
|
} else {
|
||||||
Vtable = CGM.getVtableInfo().getCtorVtable(Class, RD, Offset);
|
Vtable = GenerateDefinition ?
|
||||||
|
CGM.getVtableInfo().getCtorVtable(Class, RD, Offset) : 0;
|
||||||
VtableClass = RD;
|
VtableClass = RD;
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD, Offset);
|
llvm::Constant *Init = GenerateDefinition ?
|
||||||
|
BuildVtablePtr(Vtable, VtableClass, RD, Offset) : 0;
|
||||||
Inits.push_back(Init);
|
Inits.push_back(Init);
|
||||||
|
|
||||||
// then the secondary VTTs....
|
// then the secondary VTTs....
|
||||||
|
@ -1324,6 +1333,10 @@ class VTTBuilder {
|
||||||
continue;
|
continue;
|
||||||
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
|
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
|
||||||
uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
|
uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base);
|
||||||
|
|
||||||
|
// Remember the sub-VTT index.
|
||||||
|
SubVTTIndicies[Base] = Inits.size();
|
||||||
|
|
||||||
BuildVTT(Base, BaseOffset, MorallyVirtual);
|
BuildVTT(Base, BaseOffset, MorallyVirtual);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1336,6 +1349,9 @@ class VTTBuilder {
|
||||||
const CXXRecordDecl *Base =
|
const CXXRecordDecl *Base =
|
||||||
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
|
cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl());
|
||||||
if (i->isVirtual() && !SeenVBase.count(Base)) {
|
if (i->isVirtual() && !SeenVBase.count(Base)) {
|
||||||
|
// Remember the sub-VTT index.
|
||||||
|
SubVTTIndicies[Base] = Inits.size();
|
||||||
|
|
||||||
SeenVBase.insert(Base);
|
SeenVBase.insert(Base);
|
||||||
uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
|
uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base);
|
||||||
BuildVTT(Base, BaseOffset, true);
|
BuildVTT(Base, BaseOffset, true);
|
||||||
|
@ -1346,15 +1362,18 @@ class VTTBuilder {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
|
VTTBuilder(std::vector<llvm::Constant *> &inits, const CXXRecordDecl *c,
|
||||||
CodeGenModule &cgm)
|
CodeGenModule &cgm, bool GenerateDefinition)
|
||||||
: Inits(inits), Class(c), CGM(cgm),
|
: Inits(inits), Class(c), CGM(cgm),
|
||||||
BLayout(cgm.getContext().getASTRecordLayout(c)),
|
BLayout(cgm.getContext().getASTRecordLayout(c)),
|
||||||
AddressPoints(*cgm.AddressPoints[c]),
|
AddressPoints(*cgm.AddressPoints[c]),
|
||||||
VMContext(cgm.getModule().getContext()) {
|
VMContext(cgm.getModule().getContext()),
|
||||||
|
GenerateDefinition(GenerateDefinition) {
|
||||||
|
|
||||||
// First comes the primary virtual table pointer for the complete class...
|
// First comes the primary virtual table pointer for the complete class...
|
||||||
ClassVtbl = CGM.getVtableInfo().getVtable(Class);
|
ClassVtbl = CGM.getVtableInfo().getVtable(Class);
|
||||||
Inits.push_back(BuildVtablePtr(ClassVtbl, Class, Class, 0));
|
llvm::Constant *Init = GenerateDefinition ?
|
||||||
|
BuildVtablePtr(ClassVtbl, Class, Class, 0) : 0;
|
||||||
|
Inits.push_back(Init);
|
||||||
|
|
||||||
// then the secondary VTTs...
|
// then the secondary VTTs...
|
||||||
SecondaryVTTs(Class);
|
SecondaryVTTs(Class);
|
||||||
|
@ -1365,11 +1384,16 @@ public:
|
||||||
// and last, the virtual VTTs.
|
// and last, the virtual VTTs.
|
||||||
VirtualVTTs(Class);
|
VirtualVTTs(Class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::DenseMap<const CXXRecordDecl *, uint64_t> &getSubVTTIndicies() {
|
||||||
|
return SubVTTIndicies;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::GlobalVariable *
|
llvm::GlobalVariable *
|
||||||
CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
|
CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
|
||||||
|
bool GenerateDefinition,
|
||||||
const CXXRecordDecl *RD) {
|
const CXXRecordDecl *RD) {
|
||||||
// Only classes that have virtual bases need a VTT.
|
// Only classes that have virtual bases need a VTT.
|
||||||
if (RD->getNumVBases() == 0)
|
if (RD->getNumVBases() == 0)
|
||||||
|
@ -1379,23 +1403,36 @@ CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
|
||||||
CGM.getMangleContext().mangleCXXVTT(RD, OutName);
|
CGM.getMangleContext().mangleCXXVTT(RD, OutName);
|
||||||
llvm::StringRef Name = OutName.str();
|
llvm::StringRef Name = OutName.str();
|
||||||
|
|
||||||
|
|
||||||
D1(printf("vtt %s\n", RD->getNameAsCString()));
|
D1(printf("vtt %s\n", RD->getNameAsCString()));
|
||||||
|
|
||||||
std::vector<llvm::Constant *> inits;
|
llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
|
||||||
VTTBuilder b(inits, RD, CGM);
|
if (GV == 0 || GV->isDeclaration()) {
|
||||||
|
const llvm::Type *Int8PtrTy =
|
||||||
|
llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
|
||||||
|
|
||||||
const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
|
std::vector<llvm::Constant *> inits;
|
||||||
const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
|
VTTBuilder b(inits, RD, CGM, GenerateDefinition);
|
||||||
|
|
||||||
|
const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size());
|
||||||
|
llvm::Constant *Init = 0;
|
||||||
|
if (GenerateDefinition)
|
||||||
|
Init = llvm::ConstantArray::get(Type, inits);
|
||||||
|
|
||||||
|
llvm::GlobalVariable *OldGV = GV;
|
||||||
|
GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
|
||||||
|
Linkage, Init, Name);
|
||||||
|
CGM.setGlobalVisibility(GV, RD);
|
||||||
|
|
||||||
|
if (OldGV) {
|
||||||
|
GV->takeName(OldGV);
|
||||||
|
llvm::Constant *NewPtr =
|
||||||
|
llvm::ConstantExpr::getBitCast(GV, OldGV->getType());
|
||||||
|
OldGV->replaceAllUsesWith(NewPtr);
|
||||||
|
OldGV->eraseFromParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
llvm::Constant *Init = llvm::ConstantArray::get(Type, inits);
|
return GV;
|
||||||
|
|
||||||
llvm::GlobalVariable *VTT =
|
|
||||||
new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
|
|
||||||
Linkage, Init, Name);
|
|
||||||
CGM.setGlobalVisibility(VTT, RD);
|
|
||||||
|
|
||||||
return VTT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
|
void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
|
||||||
|
@ -1407,7 +1444,7 @@ void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage,
|
||||||
}
|
}
|
||||||
|
|
||||||
Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0);
|
Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0);
|
||||||
GenerateVTT(Linkage, RD);
|
GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
|
llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) {
|
||||||
|
@ -1428,6 +1465,13 @@ CGVtableInfo::getCtorVtable(const CXXRecordDecl *LayoutClass,
|
||||||
LayoutClass, RD, Offset);
|
LayoutClass, RD, Offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::GlobalVariable *CGVtableInfo::getVTT(const CXXRecordDecl *RD) {
|
||||||
|
return GenerateVTT(llvm::GlobalValue::ExternalLinkage,
|
||||||
|
/*GenerateDefinition=*/false, RD);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
|
void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
|
||||||
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
|
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
|
||||||
const CXXRecordDecl *RD = MD->getParent();
|
const CXXRecordDecl *RD = MD->getParent();
|
||||||
|
@ -1443,16 +1487,6 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
|
||||||
// We don't have the right key function.
|
// We don't have the right key function.
|
||||||
if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
|
if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If the key function is a destructor, we only want to emit the vtable
|
|
||||||
// once, so do it for the complete destructor.
|
|
||||||
if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Complete)
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// If there is no key function, we only want to emit the vtable if we are
|
|
||||||
// emitting a constructor.
|
|
||||||
if (!isa<CXXConstructorDecl>(MD) || GD.getCtorType() != Ctor_Complete)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::GlobalVariable::LinkageTypes Linkage;
|
llvm::GlobalVariable::LinkageTypes Linkage;
|
||||||
|
@ -1479,3 +1513,47 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CGVtableInfo::needsVTTParameter(GlobalDecl GD) {
|
||||||
|
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
|
||||||
|
|
||||||
|
// We don't have any virtual bases, just return early.
|
||||||
|
if (!MD->getParent()->getNumVBases())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check if we have a base constructor.
|
||||||
|
if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Check if we have a base destructor.
|
||||||
|
if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t CGVtableInfo::getSubVTTIndex(const CXXRecordDecl *RD,
|
||||||
|
const CXXRecordDecl *Base) {
|
||||||
|
ClassPairTy ClassPair(RD, Base);
|
||||||
|
|
||||||
|
SubVTTIndiciesTy::iterator I =
|
||||||
|
SubVTTIndicies.find(ClassPair);
|
||||||
|
if (I != SubVTTIndicies.end())
|
||||||
|
return I->second;
|
||||||
|
|
||||||
|
std::vector<llvm::Constant *> inits;
|
||||||
|
VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false);
|
||||||
|
|
||||||
|
for (llvm::DenseMap<const CXXRecordDecl *, uint64_t>::iterator I =
|
||||||
|
Builder.getSubVTTIndicies().begin(),
|
||||||
|
E = Builder.getSubVTTIndicies().end(); I != E; ++I) {
|
||||||
|
// Insert all indices.
|
||||||
|
ClassPairTy ClassPair(RD, I->first);
|
||||||
|
|
||||||
|
SubVTTIndicies.insert(std::make_pair(ClassPair, I->second));
|
||||||
|
}
|
||||||
|
|
||||||
|
I = SubVTTIndicies.find(ClassPair);
|
||||||
|
assert(I != SubVTTIndicies.end() && "Did not find index!");
|
||||||
|
|
||||||
|
return I->second;
|
||||||
|
}
|
||||||
|
|
|
@ -93,6 +93,9 @@ private:
|
||||||
SavedAdjustmentsTy SavedAdjustments;
|
SavedAdjustmentsTy SavedAdjustments;
|
||||||
llvm::DenseSet<const CXXRecordDecl*> SavedAdjustmentRecords;
|
llvm::DenseSet<const CXXRecordDecl*> SavedAdjustmentRecords;
|
||||||
|
|
||||||
|
typedef llvm::DenseMap<ClassPairTy, uint64_t> SubVTTIndiciesTy;
|
||||||
|
SubVTTIndiciesTy SubVTTIndicies;
|
||||||
|
|
||||||
/// getNumVirtualFunctionPointers - Return the number of virtual function
|
/// getNumVirtualFunctionPointers - Return the number of virtual function
|
||||||
/// pointers in the vtable for a given record decl.
|
/// pointers in the vtable for a given record decl.
|
||||||
uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
|
uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD);
|
||||||
|
@ -113,12 +116,22 @@ private:
|
||||||
const CXXRecordDecl *RD, uint64_t Offset);
|
const CXXRecordDecl *RD, uint64_t Offset);
|
||||||
|
|
||||||
llvm::GlobalVariable *GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
|
llvm::GlobalVariable *GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage,
|
||||||
|
bool GenerateDefinition,
|
||||||
const CXXRecordDecl *RD);
|
const CXXRecordDecl *RD);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CGVtableInfo(CodeGenModule &CGM)
|
CGVtableInfo(CodeGenModule &CGM)
|
||||||
: CGM(CGM) { }
|
: CGM(CGM) { }
|
||||||
|
|
||||||
|
/// needsVTTParameter - Return whether the given global decl needs a VTT
|
||||||
|
/// parameter, which it does if it's a base constructor or destructor with
|
||||||
|
/// virtual bases.
|
||||||
|
static bool needsVTTParameter(GlobalDecl GD);
|
||||||
|
|
||||||
|
/// getSubVTTIndex - Return the index of the sub-VTT for the base class of the
|
||||||
|
/// given record decl.
|
||||||
|
uint64_t getSubVTTIndex(const CXXRecordDecl *RD, const CXXRecordDecl *Base);
|
||||||
|
|
||||||
/// getMethodVtableIndex - Return the index (relative to the vtable address
|
/// getMethodVtableIndex - Return the index (relative to the vtable address
|
||||||
/// point) where the function pointer for the given virtual function is
|
/// point) where the function pointer for the given virtual function is
|
||||||
/// stored.
|
/// stored.
|
||||||
|
@ -144,6 +157,7 @@ public:
|
||||||
const CXXRecordDecl *Class,
|
const CXXRecordDecl *Class,
|
||||||
uint64_t Offset);
|
uint64_t Offset);
|
||||||
|
|
||||||
|
llvm::GlobalVariable *getVTT(const CXXRecordDecl *RD);
|
||||||
|
|
||||||
void MaybeEmitVtable(GlobalDecl GD);
|
void MaybeEmitVtable(GlobalDecl GD);
|
||||||
};
|
};
|
||||||
|
|
|
@ -230,26 +230,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool NeedsVTTParameter(GlobalDecl GD) {
|
void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) {
|
||||||
const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
|
|
||||||
|
|
||||||
// We don't have any virtual bases, just return early.
|
|
||||||
if (!MD->getParent()->getNumVBases())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Check if we have a base constructor.
|
|
||||||
if (isa<CXXConstructorDecl>(MD) && GD.getCtorType() == Ctor_Base)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Check if we have a base destructor.
|
|
||||||
if (isa<CXXDestructorDecl>(MD) && GD.getDtorType() == Dtor_Base)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CodeGenFunction::GenerateCode(GlobalDecl GD,
|
|
||||||
llvm::Function *Fn) {
|
|
||||||
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
|
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
|
||||||
|
|
||||||
// Check if we should generate debug info for this function.
|
// Check if we should generate debug info for this function.
|
||||||
|
@ -271,7 +252,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD,
|
||||||
Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType()));
|
Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType()));
|
||||||
|
|
||||||
// Check if we need a VTT parameter as well.
|
// Check if we need a VTT parameter as well.
|
||||||
if (NeedsVTTParameter(GD)) {
|
if (CGVtableInfo::needsVTTParameter(GD)) {
|
||||||
// FIXME: The comment about using a fake decl above applies here too.
|
// FIXME: The comment about using a fake decl above applies here too.
|
||||||
QualType T = getContext().getPointerType(getContext().VoidPtrTy);
|
QualType T = getContext().getPointerType(getContext().VoidPtrTy);
|
||||||
CXXVTTDecl =
|
CXXVTTDecl =
|
||||||
|
|
|
@ -728,6 +728,10 @@ public:
|
||||||
/// generating code for an C++ member function.
|
/// generating code for an C++ member function.
|
||||||
llvm::Value *LoadCXXThis();
|
llvm::Value *LoadCXXThis();
|
||||||
|
|
||||||
|
/// LoadCXXVTT - Load the VTT parameter to base constructors/destructors have
|
||||||
|
/// virtual bases.
|
||||||
|
llvm::Value *LoadCXXVTT();
|
||||||
|
|
||||||
/// GetAddressOfBaseClass - This function will add the necessary delta to the
|
/// GetAddressOfBaseClass - This function will add the necessary delta to the
|
||||||
/// load of 'this' and returns address of the base class.
|
/// load of 'this' and returns address of the base class.
|
||||||
// FIXME. This currently only does a derived to non-virtual base conversion.
|
// FIXME. This currently only does a derived to non-virtual base conversion.
|
||||||
|
@ -1057,6 +1061,7 @@ public:
|
||||||
llvm::Value *Callee,
|
llvm::Value *Callee,
|
||||||
ReturnValueSlot ReturnValue,
|
ReturnValueSlot ReturnValue,
|
||||||
llvm::Value *This,
|
llvm::Value *This,
|
||||||
|
llvm::Value *VTT,
|
||||||
CallExpr::const_arg_iterator ArgBeg,
|
CallExpr::const_arg_iterator ArgBeg,
|
||||||
CallExpr::const_arg_iterator ArgEnd);
|
CallExpr::const_arg_iterator ArgEnd);
|
||||||
RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E,
|
RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E,
|
||||||
|
|
|
@ -44,10 +44,10 @@ int main() {
|
||||||
delete node;
|
delete node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LP64: __ZN4NodeIP12BinomialNodeIiEEC1Ev:
|
// CHECK-LP64: __ZN4NodeIP12BinomialNodeIiEEC2Ev:
|
||||||
// CHECK-LP64: __ZN4ListIP12BinomialNodeIiEEC1Ev:
|
// CHECK-LP64: __ZN4ListIP12BinomialNodeIiEEC1Ev:
|
||||||
// CHECK-LP64: __ZN4ListIP12BinomialNodeIiEED1Ev:
|
// CHECK-LP64: __ZN4ListIP12BinomialNodeIiEED1Ev:
|
||||||
|
|
||||||
// CHECK-LP32: __ZN4NodeIP12BinomialNodeIiEEC1Ev:
|
// CHECK-LP32: __ZN4NodeIP12BinomialNodeIiEEC2Ev:
|
||||||
// CHECK-LP32: __ZN4ListIP12BinomialNodeIiEEC1Ev:
|
// CHECK-LP32: __ZN4ListIP12BinomialNodeIiEEC1Ev:
|
||||||
// CHECK-LP32: __ZN4ListIP12BinomialNodeIiEED1Ev:
|
// CHECK-LP32: __ZN4ListIP12BinomialNodeIiEED1Ev:
|
||||||
|
|
|
@ -5,4 +5,4 @@ struct A { A(int x = 2); };
|
||||||
struct B : public A {};
|
struct B : public A {};
|
||||||
B x;
|
B x;
|
||||||
|
|
||||||
// CHECK: call void @_ZN1AC1Ei
|
// CHECK: call void @_ZN1AC2Ei
|
||||||
|
|
|
@ -8,15 +8,15 @@ struct B : A {
|
||||||
virtual ~B();
|
virtual ~B();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Complete dtor.
|
||||||
|
// CHECK: define void @_ZN1BD1Ev
|
||||||
|
// CHECK: call void @_ZN1AD2Ev
|
||||||
|
|
||||||
// Deleting dtor.
|
// Deleting dtor.
|
||||||
// CHECK: define void @_ZN1BD0Ev
|
// CHECK: define void @_ZN1BD0Ev
|
||||||
// CHECK: call void @_ZN1AD2Ev
|
// CHECK: call void @_ZN1AD2Ev
|
||||||
// check: call void @_ZdlPv
|
// check: call void @_ZdlPv
|
||||||
|
|
||||||
// Complete dtor.
|
|
||||||
// CHECK: define void @_ZN1BD1Ev
|
|
||||||
// CHECK: call void @_ZN1AD2Ev
|
|
||||||
|
|
||||||
// Base dtor.
|
// Base dtor.
|
||||||
// CHECK: define void @_ZN1BD2Ev
|
// CHECK: define void @_ZN1BD2Ev
|
||||||
// CHECK: call void @_ZN1AD2Ev
|
// CHECK: call void @_ZN1AD2Ev
|
||||||
|
|
Загрузка…
Ссылка в новой задаче