ROSE 0.11.145.354
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 Analysis()
217 {
218 parent = that.parent;
219 partitionCond = that.partitionCond;
220 }
221
223 {
224 this->parent = parent;
225 partitionCond = NULL;
226 }
227
229 {
230 delete partitionCond;
231 }
232
233 PartitionedAnalysis* getParent() const
234 {
235 return parent;
236 }
237
238 // A dummy analysis that is associated with facts connected with the
239 // IntraPartitionDataflow-specific logic rather than the logic of a class that
240 // derives from IntraPartitionDataflow.
241 // Analysis* dummy;
242
243 // Creates a new instance of the derived object that is a copy of the original instance.
244 // This instance will be used to instantiate a new partition of the analysis.
245 virtual IntraPartitionDataflow* copy()=0;
246
247 using IntraProceduralDataflow::runAnalysis;
248 virtual bool runAnalysis(const Function& func, NodeState* fState, bool& splitPart,
249 bool &joinPart, IntraPartitionDataflowCheckpoint*& outChkpt) = 0;
250
251 // Resumes the execution of runAnalysis from the given checkpoint
252 // splitPart - set by the call to indicate that it exited because it was split
253 // joinPart - set by the call to indicate that it exited because it wishes to join the partitions that it split from
254 // outChkpt - set by the call to be the checkpoint that representing the state of this analysis at the time of the exit
255 // set to NULL in the case of a normal exit or a split exit
256 virtual bool runAnalysisResume(const Function& func, NodeState* fState,
257 IntraPartitionDataflowCheckpoint* chkpt, bool& splitPart,
258 bool &joinPart, IntraPartitionDataflowCheckpoint*& outChkpt)=0;
259
260 // Called when a partition is created to allow a specific analysis to initialize
261 // its dataflow information from the partition condition
262 virtual void initDFfromPartCond(const Function &, const DataflowNode &, NodeState &,
263 const std::vector<Lattice*> &, const std::vector<NodeFact*> &,
264 /*LogicalCond*/printable*) {
265 }
266};
267
269{
270 public:
271 // A checkpoint of the dataflow state associated with the given state of the dataflow analysis
272 dataflow::checkpoint dfChkpt;
273 // Set of nodes that this analysis has blocked progress on until the next join point
274 std::set<DataflowNode> joinNodes;
275 // The DataflowNode that that analysis was processing when the checkpoint was taken
276 DataflowNode* curNode;
277 // The logical condition that is an invariant of all the states of the dataflow analysis
278 /*LogicalCond*/printable* partitionCond;
279 // Given that the current node in the dataflow analysis has one or more successors, the index of
280 // the given node's successor
281 int partitionIndex;
282
283 // the arguments to runAnalysis() used as part of the dataflow pass
284 const Function& func;
285 NodeState* fState;
286
288 dfChkpt(that.dfChkpt), func(that.func)
289 {
290 this->joinNodes = that.joinNodes;
291 if(that.curNode)
292 this->curNode = new DataflowNode(*(that.curNode));
293 else
294 this->curNode = NULL;
295
296 this->partitionCond = that.partitionCond;
297 this->partitionIndex = that.partitionIndex;
298 this->fState = that.fState;
299 }
300
301 IntraPartitionDataflowCheckpoint(dataflow::checkpoint& dfChkpt, const std::set<DataflowNode>& joinNodes,
302 const DataflowNode* curNode,
303 /*LogicalCond*/printable* partitionCond, int partitionIndex,
304 const Function& func, NodeState* fState) :
305 dfChkpt(dfChkpt), func(func)
306 {
307 this->joinNodes = joinNodes;
308 if(curNode)
309 this->curNode = new DataflowNode(*curNode);
310 else
311 this->curNode = NULL;
312
313 this->partitionCond = partitionCond;
314 this->partitionIndex = partitionIndex;
315 this->fState = fState;
316 }
317
319 {
320 //delete partitionCond;
321 if(curNode)
322 delete curNode;
323 }
324
325 std::string str(std::string indent="")
326 {
327 std::ostringstream outs;
328 outs << indent << "[IntraPartitionDataflowCheckpoint : \n"; //fflush(stdout);
329 outs << indent << " dfChkpt = \n"<<dfChkpt.str(indent+" ")<<"\n";
330 if(curNode)
331 outs << indent << " curNode = <"<<curNode->getNode()->class_name()<<" | "<<curNode->getNode()->unparseToString()<<" | "<< curNode->getIndex() << ">\n";
332 else
333 outs << indent << " curNode = NULL\n";
334
335 if(joinNodes.size()==0)
336 outs << indent << " joinNodes = None\n";
337 else
338 {
339 outs << indent << " joinNodes = \n";
340 for(std::set<DataflowNode>::iterator it=joinNodes.begin(); it!=joinNodes.end(); it++)
341 { outs << indent << " <"<<(*it).getNode()->class_name()<<" | "<<(*it).getNode()->unparseToString()<<">\n"; }
342 }
343 if(partitionCond)
344 outs << indent << " partitionCond = \n"<<partitionCond->str(indent+" ")<<"\n";
345
346 if(partitionIndex>=0)
347 outs << indent << " partitionIndex = descendant "<<partitionIndex<<"]";
348 else
349 outs << indent << " partitionIndex = all descendants ("<<partitionIndex<<")]";
350 return outs.str();
351 }
352};
353
355{
356 public:
358 { }
359
362 {
363 }
364
365 /*IntraPartitionFWDataflow(): IntraPartitionDataflow()
366 { }*/
367
368 // the transfer function that is applied to every node
369 // n - the dataflow node that is being processed
370 // state - the NodeState object that describes the state of the node, as established by earlier
371 // analysis passes
372 // dfInfo - the Lattices that this transfer function operates on. The function takes these lattices
373 // as input and overwrites them with the result of the transfer.
374 // splitAnalysis - set by callee to
375 // - noSplit if the analysis does not want a split
376 // - splitNew if the analysis wants to perform a split and place the newly-generated partitions into
377 // a fresh split set that is nested inside this partition's current split
378 // - splitParent if the analysis wants to perform a split and place the newly-generated partitions
379 // into this partition's current split (i.e. on the same split level as the current partition)
380 typedef enum {noSplit, splitNew, splitParent} splitType;
381 // splitConditions - if splitAnalysis==splitNew or ==splitParent, the analysis sets this vector to the conditions for all the
382 // descendant CFG nodes in the split
383 /* // joinAnalysis - set to true if the analysis wants to perform a join */
384 // joinNode - set to true if progress along the given dataflow node needs to be blocked until the next join point.
385 // If all paths of dataflow progress are blocked in this analysis, this is the same as the analysis
386 // requesting to be joined.
387 // Returns true if any of the input lattices changed as a result of the transfer function and
388 // false otherwise.
389 virtual bool transfer(const Function& func, const DataflowNode& n, NodeState& state, const std::vector<Lattice*>& dfInfo,
390 splitType& splitAnalysis, std::vector</*LogicalCond*/printable*>& splitConditions, /*bool& joinAnalysis, */bool& joinNode)=0;
391
392 // Runs the intra-procedural analysis on the given function. Returns true if
393 // the function's NodeState gets modified as a result and false otherwise.
394 // state - the function's NodeState
395 bool runAnalysis(const Function& func, NodeState* fState, bool analyzeDueToCallers, std::set<Function> calleesUpdated);
396
397 // Runs the intra-procedural analysis on the given function.
398 // Returns true if the function's NodeState gets modified as a result and false otherwise.
399 // state - the function's NodeState
400 bool runAnalysis(const Function& func, NodeState* fState,
401 bool& splitPart, bool &joinPart, IntraPartitionDataflowCheckpoint*& outChkpt);
402
403 // Resumes the execution of runAnalysis from the given checkpoint
404 bool runAnalysisResume(const Function& func, NodeState* fState,
405 IntraPartitionDataflowCheckpoint* chkpt, bool& splitPart,
406 bool &joinPart, IntraPartitionDataflowCheckpoint*& outChkpt);
407
408 typedef enum {retFalse, cont, normal} partitionTranferRet;
409
410 partitionTranferRet partitionTranfer(
411 const Function& func, NodeState* fState, const DataflowNode& n, NodeState* state, VirtualCFG::dataflow& dfIt,
412 const std::vector<Lattice*>& dfInfoBelow, bool& splitPart, std::set<DataflowNode>& joinNodes,
414
415 // propagates the forward dataflow info from the current node's NodeState (curNodeState) to the next node's
416 // NodeState (nextNodeState)
417 bool propagateFWStateToNextNode(
418 const std::vector<Lattice*>& curNodeState, DataflowNode curDFNode, int nodeIndex,
419 const std::vector<Lattice*>& nextNodeState, DataflowNode nextDFNode);
420};
421
422#endif
423#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