diff options
| author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-03-21 10:50:08 +0000 | 
|---|---|---|
| committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-03-21 10:50:08 +0000 | 
| commit | c0c7bca4e5b8d12699dc93a0da49e9e4bb79671b (patch) | |
| tree | 508d4388db78f87d35bf26a0400b4b03bc4c1f13 /lib/CodeGen/CGVtable.cpp | |
| parent | 4a37f65f1c1373c9956d118a012943de2f61edb0 (diff) | |
Notes
Diffstat (limited to 'lib/CodeGen/CGVtable.cpp')
| -rw-r--r-- | lib/CodeGen/CGVtable.cpp | 108 | 
1 files changed, 101 insertions, 7 deletions
diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 9bcf986af8427..df30f479acc86 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -19,6 +19,7 @@  #include "llvm/ADT/SetVector.h"  #include "llvm/Support/Compiler.h"  #include "llvm/Support/Format.h" +#include <algorithm>  #include <cstdio>  using namespace clang; @@ -1147,6 +1148,12 @@ private:      ReturnAdjustment() : NonVirtual(0), VBaseOffsetOffset(0) { }      bool isEmpty() const { return !NonVirtual && !VBaseOffsetOffset; } + +    friend bool operator==(const ReturnAdjustment &LHS,  +                           const ReturnAdjustment &RHS) { +      return LHS.NonVirtual == RHS.NonVirtual &&  +        LHS.VBaseOffsetOffset == RHS.VBaseOffsetOffset; +    }    };    /// MethodInfo - Contains information about a method in a vtable. @@ -1191,6 +1198,12 @@ private:      ThisAdjustment() : NonVirtual(0), VCallOffsetOffset(0) { }      bool isEmpty() const { return !NonVirtual && !VCallOffsetOffset; } + +    friend bool operator==(const ThisAdjustment &LHS,  +                           const ThisAdjustment &RHS) { +      return LHS.NonVirtual == RHS.NonVirtual &&  +        LHS.VCallOffsetOffset == RHS.VCallOffsetOffset; +    }    };    /// ThunkInfo - The 'this' pointer adjustment as well as an optional return @@ -1206,8 +1219,12 @@ private:      ThunkInfo(const ThisAdjustment &This, const ReturnAdjustment &Return)        : This(This), Return(Return) { } -     -    bool isEmpty() const { return This.isEmpty() && Return.isEmpty(); }     +   +    friend bool operator==(const ThunkInfo &LHS, const ThunkInfo &RHS) { +      return LHS.This == RHS.This && LHS.Return == RHS.Return; +    } + +    bool isEmpty() const { return This.isEmpty() && Return.isEmpty(); }    };    typedef llvm::DenseMap<uint64_t, ThunkInfo> ThunksInfoMapTy; @@ -1215,6 +1232,16 @@ private:    /// Thunks - The thunks by vtable index in the vtable currently being built.    ThunksInfoMapTy Thunks; +  typedef llvm::DenseMap<const CXXMethodDecl *, +                         llvm::SmallVector<ThunkInfo, 1> > MethodThunksMapTy; +   +  /// 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); +      /// ComputeThisAdjustments - Compute the 'this' pointer adjustments for the    /// part of the vtable we're currently building.    void ComputeThisAdjustments(); @@ -1330,6 +1357,20 @@ public:    void dumpLayout(llvm::raw_ostream&);  }; +void VtableBuilder::AddThunk(const CXXMethodDecl *MD, ThunkInfo &Thunk) { +  if (isBuildingConstructorVtable()) +    return; + +  llvm::SmallVector<ThunkInfo, 1> &ThunksVector = MethodThunks[MD]; +   +  // Check if we have this thunk already. +  if (std::find(ThunksVector.begin(), ThunksVector.end(), Thunk) !=  +      ThunksVector.end()) +    return; +   +  ThunksVector.push_back(Thunk); +} +  /// OverridesMethodInBases - Checks whether whether this virtual member   /// function overrides a member function in any of the given bases.  /// Returns the overridden member function, or null if none was found. @@ -1382,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. @@ -2182,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<std::string, int64_t> ClassNamesAndOffsets; +    std::map<std::string, int64_t> 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<std::string, int64_t>::const_iterator I =           ClassNamesAndOffsets.begin(), E = ClassNamesAndOffsets.end();  @@ -2204,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<std::string, const CXXMethodDecl *> 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<std::string, const CXXMethodDecl *>::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<ThunkInfo, 1> &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'; +      } +    } +  }  }  }  | 
