forked from OSchip/llvm-project
Add code to setup the vtable pointer in the constructor. Work in progress.
llvm-svn: 77699
This commit is contained in:
parent
fe6bbd1145
commit
bc78a728ee
|
@ -377,6 +377,8 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
|
|||
if (ClassTemplateDecl *TD = getParent()->getDescribedClassTemplate())
|
||||
ClassTy = TD->getInjectedClassNameType(C);
|
||||
else
|
||||
// FIXME: What is the design on getTagDeclType when it requires casting
|
||||
// away const? mutable?
|
||||
ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(getParent()));
|
||||
ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
|
||||
return C.getPointerType(ClassTy);
|
||||
|
|
|
@ -27,7 +27,7 @@ ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
|
|||
void ASTRecordLayoutBuilder::LayoutVtable(const CXXRecordDecl *RD) {
|
||||
if (RD->isPolymorphic() || RD->getNumVBases())
|
||||
{
|
||||
assert (RD->getNumBases() == 0 && "no polymorphic inheritance yet");
|
||||
// assert (RD->getNumBases() == 0 && "no polymorphic inheritance yet");
|
||||
int AS = 0;
|
||||
UpdateAlignment(Ctx.Target.getPointerAlign(AS));
|
||||
Size += Ctx.Target.getPointerWidth(AS);
|
||||
|
|
|
@ -107,8 +107,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) {
|
|||
|
||||
const FunctionProtoType *FPT = MD->getType()->getAsFunctionProtoType();
|
||||
|
||||
// FIXME: It isn't just virtual as written, but all virtual functions.
|
||||
if (MD->isVirtualAsWritten()) {
|
||||
if (MD->isVirtual()) {
|
||||
ErrorUnsupported(CE, "virtual dispatch");
|
||||
}
|
||||
|
||||
|
@ -491,21 +490,54 @@ const char *CodeGenModule::getMangledCXXDtorName(const CXXDestructorDecl *D,
|
|||
return UniqueMangledName(Name.begin(), Name.end());
|
||||
}
|
||||
|
||||
llvm::Value *CodeGenFunction::GenerateVtable(const CXXRecordDecl *RD) {
|
||||
const llvm::FunctionType *FTy;
|
||||
FTy = llvm::FunctionType::get(llvm::Type::VoidTy,
|
||||
std::vector<const llvm::Type*>(), false);
|
||||
|
||||
llvm::SmallString<256> OutName;
|
||||
llvm::raw_svector_ostream Out(OutName);
|
||||
QualType ClassTy;
|
||||
// FIXME: What is the design on getTagDeclType when it requires casting
|
||||
// away const? mutable?
|
||||
ClassTy = getContext().getTagDeclType(const_cast<CXXRecordDecl*>(RD));
|
||||
mangleCXXVtable(ClassTy, getContext(), Out);
|
||||
const char *Name = OutName.c_str();
|
||||
llvm::Value *vtable = CGM.CreateRuntimeFunction(FTy, Name);
|
||||
llvm::SmallVector<CXXMethodDecl *,32> methods;
|
||||
typedef CXXRecordDecl::method_iterator meth_iter;
|
||||
for (meth_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;
|
||||
++mi) {
|
||||
if (mi->isVirtual())
|
||||
methods.push_back(*mi);
|
||||
}
|
||||
|
||||
llvm::Type *Ptr8Ty;
|
||||
Ptr8Ty = llvm::PointerType::get(llvm::Type::Int8Ty, 0);
|
||||
vtable = Builder.CreateBitCast(vtable, Ptr8Ty);
|
||||
// FIXME: finish layout for virtual bases and fix for 32-bit
|
||||
int64_t offset = 16;
|
||||
vtable = Builder.CreateGEP(vtable,
|
||||
llvm::ConstantInt::get(llvm::Type::Int64Ty,
|
||||
offset));
|
||||
return vtable;
|
||||
}
|
||||
|
||||
/// EmitCtorPrologue - This routine generates necessary code to initialize
|
||||
/// base classes and non-static data members belonging to this constructor.
|
||||
void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) {
|
||||
const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(CD->getDeclContext());
|
||||
assert(!ClassDecl->isPolymorphic()
|
||||
&& "FIXME: virtual table initialization unsupported");
|
||||
assert(ClassDecl->getNumVBases() == 0
|
||||
&& "FIXME: virtual base initialization unsupported");
|
||||
llvm::Value *LoadOfThis = 0;
|
||||
|
||||
|
||||
for (CXXConstructorDecl::init_const_iterator B = CD->init_begin(),
|
||||
E = CD->init_end();
|
||||
B != E; ++B) {
|
||||
CXXBaseOrMemberInitializer *Member = (*B);
|
||||
if (Member->isBaseInitializer()) {
|
||||
llvm::Value *LoadOfThis = LoadCXXThis();
|
||||
LoadOfThis = LoadCXXThis();
|
||||
Type *BaseType = Member->getBaseClass();
|
||||
CXXRecordDecl *BaseClassDecl =
|
||||
cast<CXXRecordDecl>(BaseType->getAs<RecordType>()->getDecl());
|
||||
|
@ -522,7 +554,7 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) {
|
|||
assert(!getContext().getAsArrayType(FieldType)
|
||||
&& "FIXME. Field arrays initialization unsupported");
|
||||
|
||||
llvm::Value *LoadOfThis = LoadCXXThis();
|
||||
LoadOfThis = LoadCXXThis();
|
||||
LValue LHS = EmitLValueForField(LoadOfThis, Field, false, 0);
|
||||
if (FieldType->getAs<RecordType>()) {
|
||||
|
||||
|
@ -544,6 +576,19 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD) {
|
|||
EmitStoreThroughLValue(RValue::get(RHS), LHS, FieldType);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the vtable pointer
|
||||
if (ClassDecl->isPolymorphic() || ClassDecl->getNumVBases()) {
|
||||
if (!LoadOfThis)
|
||||
LoadOfThis = LoadCXXThis();
|
||||
llvm::Value *VtableField;
|
||||
llvm::Type *Ptr8Ty, *PtrPtr8Ty;
|
||||
Ptr8Ty = llvm::PointerType::get(llvm::Type::Int8Ty, 0);
|
||||
PtrPtr8Ty = llvm::PointerType::get(Ptr8Ty, 0);
|
||||
VtableField = Builder.CreateBitCast(LoadOfThis, PtrPtr8Ty);
|
||||
llvm::Value *vtable = GenerateVtable(ClassDecl);
|
||||
Builder.CreateStore(vtable, VtableField);
|
||||
}
|
||||
}
|
||||
|
||||
/// EmitDtorEpilogue - Emit all code that comes at the end of class's
|
||||
|
|
|
@ -358,6 +358,8 @@ public:
|
|||
/// legal to call this function even if there is no current insertion point.
|
||||
void FinishFunction(SourceLocation EndLoc=SourceLocation());
|
||||
|
||||
llvm::Value *GenerateVtable(const CXXRecordDecl *RD);
|
||||
|
||||
void EmitCtorPrologue(const CXXConstructorDecl *CD);
|
||||
|
||||
/// EmitDtorEpilogue - Emit all code that comes at the end of class's
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace {
|
|||
bool mangle(const NamedDecl *D);
|
||||
void mangleGuardVariable(const VarDecl *D);
|
||||
|
||||
void mangleCXXVtable(QualType Type);
|
||||
void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type);
|
||||
void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type);
|
||||
|
||||
|
@ -158,10 +159,16 @@ void CXXNameMangler::mangleCXXDtor(const CXXDestructorDecl *D,
|
|||
mangle(D);
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleCXXVtable(QualType T) {
|
||||
// <special-name> ::= TV <type> # virtual table
|
||||
Out << "_ZTV";
|
||||
mangleType(T);
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleGuardVariable(const VarDecl *D)
|
||||
{
|
||||
// <special-name> ::= GV <object name> # Guard variable for one-time
|
||||
// # initialization
|
||||
// # initialization
|
||||
|
||||
Out << "_ZGV";
|
||||
mangleName(D);
|
||||
|
@ -808,6 +815,11 @@ namespace clang {
|
|||
os.flush();
|
||||
}
|
||||
|
||||
void mangleCXXVtable(QualType Type, ASTContext &Context,
|
||||
llvm::raw_ostream &os) {
|
||||
CXXNameMangler Mangler(Context, os);
|
||||
Mangler.mangleCXXVtable(Type);
|
||||
|
||||
os.flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define LLVM_CLANG_CODEGEN_MANGLE_H
|
||||
|
||||
#include "CGCXX.h"
|
||||
#include "clang/AST/Type.h"
|
||||
|
||||
namespace llvm {
|
||||
class raw_ostream;
|
||||
|
@ -35,6 +36,7 @@ namespace clang {
|
|||
llvm::raw_ostream &os);
|
||||
void mangleGuardVariable(const VarDecl *D, ASTContext &Context,
|
||||
llvm::raw_ostream &os);
|
||||
void mangleCXXVtable(QualType T, ASTContext &Context, llvm::raw_ostream &os);
|
||||
void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
|
||||
ASTContext &Context, llvm::raw_ostream &os);
|
||||
void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
|
||||
|
|
Loading…
Reference in New Issue