/**
*
*/
package soottocfg.soot.transformers;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import soot.PatchingChain;
import soot.Unit;
import soot.jimple.Expr;
import soot.jimple.IntConstant;
import soot.jimple.Jimple;
import soot.jimple.JimpleBody;
import soot.jimple.LookupSwitchStmt;
import soot.jimple.SwitchStmt;
import soot.jimple.TableSwitchStmt;
/**
* @author schaef
*
*/
public class SwitchStatementRemover extends AbstractSceneTransformer {
public void applyTransformation() {
for (JimpleBody body : this.getSceneBodies()) {
Map<Unit, List<Unit>> toReplace = new LinkedHashMap<Unit, List<Unit>>();
PatchingChain<Unit> units = body.getUnits();
for (Unit u : units) {
if (u instanceof SwitchStmt) {
toReplace.put(u, replaceSwitchStatement((SwitchStmt) u));
}
}
for (Entry<Unit, List<Unit>> entry : toReplace.entrySet()) {
units.insertBefore(entry.getValue(), entry.getKey());
units.remove(entry.getKey());
}
body.validate();
}
}
/**
* Replace a SwitchStatement by a sequence of IfStmts and a Goto for the
* default case.
*
* @param s
* @return
*/
private List<Unit> replaceSwitchStatement(SwitchStmt s) {
List<Unit> result = new LinkedList<Unit>();
List<Expr> cases = new LinkedList<Expr>();
List<Unit> targets = new LinkedList<Unit>();
Unit defaultTarget = s.getDefaultTarget();
if (s instanceof TableSwitchStmt) {
TableSwitchStmt arg0 = (TableSwitchStmt) s;
int counter = 0;
for (int i = arg0.getLowIndex(); i <= arg0.getHighIndex(); i++) {
cases.add(Jimple.v().newEqExpr(arg0.getKey(), IntConstant.v(i)));
targets.add(arg0.getTarget(counter));
counter++;
}
} else {
LookupSwitchStmt arg0 = (LookupSwitchStmt) s;
for (int i = 0; i < arg0.getTargetCount(); i++) {
cases.add(Jimple.v().newEqExpr(arg0.getKey(), IntConstant.v(arg0.getLookupValue(i))));
targets.add(arg0.getTarget(i));
}
}
for (int i = 0; i < cases.size(); i++) {
// create the ifstmt
Unit ifstmt = ifStmtFor(cases.get(i), targets.get(i), s);
result.add(ifstmt);
}
if (defaultTarget != null) {
Unit gotoStmt = gotoStmtFor(defaultTarget, s);
result.add(gotoStmt);
}
return result;
}
}