import soot.*;
import soot.jimple.*;
import soot.toolkits.scalar.*;
import soot.toolkits.graph.*;
import soot.util.*;
import soot.options.*;
import java.util.*;

public class FlowAnalysisClass extends <Forward/Backward>FlowAnalysis {
	FlowSet emptyset;

	protected void copy(Object src, Object dest) {
		FlowSet srcSet = (FlowSet) src, destSet = (FlowSet) dest;

		srcSet.copy(destSet);
	}

	protected void merge(Object src1, Object src2, Object dest){
		FlowSet srcSet1 = (FlowSet) src1,
						srcSet2 = (FlowSet) src2,
						destSet = (FlowSet) dest;

		/* depending on your analysis, this may not be union */
    srcSet1.union(srcSet2,destSet);
	}

	FlowAnalysisClass(UnitGraph g){
		super(g);

    /* you can choose your own Set here */
		emptyset = new ArraySparseSet();
		doAnalysis();
	}

	protected Object newInitialFlow(){
    /* this returns the initial flow info - here it is the emptyset */
		return emptyset.clone();
	}

	protected Object entryInitialFlow(){
    /* this returns the entry flow info - here it is the emptyset */
		return emptyset.clone();
	}

	protected void flowThrough(Object inset, Object unit, Object outset){
		FlowSet in = (FlowSet) inset, out = (FlowSet) outset;
		FlowSet gen = new ArraySparseSet();
		FlowSet kill = new ArraySparseSet();
		Unit s = (Unit) unit;
		List defs = s.getDefBoxes();
		List uses = s.getUseBoxes();

    /* based on this particular unit, and the information
     * from the in and out sets, as well as the defs and 
     * uses, calculate the in (or out) set 
     * 
     * After building the gens and kill sets, it may look
     * like this:
     * out(s) = gen(s) U (in(s) - kill(s)) */

     in.difference(kill,out);
		 out.union(gen,out);
	}
}
