From: Anders Carlsson Date: Thu, 18 Mar 2010 02:44:19 +0000 (+0000) Subject: When dumping vtables, also dump the thunks. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9135a84d8e2c835d8b39c92eb15e8e9034b80bad;p=clang When dumping vtables, also dump the thunks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98799 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index b0c580faaa..df30f479ac 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -1233,10 +1233,11 @@ private: ThunksInfoMapTy Thunks; typedef llvm::DenseMap > ThunksForMethodMapTy; + llvm::SmallVector > MethodThunksMapTy; - /// ThunksPerMethod - The thunks for a given method. - ThunksForMethodMapTy ThunksForMethod; + /// MethodThunks - A map that contains all the thunks needed for all methods + /// in the vtable currently being built. + MethodThunksMapTy MethodThunks; /// AddThunk - Add a thunk for the given method. void AddThunk(const CXXMethodDecl *MD, ThunkInfo &Thunk); @@ -1357,7 +1358,10 @@ public: }; void VtableBuilder::AddThunk(const CXXMethodDecl *MD, ThunkInfo &Thunk) { - llvm::SmallVector &ThunksVector = ThunksForMethod[MD]; + if (isBuildingConstructorVtable()) + return; + + llvm::SmallVector &ThunksVector = MethodThunks[MD]; // Check if we have this thunk already. if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) != @@ -1419,6 +1423,8 @@ void VtableBuilder::ComputeThisAdjustments() { // Add an adjustment for the deleting destructor as well. Thunks[VtableIndex + 1].This = ThisAdjustment; } + + AddThunk(Overrider.Method, Thunks[VtableIndex]); } /// Clear the method info map. @@ -2219,20 +2225,25 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) { Out << '\n'; - if (!isBuildingConstructorVtable() && MostDerivedClass->getNumVBases()) { - Out << "Virtual base offset offsets for '"; - Out << MostDerivedClass->getQualifiedNameAsString() << "'.\n"; - + if (isBuildingConstructorVtable()) + return; + + if (MostDerivedClass->getNumVBases()) { // We store the virtual base class names and their offsets in a map to get // a stable order. - std::map ClassNamesAndOffsets; + std::map ClassNamesAndOffsets; for (VBaseOffsetOffsetsMapTy::const_iterator I = VBaseOffsetOffsets.begin(), E = VBaseOffsetOffsets.end(); I != E; ++I) { std::string ClassName = I->first->getQualifiedNameAsString(); int64_t OffsetOffset = I->second; ClassNamesAndOffsets.insert(std::make_pair(ClassName, OffsetOffset)); } + + Out << "Virtual base offset offsets for '"; + Out << MostDerivedClass->getQualifiedNameAsString() << "' ("; + Out << ClassNamesAndOffsets.size(); + Out << (ClassNamesAndOffsets.size() == 1 ? " entry" : " entries") << ").\n"; for (std::map::const_iterator I = ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end(); @@ -2241,6 +2252,52 @@ void VtableBuilder::dumpLayout(llvm::raw_ostream& Out) { Out << "\n"; } + + if (!MethodThunks.empty()) { + + // We store the method names in a map to get a stable order. + std::map MethodNamesAndDecls; + + for (MethodThunksMapTy::const_iterator I = MethodThunks.begin(), + E = MethodThunks.end(); I != E; ++I) { + const CXXMethodDecl *MD = I->first; + std::string MethodName = + PredefinedExpr::ComputeName(PredefinedExpr::PrettyFunctionNoVirtual, + MD); + + MethodNamesAndDecls.insert(std::make_pair(MethodName, MD)); + } + + for (std::map::const_iterator I = + MethodNamesAndDecls.begin(), E = MethodNamesAndDecls.end(); + I != E; ++I) { + const std::string &MethodName = I->first; + const CXXMethodDecl *MD = I->second; + const llvm::SmallVector &ThunksVector = MethodThunks[MD]; + + Out << "Thunks for '" << MethodName << "' (" << ThunksVector.size(); + Out << (ThunksVector.size() == 1 ? " entry" : " entries") << ").\n"; + + for (unsigned I = 0, E = ThunksVector.size(); I != E; ++I) { + const ThunkInfo &Thunk = ThunksVector[I]; + + Out << llvm::format("%4d | ", I); + + // If this function pointer has a 'this' pointer adjustment, dump it. + if (!Thunk.This.isEmpty()) { + Out << "this: "; + Out << Thunk.This.NonVirtual << " nv"; + + if (Thunk.This.VCallOffsetOffset) { + Out << ", " << Thunk.This.VCallOffsetOffset; + Out << " v"; + } + } + + Out << '\n'; + } + } + } } } diff --git a/test/CodeGenCXX/vtable-layout.cpp b/test/CodeGenCXX/vtable-layout.cpp index f11ae345cc..bc3d54b8e4 100644 --- a/test/CodeGenCXX/vtable-layout.cpp +++ b/test/CodeGenCXX/vtable-layout.cpp @@ -887,8 +887,8 @@ class E : virtual C { }; // CHECK-NEXT: -- (Test21::E, 8) vtable address -- // CHECK-NEXT: 15 | [unused] void Test21::F::f() // -// CHECK: Virtual base offset offsets for 'Test21::F'. -// CHECK-NEXT: Test21::A | -32 +// CHECK: Virtual base offset offsets for 'Test21::F' (5 entries). +// CHECK-NEXT: Test21::A | -32 // CHECK-NEXT: Test21::B | -40 // CHECK-NEXT: Test21::C | -48 // CHECK-NEXT: Test21::D | -56