]> granicus.if.org Git - clang/commitdiff
Add code to setup the vtable pointer in the constructor. Work in progress.
authorMike Stump <mrs@apple.com>
Fri, 31 Jul 2009 18:25:34 +0000 (18:25 +0000)
committerMike Stump <mrs@apple.com>
Fri, 31 Jul 2009 18:25:34 +0000 (18:25 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77699 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/DeclCXX.cpp
lib/AST/RecordLayoutBuilder.cpp
lib/CodeGen/CGCXX.cpp
lib/CodeGen/CodeGenFunction.h
lib/CodeGen/CodeGenModule.h
lib/CodeGen/Mangle.cpp
lib/CodeGen/Mangle.h

index 11c7e6dfc2b012b11da61add0ecd9c93379dd052..cc481be6ba89a83f2eec1c1dde56a32f52112d13 100644 (file)
@@ -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);
@@ -652,7 +654,7 @@ CXXConstructorDecl::setBaseOrMemberInitializers(
       AllToInit.push_back(Member);
     } 
   }
-  
+
   NumInitializers = AllToInit.size();
   if (NumInitializers > 0) {
     NumBaseOrMemberInitializers = NumInitializers;
index 41bd521331d8f0f44ed1045c062bfa5180c78b4d..901d5a5b26f3f164c6ec59a378d380a34fc670b3 100644 (file)
@@ -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);
index 4d48f0801fbdee2b6f379471d1af6ebf4b7ad2bf..88d36a2c00773897eba2e874f4a33f065156dcd1 100644 (file)
@@ -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
index 4f8a14af142f4f170dc19f0cf305270f54565c51..5661343c134d6777482c0a49c46a046106e1ad29 100644 (file)
@@ -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
index 46caaaf3c1290999956efc7a7e8cd8abbc79d2f2..c7437d18efd27925a52daf4746564dce7cded6f6 100644 (file)
@@ -373,7 +373,7 @@ public:
                                     CXXDtorType Type);
 
   void EmitTentativeDefinition(const VarDecl *D);
-  
+
   enum GVALinkage {
     GVA_Internal,
     GVA_C99Inline,
index 9e389040b8185955c1cac2e360304f7958f4ecbc..36ee2a422223b8a384834662d1aae8d02d9e8753 100644 (file)
@@ -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);
@@ -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();
+  }
+}
index 77cbd9775191669476b0725f4c0fea93c9422e92..1a5ca63c50bc92f0254f8ec97354205457139d77 100644 (file)
@@ -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,