blob: b8fabf8a7472520968a40c2c97a03ffc24ef8b85 [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,
Chris Lattner1120c8b2002-03-28 17:56:03 +000023 map<const DSNode*, DSNode*> &NodeMap, bool ReinitOk = false){
24 assert((ReinitOk || PVSOut.empty()) && "Value set already initialized!");
Chris Lattnerbb2a28f2002-03-26 22:39:06 +000025
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
Chris Lattner1120c8b2002-03-28 17:56:03 +0000151AllocDSNode::AllocDSNode(AllocationInst *V)
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000152 : DSNode(NewNode, V->getType()->getElementType()), Allocation(V) {
153}
154
Chris Lattner1120c8b2002-03-28 17:56:03 +0000155bool AllocDSNode::isAllocaNode() const {
Chris Lattner6088c4f2002-03-27 19:46:05 +0000156 return isa<AllocaInst>(Allocation);
157}
158
159
Chris Lattner1120c8b2002-03-28 17:56:03 +0000160string AllocDSNode::getCaption() const {
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000161 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());
Chris Lattner1120c8b2002-03-28 17:56:03 +0000178 return "global " + OS.str() + " %" + Val->getName();
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000179}
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) {
Chris Lattner1120c8b2002-03-28 17:56:03 +0000246 const CallDSNode *Old = cast<CallDSNode>(O);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000247 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";
Chris Lattner1120c8b2002-03-28 17:56:03 +0000269 for (unsigned i = 0, e = ArgNodes.size(); i != e; ++i)
270 ArgNodes[i]->print(O);
271 for (unsigned i = 0, e = AllocNodes.size(); i != e; ++i)
272 AllocNodes[i]->print(O);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000273 for (unsigned i = 0, e = ShadowNodes.size(); i != e; ++i)
274 ShadowNodes[i]->print(O);
Chris Lattner1120c8b2002-03-28 17:56:03 +0000275 for (unsigned i = 0, e = GlobalNodes.size(); i != e; ++i)
276 GlobalNodes[i]->print(O);
277 for (unsigned i = 0, e = CallNodes.size(); i != e; ++i)
278 CallNodes[i]->print(O);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000279
280 if (RetNode.size()) {
281 O << "\t\tNode" << (void*)this << Label
282 << " [shape=\"ellipse\", label=\"Returns\"];\n";
283 writeEdges(O, this, Label, -1, RetNode);
284 }
285
286 O << "\n";
287 for (std::map<Value*, PointerValSet>::const_iterator I = ValueMap.begin(),
288 E = ValueMap.end(); I != E; ++I) {
289 if (I->second.size()) { // Only output nodes with edges...
290 stringstream OS;
291 WriteTypeSymbolic(OS, I->first->getType(), Func->getParent());
292
293 // Create node for I->first
294 O << "\t\tNode" << (void*)I->first << Label << " [shape=\"box\", label=\""
295 << escapeLabel(OS.str()) << "\\n%" << escapeLabel(I->first->getName())
296 << "\",fontsize=\"12.0\",color=\"gray70\"];\n";
297
298 // add edges from I->first to all pointers in I->second
299 writeEdges(O, I->first, Label, -1, I->second,
300 "weight=\"0.9\",color=\"gray70\"");
301 }
302 }
303
304 O << "\t}\n";
305}
306
307// Copy constructor - Since we copy the nodes over, we have to be sure to go
308// through and fix pointers to point into the new graph instead of into the old
309// graph...
310//
311FunctionDSGraph::FunctionDSGraph(const FunctionDSGraph &DSG) : Func(DSG.Func) {
312 RetNode = cloneFunctionIntoSelf(DSG, true);
313}
314
315
316// cloneFunctionIntoSelf - Clone the specified method graph into the current
317// method graph, returning the Return's set of the graph. If ValueMap is set
318// to true, the ValueMap of the function is cloned into this function as well
319// as the data structure graph itself.
320//
321PointerValSet FunctionDSGraph::cloneFunctionIntoSelf(const FunctionDSGraph &DSG,
322 bool CloneValueMap) {
323 map<const DSNode*, DSNode*> NodeMap; // Map from old graph to new graph...
Chris Lattner1120c8b2002-03-28 17:56:03 +0000324 unsigned StartArgSize = ArgNodes.size();
325 ArgNodes.reserve(StartArgSize+DSG.ArgNodes.size());
326 unsigned StartAllocSize = AllocNodes.size();
327 AllocNodes.reserve(StartAllocSize+DSG.AllocNodes.size());
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000328 unsigned StartShadowSize = ShadowNodes.size();
329 ShadowNodes.reserve(StartShadowSize+DSG.ShadowNodes.size());
Chris Lattner1120c8b2002-03-28 17:56:03 +0000330 unsigned StartGlobalSize = GlobalNodes.size();
331 GlobalNodes.reserve(StartGlobalSize+DSG.GlobalNodes.size());
332 unsigned StartCallSize = CallNodes.size();
333 CallNodes.reserve(StartCallSize+DSG.CallNodes.size());
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000334
Chris Lattner1120c8b2002-03-28 17:56:03 +0000335 // Clone all of the arg nodes...
336 for (unsigned i = 0, e = DSG.ArgNodes.size(); i != e; ++i) {
337 ArgDSNode *New = cast<ArgDSNode>(DSG.ArgNodes[i]->clone());
338 NodeMap[DSG.ArgNodes[i]] = New;
339 ArgNodes.push_back(New);
340 }
341
342 // Clone all of the alloc nodes similarly...
343 for (unsigned i = 0, e = DSG.AllocNodes.size(); i != e; ++i) {
344 AllocDSNode *New = cast<AllocDSNode>(DSG.AllocNodes[i]->clone());
345 NodeMap[DSG.AllocNodes[i]] = New;
346 AllocNodes.push_back(New);
347 }
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000348
349 // Clone all of the shadow nodes similarly...
Chris Lattnerdd3fc182002-03-27 00:54:31 +0000350 for (unsigned i = 0, e = DSG.ShadowNodes.size(); i != e; ++i) {
351 ShadowDSNode *New = cast<ShadowDSNode>(DSG.ShadowNodes[i]->clone());
352 NodeMap[DSG.ShadowNodes[i]] = New;
353 ShadowNodes.push_back(New);
354 }
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000355
Chris Lattner1120c8b2002-03-28 17:56:03 +0000356 // Clone all of the global nodes...
357 for (unsigned i = 0, e = DSG.GlobalNodes.size(); i != e; ++i) {
358 GlobalDSNode *New = cast<GlobalDSNode>(DSG.GlobalNodes[i]->clone());
359 NodeMap[DSG.GlobalNodes[i]] = New;
360 GlobalNodes.push_back(New);
361 }
362
363 // Clone all of the call nodes...
364 for (unsigned i = 0, e = DSG.CallNodes.size(); i != e; ++i) {
365 CallDSNode *New = cast<CallDSNode>(DSG.CallNodes[i]->clone());
366 NodeMap[DSG.CallNodes[i]] = New;
367 CallNodes.push_back(New);
368 }
369
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000370 // Convert all of the links over in the nodes now that the map has been filled
371 // in all the way...
372 //
Chris Lattner1120c8b2002-03-28 17:56:03 +0000373 for (unsigned i = 0, e = DSG.ArgNodes.size(); i != e; ++i)
374 ArgNodes[i+StartArgSize]->mapNode(NodeMap, DSG.ArgNodes[i]);
375 for (unsigned i = 0, e = DSG.AllocNodes.size(); i != e; ++i)
376 AllocNodes[i+StartAllocSize]->mapNode(NodeMap, DSG.AllocNodes[i]);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000377 for (unsigned i = 0, e = DSG.ShadowNodes.size(); i != e; ++i)
378 ShadowNodes[i+StartShadowSize]->mapNode(NodeMap, DSG.ShadowNodes[i]);
Chris Lattner1120c8b2002-03-28 17:56:03 +0000379 for (unsigned i = 0, e = DSG.GlobalNodes.size(); i != e; ++i)
380 GlobalNodes[i+StartGlobalSize]->mapNode(NodeMap, DSG.GlobalNodes[i]);
381 for (unsigned i = 0, e = DSG.CallNodes.size(); i != e; ++i)
382 CallNodes[i+StartCallSize]->mapNode(NodeMap, DSG.CallNodes[i]);
383
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000384
385 if (CloneValueMap) {
386 // Convert value map... the values themselves stay the same, just the nodes
387 // have to change...
388 //
389 for (std::map<Value*,PointerValSet>::const_iterator I =DSG.ValueMap.begin(),
390 E = DSG.ValueMap.end(); I != E; ++I)
Chris Lattner1120c8b2002-03-28 17:56:03 +0000391 MapPVS(ValueMap[I->first], I->second, NodeMap, true);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000392 }
393
394 // Convert over return node...
395 PointerValSet RetVals;
396 MapPVS(RetVals, DSG.RetNode, NodeMap);
397 return RetVals;
398}
399
400
401FunctionDSGraph::~FunctionDSGraph() {
402 RetNode.clear();
403 ValueMap.clear();
Chris Lattner1120c8b2002-03-28 17:56:03 +0000404 for_each(ArgNodes.begin(), ArgNodes.end(),
405 mem_fun(&DSNode::dropAllReferences));
406 for_each(AllocNodes.begin(), AllocNodes.end(),
407 mem_fun(&DSNode::dropAllReferences));
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000408 for_each(ShadowNodes.begin(), ShadowNodes.end(),
409 mem_fun(&DSNode::dropAllReferences));
Chris Lattner1120c8b2002-03-28 17:56:03 +0000410 for_each(GlobalNodes.begin(), GlobalNodes.end(),
411 mem_fun(&DSNode::dropAllReferences));
412 for_each(CallNodes.begin(), CallNodes.end(),
413 mem_fun(&DSNode::dropAllReferences));
414 for_each(ArgNodes.begin(), ArgNodes.end(), deleter<DSNode>);
415 for_each(AllocNodes.begin(), AllocNodes.end(), deleter<DSNode>);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000416 for_each(ShadowNodes.begin(), ShadowNodes.end(), deleter<DSNode>);
Chris Lattner1120c8b2002-03-28 17:56:03 +0000417 for_each(GlobalNodes.begin(), GlobalNodes.end(), deleter<DSNode>);
418 for_each(CallNodes.begin(), CallNodes.end(), deleter<DSNode>);
Chris Lattnerbb2a28f2002-03-26 22:39:06 +0000419}
420