Change DSGraph stuff to use hash_(set|map) instead of std::(set|map)
[oota-llvm.git] / include / llvm / Analysis / DSNode.h
1 //===- DSNode.h - Node definition for datastructure graphs ------*- C++ -*-===//
2 //
3 // Data structure graph nodes and some implementation of DSNodeHandle.
4 //
5 //===----------------------------------------------------------------------===//
6
7 #ifndef LLVM_ANALYSIS_DSNODE_H
8 #define LLVM_ANALYSIS_DSNODE_H
9
10 #include "llvm/Analysis/DSSupport.h"
11 template<typename BaseType>
12 class DSNodeIterator;          // Data structure graph traversal iterator
13
14 //===----------------------------------------------------------------------===//
15 /// DSNode - Data structure node class
16 ///
17 /// This class represents an untyped memory object of Size bytes.  It keeps
18 /// track of any pointers that have been stored into the object as well as the
19 /// different types represented in this object.
20 ///
21 class DSNode {
22   /// Referrers - Keep track of all of the node handles that point to this
23   /// DSNode.  These pointers may need to be updated to point to a different
24   /// node if this node gets merged with it.
25   ///
26   std::vector<DSNodeHandle*> Referrers;
27
28   /// Links - Contains one entry for every sizeof(void*) bytes in this memory
29   /// object.  Note that if the node is not a multiple of size(void*) bytes
30   /// large, that there is an extra entry for the "remainder" of the node as
31   /// well.  For this reason, nodes of 1 byte in size do have one link.
32   ///
33   std::vector<DSNodeHandle> Links;
34
35   /// Globals - The list of global values that are merged into this node.
36   ///
37   std::vector<GlobalValue*> Globals;
38
39   /// Ty - Keep track of the current outer most type of this object, in addition
40   /// to whether or not it has been indexed like an array or not.  If the
41   /// isArray bit is set, the node cannot grow.
42   ///
43   const Type *Ty;                 // The type itself...
44
45   /// Size - The current size of the node.  This should be equal to the size of
46   /// the current type record.
47   ///
48   unsigned Size;
49
50   void operator=(const DSNode &); // DO NOT IMPLEMENT
51 public:
52   enum NodeTy {
53     ShadowNode  = 0,        // Nothing is known about this node...
54     AllocaNode  = 1 << 0,   // This node was allocated with alloca
55     HeapNode    = 1 << 1,   // This node was allocated with malloc
56     GlobalNode  = 1 << 2,   // This node was allocated by a global var decl
57     UnknownNode = 1 << 3,   // This node points to unknown allocated memory 
58     Incomplete  = 1 << 4,   // This node may not be complete
59     Modified    = 1 << 5,   // This node is modified in this context
60     Read        = 1 << 6,   // This node is read in this context
61     Array       = 1 << 7,   // This node is treated like an array
62 #if 1
63     DEAD        = 1 << 8,   // This node is dead and should not be pointed to
64 #endif
65
66     Composition = AllocaNode | HeapNode | GlobalNode | UnknownNode,
67   };
68   
69   /// NodeType - A union of the above bits.  "Shadow" nodes do not add any flags
70   /// to the nodes in the data structure graph, so it is possible to have nodes
71   /// with a value of 0 for their NodeType.  Scalar and Alloca markers go away
72   /// when function graphs are inlined.
73   ///
74   unsigned short NodeType;
75
76   DSNode(enum NodeTy NT, const Type *T);
77   DSNode(const DSNode &);
78
79   ~DSNode() {
80     dropAllReferences();
81     assert(Referrers.empty() && "Referrers to dead node exist!");
82   }
83
84   // Iterator for graph interface... Defined in DSGraphTraits.h
85   typedef DSNodeIterator<DSNode> iterator;
86   typedef DSNodeIterator<const DSNode> const_iterator;
87   inline iterator begin();
88   inline iterator end();
89   inline const_iterator begin() const;
90   inline const_iterator end() const;
91
92   //===--------------------------------------------------
93   // Accessors
94
95   /// getSize - Return the maximum number of bytes occupied by this object...
96   ///
97   unsigned getSize() const { return Size; }
98
99   // getType - Return the node type of this object...
100   const Type *getType() const { return Ty; }
101   bool isArray() const { return NodeType & Array; }
102
103   /// getReferrers - Return a list of the pointers to this node...
104   ///
105   const std::vector<DSNodeHandle*> &getReferrers() const { return Referrers; }
106
107   /// hasNoReferrers - Return true if nothing is pointing to this node at all.
108   ///
109   bool hasNoReferrers() const { return Referrers.empty(); }
110
111   /// isModified - Return true if this node may be modified in this context
112   ///
113   bool isModified() const { return (NodeType & Modified) != 0; }
114
115   /// isRead - Return true if this node may be read in this context
116   ///
117   bool isRead() const { return (NodeType & Read) != 0; }
118
119
120   /// hasLink - Return true if this memory object has a link in slot #LinkNo
121   ///
122   bool hasLink(unsigned Offset) const {
123     assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
124            "Pointer offset not aligned correctly!");
125     unsigned Index = Offset >> DS::PointerShift;
126     assert(Index < Links.size() && "Link index is out of range!");
127     return Links[Index].getNode();
128   }
129
130   /// getLink - Return the link at the specified offset.
131   DSNodeHandle &getLink(unsigned Offset) {
132     assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
133            "Pointer offset not aligned correctly!");
134     unsigned Index = Offset >> DS::PointerShift;
135     assert(Index < Links.size() && "Link index is out of range!");
136     return Links[Index];
137   }
138   const DSNodeHandle &getLink(unsigned Offset) const {
139     assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
140            "Pointer offset not aligned correctly!");
141     unsigned Index = Offset >> DS::PointerShift;
142     assert(Index < Links.size() && "Link index is out of range!");
143     return Links[Index];
144   }
145
146   /// getNumLinks - Return the number of links in a node...
147   ///
148   unsigned getNumLinks() const { return Links.size(); }
149
150   /// mergeTypeInfo - This method merges the specified type into the current
151   /// node at the specified offset.  This may update the current node's type
152   /// record if this gives more information to the node, it may do nothing to
153   /// the node if this information is already known, or it may merge the node
154   /// completely (and return true) if the information is incompatible with what
155   /// is already known.
156   ///
157   /// This method returns true if the node is completely folded, otherwise
158   /// false.
159   ///
160   bool mergeTypeInfo(const Type *Ty, unsigned Offset);
161
162   /// foldNodeCompletely - If we determine that this node has some funny
163   /// behavior happening to it that we cannot represent, we fold it down to a
164   /// single, completely pessimistic, node.  This node is represented as a
165   /// single byte with a single TypeEntry of "void" with isArray = true.
166   ///
167   void foldNodeCompletely();
168
169   /// isNodeCompletelyFolded - Return true if this node has been completely
170   /// folded down to something that can never be expanded, effectively losing
171   /// all of the field sensitivity that may be present in the node.
172   ///
173   bool isNodeCompletelyFolded() const;
174
175   /// setLink - Set the link at the specified offset to the specified
176   /// NodeHandle, replacing what was there.  It is uncommon to use this method,
177   /// instead one of the higher level methods should be used, below.
178   ///
179   void setLink(unsigned Offset, const DSNodeHandle &NH) {
180     assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
181            "Pointer offset not aligned correctly!");
182     unsigned Index = Offset >> DS::PointerShift;
183     assert(Index < Links.size() && "Link index is out of range!");
184     Links[Index] = NH;
185   }
186
187   /// getPointerSize - Return the size of a pointer for the current target.
188   ///
189   unsigned getPointerSize() const { return DS::PointerSize; }
190
191   /// addEdgeTo - Add an edge from the current node to the specified node.  This
192   /// can cause merging of nodes in the graph.
193   ///
194   void addEdgeTo(unsigned Offset, const DSNodeHandle &NH);
195
196   /// mergeWith - Merge this node and the specified node, moving all links to
197   /// and from the argument node into the current node, deleting the node
198   /// argument.  Offset indicates what offset the specified node is to be merged
199   /// into the current node.
200   ///
201   /// The specified node may be a null pointer (in which case, nothing happens).
202   ///
203   void mergeWith(const DSNodeHandle &NH, unsigned Offset);
204
205   /// addGlobal - Add an entry for a global value to the Globals list.  This
206   /// also marks the node with the 'G' flag if it does not already have it.
207   ///
208   void addGlobal(GlobalValue *GV);
209   const std::vector<GlobalValue*> &getGlobals() const { return Globals; }
210   std::vector<GlobalValue*> &getGlobals() { return Globals; }
211
212   void print(std::ostream &O, const DSGraph *G) const;
213   void dump() const;
214
215   void dropAllReferences() {
216     Links.clear();
217   }
218
219   /// remapLinks - Change all of the Links in the current node according to the
220   /// specified mapping.
221   void remapLinks(hash_map<const DSNode*, DSNodeHandle> &OldNodeMap);
222
223   /// markReachableNodes - This method recursively traverses the specified
224   /// DSNodes, marking any nodes which are reachable.  All reachable nodes it
225   /// adds to the set, which allows it to only traverse visited nodes once.
226   ///
227   void markReachableNodes(hash_set<DSNode*> &ReachableNodes);
228
229 private:
230   friend class DSNodeHandle;
231
232   // addReferrer - Keep the referrer set up to date...
233   void addReferrer(DSNodeHandle *H) { Referrers.push_back(H); }
234   void removeReferrer(DSNodeHandle *H);
235
236   // static mergeNodes - Helper for mergeWith()
237   static void MergeNodes(DSNodeHandle& CurNodeH, DSNodeHandle& NH);
238 };
239
240
241 //===----------------------------------------------------------------------===//
242 // Define inline DSNodeHandle functions that depend on the definition of DSNode
243 //
244 inline void DSNodeHandle::setNode(DSNode *n) {
245   if (N) N->removeReferrer(this);
246   N = n;
247   if (N) N->addReferrer(this);
248   assert(!N || ((N->NodeType & DSNode::DEAD) == 0));
249 }
250
251 inline bool DSNodeHandle::hasLink(unsigned Num) const {
252   assert(N && "DSNodeHandle does not point to a node yet!");
253   return N->hasLink(Num+Offset);
254 }
255
256
257 /// getLink - Treat this current node pointer as a pointer to a structure of
258 /// some sort.  This method will return the pointer a mem[this+Num]
259 ///
260 inline const DSNodeHandle &DSNodeHandle::getLink(unsigned Off) const {
261   assert(N && "DSNodeHandle does not point to a node yet!");
262   return N->getLink(Offset+Off);
263 }
264 inline DSNodeHandle &DSNodeHandle::getLink(unsigned Off) {
265   assert(N && "DSNodeHandle does not point to a node yet!");
266   return N->getLink(Off+Offset);
267 }
268
269 inline void DSNodeHandle::setLink(unsigned Off, const DSNodeHandle &NH) {
270   assert(N && "DSNodeHandle does not point to a node yet!");
271   N->setLink(Off+Offset, NH);
272 }
273
274 ///  addEdgeTo - Add an edge from the current node to the specified node.  This
275 /// can cause merging of nodes in the graph.
276 ///
277 inline void DSNodeHandle::addEdgeTo(unsigned Off, const DSNodeHandle &Node) {
278   assert(N && "DSNodeHandle does not point to a node yet!");
279   N->addEdgeTo(Off+Offset, Node);
280 }
281
282 /// mergeWith - Merge the logical node pointed to by 'this' with the node
283 /// pointed to by 'N'.
284 ///
285 inline void DSNodeHandle::mergeWith(const DSNodeHandle &Node) {
286   if (N != 0)
287     N->mergeWith(Node, Offset);
288   else     // No node to merge with, so just point to Node
289     *this = Node;
290 }
291
292 inline void DSNodeHandle::swap(DSNodeHandle &NH) {
293   std::swap(Offset, NH.Offset);
294   if (N != NH.N) {
295     if (N) {
296       N->removeReferrer(this);
297       N->addReferrer(&NH);
298     }
299     if (NH.N) {
300       N->removeReferrer(&NH);
301       N->addReferrer(this);
302     }
303     std::swap(N, NH.N);
304   }
305 }
306
307 #endif