soot.shimple.toolkits.scalar.ShimpleLocalUses Maven / Gradle / Ivy
package soot.shimple.toolkits.scalar;
/*-
* #%L
* Soot - a J*va Optimization Framework
* %%
* Copyright (C) 2003 Navindra Umanee
* %%
* 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 java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import soot.Local;
import soot.Unit;
import soot.Value;
import soot.ValueBox;
import soot.shimple.ShimpleBody;
import soot.toolkits.scalar.LocalUses;
import soot.toolkits.scalar.UnitValueBoxPair;
/**
* This class implements the LocalUses interface for Shimple. ShimpleLocalUses can be used in conjunction with
* SimpleLocalDefs to provide Definition/Use and Use/Definition chains in SSA.
*
*
* In addition to the interface required by LocalUses, ShimpleLocalUses also provides a method for obtaining the list of uses
* given only the Local. Furthermore, unlike SimpleLocalUses, a LocalDefs object is not required when constructing
* ShimpleLocalUses.
*
* @author Navindra Umanee
* @see ShimpleLocalDefs
* @see soot.toolkits.scalar.SimpleLocalDefs
* @see soot.toolkits.scalar.SimpleLocalUses
**/
public class ShimpleLocalUses implements LocalUses {
private static final Logger logger = LoggerFactory.getLogger(ShimpleLocalUses.class);
protected Map localToUses;
/**
* Build a LocalUses interface from a ShimpleBody. Proper SSA form is required, otherwise correct behaviour is not
* guaranteed.
**/
public ShimpleLocalUses(ShimpleBody sb) {
// Instead of rebuilding the ShimpleBody without the
// programmer's knowledge, throw a RuntimeException
if (!sb.isSSA()) {
throw new RuntimeException("ShimpleBody is not in proper SSA form as required by ShimpleLocalUses."
+ "You may need to rebuild it or use SimpleLocalUses instead.");
}
// initialise the map
localToUses = new HashMap();
Iterator localsIt = sb.getLocals().iterator();
while (localsIt.hasNext()) {
Local local = (Local) localsIt.next();
localToUses.put(local, new ArrayList());
}
// iterate through the units and save each Local use in the
// appropriate list -- due to SSA form, each Local has a
// unique def, and therefore one appropriate list.
Iterator unitsIt = sb.getUnits().iterator();
while (unitsIt.hasNext()) {
Unit unit = (Unit) unitsIt.next();
Iterator boxIt = unit.getUseBoxes().iterator();
while (boxIt.hasNext()) {
ValueBox box = (ValueBox) boxIt.next();
Value value = box.getValue();
if (!(value instanceof Local)) {
continue;
}
List useList = localToUses.get(value);
useList.add(new UnitValueBoxPair(unit, box));
}
}
}
/**
* Returns all the uses of the given Local as a list of UnitValueBoxPairs, each containing a Unit that uses the local and
* the corresponding ValueBox containing the Local.
*
*
* This method is currently not required by the LocalUses interface.
**/
public List getUsesOf(Local local) {
List uses = localToUses.get(local);
if (uses == null) {
return Collections.EMPTY_LIST;
}
return uses;
}
/**
* If a Local is defined in the Unit, returns all the uses of that Local as a list of UnitValueBoxPairs, each containing a
* Unit that uses the local and the corresponding ValueBox containing the Local.
**/
public List getUsesOf(Unit unit) {
List defBoxes = unit.getDefBoxes();
switch (defBoxes.size()) {
case 0:
return Collections.EMPTY_LIST;
case 1:
Value local = ((ValueBox) defBoxes.get(0)).getValue();
if (!(local instanceof Local)) {
return Collections.EMPTY_LIST;
}
return getUsesOf((Local) local);
default:
logger.warn("Unit has multiple definition boxes?");
List usesList = new ArrayList();
Iterator defBoxesIt = defBoxes.iterator();
while (defBoxesIt.hasNext()) {
Value def = ((ValueBox) defBoxesIt.next()).getValue();
if (def instanceof Local) {
usesList.addAll(getUsesOf((Local) def));
}
}
return usesList;
}
}
}