C++程序  |  178行  |  4.8 KB

//===- FragmentGraph.h ----------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_FRAGMENTGRAPH_H
#define MCLD_FRAGMENTGRAPH_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif

#include <vector>

#include <mcld/ADT/HashTable.h>
#include <mcld/ADT/HashEntry.h>
#include <mcld/Config/Config.h>
#include <mcld/Fragment/FGNode.h>
#include <mcld/Fragment/FGEdge.h>
#include <mcld/Support/GCFactory.h>

#include <llvm/Support/DataTypes.h>

namespace mcld
{
class Module;
class ResolveInfo;
class Relocation;
class LinkerConfig;

/** \class FragmentGraph
 *  \brief FragmentGraph describes the references between fragments.
 */
class FragmentGraph
{
public:
  typedef FGNode::Slot   Slot;
  typedef FGNode::Signal Signal;

  typedef GCFactory<FGNode, MCLD_SECTIONS_PER_INPUT> NodeFactoryType;
  typedef NodeFactoryType::iterator node_iterator;
  typedef NodeFactoryType::const_iterator const_node_iterator;

  typedef std::vector<FGEdge> EdgeListType;
  typedef EdgeListType::iterator edge_iterator;
  typedef EdgeListType::const_iterator const_edge_iterator;


public:
  FragmentGraph();
  ~FragmentGraph();

  /// construct - construct the whole graph from input Fragments, relocations
  /// and symbols
  bool construct(const LinkerConfig& pConfig, Module& pModule);

  /// connect - connect two nodes
  bool connect(Signal pSignal, Slot pSlot);
  bool connect(FGNode& pFrom, Slot pSlot);

  /// getEdges - given a node, get the list of edges which are the fan-out of
  /// this node
  /// @param pEdges - the edge list which contains the found edges
  /// @return false - the given node
  bool getEdges(FGNode& pNode, EdgeListType& pEdges);

  /// ----- observers -----///
  /// getNode - given a fragment, finde the node which the fragment is belong to
  FGNode* getNode(const Fragment& pFrag);
  const FGNode* getNode(const Fragment& pFrag) const;

  FGNode* getNode(const ResolveInfo& pSym);
  const FGNode* getNode(const ResolveInfo& pSym) const;

private:
  typedef std::vector<Relocation*> RelocationListType;
  typedef RelocationListType::iterator reloc_iterator;
  typedef RelocationListType::const_iterator const_reloc_iterator;

  struct PtrCompare
  {
    bool operator()(const void* X, const void* Y) const
    { return (X==Y); }
  };

  struct PtrHash
  {
    size_t operator()(const void* pKey) const
    {
      return (unsigned((uintptr_t)pKey) >> 4) ^
             (unsigned((uintptr_t)pKey) >> 9);
    }
  };

  /// HashTable for Fragment* to Node*
  typedef HashEntry<const Fragment*, FGNode*, PtrCompare> FragHashEntryType;
  typedef HashTable<FragHashEntryType,
                    PtrHash,
                    EntryFactory<FragHashEntryType> > FragHashTableType;

  /// HashTable for ResolveInfo* to Node*
  typedef HashEntry<const ResolveInfo*, FGNode*, PtrCompare> SymHashEntryType;
  typedef HashTable<SymHashEntryType,
                    PtrHash,
                    EntryFactory<SymHashEntryType> > SymHashTableType;

  /** \class ReachMatrix
   *  \brief ReachMatrix is the reachability matrix which describes the relation
   *   of Nodes in FragmentGraph
   */
  class ReachMatrix
  {
  public:
    typedef std::vector<uint32_t> MatrixDataType;

  public:
    ReachMatrix(size_t pSize);
    ~ReachMatrix();
    uint32_t& at(uint32_t pX, uint32_t pY);
    uint32_t at(uint32_t pX, uint32_t pY) const;

    uint32_t getN() const
    { return m_N; }

    void print();

  private:
    // m_Data - the contents of the matrix. Here we use a one dimensional array
    // to represent the two dimensional matrix
    MatrixDataType m_Data;

    // m_N - this is an m_N x m_N matrix
    size_t m_N;
  };

private:
  FGNode* producePseudoNode();
  FGNode* produceRegularNode();
  void destroyPseudoNode();
  void destroyRegularNode();

  void initMatrix();

  bool createRegularNodes(Module& pModule);
  bool setNodeSlots(Module& pModule);
  bool createPseudoNodes(Module& pModule);

  bool createRegularEdges(Module& pModule);
  bool createPseudoEdges(Module& pModule);

private:
  NodeFactoryType* m_pPseudoNodeFactory;
  NodeFactoryType* m_pRegularNodeFactory;

  /// m_pFragNodeMap - HashTable to map the fragment to the node it belongs to
  FragHashTableType* m_pFragNodeMap;

  /// m_pSymNodeMap - HashTable to map the ResolveInfo to the node. The node is
  /// the pseudo node which the contains it's fan-out is to the ResolveInfo
  SymHashTableType* m_pSymNodeMap;

  ReachMatrix* m_pMatrix;

  /// m_NumOfPNodes - number of pseudo nodes
  size_t m_NumOfPNodes;
  /// m_NumOfRNodes - number of regular nodes
  size_t m_NumOfRNodes;
  /// m_NumOfEdges - number of edges
  size_t m_NumOfEdges;
};

} // namespace of mcld

#endif