From 28cbc8b512db420748601dba276144d729a0d7a2 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Fri, 12 Feb 2010 07:43:48 +0000 Subject: [PATCH] Keep track of the address points for all primary bases, and add the ability to dump multiple address points for a single offset. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95970 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGVtable.cpp | 59 +++++++++++++++++++++++++------ test/CodeGenCXX/vtable-layout.cpp | 4 +++ 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index e2ea4736d3..226be1972e 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -16,6 +16,7 @@ #include "clang/AST/CXXInheritance.h" #include "clang/AST/RecordLayout.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/Format.h" #include @@ -608,14 +609,26 @@ void VtableBuilder::layoutSimpleVtable(BaseSubobject Base) { // Next, add the RTTI. Components.push_back(VtableComponent::MakeRTTI(RD)); - // Record the address point. - // FIXME: Record the address point for all primary bases. - AddressPoints.insert(std::make_pair(Base, Components.size())); + uint64_t AddressPoint = Components.size(); // Now go through all virtual member functions and add them. PrimaryBasesSetTy PrimaryBases; layoutVirtualMemberFunctions(Base, PrimaryBases); + // Record the address point. + AddressPoints.insert(std::make_pair(Base, AddressPoint)); + + // Record the address points for all primary bases. + for (PrimaryBasesSetTy::const_iterator I = PrimaryBases.begin(), + E = PrimaryBases.end(); I != E; ++I) { + const CXXRecordDecl *BaseDecl = *I; + + // We know that all the primary bases have the same offset as the base + // subobject. + BaseSubobject PrimaryBase(BaseDecl, Base.getBaseOffset()); + AddressPoints.insert(std::make_pair(PrimaryBase, AddressPoint)); + } + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); const CXXRecordDecl *PrimaryBase = Layout.getPrimaryBase(); @@ -655,16 +668,40 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) { } for (unsigned I = 0, E = Components.size(); I != E; ++I) { + uint64_t Index = 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(); + std::string Str; + - // FIXME: Instead of dividing by 8, we should be using CharUnits. - Out << ", " << Base.getBaseOffset() / 8 << ") vtable address --\n"; + if (AddressPointsByIndex.count(Index) == 1) { + const BaseSubobject &Base = AddressPointsByIndex.find(Index)->second; + + // FIXME: Instead of dividing by 8, we should be using CharUnits. + Out << " -- (" << Base.getBase()->getQualifiedNameAsString(); + Out << ", " << Base.getBaseOffset() / 8 << ") vtable address --\n"; + } else { + uint64_t BaseOffset = + AddressPointsByIndex.lower_bound(Index)->second.getBaseOffset(); + + // We store the class names in a set to get a stable order. + std::set ClassNames; + for (std::multimap::const_iterator I = + AddressPointsByIndex.lower_bound(Index), E = + AddressPointsByIndex.upper_bound(Index); I != E; ++I) { + assert(I->second.getBaseOffset() == BaseOffset && + "Invalid base offset!"); + const CXXRecordDecl *RD = I->second.getBase(); + ClassNames.insert(RD->getQualifiedNameAsString()); + } + + for (std::set::const_iterator I = ClassNames.begin(), + E = ClassNames.end(); I != E; ++I) { + // FIXME: Instead of dividing by 8, we should be using CharUnits. + Out << " -- (" << *I; + Out << ", " << BaseOffset / 8 << ") vtable address --\n"; + } + } } Out << llvm::format("%4d | ", I); diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index 6cc1b0b691..b9054410a9 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -76,6 +76,7 @@ void A::f() { } // CHECK: Vtable for 'Test3::B' (4 entries). // CHECK-NEXT: 0 | offset_to_top (0) // CHECK-NEXT: 1 | Test3::B RTTI +// CHECK-NEXT: -- (Test3::A, 0) vtable address -- // CHECK-NEXT: -- (Test3::B, 0) vtable address -- // CHECK-NEXT: 2 | void Test3::A::f() // CHECK-NEXT: 3 | void Test3::B::g() @@ -88,6 +89,7 @@ void B::f() { } // CHECK: Vtable for 'Test3::C' (5 entries). // CHECK-NEXT: 0 | offset_to_top (0) // CHECK-NEXT: 1 | Test3::C RTTI +// CHECK-NEXT: -- (Test3::A, 0) vtable address -- // CHECK-NEXT: -- (Test3::C, 0) vtable address -- // CHECK-NEXT: 2 | void Test3::A::f() // CHECK-NEXT: 3 | void Test3::C::g() @@ -101,6 +103,8 @@ void C::g() { } // CHECK: Vtable for 'Test3::D' (5 entries). // CHECK-NEXT: 0 | offset_to_top (0) // CHECK-NEXT: 1 | Test3::D RTTI +// CHECK-NEXT: -- (Test3::A, 0) vtable address -- +// CHECK-NEXT: -- (Test3::B, 0) vtable address -- // CHECK-NEXT: -- (Test3::D, 0) vtable address -- // CHECK-NEXT: 2 | void Test3::A::f() // CHECK-NEXT: 3 | void Test3::B::g() -- 2.40.0