/* Soot - a J*va Optimization Framework
* Copyright (C) 1997-1999 Raja Vallee-Rai
*
* 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.jbco.bafTransformations;
import java.util.*;
import soot.*;
import soot.baf.*;
import soot.baf.internal.AbstractOpTypeInst;
import soot.jbco.IJbcoTransform;
import soot.jimple.DoubleConstant;
import soot.jimple.FloatConstant;
import soot.jimple.IntConstant;
import soot.jimple.LongConstant;
import soot.jimple.NullConstant;
import soot.toolkits.scalar.GuaranteedDefs;
/**
* @author Michael Batchelder
*
* Created on 16-Jun-2006
*/
public class FixUndefinedLocals extends BodyTransformer implements IJbcoTransform {
private int undefined = 0;
public static String dependancies[] = new String[] {"bb.jbco_j2bl", "bb.jbco_ful", "bb.lp" };
public String[] getDependancies() {
return dependancies;
}
public static String name = "bb.jbco_ful";
public String getName() {
return name;
}
public void outputSummary() {
out.println("Undefined Locals fixed with pre-initializers: "+undefined);
}
protected void internalTransform(Body b, String phaseName, Map options) {
// deal with locals not defined at all used points
int icount = 0;
boolean passedIDs = false;
HashMap bafToJLocals = soot.jbco.Main.methods2Baf2JLocals.get(b.getMethod());
ArrayList<Value> initialized = new ArrayList<Value>();
PatchingChain units = b.getUnits();
GuaranteedDefs gd = new GuaranteedDefs(new soot.toolkits.graph.ExceptionalUnitGraph(b));
Iterator unitIt = units.snapshotIterator();
Unit after = null;
while (unitIt.hasNext()) {
Unit u = (Unit) unitIt.next();
if (!passedIDs && u instanceof IdentityInst) {
Value v = ((IdentityInst)u).getLeftOp();
if (v instanceof Local) {
initialized.add(v);
icount++;
}
after = u;
continue;
}
passedIDs = true;
if (after == null) {
after = Baf.v().newNopInst();
units.addFirst(after);
}
List defs = gd.getGuaranteedDefs(u);
Iterator useIt = u.getUseBoxes().iterator();
while (useIt.hasNext()) {
Value v = ((ValueBox) useIt.next()).getValue();
if (!(v instanceof Local) || defs.contains(v) || initialized.contains(v))
continue;
Type t = null;
Local l = (Local) v;
Local jl = (Local) bafToJLocals.get(l);
if (jl != null) {
t = jl.getType();
} else {
// We should hopefully never get here. There should be a jimple
// local unless it's one of our ControlDups
t = l.getType();
if (u instanceof OpTypeArgInst) {
OpTypeArgInst ota = (OpTypeArgInst) u;
t = ota.getOpType();
} else if (u instanceof AbstractOpTypeInst) {
AbstractOpTypeInst ota = (AbstractOpTypeInst) u;
t = ota.getOpType();
} else if (u instanceof IncInst)
t = IntType.v();
if (t instanceof DoubleWordType || t instanceof WordType) {
throw new RuntimeException("Shouldn't get here (t is a double or word type: in FixUndefinedLocals)");
}
}
Unit store = Baf.v().newStoreInst(t, l);
units.insertAfter(store,after);
// TODO: is this necessary if I fix the other casting issues?
if (t instanceof ArrayType) {
Unit tmp = Baf.v().newInstanceCastInst(t);
units.insertBefore(tmp,store);
store = tmp;
}
/////
Unit pinit = getPushInitializer(l, t);
units.insertBefore(pinit,store);
/*if (t instanceof RefType) {
SootClass sc = ((RefType)t).getSootClass();
if (sc != null)
units.insertAfter(Baf.v().newInstanceCastInst(t), pinit);
}*/
initialized.add(l);
}
}
if (after instanceof NopInst)
units.remove(after);
undefined += initialized.size() - icount;
}
public static PushInst getPushInitializer(Local l, Type t) {
if (t instanceof IntegerType) {
return Baf.v().newPushInst(IntConstant.v(soot.jbco.util.Rand.getInt()));
} else if (t instanceof RefLikeType || t instanceof StmtAddressType) {
return Baf.v().newPushInst(NullConstant.v());
} else if (t instanceof LongType) {
return Baf.v().newPushInst(LongConstant.v(soot.jbco.util.Rand.getLong()));
} else if (t instanceof FloatType) {
return Baf.v().newPushInst(
FloatConstant.v(soot.jbco.util.Rand.getFloat()));
} else if (t instanceof DoubleType) {
return Baf.v().newPushInst(
DoubleConstant.v(soot.jbco.util.Rand.getDouble()));
}
return null;
}
/*
*
private Unit findInitializerSpotFor(Value v, Unit u, UnitGraph ug,
GuaranteedDefs gd) {
List preds = ug.getPredsOf(u);
while (preds.size() == 1) {
Unit p = (Unit) preds.get(0);
//if (p instanceof IdentityInst)
// break;
u = p;
preds = ug.getPredsOf(u);
}
if (preds.size() <= 1)
return u;
ArrayList nodef = new ArrayList();
Iterator pIt = preds.iterator();
while (pIt.hasNext()) {
Unit u1 = (Unit) pIt.next();
if (!gd.getGuaranteedDefs(u1).contains(v)) {
nodef.add(u1);
}
}
if (nodef.size() == preds.size())
return u;
if (nodef.size() == 1)
return findInitializerSpotFor(v, (Unit) nodef.get(0), ug, gd);
throw new RuntimeException("Shouldn't Ever Get Here!");
}*/
}