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