Iterator that enumerates the ProgramDependenceGraph (PDG) for a function,
[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   
67   /// NodeType - A union of the above bits.  "Shadow" nodes do not add any flags
68   /// to the nodes in the data structure graph, so it is possible to have nodes
69   /// with a value of 0 for their NodeType.  Scalar and Alloca markers go away
70   /// when function graphs are inlined.
71   ///
72   unsigned short NodeType;
73
74   DSNode(enum NodeTy NT, const Type *T);
75   DSNode(const DSNode &);
76
77   ~DSNode() {
78     dropAllReferences();
79     assert(Referrers.empty() && "Referrers to dead node exist!");
80   }
81
82   // Iterator for graph interface... Defined in DSGraphTraits.h
83   typedef DSNodeIterator<DSNode> iterator;
84   typedef DSNodeIterator<const DSNode> const_iterator;
85   inline iterator begin();
86   inline iterator end();
87   inline const_iterator begin() const;
88   inline const_iterator end() const;
89
90   //===--------------------------------------------------
91   // Accessors
92
93   /// getSize - Return the maximum number of bytes occupied by this object...
94   ///
95   unsigned getSize() const { return Size; }
96
97   // getType - Return the node type of this object...
98   const Type *getType() const { return Ty; }
99   bool isArray() const { return NodeType & Array; }
100
101   /// getReferrers - Return a list of the pointers to this node...
102   ///
103   const std::vector<DSNodeHandle*> &getReferrers() const { return Referrers; }
104
105   /// hasNoReferrers - Return true if nothing is pointing to this node at all.
106   ///
107   bool hasNoReferrers() const { return Referrers.empty(); }
108
109   /// isModified - Return true if this node may be modified in this context
110   ///
111   bool isModified() const { return (NodeType & Modified) != 0; }
112
113   /// isRead - Return true if this node may be read in this context
114   ///
115   bool isRead() const { return (NodeType & Read) != 0; }
116
117
118   /// hasLink - Return true if this memory object has a link in slot #LinkNo
119   ///
120   bool hasLink(unsigned Offset) const {
121     assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
122            "Pointer offset not aligned correctly!");
123     unsigned Index = Offset >> DS::PointerShift;
124     assert(Index < Links.size() && "Link index is out of range!");
125     return Links[Index].getNode();
126   }
127
128   /// getLink - Return the link at the specified offset.
129   DSNodeHandle &getLink(unsigned Offset) {
130     assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
131            "Pointer offset not aligned correctly!");
132     unsigned Index = Offset >> DS::PointerShift;
133     assert(Index < Links.size() && "Link index is out of range!");
134     return Links[Index];
135   }
136   const DSNodeHandle &getLink(unsigned Offset) const {
137     assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
138            "Pointer offset not aligned correctly!");
139     unsigned Index = Offset >> DS::PointerShift;
140     assert(Index < Links.size() && "Link index is out of range!");
141     return Links[Index];
142   }
143
144   /// getNumLinks - Return the number of links in a node...
145   ///
146   unsigned getNumLinks() const { return Links.size(); }
147
148   /// mergeTypeInfo - This method merges the specified type into the current
149   /// node at the specified offset.  This may update the current node's type
150   /// record if this gives more information to the node, it may do nothing to
151   /// the node if this information is already known, or it may merge the node
152   /// completely (and return true) if the information is incompatible with what
153   /// is already known.
154   ///
155   /// This method returns true if the node is completely folded, otherwise
156   /// false.
157   ///
158   bool mergeTypeInfo(const Type *Ty, unsigned Offset);
159
160   /// foldNodeCompletely - If we determine that this node has some funny
161   /// behavior happening to it that we cannot represent, we fold it down to a
162   /// single, completely pessimistic, node.  This node is represented as a
163   /// single byte with a single TypeEntry of "void" with isArray = true.
164   ///
165   void foldNodeCompletely();
166
167   /// isNodeCompletelyFolded - Return true if this node has been completely
168   /// folded down to something that can never be expanded, effectively losing
169   /// all of the field sensitivity that may be present in the node.
170   ///
171   bool isNodeCompletelyFolded() const;
172
173   /// setLink - Set the link at the specified offset to the specified
174   /// NodeHandle, replacing what was there.  It is uncommon to use this method,
175   /// instead one of the higher level methods should be used, below.
176   ///
177   void setLink(unsigned Offset, const DSNodeHandle &NH) {
178     assert((Offset & ((1 << DS::PointerShift)-1)) == 0 &&
179            "Pointer offset not aligned correctly!");
180     unsigned Index = Offset >> DS::PointerShift;
181     assert(Index < Links.size() && "Link index is out of range!");
182     Links[Index] = NH;
183   }
184
185   /// getPointerSize - Return the size of a pointer for the current target.
186   ///
187   unsigned getPointerSize() const { return DS::PointerSize; }
188
189   /// addEdgeTo - Add an edge from the current node to the specified node.  This
190   /// can cause merging of nodes in the graph.
191   ///
192   void addEdgeTo(unsigned Offset, const DSNodeHandle &NH);
193
194   /// mergeWith - Merge this node and the specified node, moving all links to
195   /// and from the argument node into the current node, deleting the node
196   /// argument.  Offset indicates what offset the specified node is to be merged
197   /// into the current node.
198   ///
199   /// The specified node may be a null pointer (in which case, nothing happens).
200   ///
201   void mergeWith(const DSNodeHandle &NH, unsigned Offset);
202
203   /// addGlobal - Add an entry for a global value to the Globals list.  This
204   /// also marks the node with the 'G' flag if it does not already have it.
205   ///
206   void addGlobal(GlobalValue *GV);
207   const std::vector<GlobalValue*> &getGlobals() const { return Globals; }
208   std::vector<GlobalValue*> &getGlobals() { return Globals; }
209
210   void print(std::ostream &O, const DSGraph *G) const;
211   void dump() const;
212
213   void dropAllReferences() {
214     Links.clear();
215   }
216
217   /// remapLinks - Change all of the Links in the current node according to the
218   /// specified mapping.
219   void remapLinks(std::map<const DSNode*, DSNodeHandle> &OldNodeMap);
220
221 private:
222   friend class DSNodeHandle;
223
224   // addReferrer - Keep the referrer set up to date...
225   void addReferrer(DSNodeHandle *H) { Referrers.push_back(H); }
226   void removeReferrer(DSNodeHandle *H);
227
228   // static mergeNodes - Helper for mergeWith()
229   static void MergeNodes(DSNodeHandle& CurNodeH, DSNodeHandle& NH);
230 };
231
232
233 //===----------------------------------------------------------------------===//
234 // Define inline DSNodeHandle functions that depend on the definition of DSNode
235 //
236 inline void DSNodeHandle::setNode(DSNode *n) {
237   if (N) N->removeReferrer(this);
238   N = n;
239   if (N) N->addReferrer(this);
240   assert(!N || ((N->NodeType & DSNode::DEAD) == 0));
241 }
242
243 inline bool DSNodeHandle::hasLink(unsigned Num) const {
244   assert(N && "DSNodeHandle does not point to a node yet!");
245   return N->hasLink(Num+Offset);
246 }
247
248
249 /// getLink - Treat this current node pointer as a pointer to a structure of
250 /// some sort.  This method will return the pointer a mem[this+Num]
251 ///
252 inline const DSNodeHandle &DSNodeHandle::getLink(unsigned Off) const {
253   assert(N && "DSNodeHandle does not point to a node yet!");
254   return N->getLink(Offset+Off);
255 }
256 inline DSNodeHandle &DSNodeHandle::getLink(unsigned Off) {
257   assert(N && "DSNodeHandle does not point to a node yet!");
258   return N->getLink(Off+Offset);
259 }
260
261 inline void DSNodeHandle::setLink(unsigned Off, const DSNodeHandle &NH) {
262   assert(N && "DSNodeHandle does not point to a node yet!");
263   N->setLink(Off+Offset, NH);
264 }
265
266 ///  addEdgeTo - Add an edge from the current node to the specified node.  This
267 /// can cause merging of nodes in the graph.
268 ///
269 inline void DSNodeHandle::addEdgeTo(unsigned Off, const DSNodeHandle &Node) {
270   assert(N && "DSNodeHandle does not point to a node yet!");
271   N->addEdgeTo(Off+Offset, Node);
272 }
273
274 /// mergeWith - Merge the logical node pointed to by 'this' with the node
275 /// pointed to by 'N'.
276 ///
277 inline void DSNodeHandle::mergeWith(const DSNodeHandle &Node) {
278   if (N != 0)
279     N->mergeWith(Node, Offset);
280   else     // No node to merge with, so just point to Node
281     *this = Node;
282 }
283
284 inline void DSNodeHandle::swap(DSNodeHandle &NH) {
285   std::swap(Offset, NH.Offset);
286   if (N != NH.N) {
287     if (N) {
288       N->removeReferrer(this);
289       N->addReferrer(&NH);
290     }
291     if (NH.N) {
292       N->removeReferrer(&NH);
293       N->addReferrer(this);
294     }
295     std::swap(N, NH.N);
296   }
297 }
298
299 #endif