![JAR search and dependency download from the Maven repository](/logo.png)
soot.jimple.toolkits.annotation.parity.ParityAnalysis Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of soot Show documentation
Show all versions of soot Show documentation
A Java Optimization Framework
package soot.jimple.toolkits.annotation.parity;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2003 Jennifer Lhotak
* %%
* This program 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 program 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 General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import static soot.jimple.toolkits.annotation.parity.ParityAnalysis.Parity.BOTTOM;
import static soot.jimple.toolkits.annotation.parity.ParityAnalysis.Parity.EVEN;
import static soot.jimple.toolkits.annotation.parity.ParityAnalysis.Parity.ODD;
import static soot.jimple.toolkits.annotation.parity.ParityAnalysis.Parity.TOP;
import static soot.jimple.toolkits.annotation.parity.ParityAnalysis.Parity.valueOf;
import java.util.HashMap;
import java.util.Map;
import soot.IntegerType;
import soot.Local;
import soot.LongType;
import soot.Type;
import soot.Unit;
import soot.Value;
import soot.ValueBox;
import soot.jimple.AddExpr;
import soot.jimple.ArithmeticConstant;
import soot.jimple.BinopExpr;
import soot.jimple.DefinitionStmt;
import soot.jimple.IntConstant;
import soot.jimple.LongConstant;
import soot.jimple.MulExpr;
import soot.jimple.SubExpr;
import soot.options.Options;
import soot.toolkits.graph.UnitGraph;
import soot.toolkits.scalar.ForwardFlowAnalysis;
import soot.toolkits.scalar.LiveLocals;
// 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> {
public enum Parity {
TOP, BOTTOM, EVEN, ODD;
static Parity valueOf(int v) {
return (v % 2) == 0 ? EVEN : ODD;
}
static Parity valueOf(long v) {
return (v % 2) == 0 ? EVEN : ODD;
}
}
private UnitGraph g;
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() {
for (Unit s : g.getBody().getUnits()) {
// 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;
Map map = new HashMap();
for (Local l : filter.getLiveLocalsBefore(s)) {
map.put(l, 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
//
@Override
protected void merge(Map inMap1, Map inMap2, Map outMap) {
for (Value var1 : inMap1.keySet()) {
// System.out.println(var1);
Parity inVal1 = inMap1.get(var1);
// System.out.println(inVal1);
Parity inVal2 = 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)
//
@Override
protected void copy(Map sourceIn, Map destOut) {
destOut.clear();
destOut.putAll(sourceIn);
}
// 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 Parity getParity(Map in, Value val) {
// System.out.println("get Parity in: "+in);
if ((val instanceof AddExpr) | (val instanceof SubExpr)) {
Parity resVal1 = getParity(in, ((BinopExpr) val).getOp1());
Parity resVal2 = getParity(in, ((BinopExpr) val).getOp2());
if (resVal1.equals(TOP) | resVal2.equals(TOP)) {
return TOP;
}
if (resVal1.equals(BOTTOM) | resVal2.equals(BOTTOM)) {
return BOTTOM;
}
if (resVal1.equals(resVal2)) {
return EVEN;
}
return ODD;
}
if (val instanceof MulExpr) {
Parity resVal1 = getParity(in, ((BinopExpr) val).getOp1());
Parity resVal2 = getParity(in, ((BinopExpr) val).getOp2());
if (resVal1.equals(TOP) | resVal2.equals(TOP)) {
return TOP;
}
if (resVal1.equals(BOTTOM) | resVal2.equals(BOTTOM)) {
return BOTTOM;
}
if (resVal1.equals(resVal2)) {
return resVal1;
}
return EVEN;
}
if (val instanceof IntConstant) {
int value = ((IntConstant) val).value;
return valueOf(value);
}
if (val instanceof LongConstant) {
long value = ((LongConstant) val).value;
return valueOf(value);
}
Parity p = in.get(val);
if (p == null) {
return TOP;
}
return p;
}
@Override
protected void flowThrough(Map in, Unit s, Map out) {
// 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
for (ValueBox next : s.getUseAndDefBoxes()) {
Value val = 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(Unit s) {
Map map = new HashMap();
for (Local local : filter.getLiveLocalsAfter(s)) {
map.put(local, 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
@Override
protected Map 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() {
for (Unit s : filterUnitToBeforeFlow.keySet()) {
Map allData = getFlowBefore(s);
Map filterData = filterUnitToBeforeFlow.get(s);
filterUnitToBeforeFlow.put(s, updateFilter(allData, filterData));
}
}
private void updateAfterFilterMap(Unit s) {
Map allData = getFlowAfter(s);
Map filterData = filterUnitToAfterFlow.get(s);
filterUnitToAfterFlow.put(s, updateFilter(allData, filterData));
}
private Map updateFilter(Map allData, Map filterData) {
if (allData == null) {
return filterData;
}
for (Value v : filterData.keySet()) {
Parity d = allData.get(v);
if (d == null) {
filterData.remove(v);
} else {
filterData.put(v, d);
}
}
return filterData;
}
@Override
protected Map newInitialFlow() {
Map initMap = new HashMap();
for (Local l : g.getBody().getLocals()) {
Type t = l.getType();
// System.out.println("next local: "+next);
if ((t instanceof IntegerType) || (t instanceof LongType)) {
initMap.put(l, BOTTOM);
}
}
for (ValueBox vb : g.getBody().getUseAndDefBoxes()) {
Value val = vb.getValue();
if (val instanceof ArithmeticConstant) {
initMap.put(val, getParity(initMap, val));
}
}
if (Options.v().interactive_mode()) {
updateBeforeFilterMap();
}
return initMap;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy