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