All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.toolkits.graph.pdg.PDGRegion Maven / Gradle / Ivy

There is a newer version: 2.5.0-9
Show newest version
/* 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;
		
	}
	
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy