From: Mike Stump Date: Fri, 31 Jul 2009 18:25:34 +0000 (+0000) Subject: Add code to setup the vtable pointer in the constructor. Work in progress. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f121677b6bbbf4e4a51ee7a1120b77adf187bad4;p=clang Add code to setup the vtable pointer in the constructor. Work in progress. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77699 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 11c7e6dfc2..cc481be6ba 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -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(getParent())); ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers()); return C.getPointerType(ClassTy); @@ -652,7 +654,7 @@ CXXConstructorDecl::setBaseOrMemberInitializers( AllToInit.push_back(Member); } } - + NumInitializers = AllToInit.size(); if (NumInitializers > 0) { NumBaseOrMemberInitializers = NumInitializers; diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 41bd521331..901d5a5b26 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -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); diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 4d48f0801f..88d36a2c00 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -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(), 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(RD)); + mangleCXXVtable(ClassTy, getContext(), Out); + const char *Name = OutName.c_str(); + llvm::Value *vtable = CGM.CreateRuntimeFunction(FTy, Name); + llvm::SmallVector 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(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(BaseType->getAs()->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()) { @@ -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 diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 4f8a14af14..5661343c13 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -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 diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 46caaaf3c1..c7437d18ef 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -373,7 +373,7 @@ public: CXXDtorType Type); void EmitTentativeDefinition(const VarDecl *D); - + enum GVALinkage { GVA_Internal, GVA_C99Inline, diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 9e389040b8..36ee2a4222 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -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) { + // ::= TV # virtual table + Out << "_ZTV"; + mangleType(T); +} + void CXXNameMangler::mangleGuardVariable(const VarDecl *D) { // ::= GV # Guard variable for one-time - // # initialization + // # initialization Out << "_ZGV"; mangleName(D); @@ -807,7 +814,12 @@ namespace clang { os.flush(); } - - -} + void mangleCXXVtable(QualType Type, ASTContext &Context, + llvm::raw_ostream &os) { + CXXNameMangler Mangler(Context, os); + Mangler.mangleCXXVtable(Type); + + os.flush(); + } +} diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index 77cbd97751..1a5ca63c50 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -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,