/*******************************************************************************
* Copyright (c) 2014 Imperial College London
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Raul Castro Fernandez - initial API and implementation
******************************************************************************/
package uk.ac.imperial.lsds.java2sdg.flowanalysis;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.logging.Logger;
import soot.Unit;
import soot.Value;
import soot.tagkit.SourceLnPosTag;
import soot.toolkits.graph.UnitGraph;
import soot.toolkits.scalar.SimpleLiveLocals;
import uk.ac.imperial.lsds.java2sdg.Main;
import uk.ac.imperial.lsds.java2sdg.bricks.Variable;
public class LiveVariableAnalysis {
private final static Logger log = Logger.getLogger(Main.class.getCanonicalName());
private static final LiveVariableAnalysis instance = null;
private UnitGraph cfg = null;
private SimpleLiveLocals sll = null;
private Iterator<Unit> units = null;
// map line with live variables at that point
private SortedMap<Integer, List<Variable>> outLive = new TreeMap<Integer, List<Variable>>();
private SortedMap<Integer, List<Variable>> inLive = new TreeMap<Integer, List<Variable>>();
private LiveVariableAnalysis(){
}
private LiveVariableAnalysis(UnitGraph cfg){
this.cfg = cfg;
sll = new SimpleLiveLocals(cfg);
units = cfg.iterator();
}
public static LiveVariableAnalysis getInstance(UnitGraph cfg){
if(instance == null){
return new LiveVariableAnalysis(cfg).computeLiveVariables();
}
else{
return instance;
}
}
public List<Variable> getOutLiveVariablesAtLine(int line) throws NoDataForLine{
if(outLive.containsKey(line)){
return outLive.get(line);
}
else{
throw new NoDataForLine();
}
}
public List<Variable> getInLiveVariablesAtLine(int line) throws NoDataForLine{
if(inLive.containsKey(line)){
return inLive.get(line);
}
else{
throw new NoDataForLine();
}
}
private int getLineNumberFromUnit(Unit u){
int lineNumber = -1;
SourceLnPosTag tag = (SourceLnPosTag)u.getTag("SourceLnPosTag");
if (tag != null){
lineNumber = tag.startLn();
}
return lineNumber;
}
private LiveVariableAnalysis computeLiveVariables(){
units = cfg.iterator(); // Iterator from scratch
while(units.hasNext()){
Unit u = units.next();
int lineNumber = getLineNumberFromUnit(u);
List<Value> OUT = sll.getLiveLocalsAfter(u);
List<Value> IN = sll.getLiveLocalsBefore(u);
// In case several
outLive.put(lineNumber, getVars(OUT));
inLive.put(lineNumber, getVars(IN));
}
return this;
}
private List<Variable> getVars(List<Value> out){
List<Variable> vars = new ArrayList<Variable>();
for(Value v : out){
vars.add(Variable.var(v.getType(), v.toString()));
}
return vars;
}
public void printTest(){
for(Map.Entry<Integer, List<Variable>> entry : outLive.entrySet()){
System.out.println("L: "+entry.getKey()+" V: "+entry.getValue());
}
}
public void printInfo(){
for(Integer line : outLive.keySet()){
System.out.println(line+" "+outLive.get(line));
}
}
public void printLiveVariables(){
log.info("-> LIVE VARIABLE ANALYSIS");
units = cfg.iterator();
while(units.hasNext()){
Unit u = units.next();
int lineNumber = -1;
SourceLnPosTag tag = (SourceLnPosTag)u.getTag("SourceLnPosTag");
if (tag != null){
lineNumber = tag.startLn();
}
List<Value> IN = sll.getLiveLocalsBefore(u);
List<Value> OUT = sll.getLiveLocalsAfter(u);
System.out.println("#############");
System.out.println("LINE: "+lineNumber);
System.out.println(u.toString());
System.out.println("-> IN");
for(Value l : IN){
System.out.println("- "+l.toString());
}
System.out.println("-> OUT");
for(Value l : OUT){
System.out.println("- "+l.toString());
}
}
units = cfg.iterator();
}
}