]> granicus.if.org Git - clang/commitdiff
Emit vbase offsets.
authorAnders Carlsson <andersca@mac.com>
Tue, 16 Feb 2010 04:59:55 +0000 (04:59 +0000)
committerAnders Carlsson <andersca@mac.com>
Tue, 16 Feb 2010 04:59:55 +0000 (04:59 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96329 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGVtable.cpp
test/CodeGenCXX/vtable-layout.cpp

index 9233838c93bf8f608680566f0072a6daf59f2d0d..970bbd777f1418662ca94628e8391bb8267c615d 100644 (file)
@@ -912,6 +912,27 @@ VtableBuilder::AddVCallAndVBaseOffsets(const CXXRecordDecl *RD,
 void VtableBuilder::AddVBaseOffsets(const CXXRecordDecl *RD,
                                     int64_t OffsetToTop,
                                     VisitedVirtualBasesSetTy &VBases) {
+  const ASTRecordLayout &MostDerivedClassLayout = 
+    Context.getASTRecordLayout(MostDerivedClass);
+
+  // Add vbase offsets.
+  for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
+       E = RD->bases_end(); I != E; ++I) {
+    const CXXRecordDecl *BaseDecl =
+      cast<CXXRecordDecl>(I->getType()->getAs<RecordType>()->getDecl());
+
+    // Check if this is a virtual base that we haven't visited before.
+    if (I->isVirtual() && VBases.insert(BaseDecl)) {
+      // FIXME: We shouldn't use / 8 here.
+      uint64_t Offset = 
+        OffsetToTop + MostDerivedClassLayout.getVBaseClassOffset(BaseDecl) / 8;
+    
+      VCallAndVBaseOffsets.push_back(VtableComponent::MakeVBaseOffset(Offset));
+    }
+    
+    // Check the base class looking for more vbase offsets.
+    AddVBaseOffsets(BaseDecl, OffsetToTop, VBases);
+  }
 }
 
 void 
@@ -1008,13 +1029,22 @@ VtableBuilder::AddMethods(BaseSubobject Base, PrimaryBasesSetTy &PrimaryBases) {
 
 void VtableBuilder::LayoutVtable(BaseSubobject Base) {
   const CXXRecordDecl *RD = Base.getBase();
-
   assert(RD->isDynamicClass() && "class does not have a vtable!");
 
-  // First, add the offset to top.
+  int64_t OffsetToTop = -(int64_t)Base.getBaseOffset() / 8;
+
+  // Add vcall and vbase offsets for this vtable.
+  VisitedVirtualBasesSetTy VBases;
+  AddVCallAndVBaseOffsets(RD, OffsetToTop, VBases);
+
+  // Reverse them and add them to the vtable components.
+  std::reverse(VCallAndVBaseOffsets.begin(), VCallAndVBaseOffsets.end());
+  Components.append(VCallAndVBaseOffsets.begin(), VCallAndVBaseOffsets.end());
+  VCallAndVBaseOffsets.clear();
+  
+  // Add the offset to top.
   // FIXME: This is not going to be right for construction vtables.
   // FIXME: We should not use / 8 here.
-  int64_t OffsetToTop = -(int64_t)Base.getBaseOffset() / 8;
   Components.push_back(VtableComponent::MakeOffsetToTop(OffsetToTop));
   
   // Next, add the RTTI.
@@ -1137,7 +1167,11 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
     default:
       assert(false && "Unhandled component kind!");
       break;
-      
+
+    case VtableComponent::CK_VBaseOffset:
+      Out << "vbase_offset (" << Component.getVBaseOffset() << ")";
+      break;
+
     case VtableComponent::CK_OffsetToTop:
       Out << "offset_to_top (" << Component.getOffsetToTop() << ")";
       break;
index a41aad41f9be26cdfc9ea5c04833185e7ee695c2..8fbe486faa473dd0d27ed0935e98ba6a933abdca 100644 (file)
@@ -340,3 +340,28 @@ struct B : A {
 void B::f() { }
 
 }
+
+namespace Test9 {
+
+// Simple test of vbase offsets.
+
+struct A1 { int a1; };
+struct A2 { int a2; };
+
+// CHECK:     Vtable for 'Test9::B' (5 entries).
+// CHECK-NEXT:   0 | vbase_offset (16)
+// CHECK-NEXT:   1 | vbase_offset (12)
+// CHECK-NEXT:   2 | offset_to_top (0)
+// CHECK-NEXT:   3 | Test9::B RTTI
+// CHECK-NEXT:       -- (Test9::B, 0) vtable address --
+// CHECK-NEXT:   4 | void Test9::B::f()
+struct B : virtual A1, virtual A2 {
+  int b;
+
+  virtual void f();
+};
+
+
+void B::f() { }
+
+}