//===- 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