package dk.brics.jspointers.flowgraph.analysis;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import dk.brics.tajs.flowgraph.BasicBlock;
import dk.brics.tajs.flowgraph.Function;
import dk.brics.tajs.flowgraph.Node;
import dk.brics.tajs.flowgraph.nodes.AssignmentNode;
/**
* For each assignment node, determines which nodes may read the variable it assigns.
* Requires the results from the reaching definitions analysis.
*/
public class ReachesTo {
private Map<Assignment,Set<Node>> reachesTo = new HashMap<Assignment,Set<Node>>();
private Set<Node> fetch(Assignment an) {
Set<Node> set = reachesTo.get(an);
if (set == null) {
set = new HashSet<Node>();
reachesTo.put(an, set);
}
return set;
}
public ReachesTo(Function function, ReachingDefs reachingDefs) {
for (BasicBlock block : function.getBlocks()) {
for (Node node : block.getNodes()) {
int[] vars = new ReadVarsVisitor().getReadVars(node);
for (int var : vars) {
Set<Assignment> assigns = reachingDefs.getReachingDefsForTempVar(node, var);
if (assigns == null)
continue;
for (Assignment an : assigns) {
fetch(an).add(node);
}
}
}
}
}
/**
* Returns the set of nodes that may read the value assigned by the given assignment node.
* @param an an assignment node
* @return unmodifiable set. Not null; possibly empty.
*/
public Set<Node> getReachesTo(AssignmentNode an) {
Set<Node> set = reachesTo.get(new TempVarAssignment(an));
if (set == null)
return Collections.<Node>emptySet();
else
return Collections.unmodifiableSet(set);
}
}