WALA/com.ibm.wala.core/src/com/ibm/wala/dataflow/IFDS/ICFGSupergraph.java

335 lines
9.8 KiB
Java

/******************************************************************************
* 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<BasicBlockInContext<IExplodedBasicBlock>, 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<? extends CGNode> 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<IExplodedBasicBlock> src, BasicBlockInContext<IExplodedBasicBlock> 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<BasicBlockInContext<IExplodedBasicBlock>> getCallSites(BasicBlockInContext<IExplodedBasicBlock> r, CGNode callee) {
return icfg.getCallSites(r, callee);
}
@Override
public Iterator<? extends BasicBlockInContext<IExplodedBasicBlock>> getCalledNodes(BasicBlockInContext<IExplodedBasicBlock> call) {
final Filter<BasicBlockInContext<IExplodedBasicBlock>> isEntryFilter = new Filter<BasicBlockInContext<IExplodedBasicBlock>>() {
@Override
public boolean accepts(BasicBlockInContext<IExplodedBasicBlock> o) {
return o.isEntryBlock();
}
};
return new FilterIterator<BasicBlockInContext<IExplodedBasicBlock>>(getSuccNodes(call), isEntryFilter);
}
@Override
@SuppressWarnings("unchecked")
public BasicBlockInContext<IExplodedBasicBlock>[] getEntriesForProcedure(CGNode procedure) {
return new BasicBlockInContext[] { icfg.getEntry(procedure) };
}
@Override
@SuppressWarnings("unchecked")
public BasicBlockInContext<IExplodedBasicBlock>[] getExitsForProcedure(CGNode procedure) {
return new BasicBlockInContext[] { icfg.getExit(procedure) };
}
@Override
public BasicBlockInContext<IExplodedBasicBlock> getLocalBlock(CGNode procedure, int i) {
IExplodedBasicBlock b = icfg.getCFG(procedure).getNode(i);
return new BasicBlockInContext<IExplodedBasicBlock>(procedure, b);
}
@Override
public int getLocalBlockNumber(BasicBlockInContext<IExplodedBasicBlock> n) {
return n.getDelegate().getNumber();
}
public BasicBlockInContext<IExplodedBasicBlock> getMainEntry() {
Assertions.UNREACHABLE();
return null;
}
@Override
public Iterator<BasicBlockInContext<IExplodedBasicBlock>> getNormalSuccessors(BasicBlockInContext<IExplodedBasicBlock> call) {
return EmptyIterator.instance();
}
@Override
public int getNumberOfBlocks(CGNode procedure) {
Assertions.UNREACHABLE();
return 0;
}
@Override
public CGNode getProcOf(BasicBlockInContext<IExplodedBasicBlock> n) {
return icfg.getCGNode(n);
}
@Override
public Iterator<? extends BasicBlockInContext<IExplodedBasicBlock>> getReturnSites(BasicBlockInContext<IExplodedBasicBlock> call,
CGNode callee) {
return icfg.getReturnSites(call);
}
@Override
public boolean isCall(BasicBlockInContext<IExplodedBasicBlock> n) {
return n.getDelegate().getInstruction() instanceof SSAAbstractInvokeInstruction;
}
@Override
public boolean isEntry(BasicBlockInContext<IExplodedBasicBlock> n) {
return n.getDelegate().isEntryBlock();
}
@Override
public boolean isExit(BasicBlockInContext<IExplodedBasicBlock> n) {
return n.getDelegate().isExitBlock();
}
@Override
public boolean isReturn(BasicBlockInContext<IExplodedBasicBlock> n) {
return icfg.isReturn(n);
}
@Override
public void removeNodeAndEdges(BasicBlockInContext<IExplodedBasicBlock> N) throws UnsupportedOperationException {
Assertions.UNREACHABLE();
}
@Override
public void addNode(BasicBlockInContext<IExplodedBasicBlock> n) {
Assertions.UNREACHABLE();
}
@Override
public boolean containsNode(BasicBlockInContext<IExplodedBasicBlock> N) {
return icfg.containsNode(N);
}
@Override
public int getNumberOfNodes() {
return icfg.getNumberOfNodes();
}
@Override
public Iterator<BasicBlockInContext<IExplodedBasicBlock>> iterator() {
return icfg.iterator();
}
@Override
public void removeNode(BasicBlockInContext<IExplodedBasicBlock> n) {
Assertions.UNREACHABLE();
}
@Override
public void addEdge(BasicBlockInContext<IExplodedBasicBlock> src, BasicBlockInContext<IExplodedBasicBlock> dst) {
Assertions.UNREACHABLE();
}
@Override
public int getPredNodeCount(BasicBlockInContext<IExplodedBasicBlock> N) {
return icfg.getPredNodeCount(N);
}
@Override
public Iterator<BasicBlockInContext<IExplodedBasicBlock>> getPredNodes(BasicBlockInContext<IExplodedBasicBlock> N) {
return icfg.getPredNodes(N);
}
@Override
public int getSuccNodeCount(BasicBlockInContext<IExplodedBasicBlock> N) {
return icfg.getSuccNodeCount(N);
}
@Override
public Iterator<BasicBlockInContext<IExplodedBasicBlock>> getSuccNodes(BasicBlockInContext<IExplodedBasicBlock> N) {
return icfg.getSuccNodes(N);
}
@Override
public boolean hasEdge(BasicBlockInContext<IExplodedBasicBlock> src, BasicBlockInContext<IExplodedBasicBlock> dst) {
return icfg.hasEdge(src, dst);
}
@Override
public void removeAllIncidentEdges(BasicBlockInContext<IExplodedBasicBlock> node) throws UnsupportedOperationException {
Assertions.UNREACHABLE();
}
@Override
public void removeEdge(BasicBlockInContext<IExplodedBasicBlock> src, BasicBlockInContext<IExplodedBasicBlock> dst)
throws UnsupportedOperationException {
Assertions.UNREACHABLE();
}
@Override
public void removeIncomingEdges(BasicBlockInContext<IExplodedBasicBlock> node) throws UnsupportedOperationException {
Assertions.UNREACHABLE();
}
@Override
public void removeOutgoingEdges(BasicBlockInContext<IExplodedBasicBlock> node) throws UnsupportedOperationException {
Assertions.UNREACHABLE();
}
@Override
public int getMaxNumber() {
return icfg.getMaxNumber();
}
@Override
public BasicBlockInContext<IExplodedBasicBlock> getNode(int number) {
return icfg.getNode(number);
}
@Override
public int getNumber(BasicBlockInContext<IExplodedBasicBlock> N) {
return icfg.getNumber(N);
}
@Override
public Iterator<BasicBlockInContext<IExplodedBasicBlock>> iterateNodes(IntSet s) {
Assertions.UNREACHABLE();
return null;
}
@Override
public IntSet getPredNodeNumbers(BasicBlockInContext<IExplodedBasicBlock> node) {
return icfg.getPredNodeNumbers(node);
}
@Override
public IntSet getSuccNodeNumbers(BasicBlockInContext<IExplodedBasicBlock> node) {
return icfg.getSuccNodeNumbers(node);
}
public ControlFlowGraph<SSAInstruction,IExplodedBasicBlock> getCFG(BasicBlockInContext<IExplodedBasicBlock> node) {
return icfg.getCFG(node);
}
public ExplodedInterproceduralCFG getICFG() {
return icfg;
}
@Override
public String toString() {
return icfg.toString();
}
}