/****************************************************************************** * Copyright (c) 2002 - 2014 IBM Corporation. * 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: * IBM Corporation - initial API and implementation *****************************************************************************/ /******************************************************************************* * Licensed Materials - Property of IBM * * "Restricted Materials of IBM" * * Copyright (c) 2008 IBM Corporation. * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package com.ibm.wala.dataflow.IFDS; import java.util.Iterator; import com.ibm.wala.cfg.ControlFlowGraph; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.ipa.callgraph.AnalysisCache; import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.Context; import com.ibm.wala.ipa.cfg.BasicBlockInContext; import com.ibm.wala.ipa.cfg.ExplodedInterproceduralCFG; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ssa.IR; import com.ibm.wala.ssa.SSAAbstractInvokeInstruction; import com.ibm.wala.ssa.SSAInstruction; import com.ibm.wala.ssa.analysis.IExplodedBasicBlock; import com.ibm.wala.util.collections.EmptyIterator; import com.ibm.wala.util.collections.Filter; import com.ibm.wala.util.collections.FilterIterator; import com.ibm.wala.util.debug.Assertions; import com.ibm.wala.util.graph.Graph; import com.ibm.wala.util.intset.IntSet; /** * Forward supergraph induced over an {@link ExplodedInterproceduralCFG} * * This should lazily build the supergraph as it is explored. * * @author sjfink * */ public class ICFGSupergraph implements ISupergraph, CGNode> { private final AnalysisCache analysisCache; private final AnalysisOptions options = new AnalysisOptions(); private final ExplodedInterproceduralCFG icfg; protected ICFGSupergraph(ExplodedInterproceduralCFG icfg, AnalysisCache cache) { this.icfg = icfg; this.analysisCache = cache; } public static ICFGSupergraph make(CallGraph cg, AnalysisCache cache) { ICFGSupergraph w = new ICFGSupergraph(ExplodedInterproceduralCFG.make(cg), cache); return w; } @Override public Graph getProcedureGraph() { return icfg.getCallGraph(); } public IClassHierarchy getClassHierarchy() { return icfg.getCallGraph().getClassHierarchy(); } public IR getIR(IMethod m, Context c) { //AnalysisOptions options = new AnalysisOptions(); IR ir = analysisCache.getSSACache().findOrCreateIR(m, c, options.getSSAOptions()); return ir; } public IR getIR(CGNode n) { //AnalysisOptions options = new AnalysisOptions(); IR ir = analysisCache.getSSACache().findOrCreateIR(n.getMethod(), n.getContext(), options.getSSAOptions()); return ir; } @Override public byte classifyEdge(BasicBlockInContext src, BasicBlockInContext dest) { if (isCall(src)) { if (isEntry(dest)) { return CALL_EDGE; } else { return CALL_TO_RETURN_EDGE; } } else if (isExit(src)) { return RETURN_EDGE; } else { return OTHER; } } /* * @see com.ibm.wala.dataflow.IFDS.ISupergraph#getCallSites(java.lang.Object, * java.lang.Object) */ @Override public Iterator> getCallSites(BasicBlockInContext r, CGNode callee) { return icfg.getCallSites(r, callee); } @Override public Iterator> getCalledNodes(BasicBlockInContext call) { final Filter> isEntryFilter = new Filter>() { @Override public boolean accepts(BasicBlockInContext o) { return o.isEntryBlock(); } }; return new FilterIterator>(getSuccNodes(call), isEntryFilter); } @Override @SuppressWarnings("unchecked") public BasicBlockInContext[] getEntriesForProcedure(CGNode procedure) { return new BasicBlockInContext[] { icfg.getEntry(procedure) }; } @Override @SuppressWarnings("unchecked") public BasicBlockInContext[] getExitsForProcedure(CGNode procedure) { return new BasicBlockInContext[] { icfg.getExit(procedure) }; } @Override public BasicBlockInContext getLocalBlock(CGNode procedure, int i) { IExplodedBasicBlock b = icfg.getCFG(procedure).getNode(i); return new BasicBlockInContext(procedure, b); } @Override public int getLocalBlockNumber(BasicBlockInContext n) { return n.getDelegate().getNumber(); } public BasicBlockInContext getMainEntry() { Assertions.UNREACHABLE(); return null; } @Override public Iterator> getNormalSuccessors(BasicBlockInContext call) { return EmptyIterator.instance(); } @Override public int getNumberOfBlocks(CGNode procedure) { Assertions.UNREACHABLE(); return 0; } @Override public CGNode getProcOf(BasicBlockInContext n) { return icfg.getCGNode(n); } @Override public Iterator> getReturnSites(BasicBlockInContext call, CGNode callee) { return icfg.getReturnSites(call); } @Override public boolean isCall(BasicBlockInContext n) { return n.getDelegate().getInstruction() instanceof SSAAbstractInvokeInstruction; } @Override public boolean isEntry(BasicBlockInContext n) { return n.getDelegate().isEntryBlock(); } @Override public boolean isExit(BasicBlockInContext n) { return n.getDelegate().isExitBlock(); } @Override public boolean isReturn(BasicBlockInContext n) { return icfg.isReturn(n); } @Override public void removeNodeAndEdges(BasicBlockInContext N) throws UnsupportedOperationException { Assertions.UNREACHABLE(); } @Override public void addNode(BasicBlockInContext n) { Assertions.UNREACHABLE(); } @Override public boolean containsNode(BasicBlockInContext N) { return icfg.containsNode(N); } @Override public int getNumberOfNodes() { return icfg.getNumberOfNodes(); } @Override public Iterator> iterator() { return icfg.iterator(); } @Override public void removeNode(BasicBlockInContext n) { Assertions.UNREACHABLE(); } @Override public void addEdge(BasicBlockInContext src, BasicBlockInContext dst) { Assertions.UNREACHABLE(); } @Override public int getPredNodeCount(BasicBlockInContext N) { return icfg.getPredNodeCount(N); } @Override public Iterator> getPredNodes(BasicBlockInContext N) { return icfg.getPredNodes(N); } @Override public int getSuccNodeCount(BasicBlockInContext N) { return icfg.getSuccNodeCount(N); } @Override public Iterator> getSuccNodes(BasicBlockInContext N) { return icfg.getSuccNodes(N); } @Override public boolean hasEdge(BasicBlockInContext src, BasicBlockInContext dst) { return icfg.hasEdge(src, dst); } @Override public void removeAllIncidentEdges(BasicBlockInContext node) throws UnsupportedOperationException { Assertions.UNREACHABLE(); } @Override public void removeEdge(BasicBlockInContext src, BasicBlockInContext dst) throws UnsupportedOperationException { Assertions.UNREACHABLE(); } @Override public void removeIncomingEdges(BasicBlockInContext node) throws UnsupportedOperationException { Assertions.UNREACHABLE(); } @Override public void removeOutgoingEdges(BasicBlockInContext node) throws UnsupportedOperationException { Assertions.UNREACHABLE(); } @Override public int getMaxNumber() { return icfg.getMaxNumber(); } @Override public BasicBlockInContext getNode(int number) { return icfg.getNode(number); } @Override public int getNumber(BasicBlockInContext N) { return icfg.getNumber(N); } @Override public Iterator> iterateNodes(IntSet s) { Assertions.UNREACHABLE(); return null; } @Override public IntSet getPredNodeNumbers(BasicBlockInContext node) { return icfg.getPredNodeNumbers(node); } @Override public IntSet getSuccNodeNumbers(BasicBlockInContext node) { return icfg.getSuccNodeNumbers(node); } public ControlFlowGraph getCFG(BasicBlockInContext node) { return icfg.getCFG(node); } public ExplodedInterproceduralCFG getICFG() { return icfg; } @Override public String toString() { return icfg.toString(); } }