More vtable work; preparations for moving over to the new vtable layout code (finally).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99381 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 4d5fdfe..af84632 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -1560,9 +1560,10 @@
   if (!ClassDecl->isDynamicClass())
     return;
 
-  llvm::Constant *VTable = CGM.getVTables().getVtable(ClassDecl);
-  CodeGenVTables::AddrSubMap_t& AddressPoints =
-      *(*CGM.getVTables().AddressPoints[ClassDecl])[ClassDecl];
+  llvm::Constant *VTable = CGM.getVTables().getAddrOfVTable(ClassDecl);
+  const CodeGenVTables::AddrSubMap_t& AddressPoints =
+    CGM.getVTables().getAddressPoints(ClassDecl);
+
   llvm::Value *ThisPtr = LoadCXXThis();
   const ASTRecordLayout &Layout = getContext().getASTRecordLayout(ClassDecl);
 
@@ -1584,7 +1585,7 @@
 void CodeGenFunction::InitializeVtablePtrsRecursive(
         const CXXRecordDecl *ClassDecl,
         llvm::Constant *Vtable,
-        CodeGenVTables::AddrSubMap_t& AddressPoints,
+        const CodeGenVTables::AddrSubMap_t& AddressPoints,
         llvm::Value *ThisPtr,
         uint64_t Offset) {
   if (!ClassDecl->isDynamicClass())
@@ -1607,7 +1608,8 @@
   // Compute the address point
   assert(AddressPoints.count(std::make_pair(ClassDecl, Offset)) &&
          "Missing address point for class");
-  uint64_t AddressPoint = AddressPoints[std::make_pair(ClassDecl, Offset)];
+  uint64_t AddressPoint = 
+    AddressPoints.lookup(std::make_pair(ClassDecl, Offset));
   llvm::Value *VtableAddressPoint =
       Builder.CreateConstInBoundsGEP2_64(Vtable, 0, AddressPoint);
 
diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp
index 990a5f6..b7b24b8 100644
--- a/lib/CodeGen/CGVTT.cpp
+++ b/lib/CodeGen/CGVTT.cpp
@@ -268,7 +268,7 @@
       GenerateDefinition(GenerateDefinition) {
     
     // First comes the primary virtual table pointer for the complete class...
-    ClassVtbl = GenerateDefinition ? CGM.getVTables().getVtable(Class) : 0;
+    ClassVtbl = GenerateDefinition ? CGM.getVTables().getAddrOfVTable(Class) :0;
 
     llvm::Constant *Init = BuildVtablePtr(ClassVtbl, Class, Class, 0);
     Inits.push_back(Init);
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp
index f492169..c9b099b 100644
--- a/lib/CodeGen/CGVtable.cpp
+++ b/lib/CodeGen/CGVtable.cpp
@@ -3551,6 +3551,19 @@
   return I->second;
 }
 
+const CodeGenVTables::AddrSubMap_t &
+CodeGenVTables::getAddressPoints(const CXXRecordDecl *RD) {
+  if (!AddressPoints[RD]) {
+    AddressPointsMapTy AddressPoints;
+    OldVtableBuilder b(RD, RD, 0, CGM, false, AddressPoints);
+    
+    b.GenerateVtableForBase(RD, 0);
+    b.GenerateVtableForVBases(RD, 0);
+  }
+  
+  return *(*AddressPoints[RD])[RD];
+}
+
 llvm::GlobalVariable *
 CodeGenVTables::GenerateVtable(llvm::GlobalVariable::LinkageTypes Linkage,
                                bool GenerateDefinition,
@@ -3583,8 +3596,7 @@
   llvm::StringRef Name = OutName.str();
 
   llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
-  if (GV == 0 || CGM.getVTables().AddressPoints[LayoutClass] == 0 || 
-      GV->isDeclaration()) {
+  if (GV == 0 || GV->isDeclaration()) {
     OldVtableBuilder b(RD, LayoutClass, Offset, CGM, GenerateDefinition,
                        AddressPoints);
 
@@ -3906,17 +3918,26 @@
   GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD);
 }
 
-llvm::GlobalVariable *CodeGenVTables::getVtable(const CXXRecordDecl *RD) {
-  llvm::GlobalVariable *Vtable = Vtables.lookup(RD);
-  
-  if (!Vtable) {
-    AddressPointsMapTy AddressPoints;
-    Vtable = GenerateVtable(llvm::GlobalValue::ExternalLinkage, 
-                            /*GenerateDefinition=*/false, RD, RD, 0,
-                            /*IsVirtual=*/false, AddressPoints);
-  }
+llvm::Constant *CodeGenVTables::getAddrOfVTable(const CXXRecordDecl *RD) {
+  llvm::SmallString<256> OutName;
+  CGM.getMangleContext().mangleCXXVtable(RD, OutName);
+  llvm::StringRef Name = OutName.str();
 
-  return Vtable;
+  const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
+  llvm::ArrayType *ArrayType = llvm::ArrayType::get(Int8PtrTy, 0);
+  
+  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
+  if (GV) {
+    if (!GV->isDeclaration() || GV->getType()->getElementType() == ArrayType)
+      return GV;
+  
+    return llvm::ConstantExpr::getBitCast(GV, ArrayType->getPointerTo());
+  }
+  
+  GV = new llvm::GlobalVariable(CGM.getModule(), ArrayType, /*isConstant=*/true,
+                                llvm::GlobalValue::ExternalLinkage, 0, Name);
+
+  return GV;
 }
 
 void CodeGenVTables::EmitVTableRelatedData(GlobalDecl GD) {
diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h
index ebccb51..a38153b 100644
--- a/lib/CodeGen/CGVtable.h
+++ b/lib/CodeGen/CGVtable.h
@@ -222,13 +222,17 @@
   typedef std::pair<const CXXRecordDecl *, uint64_t> CtorVtable_t;
   typedef llvm::DenseMap<CtorVtable_t, int64_t> AddrSubMap_t;
   typedef llvm::DenseMap<const CXXRecordDecl *, AddrSubMap_t *> AddrMap_t;
-  llvm::DenseMap<const CXXRecordDecl *, AddrMap_t*> AddressPoints;
 
   typedef llvm::DenseMap<BaseSubobject, uint64_t> AddressPointsMapTy;
 
+  const CodeGenVTables::AddrSubMap_t& getAddressPoints(const CXXRecordDecl *RD);
+
+  llvm::DenseMap<const CXXRecordDecl *, AddrMap_t*> AddressPoints;
+
 private:
   CodeGenModule &CGM;
 
+
   /// MethodVtableIndices - Contains the index (relative to the vtable address
   /// point) where the function pointer for a virtual function is stored.
   typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVtableIndicesTy;
@@ -312,8 +316,9 @@
   int64_t getVirtualBaseOffsetOffset(const CXXRecordDecl *RD,
                                      const CXXRecordDecl *VBase);
 
-  llvm::GlobalVariable *getVtable(const CXXRecordDecl *RD);
-  
+  /// getAddrOfVTable - Get the address of the vtable for the given record decl.
+  llvm::Constant *getAddrOfVTable(const CXXRecordDecl *RD);
+
   /// CtorVtableInfo - Information about a constructor vtable.
   struct CtorVtableInfo {
     /// Vtable - The vtable itself.
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index cc51045..f5c25b2 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -513,7 +513,7 @@
 
   void InitializeVtablePtrsRecursive(const CXXRecordDecl *ClassDecl,
                                      llvm::Constant *Vtable,
-                                    CodeGenVTables::AddrSubMap_t& AddressPoints,
+                              const CodeGenVTables::AddrSubMap_t& AddressPoints,
                                      llvm::Value *ThisPtr,
                                      uint64_t Offset);
 
diff --git a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
index 2f7c79b..4d40372 100644
--- a/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
+++ b/test/CodeGenCXX/copy-constructor-synthesis-2.cpp
@@ -4,4 +4,4 @@
 A x(A& y) { return y; }
 
 // CHECK: define linkonce_odr void @_ZN1AC1ERKS_(
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2)
+// CHECK: store i8** getelementptr inbounds ([0 x i8*]* @_ZTV1A, i64 0, i64 2)
diff --git a/test/CodeGenCXX/vtable-pointer-initialization.cpp b/test/CodeGenCXX/vtable-pointer-initialization.cpp
index 75620ab..bf8575a 100644
--- a/test/CodeGenCXX/vtable-pointer-initialization.cpp
+++ b/test/CodeGenCXX/vtable-pointer-initialization.cpp
@@ -21,13 +21,13 @@
 
 // CHECK: define void @_ZN1AC2Ev(
 // CHECK: call void @_ZN4BaseC2Ev(
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2)
+// CHECK: store i8** getelementptr inbounds ([0 x i8*]* @_ZTV1A, i64 0, i64 2)
 // CHECK: call void @_ZN5FieldC1Ev(
 // CHECK: ret void
 A::A() { }
 
 // CHECK: define void @_ZN1AD2Ev(
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2)
+// CHECK: store i8** getelementptr inbounds ([0 x i8*]* @_ZTV1A, i64 0, i64 2)
 // CHECK: call void @_ZN5FieldD1Ev(
 // CHECK: call void @_ZN4BaseD2Ev(
 // CHECK: ret void
@@ -45,13 +45,13 @@
 // CHECK: call void @_ZN1BC2Ev(
 
 // CHECK: define linkonce_odr void @_ZN1BD1Ev(
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2)
+// CHECK: store i8** getelementptr inbounds ([0 x i8*]* @_ZTV1B, i64 0, i64 2)
 // CHECK: call void @_ZN5FieldD1Ev(
 // CHECK: call void @_ZN4BaseD2Ev(
 // CHECK: ret void
 
 // CHECK: define linkonce_odr void @_ZN1BC2Ev(
 // CHECK: call void @_ZN4BaseC2Ev(
-// CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1B, i64 0, i64 2)
+// CHECK: store i8** getelementptr inbounds ([0 x i8*]* @_ZTV1B, i64 0, i64 2)
 // CHECK: call void @_ZN5FieldC1Ev
 // CHECK: ret void