ROSE 0.11.145.147
partitionedAnalysis.h
1#include <featureTests.h>
2#ifdef ROSE_ENABLE_SOURCE_ANALYSIS
3
4#ifndef PARTITIONED_ANALYSIS_H
5#define PARTITIONED_ANALYSIS_H
6
7#include <sage3.h>
8
9#include "genericDataflowCommon.h"
10#include "variables.h"
11#include "cfgUtils.h"
12#include "analysisCommon.h"
13#include "functionState.h"
14#include "latticeFull.h"
15#include "analysis.h"
16#include "dataflow.h"
17#include "VirtualCFGIterator.h"
18#include "LogicalCond.h"
19#include "printAnalysisStates.h"
20
21#include <list>
22#include <sstream>
23#include <iostream>
24#include <fstream>
25#include <string>
26#include <vector>
27
30
31// Set of partition dataflow analyses that were split in a given call to split.
32// The original analysis that was split is explicitly identified as the "master" of the split.
34{
35 public:
36 std::set<IntraPartitionDataflow*> splitSet;
38
40 {
41 this->master = master;
42 splitSet.insert(master);
43 }
44
45 void addChild(IntraPartitionDataflow* child)
46 {
47 splitSet.insert(child);
48 }
49
50 std::string str(std::string indent="")
51 {
52 std::ostringstream oss;
53
54 oss << indent << "[partSplit:\n";
55 oss << indent << " splitSet = <";
56 for(std::set<IntraPartitionDataflow*>::iterator it=splitSet.begin(); it!=splitSet.end(); )
57 {
58 oss << (*it);
59 it++;
60 if(it!=splitSet.end()) oss << ", ";
61 }
62 oss << ">\n";
63 oss << indent << " master = "<< master << "]\n";
64
65 return oss.str();
66 }
67};
68
70{
71 // the partitions that are currently executing
72 std::set<IntraPartitionDataflow*> activeParts;
73 // the set of partitions that are currently blocked and need to be explicitly
74 // unblocked before they may resume execution
75 //std::set<IntraPartitionDataflow*> blockedParts;
76 // the set of partitions that have called join and are simply waiting to be joined
77 // to the master partitions that they split from
78 std::set<IntraPartitionDataflow*> joinParts;
79
80 // Maps partitions to their respective splits. A given partition may be split
81 // multiple times in a hierarchical fashion (split-join). The first split
82 // in the list corresponds to the outer-most split and the last split
83 // is the inner-most split. Thus, if a given partition performs a join,
84 // the jointed split is the last/inner-most split in parts2splits.
85 std::map<IntraPartitionDataflow*, std::list<partSplit*> > parts2splits;
86
87 // Maps analysis partitions to their respective current execution states
88 // (these are only upto-date for analyses that are currently stopped)
89 std::map<IntraPartitionDataflow*, IntraPartitionDataflowCheckpoint*> parts2chkpts;
90
91 // Sample interprocedural analysis object that we'll use as a factory to create more such objects
92 IntraPartitionDataflow* intraFactory;
93
94 public:
95 // Creates a PartitionedAnalysis, starting the analysis with the given
96 // master analysis partition and creating an initial split that only contains the master.
98
99 // Create the initial partition state for analyzing some function
100 void initMaster();
101
102 // Returns a reference to the master dataflow analysis. At the end of the partitioned analysis,
103 // it is this object that owns all the dataflow state generated by the overall analysis.
104 IntraPartitionDataflow* getMasterDFAnalysis();
105
106 // Activates the given partition, returning true if it was previously inactive and false otherwise.
107 bool activatePart(IntraPartitionDataflow* part);
108
109 // Splits the given dataflow analysis partition into several partitions, one for each given checkpoint
110 // The partition origA will be assigned the last checkpoint in partitionChkpts.
111 // If newSplit==true, this split operation creates a new split within origA's current split and place
112 // the newly-generated partitions into this split.
113 // If newSplit==false, the newly-generated partitions will be added to origA's current split.
114 // If newPartActive==true, the newly-generated partitions will be made initially active. If not,
115 // they will start out in joined status.
116 // Returns the set of newly-created partitions.
117 std::set<IntraPartitionDataflow*> split(IntraPartitionDataflow* origA, std::vector<IntraPartitionDataflowCheckpoint*> partitionChkpts,
118 const Function& func, NodeState* fState, bool newSplit, bool newPartActive);
119
120 // Joins all the analysis partitions in a given split into a single partition, unioning
121 // their respective dataflow information
123 const Function& func, NodeState* fState);
124
125 // Called by the base PartitionedAnalysis class when all partitions in a given split have decided
126 // to join to decide whether they should be joined or all released. It may also do some
127 // processing of their state prior to the release or join.
128 // Returns the set of partitions that will remain in joined status after this join. If all partitions in the split
129 // set are on this list, they are all joined(all but one will be deleted). Any remaining partitions will be released.
130 virtual std::set<IntraPartitionDataflow*> preJoin(partSplit* s, const Function& func, NodeState* fState,
131 const std::map<IntraPartitionDataflow*,
132 IntraPartitionDataflowCheckpoint*>& parts2chkpts)=0;
133
134 // Called by the base PartitionedAnalysis class when all partitions in a given split have
135 // finished their respective executions.
136 virtual void postFinish(partSplit* s,
137 const std::map<IntraPartitionDataflow*, IntraPartitionDataflowCheckpoint*>& parts2chkpts)=0;
138
139 // runs the intra-procedural analysis on the given function, returns true if
140 // the function's NodeState gets modified as a result and false otherwise
141 // state - the function's NodeState
142 bool runAnalysis(const Function& func, NodeState* state);
143};
144
145// Given a source analysis, splits the dataflow states of all the CFG nodes in
146// a given function so that the target analysis gets copies of the source analysis'
147// state.
149{
150 Analysis* srcAnalysis;
151 Analysis* tgtAnalysis;
152
153 public:
154 partitionDFAnalysisState(Analysis* srcAnalysis, Analysis* tgtAnalysis)
155 {
156 this->srcAnalysis = srcAnalysis;
157 this->tgtAnalysis = tgtAnalysis;
158 }
159
160 void visit(const Function &/*func*/, const DataflowNode &/*n*/, NodeState &state)
161 {
162 state.cloneAnalysisState(srcAnalysis, tgtAnalysis);
163 }
164};
165
166// Given a set of analyses, one of which is designated as a master, unions together the
167// dataflow states associated on each CFG node with each of these analyses.
168// The results are associated on each CFG node with the master analysis.
170{
171 std::set<Analysis*> unionSet;
172 Analysis* master;
173
174 public:
176 std::set<Analysis*>& unionSet, Analysis* master)
177 {
178 for(std::set<Analysis*>::iterator it = unionSet.begin(); it!=unionSet.end(); it++)
179 { this->unionSet.insert(*it); }
180 //this->unionSet = unionSet;
181 this->master = master;
182 }
183
184 void visit(const Function& func, const DataflowNode& n, NodeState& state);
185};
186
187// Deletes all the state associated with the given analyses
189{
190 std::set<IntraPartitionDataflow*> tgtA;
191
192 public:
193 deleteDFAnalysisState(std::set<IntraPartitionDataflow*>& tgtA)
194 {
195 this->tgtA = tgtA;
196 }
197
198 void visit(const Function &/*func*/, const DataflowNode &/*n*/, NodeState &state)
199 {
200 for(std::set<IntraPartitionDataflow*>::iterator it = tgtA.begin(); it!=tgtA.end(); it++)
201 state.deleteState((Analysis*)*it);
202 }
203};
204
205
207{
208 protected:
209 PartitionedAnalysis* parent;
210
211 public:
212 // The logic expression that describes the invariant that holds for this partition
213 /*LogicalCond*/printable* partitionCond;
214
216 {
217 parent = that.parent;
218 partitionCond = that.partitionCond;
219 }
220
222 {
223 this->parent = parent;
224 partitionCond = NULL;
225 }
226
228 {
229 delete partitionCond;
230 }
231
232 PartitionedAnalysis* getParent() const
233 {
234 return parent;
235 }
236
237 // A dummy analysis that is associated with facts connected with the
238 // IntraPartitionDataflow-specific logic rather than the logic of a class that
239 // derives from IntraPartitionDataflow.
240 // Analysis* dummy;
241
242 // Creates a new instance of the derived object that is a copy of the original instance.
243 // This instance will be used to instantiate a new partition of the analysis.
244 virtual IntraPartitionDataflow* copy()=0;
245
246 using IntraProceduralDataflow::runAnalysis;
247 virtual bool runAnalysis(const Function& func, NodeState* fState, bool& splitPart,
248 bool &joinPart, IntraPartitionDataflowCheckpoint*& outChkpt) = 0;
249
250 // Resumes the execution of runAnalysis from the given checkpoint
251 // splitPart - set by the call to indicate that it exited because it was split
252 // joinPart - set by the call to indicate that it exited because it wishes to join the partitions that it split from
253 // outChkpt - set by the call to be the checkpoint that representing the state of this analysis at the time of the exit
254 // set to NULL in the case of a normal exit or a split exit
255 virtual bool runAnalysisResume(const Function& func, NodeState* fState,
256 IntraPartitionDataflowCheckpoint* chkpt, bool& splitPart,
257 bool &joinPart, IntraPartitionDataflowCheckpoint*& outChkpt)=0;
258
259 // Called when a partition is created to allow a specific analysis to initialize
260 // its dataflow information from the partition condition
261 virtual void initDFfromPartCond(const Function &, const DataflowNode &, NodeState &,
262 const std::vector<Lattice*> &, const std::vector<NodeFact*> &,
263 /*LogicalCond*/printable*) {
264 }
265};
266
268{
269 public:
270 // A checkpoint of the dataflow state associated with the given state of the dataflow analysis
271 dataflow::checkpoint dfChkpt;
272 // Set of nodes that this analysis has blocked progress on until the next join point
273 std::set<DataflowNode> joinNodes;
274 // The DataflowNode that that analysis was processing when the checkpoint was taken
275 DataflowNode* curNode;
276 // The logical condition that is an invariant of all the states of the dataflow analysis
277 /*LogicalCond*/printable* partitionCond;
278 // Given that the current node in the dataflow analysis has one or more successors, the index of
279 // the given node's successor
280 int partitionIndex;
281
282 // the arguments to runAnalysis() used as part of the dataflow pass
283 const Function& func;
284 NodeState* fState;
285
287 dfChkpt(that.dfChkpt), func(that.func)
288 {
289 this->joinNodes = that.joinNodes;
290 if(that.curNode)
291 this->curNode = new DataflowNode(*(that.curNode));
292 else
293 this->curNode = NULL;
294
295 this->partitionCond = that.partitionCond;
296 this->partitionIndex = that.partitionIndex;
297 this->fState = that.fState;
298 }
299
300 IntraPartitionDataflowCheckpoint(dataflow::checkpoint& dfChkpt, const std::set<DataflowNode>& joinNodes,
301 const DataflowNode* curNode,
302 /*LogicalCond*/printable* partitionCond, int partitionIndex,
303 const Function& func, NodeState* fState) :
304 dfChkpt(dfChkpt), func(func)
305 {
306 this->joinNodes = joinNodes;
307 if(curNode)
308 this->curNode = new DataflowNode(*curNode);
309 else
310 this->curNode = NULL;
311
312 this->partitionCond = partitionCond;
313 this->partitionIndex = partitionIndex;
314 this->fState = fState;
315 }
316
318 {
319 //delete partitionCond;
320 if(curNode)
321 delete curNode;
322 }
323
324 std::string str(std::string indent="")
325 {
326 std::ostringstream outs;
327 outs << indent << "[IntraPartitionDataflowCheckpoint : \n"; //fflush(stdout);
328 outs << indent << " dfChkpt = \n"<<dfChkpt.str(indent+" ")<<"\n";
329 if(curNode)
330 outs << indent << " curNode = <"<<curNode->getNode()->class_name()<<" | "<<curNode->getNode()->unparseToString()<<" | "<< curNode->getIndex() << ">\n";
331 else
332 outs << indent << " curNode = NULL\n";
333
334 if(joinNodes.size()==0)
335 outs << indent << " joinNodes = None\n";
336 else
337 {
338 outs << indent << " joinNodes = \n";
339 for(std::set<DataflowNode>::iterator it=joinNodes.begin(); it!=joinNodes.end(); it++)
340 { outs << indent << " <"<<(*it).getNode()->class_name()<<" | "<<(*it).getNode()->unparseToString()<<">\n"; }
341 }
342 if(partitionCond)
343 outs << indent << " partitionCond = \n"<<partitionCond->str(indent+" ")<<"\n";
344
345 if(partitionIndex>=0)
346 outs << indent << " partitionIndex = descendant "<<partitionIndex<<"]";
347 else
348 outs << indent << " partitionIndex = all descendants ("<<partitionIndex<<")]";
349 return outs.str();
350 }
351};
352
354{
355 public:
357 { }
358
361 {
362 }
363
364 /*IntraPartitionFWDataflow(): IntraPartitionDataflow()
365 { }*/
366
367 // the transfer function that is applied to every node
368 // n - the dataflow node that is being processed
369 // state - the NodeState object that describes the state of the node, as established by earlier
370 // analysis passes
371 // dfInfo - the Lattices that this transfer function operates on. The function takes these lattices
372 // as input and overwrites them with the result of the transfer.
373 // splitAnalysis - set by callee to
374 // - noSplit if the analysis does not want a split
375 // - splitNew if the analysis wants to perform a split and place the newly-generated partitions into
376 // a fresh split set that is nested inside this partition's current split
377 // - splitParent if the analysis wants to perform a split and place the newly-generated partitions
378 // into this partition's current split (i.e. on the same split level as the current partition)
379 typedef enum {noSplit, splitNew, splitParent} splitType;
380 // splitConditions - if splitAnalysis==splitNew or ==splitParent, the analysis sets this vector to the conditions for all the
381 // descendant CFG nodes in the split
382 /* // joinAnalysis - set to true if the analysis wants to perform a join */
383 // joinNode - set to true if progress along the given dataflow node needs to be blocked until the next join point.
384 // If all paths of dataflow progress are blocked in this analysis, this is the same as the analysis
385 // requesting to be joined.
386 // Returns true if any of the input lattices changed as a result of the transfer function and
387 // false otherwise.
388 virtual bool transfer(const Function& func, const DataflowNode& n, NodeState& state, const std::vector<Lattice*>& dfInfo,
389 splitType& splitAnalysis, std::vector</*LogicalCond*/printable*>& splitConditions, /*bool& joinAnalysis, */bool& joinNode)=0;
390
391 // Runs the intra-procedural analysis on the given function. Returns true if
392 // the function's NodeState gets modified as a result and false otherwise.
393 // state - the function's NodeState
394 bool runAnalysis(const Function& func, NodeState* fState, bool analyzeDueToCallers, std::set<Function> calleesUpdated);
395
396 // Runs the intra-procedural analysis on the given function.
397 // Returns true if the function's NodeState gets modified as a result and false otherwise.
398 // state - the function's NodeState
399 bool runAnalysis(const Function& func, NodeState* fState,
400 bool& splitPart, bool &joinPart, IntraPartitionDataflowCheckpoint*& outChkpt);
401
402 // Resumes the execution of runAnalysis from the given checkpoint
403 bool runAnalysisResume(const Function& func, NodeState* fState,
404 IntraPartitionDataflowCheckpoint* chkpt, bool& splitPart,
405 bool &joinPart, IntraPartitionDataflowCheckpoint*& outChkpt);
406
407 typedef enum {retFalse, cont, normal} partitionTranferRet;
408
409 partitionTranferRet partitionTranfer(
410 const Function& func, NodeState* fState, const DataflowNode& n, NodeState* state, VirtualCFG::dataflow& dfIt,
411 const std::vector<Lattice*>& dfInfoBelow, bool& splitPart, std::set<DataflowNode>& joinNodes,
413
414 // propagates the forward dataflow info from the current node's NodeState (curNodeState) to the next node's
415 // NodeState (nextNodeState)
416 bool propagateFWStateToNextNode(
417 const std::vector<Lattice*>& curNodeState, DataflowNode curDFNode, int nodeIndex,
418 const std::vector<Lattice*>& nextNodeState, DataflowNode nextDFNode);
419};
420
421#endif
422#endif
virtual std::string unparseToString(SgUnparse_Info *info) const
This function unparses the AST node (excluding comments and unnecessary white space)
virtual std::string class_name() const
returns a string representing the class name