soot.toolkits.graph.pdg.PDGRegion Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of robovm-soot Show documentation
Show all versions of robovm-soot Show documentation
RoboVM fork of Soot - A Java optimization framework
/* Soot - a J*va Optimization Framework
* Copyright (C) 1999-2010 Hossein Sadat-Mohtasham
*
* 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.toolkits.graph.pdg;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import soot.G;
import soot.SootClass;
import soot.SootMethod;
import soot.Unit;
import soot.options.Options;
import soot.toolkits.graph.Block;
import soot.toolkits.graph.UnitGraph;
/**
* This represents a region of control dependence obtained by constructing a
* program dependence graph. A PDGRegion is slightly different than a weak or
* strong region; the loops and conditional relations between regions are
* explicitly represented in the PDGRegion.
*
* @author Hossein Sadat-Mohtasham
* Sep 2009
*/
public class PDGRegion implements IRegion, Iterable{
private SootClass m_class = null;;
private SootMethod m_method = null;
private List m_nodes = null;
private List m_units = null;
private LinkedHashMap m_unit2pdgnode = null;
private int m_id = -1;
private UnitGraph m_unitGraph = null;
private PDGNode m_corrspondingPDGNode = null;
//The following are needed to create a tree of regions based on the containment (dependency)
//relation between regions.
private IRegion m_parent = null;
//The following keeps the child regions
private List m_children = new ArrayList();
public PDGRegion(int id, SootMethod m, SootClass c, UnitGraph ug, PDGNode node)
{
this(id, new ArrayList(), m, c, ug, node);
}
public PDGRegion(int id, List nodes, SootMethod m, SootClass c, UnitGraph ug, PDGNode node)
{
this.m_nodes = nodes;
this.m_id = id;
this.m_method = m;
this.m_class = c;
this.m_unitGraph = ug;
this.m_units = null;
this.m_corrspondingPDGNode = node;
if(Options.v().verbose())
G.v().out.println("New pdg region create: " + id);
}
public PDGRegion(PDGNode node)
{
this(((IRegion)node.getNode()).getID(),
(List)new ArrayList(),
((IRegion)node.getNode()).getSootMethod(),
((IRegion)node.getNode()).getSootClass(),
((IRegion)node.getNode()).getUnitGraph(),
node);
}
public PDGNode getCorrespondingPDGNode()
{
return this.m_corrspondingPDGNode;
}
@SuppressWarnings("unchecked")
public Object clone()
{
PDGRegion r = new PDGRegion(this.m_id, this.m_method, this.m_class, this.m_unitGraph, m_corrspondingPDGNode);
r.m_nodes = (List)((ArrayList)this.m_nodes).clone();
return r;
}
public SootMethod getSootMethod()
{
return this.m_method;
}
public SootClass getSootClass()
{
return this.m_class;
}
public List getNodes()
{
return this.m_nodes;
}
public UnitGraph getUnitGraph()
{
return this.m_unitGraph;
}
/**
* This is an iterator that knows how to follow the control flow in a region. It
* only iterates through the
* dependent nodes that contribute to the list of units in a region as defined
* by a weak region.
*
*/
class ChildPDGFlowIterator implements Iterator
{
List m_list = null;
PDGNode m_current = null;
boolean beginning = true;
public ChildPDGFlowIterator(List list)
{
m_list = list;
}
public boolean hasNext() {
if(beginning)
if(m_list.size() > 0)
return true;
return (m_current != null && m_current.getNext() != null);
}
public PDGNode next() {
if(beginning)
{
beginning = false;
m_current = m_list.get(0);
//Find the first node in the control flow
/*
* There cannot be more than one CFG node in a region
* unless there is a control flow edge between them. However,
* there could be a CFG node and other region nodes (back
* dependency, or other.) In such cases, the one CFG node
* should be found and returned, and other region nodes should
* be ignored. Unless it's a LoopedPDGNode (in which case control
* flow edge should still exist if there are other sibling Looped
* PDGNodes or CFG nodes.)
*
*/
while(m_current.getPrev() != null)
m_current = m_current.getPrev();
if(m_current.getType() != PDGNode.Type.CFGNODE && m_current.getAttrib() != PDGNode.Attribute.LOOPHEADER)
{
/*
* Look for useful dependence whose units are considered to be part of this region (loop header
* or CFG block nodes.)
*
*/
for(Iterator depItr = m_list.iterator(); depItr.hasNext(); )
{
PDGNode dep = depItr.next();
if(dep.getType() == PDGNode.Type.CFGNODE || dep.getAttrib() == PDGNode.Attribute.LOOPHEADER)
{
m_current = dep;
//go to the beginning of the flow
while(m_current.getPrev() != null)
m_current = m_current.getPrev();
break;
}
}
}
return m_current;
}
if(!hasNext())
throw new RuntimeException("No more nodes!");
m_current = m_current.getNext();
return m_current;
}
public void remove() {
}
}
/**
* return an iterator that know how to follow the control flow in a region. This
* actually returns a ChildPDGFlowIterator that only iterates through the
* dependent nodes that contribute to the units that belong to a region as defined
* by a weak region.
*
*/
public Iterator iterator()
{
return new ChildPDGFlowIterator(this.m_nodes);
}
public List getUnits()
{
if(this.m_units == null)
{
this.m_units = new LinkedList();
this.m_unit2pdgnode = new LinkedHashMap();
for(Iterator itr = this.iterator(); itr.hasNext();)
{
PDGNode node = itr.next();
if(node.getType() == PDGNode.Type.REGION)
{
//Actually, we should only get here if a loop header region is in this region's children list.
//Or if the PDG is based on an ExceptionalUnitGraph, then this could be the region corresponding
//to a handler, in which case it's ignored.
//if(node.getAttrib() == PDGNode.Attribute.LOOPHEADER)
if(node instanceof LoopedPDGNode)
{
LoopedPDGNode n = (LoopedPDGNode) node;
PDGNode header = n.getHeader();
Block headerBlock = (Block) header.getNode();
for(Iterator itr1 = headerBlock.iterator(); itr1.hasNext();)
{
Unit u = itr1.next();
((LinkedList)this.m_units).addLast(u);
this.m_unit2pdgnode.put(u, header);
}
}
}
else if(node.getType() == PDGNode.Type.CFGNODE)
{
Block b = (Block) node.getNode();
for(Iterator itr1 = b.iterator(); itr1.hasNext();)
{
Unit u = itr1.next();
((LinkedList)this.m_units).addLast(u);
this.m_unit2pdgnode.put(u, node);
}
}
else
throw new RuntimeException("Exception in PDGRegion.getUnits: PDGNode's type is undefined!");
}
}
return this.m_units;
}
/**
*
* @param a Statement within the region
*
* @return The PDGNode that contains that unit, if this unit is in this region.
*/
public PDGNode unit2PDGNode(Unit u)
{
if(this.m_unit2pdgnode.containsKey(u))
return this.m_unit2pdgnode.get(u);
else
return null;
}
public List getUnits(Unit from, Unit to)
{
return m_units.subList(m_units.indexOf(from), m_units.indexOf(to));
}
public Unit getLast()
{
if(this.m_units != null)
if(this.m_units.size() > 0)
return ((LinkedList)this.m_units).getLast();
return null;
}
public Unit getFirst()
{
if(this.m_units != null)
if(this.m_units.size() > 0)
return ((LinkedList)this.m_units).getFirst();
return null;
}
//FIXME: return the real list of blocks
public List getBlocks()
{
return new ArrayList();
}
public void addPDGNode(PDGNode node)
{
this.m_nodes.add(node);
}
public int getID()
{
return this.m_id;
}
public boolean occursBefore(Unit u1, Unit u2)
{
int i = this.m_units.lastIndexOf(u1);
int j = this.m_units.lastIndexOf(u2);
if(i == -1 || j == -1)
throw new RuntimeException("These units don't exist in the region!");
return i < j;
}
public void setParent(IRegion pr)
{
this.m_parent = pr;
}
public IRegion getParent()
{
return this.m_parent;
}
public void addChildRegion(IRegion chr)
{
if(!this.m_children.contains(chr))
this.m_children.add(chr);
}
public List getChildRegions()
{
return this.m_children;
}
public String toString()
{
String str = new String();
str += "Begin-----------PDGRegion: " + this.m_id + "-------------\n";
if(this.m_parent != null)
str += "Parent is: " + this.m_parent.getID() + "----\n";
str += "Children Regions are: ";
for(Iterator ritr = this.m_children.iterator(); ritr.hasNext();)
str += ((IRegion)ritr.next()).getID() + ", ";
str += "\nUnits are: \n";
List regionUnits = this.getUnits();
for (Iterator itr = regionUnits.iterator(); itr.hasNext();)
{
Unit u = itr.next();
str += u + "\n";
}
str += "End of PDG Region " + this.m_id + " -----------------------------\n";
return str;
}
}