package x10.wala.util;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Stack;
import com.ibm.wala.cfg.ControlFlowGraph;
import com.ibm.wala.ssa.ISSABasicBlock;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.util.graph.dominators.NumberedDominators;
public class NatLoopSolver {
/**
* given a control flow graph and two nodes in the graph, return
* a list of nodes that forms a loop. In cfg, "start" dominates "end".
* @param start of the loop
* @param end of the loop
* @param control flow graph
* @return a loop starts from "start" and ends at "end".
*/
public static NatLoop findOneLoop(ISSABasicBlock start, ISSABasicBlock end,
ControlFlowGraph<SSAInstruction,ISSABasicBlock> cfg){
Stack<ISSABasicBlock> st = new Stack<ISSABasicBlock>();
NatLoop loop = new NatLoop(start,end);
ISSABasicBlock p,q;
if(start.getNumber()!=end.getNumber()){
st.push(end);
}
while(!st.isEmpty()){
p = st.pop();
Iterator<ISSABasicBlock> it = cfg.getPredNodes(p);
while (it.hasNext()) {
q = it.next();
if(!loop.isInLoop(q)){
loop.addNode(q);
st.push(q);
}
}
}
return loop;
}
/**
* findAllLoops does a depth-first search on cfg, when it sees a "back edge" it calls
* findOneLoop to find all nodes belongs to this natural loop. Finally, it returns a
* set of loops in this cfg.
*
* @param cfg is the control flow graph
* @param dom is a set of "domination-relationship" of all nodes in cfg
* @param loops contains all loops found in cfg as the return value
* @param visited contains nodes that have been visited in cfg
* @param cur is the number of current node to be visited
*/
public static void findAllLoops(ControlFlowGraph<SSAInstruction,ISSABasicBlock> cfg,
NumberedDominators<ISSABasicBlock> dom, HashSet<NatLoop> loops, HashSet<Integer> visited, ISSABasicBlock curblk){
//DFS
assert(curblk!=null);
Iterator<ISSABasicBlock> it = cfg.getSuccNodes(curblk);
while (it.hasNext()) {
ISSABasicBlock nextblk = it.next();
if(dom.isDominatedBy(curblk, nextblk)){
NatLoop nl = findOneLoop(nextblk,curblk,cfg);
assert(nl!=null);
loops.add(nl);
}
if (!visited.contains(Integer.valueOf(nextblk.getNumber()))) {
visited.add(Integer.valueOf(nextblk.getNumber()));
findAllLoops(cfg,dom,loops,visited,nextblk);
}
}
}
/**
*
* @param loops: the set of loops found in a control flow graph
* @param n: block(node of a cfg) number
* @return a set of all loops that contain this block n
*/
public static HashSet<NatLoop> getLoops(HashSet<NatLoop> loops, ISSABasicBlock n){
HashSet<NatLoop> targets = new HashSet<NatLoop>();
Iterator<NatLoop> it = loops.iterator();
while(it.hasNext()){
NatLoop l = it.next();
if(l.isInLoop(n)){
targets.add(l);
}
}
return targets;
}
public static boolean containsNode(HashSet<NatLoop> loops, ISSABasicBlock n){
HashSet<NatLoop> targets = getLoops(loops,n);
if(targets.size()>0){
return true;
}
return false;
}
/**
* print all loops in a set in the format of "#id loop[start,end]: {all nodes of this loop}"
* For example, we might see "1 loop[2,9]: {2 3 8 9}".
*
* @param loops to be printed
*/
public static void printAllLoops(HashSet<NatLoop> loops){
Iterator<NatLoop> it = loops.iterator();
int cnt = 1;
while(it.hasNext()){
NatLoop l = it.next();
System.out.println(cnt+"\tloop["+l.getStart().getNumber()+","+l.getEnd().getNumber()+"]:\t{"+l.toString()+"}");
cnt++;
}
}
}