]> granicus.if.org Git - clang/commitdiff
Keep track of, and dump, vtable address points.
authorAnders Carlsson <andersca@mac.com>
Thu, 11 Feb 2010 17:18:51 +0000 (17:18 +0000)
committerAnders Carlsson <andersca@mac.com>
Thu, 11 Feb 2010 17:18:51 +0000 (17:18 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95874 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 5d3944f6dd018529e5b5f7ce8388cc3e766f99ad..d2b6c08712ed2db5f5eeb9fe2414b379fd77f9df 100644 (file)
@@ -132,6 +132,9 @@ class VtableBuilder {
   /// Components - The components of the vtable being built.
   llvm::SmallVector<VtableComponent, 64> Components;
 
+  /// AddressPoints - Address points for the vtable being built.
+  CGVtableInfo::AddressPointsMapTy AddressPoints;
+
   /// layoutSimpleVtable - A test function that will layout very simple vtables
   /// without any bases. Just used for testing for now.
   void layoutSimpleVtable(const CXXRecordDecl *RD);
@@ -159,6 +162,9 @@ void VtableBuilder::layoutSimpleVtable(const CXXRecordDecl *RD) {
   // Next, add the RTTI.
   Components.push_back(VtableComponent::MakeRTTI(RD));
   
+  // Record the address point.
+  AddressPoints.insert(std::make_pair(BaseSubobject(RD, 0), Components.size()));
+
   // Now go through all virtual member functions and add them.
   for (CXXRecordDecl::method_iterator I = RD->method_begin(),
        E = RD->method_end(); I != E; ++I) {
@@ -178,9 +184,34 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
   Out << "Vtable for '" << MostDerivedClass->getQualifiedNameAsString();
   Out << "' (" << Components.size() << " entries).\n";
 
+  // Iterate through the address points and insert them into a new map where
+  // they are keyed by the index and not the base object.
+  // Since an address point can be shared by multiple subobjects, we use an
+  // STL multimap.
+  std::multimap<uint64_t, BaseSubobject> AddressPointsByIndex;
+  for (CGVtableInfo::AddressPointsMapTy::const_iterator I = 
+       AddressPoints.begin(), E = AddressPoints.end(); I != E; ++I) {
+    const BaseSubobject& Base = I->first;
+    uint64_t Index = I->second;
+    
+    AddressPointsByIndex.insert(std::make_pair(Index, Base));
+  }
+  
   for (unsigned I = 0, E = Components.size(); I != E; ++I) {
+    if (AddressPointsByIndex.count(I)) {
+      assert(AddressPointsByIndex.count(I) == 1 &&
+             "FIXME: Handle dumping multiple base subobjects for a single "
+             "address point!");
+      
+      const BaseSubobject &Base = AddressPointsByIndex.find(I)->second;
+      Out << "       -- (" << Base.getBase()->getQualifiedNameAsString();
+      
+      // FIXME: Instead of dividing by 8, we should be using CharUnits.
+      Out << ", " << Base.getBaseOffset() / 8 << ") vtable address --\n";
+    }
+
     Out << llvm::format("%4d | ", I);
-    
+
     const VtableComponent &Component = Components[I];
 
     // Dump the component.
@@ -207,7 +238,7 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) {
     }
 
     }
-    
+
     Out << '\n';
   }
   
index 6bfa025beaab78d73535040fa1dc7971c8aa8b58..beb82ef90548f87e102148baf15e67ece9fdc9e0 100644 (file)
@@ -4,6 +4,7 @@ namespace Test1 {
 // CHECK:      Vtable for 'Test1::A' (3 entries).
 // CHECK-NEXT:   0 | offset_to_top (0)
 // CHECK-NEXT:   1 | Test1::A RTTI
+// CHECK-NEXT:       -- (Test1::A, 0) vtable address --
 // CHECK-NEXT:   2 | Test1::A::f
 struct A {
   virtual void f();