Disable the parent graph code when not compiled in DEBUG mode
[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
12 #ifndef NDEBUG
13 #define INCLUDE_PARENT_GRAPH 1
14 #endif
15
16 template<typename BaseType>
17 class DSNodeIterator;          // Data structure graph traversal iterator
18
19 //===----------------------------------------------------------------------===//
20 /// DSNode - Data structure node class
21 ///
22 /// This class represents an untyped memory object of Size bytes.  It keeps
23 /// track of any pointers that have been stored into the object as well as the
24 /// different types represented in this object.
25 ///
26 class DSNode {
27   /// NumReferrers - The number of DSNodeHandles pointing to this node... if
28   /// this is a forwarding node, then this is the number of node handles which
29   /// are still forwarding over us.
30   ///
31   unsigned NumReferrers;
32
33   /// ForwardNH - This NodeHandle contain the node (and offset into the node)
34   /// that this node really is.  When nodes get folded together, the node to be
35   /// eliminated has these fields filled in, otherwise ForwardNH.getNode() is
36   /// null.
37   DSNodeHandle ForwardNH;
38
39   /// Size - The current size of the node.  This should be equal to the size of
40   /// the current type record.
41   ///
42   unsigned Size;
43
44 #ifdef INCLUDE_PARENT_GRAPH
45   /// ParentGraph - The graph this node is currently embedded into.
46   ///
47   DSGraph *ParentGraph;
48 #endif
49
50   /// Ty - Keep track of the current outer most type of this object, in addition
51   /// to whether or not it has been indexed like an array or not.  If the
52   /// isArray bit is set, the node cannot grow.
53   ///
54   const Type *Ty;                 // The type itself...
55
56   /// Links - Contains one entry for every sizeof(void*) bytes in this memory
57   /// object.  Note that if the node is not a multiple of size(void*) bytes
58   /// large, that there is an extra entry for the "remainder" of the node as
59   /// well.  For this reason, nodes of 1 byte in size do have one link.
60   ///
61   std::vector<DSNodeHandle> Links;
62
63   /// Globals - The list of global values that are merged into this node.
64   ///
65   std::vector<GlobalValue*> Globals;
66
67   void operator=(const DSNode &); // DO NOT IMPLEMENT
68   DSNode(const DSNode &);         // DO NOT IMPLEMENT
69 public:
70   enum NodeTy {
71     ShadowNode  = 0,        // Nothing is known about this node...
72     AllocaNode  = 1 << 0,   // This node was allocated with alloca
73     HeapNode    = 1 << 1,   // This node was allocated with malloc
74     GlobalNode  = 1 << 2,   // This node was allocated by a global var decl
75     UnknownNode = 1 << 3,   // This node points to unknown allocated memory 
76     Incomplete  = 1 << 4,   // This node may not be complete
77
78     Modified    = 1 << 5,   // This node is modified in this context
79     Read        = 1 << 6,   // This node is read in this context
80
81     Array       = 1 << 7,   // This node is treated like an array
82     //#ifndef NDEBUG
83     DEAD        = 1 << 8,   // This node is dead and should not be pointed to
84     //#endif
85
86     Composition = AllocaNode | HeapNode | GlobalNode | UnknownNode,
87   };
88   
89   /// NodeType - A union of the above bits.  "Shadow" nodes do not add any flags
90   /// to the nodes in the data structure graph, so it is possible to have nodes
91   /// with a value of 0 for their NodeType.
92   ///
93 private:
94   unsigned short NodeType;
95 public:
96
97   DSNode(const Type *T, DSGraph *G);
98   DSNode(const DSNode &, DSGraph *G);
99
100   ~DSNode() {
101     dropAllReferences();
102     assert(hasNoReferrers() && "Referrers to dead node exist!");
103   }
104
105   // Iterator for graph interface... Defined in DSGraphTraits.h
106   typedef DSNodeIterator<DSNode> iterator;
107   typedef DSNodeIterator<const DSNode> const_iterator;
108   inline iterator begin();
109   inline iterator end();
110   inline const_iterator begin() const;
111   inline const_iterator end() const;
112
113   //===--------------------------------------------------
114   // Accessors
115
116   /// getSize - Return the maximum number of bytes occupied by this object...
117   ///
118   unsigned getSize() const { return Size; }
119
120   // getType - Return the node type of this object...
121   const Type *getType() const { return Ty; }
122   bool isArray() const { return NodeType & Array; }
123
124   /// hasNoReferrers - Return true if nothing is pointing to this node at all.
125   ///
126   bool hasNoReferrers() const { return getNumReferrers() == 0; }
127
128   /// getNumReferrers - This method returns the number of referrers to the
129   /// current node.  Note that if this node is a forwarding node, this will
130   /// return the number of nodes forwarding over the node!
131   unsigned getNumReferrers() const { return NumReferrers; }
132
133 #ifdef INCLUDE_PARENT_GRAPH
134   DSGraph *getParentGraph() const { return ParentGraph; }
135   void setParentGraph(DSGraph *G) { ParentGraph = G; }
136 #endif
137
138   /// getForwardNode - This method returns the node that this node is forwarded
139   /// to, if any.
140   DSNode *getForwardNode() const { return ForwardNH.getNode(); }
141   void stopForwarding() {
142     assert(!ForwardNH.isNull() &&
143            "Node isn't forwarding, cannot stopForwarding!");
144     ForwardNH.setNode(0);
145   }
146
147   /// hasLink - Return true if this memory object has a link in slot #LinkNo
148   ///
149   bool hasLink(unsigned Offset) const {
150     assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
151            "Pointer offset not aligned correctly!");
152     unsigned Index = Offset >> DS::PointerShift;
153     assert(Index < Links.size() && "Link index is out of range!");
154     return Links[Index].getNode();
155   }
156
157   /// getLink - Return the link at the specified offset.
158   DSNodeHandle &getLink(unsigned Offset) {
159     assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
160            "Pointer offset not aligned correctly!");
161     unsigned Index = Offset >> DS::PointerShift;
162     assert(Index < Links.size() && "Link index is out of range!");
163     return Links[Index];
164   }
165   const DSNodeHandle &getLink(unsigned Offset) const {
166     assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
167            "Pointer offset not aligned correctly!");
168     unsigned Index = Offset >> DS::PointerShift;
169     assert(Index < Links.size() && "Link index is out of range!");
170     return Links[Index];
171   }
172
173   /// getNumLinks - Return the number of links in a node...
174   ///
175   unsigned getNumLinks() const { return Links.size(); }
176
177   /// mergeTypeInfo - This method merges the specified type into the current
178   /// node at the specified offset.  This may update the current node's type
179   /// record if this gives more information to the node, it may do nothing to
180   /// the node if this information is already known, or it may merge the node
181   /// completely (and return true) if the information is incompatible with what
182   /// is already known.
183   ///
184   /// This method returns true if the node is completely folded, otherwise
185   /// false.
186   ///
187   bool mergeTypeInfo(const Type *Ty, unsigned Offset,
188                      bool FoldIfIncompatible = true);
189
190   /// foldNodeCompletely - If we determine that this node has some funny
191   /// behavior happening to it that we cannot represent, we fold it down to a
192   /// single, completely pessimistic, node.  This node is represented as a
193   /// single byte with a single TypeEntry of "void" with isArray = true.
194   ///
195   void foldNodeCompletely();
196
197   /// isNodeCompletelyFolded - Return true if this node has been completely
198   /// folded down to something that can never be expanded, effectively losing
199   /// all of the field sensitivity that may be present in the node.
200   ///
201   bool isNodeCompletelyFolded() const;
202
203   /// setLink - Set the link at the specified offset to the specified
204   /// NodeHandle, replacing what was there.  It is uncommon to use this method,
205   /// instead one of the higher level methods should be used, below.
206   ///
207   void setLink(unsigned Offset, const DSNodeHandle &NH) {
208     assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
209            "Pointer offset not aligned correctly!");
210     unsigned Index = Offset >> DS::PointerShift;
211     assert(Index < Links.size() && "Link index is out of range!");
212     Links[Index] = NH;
213   }
214
215   /// getPointerSize - Return the size of a pointer for the current target.
216   ///
217   unsigned getPointerSize() const { return DS::PointerSize; }
218
219   /// addEdgeTo - Add an edge from the current node to the specified node.  This
220   /// can cause merging of nodes in the graph.
221   ///
222   void addEdgeTo(unsigned Offset, const DSNodeHandle &NH);
223
224   /// mergeWith - Merge this node and the specified node, moving all links to
225   /// and from the argument node into the current node, deleting the node
226   /// argument.  Offset indicates what offset the specified node is to be merged
227   /// into the current node.
228   ///
229   /// The specified node may be a null pointer (in which case, nothing happens).
230   ///
231   void mergeWith(const DSNodeHandle &NH, unsigned Offset);
232
233   /// addGlobal - Add an entry for a global value to the Globals list.  This
234   /// also marks the node with the 'G' flag if it does not already have it.
235   ///
236   void addGlobal(GlobalValue *GV);
237   const std::vector<GlobalValue*> &getGlobals() const { return Globals; }
238
239   /// maskNodeTypes - Apply a mask to the node types bitfield.
240   ///
241   void maskNodeTypes(unsigned Mask) {
242     NodeType &= Mask;
243   }
244
245   /// getNodeFlags - Return all of the flags set on the node.  If the DEAD flag
246   /// is set, hide it from the caller.
247   unsigned getNodeFlags() const { return NodeType & ~DEAD; }
248
249   bool isAllocaNode()  const { return NodeType & AllocaNode; }
250   bool isHeapNode()    const { return NodeType & HeapNode; }
251   bool isGlobalNode()  const { return NodeType & GlobalNode; }
252   bool isUnknownNode() const { return NodeType & UnknownNode; }
253
254   bool isModified() const   { return NodeType & Modified; }
255   bool isRead() const       { return NodeType & Read; }
256
257   bool isIncomplete() const { return NodeType & Incomplete; }
258   bool isComplete() const   { return !isIncomplete(); }
259   bool isDeadNode() const   { return NodeType & DEAD; }
260
261   DSNode *setAllocaNodeMarker()  { NodeType |= AllocaNode;  return this; }
262   DSNode *setHeapNodeMarker()    { NodeType |= HeapNode;    return this; }
263   DSNode *setGlobalNodeMarker()  { NodeType |= GlobalNode;  return this; }
264   DSNode *setUnknownNodeMarker() { NodeType |= UnknownNode; return this; }
265
266   DSNode *setIncompleteMarker() { NodeType |= Incomplete; return this; }
267   DSNode *setModifiedMarker()   { NodeType |= Modified;   return this; }
268   DSNode *setReadMarker()       { NodeType |= Read;       return this; }
269
270   void makeNodeDead() {
271     Globals.clear();
272     assert(hasNoReferrers() && "Dead node shouldn't have refs!");
273     NodeType = DEAD;
274   }
275
276   /// forwardNode - Mark this node as being obsolete, and all references to it
277   /// should be forwarded to the specified node and offset.
278   ///
279   void forwardNode(DSNode *To, unsigned Offset);
280
281   void print(std::ostream &O, const DSGraph *G) const;
282   void dump() const;
283
284   void assertOK() const;
285
286   void dropAllReferences() {
287     Links.clear();
288     if (!ForwardNH.isNull())
289       ForwardNH.setNode(0);
290   }
291
292   /// remapLinks - Change all of the Links in the current node according to the
293   /// specified mapping.
294   void remapLinks(hash_map<const DSNode*, DSNodeHandle> &OldNodeMap);
295
296   /// markReachableNodes - This method recursively traverses the specified
297   /// DSNodes, marking any nodes which are reachable.  All reachable nodes it
298   /// adds to the set, which allows it to only traverse visited nodes once.
299   ///
300   void markReachableNodes(hash_set<DSNode*> &ReachableNodes);
301
302 private:
303   friend class DSNodeHandle;
304
305   // static mergeNodes - Helper for mergeWith()
306   static void MergeNodes(DSNodeHandle& CurNodeH, DSNodeHandle& NH);
307 };
308
309
310 //===----------------------------------------------------------------------===//
311 // Define inline DSNodeHandle functions that depend on the definition of DSNode
312 //
313 inline DSNode *DSNodeHandle::getNode() const {
314   assert((!N || Offset < N->Size || (N->Size == 0 && Offset == 0) ||
315           !N->ForwardNH.isNull()) && "Node handle offset out of range!");
316   if (!N || N->ForwardNH.isNull())
317     return N;
318
319   return HandleForwarding();
320 }
321
322 inline void DSNodeHandle::setNode(DSNode *n) {
323   assert(!n || !n->getForwardNode() && "Cannot set node to a forwarded node!");
324   if (N) N->NumReferrers--;
325   N = n;
326   if (N) {
327     N->NumReferrers++;
328     if (Offset >= N->Size) {
329       assert((Offset == 0 || N->Size == 1) &&
330              "Pointer to non-collapsed node with invalid offset!");
331       Offset = 0;
332     }
333   }
334   assert(!N || ((N->NodeType & DSNode::DEAD) == 0));
335   assert((!N || Offset < N->Size || (N->Size == 0 && Offset == 0) ||
336           !N->ForwardNH.isNull()) && "Node handle offset out of range!");
337 }
338
339 inline bool DSNodeHandle::hasLink(unsigned Num) const {
340   assert(N && "DSNodeHandle does not point to a node yet!");
341   return getNode()->hasLink(Num+Offset);
342 }
343
344
345 /// getLink - Treat this current node pointer as a pointer to a structure of
346 /// some sort.  This method will return the pointer a mem[this+Num]
347 ///
348 inline const DSNodeHandle &DSNodeHandle::getLink(unsigned Off) const {
349   assert(N && "DSNodeHandle does not point to a node yet!");
350   return getNode()->getLink(Offset+Off);
351 }
352 inline DSNodeHandle &DSNodeHandle::getLink(unsigned Off) {
353   assert(N && "DSNodeHandle does not point to a node yet!");
354   return getNode()->getLink(Off+Offset);
355 }
356
357 inline void DSNodeHandle::setLink(unsigned Off, const DSNodeHandle &NH) {
358   assert(N && "DSNodeHandle does not point to a node yet!");
359   getNode()->setLink(Off+Offset, NH);
360 }
361
362 ///  addEdgeTo - Add an edge from the current node to the specified node.  This
363 /// can cause merging of nodes in the graph.
364 ///
365 inline void DSNodeHandle::addEdgeTo(unsigned Off, const DSNodeHandle &Node) {
366   assert(N && "DSNodeHandle does not point to a node yet!");
367   getNode()->addEdgeTo(Off+Offset, Node);
368 }
369
370 /// mergeWith - Merge the logical node pointed to by 'this' with the node
371 /// pointed to by 'N'.
372 ///
373 inline void DSNodeHandle::mergeWith(const DSNodeHandle &Node) {
374   if (N != 0)
375     getNode()->mergeWith(Node, Offset);
376   else     // No node to merge with, so just point to Node
377     *this = Node;
378 }
379
380 #endif