blob: 967c67eea0ffdeca39f853c034793dc5d53427b2 [file] [log] [blame]
Chris Lattnerbb2a28f2002-03-26 22:39:06 +00001//===- NodeImpl.cpp - Implement the data structure analysis nodes ---------===//
2//
3// Implement the LLVM data structure analysis library.
4//
5//===----------------------------------------------------------------------===//
6
7#include "llvm/Analysis/DataStructure.h"
8#include "llvm/DerivedTypes.h"
9#include "llvm/Function.h"
10#include "llvm/BasicBlock.h"
11#include "llvm/iMemory.h"
12#include "llvm/iOther.h"
13#include "llvm/Assembly/Writer.h"
14#include "Support/STLExtras.h"
15#include <algorithm>
16#include <sstream>
17
18//===----------------------------------------------------------------------===//
19// DSNode Class Implementation
20//
21
22static void MapPVS(PointerValSet &PVSOut, const PointerValSet &PVSIn,
23 map<const DSNode*, DSNode*> &NodeMap) {
24 assert(PVSOut.empty() && "Value set already initialized!");
25
26 for (unsigned i = 0, e = PVSIn.size(); i != e; ++i)
27 PVSOut.add(PointerVal(NodeMap[PVSIn[i].Node], PVSIn[i].Index));
28}
29
30
31
32unsigned countPointerFields(const Type *Ty) {
33 switch (Ty->getPrimitiveID()) {
34 case Type::StructTyID: {
35 const StructType *ST = cast<StructType>(Ty);
36 unsigned Sum = 0;
37 for (unsigned i = 0, e = ST->getNumContainedTypes(); i != e; ++i)
38 Sum += countPointerFields(ST->getContainedType(i));
39
40 return Sum;
41 }
42
43 case Type::ArrayTyID:
44 // All array elements are folded together...
45 return countPointerFields(cast<ArrayType>(Ty)->getElementType());
46
47 case Type::PointerTyID:
48 return 1;
49
50 default: // Some other type, just treat it like a scalar
51 return 0;
52 }
53}
54
55DSNode::DSNode(enum NodeTy NT, const Type *T) : Ty(T), NodeType(NT) {
56 // Create field entries for all of the values in this type...
57 FieldLinks.resize(countPointerFields(getType()));
58}
59
60void DSNode::removeReferrer(PointerValSet *PVS) {
61 vector<PointerValSet*>::iterator I = std::find(Referrers.begin(),
62 Referrers.end(), PVS);
63 assert(I != Referrers.end() && "PVS not pointing to node!");
64 Referrers.erase(I);
65}
66
67
Chris Lattner6088c4f2002-03-27 19:46:05 +000068// removeAllIncomingEdges - Erase all edges in the graph that point to this node
69void DSNode::removeAllIncomingEdges() {
70 while (!Referrers.empty())
71 Referrers.back()->removePointerTo(this);
72}
73
74
Chris Lattnerbb2a28f2002-03-26 22:39:06 +000075static void replaceIn(std::string &S, char From, const std::string &To) {
76 for (unsigned i = 0; i < S.size(); )
77 if (S[i] == From) {
78 S.replace(S.begin()+i, S.begin()+i+1,
79 To.begin(), To.end());
80 i += To.size();
81 } else {
82 ++i;
83 }
84}
85
86static void writeEdges(std::ostream &O, const void *SrcNode,
87 const char *SrcNodePortName, int SrcNodeIdx,
88 const PointerValSet &VS, const string &EdgeAttr = "") {
89 for (unsigned j = 0, je = VS.size(); j != je; ++j) {
90 O << "\t\tNode" << SrcNode << SrcNodePortName;
91 if (SrcNodeIdx != -1) O << SrcNodeIdx;
92
93 O << " -> Node" << VS[j].Node;
94 if (VS[j].Index)
95 O << ":g" << VS[j].Index;
96
97 if (!EdgeAttr.empty())
98 O << "[" << EdgeAttr << "]";
99 O << ";\n";
100 }
101}
102
103static string escapeLabel(const string &In) {
104 string Label(In);
105 replaceIn(Label, '\\', "\\\\\\\\"); // Escape caption...
106 replaceIn(Label, ' ', "\\ ");
107 replaceIn(Label, '{', "\\{");
108 replaceIn(Label, '}', "\\}");
109 return Label;
110}
111
112void DSNode::print(std::ostream &O) const {
113 string Caption = escapeLabel(getCaption());
114
115 O << "\t\tNode" << (void*)this << " [ label =\"{" << Caption;
116
117 const vector<PointerValSet> *Links = getAuxLinks();
118 if (Links && !Links->empty()) {
119 O << "|{";
120 for (unsigned i = 0; i < Links->size(); ++i) {
121 if (i) O << "|";
122 O << "<f" << i << ">";
123 }
124 O << "}";
125 }
126
127 if (!FieldLinks.empty()) {
128 O << "|{";
129 for (unsigned i = 0; i < FieldLinks.size(); ++i) {
130 if (i) O << "|";
131 O << "<g" << i << ">";
132 }
133 O << "}";
134 }
135 O << "}\"];\n";
136
137 if (Links)
138 for (unsigned i = 0; i < Links->size(); ++i)
139 writeEdges(O, this, ":f", i, (*Links)[i]);
140 for (unsigned i = 0; i < FieldLinks.size(); ++i)
141 writeEdges(O, this, ":g", i, FieldLinks[i]);
142}
143
144void DSNode::mapNode(map<const DSNode*, DSNode*> &NodeMap, const DSNode *Old) {
145 assert(FieldLinks.size() == Old->FieldLinks.size() &&
146 "Cloned nodes do not have the same number of links!");
147 for (unsigned j = 0, je = FieldLinks.size(); j != je; ++j)
148 MapPVS(FieldLinks[j], Old->FieldLinks[j], NodeMap);
149}
150
151NewDSNode::NewDSNode(AllocationInst *V)
152 : DSNode(NewNode, V->getType()->getElementType()), Allocation(V) {
153}
154
Chris Lattner6088c4f2002-03-27 19:46:05 +0000155bool NewDSNode::isAllocaNode() const {
156 return isa<AllocaInst>(Allocation);
157}
158
159
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000160string NewDSNode::getCaption() const {
161 stringstream OS;
Chris Lattner6088c4f2002-03-27 19:46:05 +0000162 OS << (isMallocNode() ? "new " : "alloca ");
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000163
164 WriteTypeSymbolic(OS, getType(),
165 Allocation->getParent()->getParent()->getParent());
166 if (Allocation->isArrayAllocation())
167 OS << "[ ]";
168 return OS.str();
169}
170
171GlobalDSNode::GlobalDSNode(GlobalValue *V)
172 : DSNode(GlobalNode, V->getType()->getElementType()), Val(V) {
173}
174
175string GlobalDSNode::getCaption() const {
176 stringstream OS;
177 WriteTypeSymbolic(OS, getType(), Val->getParent());
178 return "global " + OS.str();
179}
180
181
Chris Lattner6088c4f2002-03-27 19:46:05 +0000182ShadowDSNode::ShadowDSNode(DSNode *P, Module *M, bool C = false)
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000183 : DSNode(ShadowNode, cast<PointerType>(P->getType())->getElementType()) {
184 Parent = P;
185 Mod = M;
186 ShadowParent = 0;
Chris Lattner6088c4f2002-03-27 19:46:05 +0000187 CriticalNode = C;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000188}
189
190ShadowDSNode::ShadowDSNode(const Type *Ty, Module *M, ShadowDSNode *ShadParent)
191 : DSNode(ShadowNode, Ty) {
192 Parent = 0;
193 Mod = M;
194 ShadowParent = ShadParent;
Chris Lattner6088c4f2002-03-27 19:46:05 +0000195 CriticalNode = false;
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000196}
197
198std::string ShadowDSNode::getCaption() const {
199 stringstream OS;
Chris Lattner6088c4f2002-03-27 19:46:05 +0000200 if (CriticalNode) OS << "# ";
201 OS << "shadow ";
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000202 WriteTypeSymbolic(OS, getType(), Mod);
Chris Lattner6088c4f2002-03-27 19:46:05 +0000203 if (CriticalNode) OS << " #";
204 return OS.str();
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000205}
206
207void ShadowDSNode::mapNode(map<const DSNode*, DSNode*> &NodeMap,
208 const DSNode *O) {
209 const ShadowDSNode *Old = (ShadowDSNode*)O;
210 DSNode::mapNode(NodeMap, Old); // Map base portions first...
211
212 // Map our SynthNodes...
213 assert(SynthNodes.empty() && "Synthnodes already mapped?");
214 SynthNodes.reserve(Old->SynthNodes.size());
215 for (unsigned i = 0, e = Old->SynthNodes.size(); i != e; ++i)
216 SynthNodes.push_back(std::make_pair(Old->SynthNodes[i].first,
217 (ShadowDSNode*)NodeMap[Old->SynthNodes[i].second]));
218}
219
220
221CallDSNode::CallDSNode(CallInst *ci) : DSNode(CallNode, ci->getType()), CI(ci) {
222 unsigned NumPtrs = 0;
223 if (!isa<Function>(ci->getOperand(0)))
224 NumPtrs++; // Include the method pointer...
225
226 for (unsigned i = 1, e = ci->getNumOperands(); i != e; ++i)
227 if (isa<PointerType>(ci->getOperand(i)->getType()))
228 NumPtrs++;
229 ArgLinks.resize(NumPtrs);
230}
231
232string CallDSNode::getCaption() const {
233 stringstream OS;
234 if (const Function *CM = CI->getCalledFunction())
235 OS << "call " << CM->getName();
236 else
237 OS << "call <indirect>";
238 OS << "|Ret: ";
239 WriteTypeSymbolic(OS, getType(),
240 CI->getParent()->getParent()->getParent());
241 return OS.str();
242}
243
244void CallDSNode::mapNode(map<const DSNode*, DSNode*> &NodeMap,
245 const DSNode *O) {
246 const CallDSNode *Old = (CallDSNode*)O;
247 DSNode::mapNode(NodeMap, Old); // Map base portions first...
248
249 assert(ArgLinks.size() == Old->ArgLinks.size() && "# Arguments changed!?");
250 for (unsigned i = 0, e = Old->ArgLinks.size(); i != e; ++i)
251 MapPVS(ArgLinks[i], Old->ArgLinks[i], NodeMap);
252}
253
254ArgDSNode::ArgDSNode(FunctionArgument *FA)
255 : DSNode(ArgNode, FA->getType()), FuncArg(FA) {
256}
257
258string ArgDSNode::getCaption() const {
259 stringstream OS;
260 OS << "arg %" << FuncArg->getName() << "|Ty: ";
261 WriteTypeSymbolic(OS, getType(), FuncArg->getParent()->getParent());
262 return OS.str();
263}
264
265void FunctionDSGraph::printFunction(std::ostream &O,
266 const char *Label) const {
267 O << "\tsubgraph cluster_" << Label << "_Function" << (void*)this << " {\n";
268 O << "\t\tlabel=\"" << Label << " Function\\ " << Func->getName() << "\";\n";
269 for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
270 Nodes[i]->print(O);
271 for (unsigned i = 0, e = ShadowNodes.size(); i != e; ++i)
272 ShadowNodes[i]->print(O);
273
274 if (RetNode.size()) {
275 O << "\t\tNode" << (void*)this << Label
276 << " [shape=\"ellipse\", label=\"Returns\"];\n";
277 writeEdges(O, this, Label, -1, RetNode);
278 }
279
280 O << "\n";
281 for (std::map<Value*, PointerValSet>::const_iterator I = ValueMap.begin(),
282 E = ValueMap.end(); I != E; ++I) {
283 if (I->second.size()) { // Only output nodes with edges...
284 stringstream OS;
285 WriteTypeSymbolic(OS, I->first->getType(), Func->getParent());
286
287 // Create node for I->first
288 O << "\t\tNode" << (void*)I->first << Label << " [shape=\"box\", label=\""
289 << escapeLabel(OS.str()) << "\\n%" << escapeLabel(I->first->getName())
290 << "\",fontsize=\"12.0\",color=\"gray70\"];\n";
291
292 // add edges from I->first to all pointers in I->second
293 writeEdges(O, I->first, Label, -1, I->second,
294 "weight=\"0.9\",color=\"gray70\"");
295 }
296 }
297
298 O << "\t}\n";
299}
300
301// Copy constructor - Since we copy the nodes over, we have to be sure to go
302// through and fix pointers to point into the new graph instead of into the old
303// graph...
304//
305FunctionDSGraph::FunctionDSGraph(const FunctionDSGraph &DSG) : Func(DSG.Func) {
306 RetNode = cloneFunctionIntoSelf(DSG, true);
307}
308
309
310// cloneFunctionIntoSelf - Clone the specified method graph into the current
311// method graph, returning the Return's set of the graph. If ValueMap is set
312// to true, the ValueMap of the function is cloned into this function as well
313// as the data structure graph itself.
314//
315PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG,
316 bool CloneValueMap) {
317 map<const DSNode*, DSNode*> NodeMap; // Map from old graph to new graph...
318 unsigned StartSize = Nodes.size(); // We probably already have nodes...
319 Nodes.reserve(StartSize+DSG.Nodes.size());
320 unsigned StartShadowSize = ShadowNodes.size();
321 ShadowNodes.reserve(StartShadowSize+DSG.ShadowNodes.size());
322
323 // Clone all of the nodes, keeping track of the mapping...
324 for (unsigned i = 0, e = DSG.Nodes.size(); i != e; ++i)
325 Nodes.push_back(NodeMap[DSG.Nodes[i]] = DSG.Nodes[i]->clone());
326
327 // Clone all of the shadow nodes similarly...
Chris Lattnerdd3fc182002-03-27 00:54:31 +0000328 for (unsigned i = 0, e = DSG.ShadowNodes.size(); i != e; ++i) {
329 ShadowDSNode *New = cast<ShadowDSNode>(DSG.ShadowNodes[i]->clone());
330 NodeMap[DSG.ShadowNodes[i]] = New;
331 ShadowNodes.push_back(New);
332 }
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000333
334 // Convert all of the links over in the nodes now that the map has been filled
335 // in all the way...
336 //
337 for (unsigned i = 0, e = DSG.Nodes.size(); i != e; ++i)
338 Nodes[i+StartSize]->mapNode(NodeMap, DSG.Nodes[i]);
339
340 for (unsigned i = 0, e = DSG.ShadowNodes.size(); i != e; ++i)
341 ShadowNodes[i+StartShadowSize]->mapNode(NodeMap, DSG.ShadowNodes[i]);
342
343 if (CloneValueMap) {
344 // Convert value map... the values themselves stay the same, just the nodes
345 // have to change...
346 //
347 for (std::map<Value*,PointerValSet>::const_iterator I =DSG.ValueMap.begin(),
348 E = DSG.ValueMap.end(); I != E; ++I)
349 MapPVS(ValueMap[I->first], I->second, NodeMap);
350 }
351
352 // Convert over return node...
353 PointerValSet RetVals;
354 MapPVS(RetVals, DSG.RetNode, NodeMap);
355 return RetVals;
356}
357
358
359FunctionDSGraph::~FunctionDSGraph() {
360 RetNode.clear();
361 ValueMap.clear();
362 for_each(Nodes.begin(), Nodes.end(), mem_fun(&DSNode::dropAllReferences));
363 for_each(ShadowNodes.begin(), ShadowNodes.end(),
364 mem_fun(&DSNode::dropAllReferences));
365 for_each(Nodes.begin(), Nodes.end(), deleter<DSNode>);
366 for_each(ShadowNodes.begin(), ShadowNodes.end(), deleter<DSNode>);
367}
368