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