All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.jimple.toolkits.annotation.parity.ParityAnalysis Maven / Gradle / Ivy

There is a newer version: 1.12.0
Show newest version
/* Soot - a J*va Optimization Framework
 * Copyright (C) 2003 Jennifer Lhotak
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

package soot.jimple.toolkits.annotation.parity;

import soot.*;
import soot.util.*;
import java.util.*;

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

// STEP 1: What are we computing?
// SETS OF PAIRS of form (X, T) => Use ArraySparseSet.
//
// STEP 2: Precisely define what we are computing.
// For each statement compute the parity of all variables 
// in the program.
// 
// STEP 3: Decide whether it is a backwards or forwards analysis.
// FORWARDS
//
//
public class ParityAnalysis extends ForwardFlowAnalysis {

    private UnitGraph g;
    private final static String TOP = "top";
    private final static String BOTTOM = "bottom";
    private final static String EVEN = "even";
    private final static String ODD = "odd";

    private LiveLocals filter;
    
    public ParityAnalysis(UnitGraph g, LiveLocals filter)
    {
        super(g);
        this.g = g;

        this.filter = filter;
        
        filterUnitToBeforeFlow = new HashMap();
        buildBeforeFilterMap();
        
        filterUnitToAfterFlow = new HashMap();
        
        doAnalysis();
        
    }

    public ParityAnalysis(UnitGraph g){
        super(g);
        this.g = g;

        doAnalysis();
    }
    
    private void buildBeforeFilterMap(){
        
        Iterator it = g.getBody().getUnits().iterator();
        while (it.hasNext()){
            Stmt s = (Stmt)it.next();
            //if (!(s instanceof DefinitionStmt)) continue;
            //Value left = ((DefinitionStmt)s).getLeftOp();
            //if (!(left instanceof Local)) continue;
        
            //if (!((left.getType() instanceof IntegerType) || (left.getType() instanceof LongType))) continue;
            List list = filter.getLiveLocalsBefore(s);
            HashMap map = new HashMap(); 
            Iterator listIt = list.iterator();
            while (listIt.hasNext()){
                map.put(listIt.next(), BOTTOM);
            }
            filterUnitToBeforeFlow.put(s, map);
        } 
        //System.out.println("init filtBeforeMap: "+filterUnitToBeforeFlow);           
    }

// STEP 4: Is the merge operator union or intersection?
// 
// merge  | bottom | even   | odd   | top
// -------+--------+--------+-------+--------
// bottom | bottom | even   | odd   | top
// -------+--------+--------+-------+--------
// even   | even   | even   | top   | top
// -------+--------+--------+-------+--------
// odd    | odd    | top    | odd   | top  
// -------+--------+--------+-------+--------
// top    | top    | top    | top   | top
//

    protected void merge(Object in1, Object in2, Object out)
    {
	HashMap inMap1 = (HashMap) in1;
	HashMap inMap2 = (HashMap) in2;
	HashMap outMap = (HashMap) out;

	Set keys = inMap1.keySet();
	Iterator it = keys.iterator();
	while (it.hasNext()) {
	 	Object var1 = it.next();
        //System.out.println(var1);
		String inVal1 = (String)inMap1.get(var1);
        //System.out.println(inVal1);
		String inVal2 = (String)inMap2.get(var1);
        //System.out.println(inVal2);
       // System.out.println("before out "+outMap.get(var1));

        if (inVal2 == null){
            outMap.put(var1, inVal1);
        }
	    else if (inVal1.equals(BOTTOM)) {
			outMap.put(var1, inVal2);
		}
		else if (inVal2.equals(BOTTOM)) {
		        outMap.put(var1, inVal1);
		}
		else if ((inVal1.equals(EVEN)) &&
		   	(inVal2.equals(EVEN))) {
			outMap.put(var1, EVEN);
		}
		else if ((inVal1.equals(ODD)) &&
		   	(inVal2.equals(ODD))) {
			outMap.put(var1, ODD);
		}
		else {
			outMap.put(var1, TOP);
		}
	}
	
    }

// STEP 5: Define flow equations.
// in(s) = ( out(s) minus defs(s) ) union uses(s)
//

    protected void copy(Object source, Object dest) {

        //System.out.println("copy");
        HashMap sourceIn = (HashMap)source;
        HashMap destOut = (HashMap)dest;
        //dest = new HashMap();
        //HashMap destOut = new HashMap();
        destOut.putAll(sourceIn);
        dest = destOut;

    }
   
    // Parity Tests: 	even + even = even
    // 			even + odd = odd 
    // 			odd + odd = even
    //
    // 			even * even = even
    // 			even * odd = even
    // 			odd * odd = odd
    //
    // 			constants are tested mod 2
    //

    private String getParity(HashMap in, Value val) {
        //System.out.println("get Parity in: "+in);
        if ((val instanceof AddExpr) | (val instanceof SubExpr)) {
        	String resVal1 = getParity(in, ((BinopExpr)val).getOp1());
	        String resVal2 = getParity(in, ((BinopExpr)val).getOp2());
	        if (resVal1.equals(TOP) | resVal2.equals(TOP)) {
                return TOP;
	        }  
            else if (resVal1.equals(BOTTOM) | resVal2.equals(BOTTOM)){
                return BOTTOM;
            }
	        else if (resVal1.equals(resVal2)) {
                return EVEN;
	        }
	        else {
	            return ODD;
	        }
        }
        else if (val instanceof MulExpr) {
	        String resVal1 = getParity(in, ((BinopExpr)val).getOp1());
	        String resVal2 = getParity(in, ((BinopExpr)val).getOp2());
	        if (resVal1.equals(TOP) | resVal2.equals(TOP)) {
	            return TOP;
	        }
            else if (resVal1.equals(BOTTOM) | resVal2.equals(BOTTOM)){
                return BOTTOM;
            }
	        else if (resVal1.equals(ODD) && resVal2.equals(ODD)) {
	            return ODD;
	        }
	        else {
	            return EVEN;
	        }
        }
        else if (val instanceof IntConstant) {
	        int value = ((IntConstant)val).value;
	        if ((value % 2) == 0) {
                return EVEN;
	        }
	        else {
	            return ODD;
	        }
        }
        else if (val instanceof LongConstant) {
	        long value = ((LongConstant)val).value;
	        if ((value % 2) == 0) {
	            return EVEN;
	        }
	        else {
	            return ODD;
	        }
        }
        else if (in.containsKey(val)) {
      	    return in.get(val);
        }
        else {
            return TOP;
        }
     
    }
    
    
    protected void flowThrough(Object inValue, Object unit,
            Object outValue)
    {
        HashMap in  = (HashMap) inValue;
        HashMap out = (HashMap) outValue;
        Stmt    s   = (Stmt)    unit;

	    // copy in to out 
	    out.putAll(in);
	
        // for each stmt where leftOp is defintionStmt find the parity
	    // of rightOp and update parity to EVEN, ODD or TOP

        //boolean useS = false;
        
	    if (s instanceof DefinitionStmt) {
	        Value left = ((DefinitionStmt)s).getLeftOp();
	        if (left instanceof Local) {
                if ((left.getType() instanceof IntegerType) || (left.getType() instanceof LongType)){
                    //useS = true;
	  	            Value right = ((DefinitionStmt)s).getRightOp();
		            out.put(left, getParity(out, right));
                }
	        }
	    }

        // get all use and def boxes of s 
        // if use or def is int or long constant add their parity
        Iterator it = s.getUseAndDefBoxes().iterator();
        while (it.hasNext()){
            Object next = it.next();
            Value val = ((ValueBox)next).getValue();
            //System.out.println("val: "+val.getClass());
            if (val instanceof ArithmeticConstant){
                out.put(val, getParity(out, val));
                //System.out.println("out map: "+out);
            }
        }
        
        //if (useS){
        if (Options.v().interactive_mode()){
            buildAfterFilterMap(s);
            updateAfterFilterMap(s);
        }
        //}
    }
    
    private void buildAfterFilterMap(Stmt s){
        
        List list = filter.getLiveLocalsAfter(s);
        HashMap map = new HashMap(); 
        Iterator listIt = list.iterator();
        while (listIt.hasNext()){
            map.put(listIt.next(), BOTTOM);
        }
        filterUnitToAfterFlow.put(s, map);
        //System.out.println("built afterflow filter map: "+filterUnitToAfterFlow);
    }


// STEP 6: Determine value for start/end node, and
// initial approximation.
//
// start node: locals with BOTTOM
// initial approximation: locals with BOTTOM
    protected Object entryInitialFlow()
    {
	/*HashMap initMap = new HashMap();
	
	Chain locals = g.getBody().getLocals();
	Iterator it = locals.iterator();
	while (it.hasNext()) {
	  initMap.put(it.next(), BOTTOM);
	}
        return initMap;*/

        return newInitialFlow();
    }

    private void updateBeforeFilterMap(){
    
        Iterator filterIt = filterUnitToBeforeFlow.keySet().iterator();
        while (filterIt.hasNext()){
            Stmt s = filterIt.next();
            HashMap allData = (HashMap)unitToBeforeFlow.get(s);
            
            HashMap filterData = (HashMap) filterUnitToBeforeFlow.get(s);

            filterUnitToBeforeFlow.put(s, updateFilter(allData, filterData));
            
        }
    }
        
    private void updateAfterFilterMap(Stmt s){
    
        HashMap allData = (HashMap)unitToAfterFlow.get(s);
            
        HashMap filterData = (HashMap) filterUnitToAfterFlow.get(s);

        filterUnitToAfterFlow.put(s, updateFilter(allData, filterData));
            
    }
        
    private HashMap updateFilter(HashMap allData, HashMap filterData){

        if (allData == null) return filterData;
        Iterator filterVarsIt = filterData.keySet().iterator();
        ArrayList toRemove = new ArrayList();
        while (filterVarsIt.hasNext()){
            Value v = filterVarsIt.next();
            if (allData.get(v) == null){
                toRemove.add(v);
                //filterData.put(v, new HashMap());
            }
            else {
                filterData.put(v, allData.get(v));
            }
        }
        Iterator removeIt = toRemove.iterator();
        while (removeIt.hasNext()){
            filterData.remove(removeIt.next());
        }

        return filterData;
    }

    protected Object newInitialFlow()
    {
	    HashMap initMap = new HashMap();
	
	    Chain locals = g.getBody().getLocals();
	    Iterator it = locals.iterator();
	    while (it.hasNext()) {
            Local next = (Local)it.next();
            //System.out.println("next local: "+next);
            if ((next.getType() instanceof IntegerType) || (next.getType() instanceof LongType)){
	            initMap.put(next, BOTTOM);
            }
	    }
    
        Iterator boxIt = g.getBody().getUseAndDefBoxes().iterator();
        while (boxIt.hasNext()){
            Value val = ((ValueBox)boxIt.next()).getValue();
            if (val instanceof ArithmeticConstant) {
                initMap.put(val, getParity(initMap, val));
            }
        }

        if (Options.v().interactive_mode()){
            updateBeforeFilterMap();
        }
        
        return initMap;

    }
        

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy