147 lines
4.8 KiB
Java
147 lines
4.8 KiB
Java
/*******************************************************************************
|
|
* Copyright (c) 2002 - 2006 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
|
|
*******************************************************************************/
|
|
package com.ibm.wala.util.graph;
|
|
|
|
import java.util.Iterator;
|
|
import java.util.function.Predicate;
|
|
|
|
import com.ibm.wala.dataflow.graph.AbstractMeetOperator;
|
|
import com.ibm.wala.dataflow.graph.BitVectorFramework;
|
|
import com.ibm.wala.dataflow.graph.BitVectorIdentity;
|
|
import com.ibm.wala.dataflow.graph.BitVectorSolver;
|
|
import com.ibm.wala.dataflow.graph.BitVectorUnion;
|
|
import com.ibm.wala.dataflow.graph.BitVectorUnionConstant;
|
|
import com.ibm.wala.dataflow.graph.DataflowSolver;
|
|
import com.ibm.wala.dataflow.graph.ITransferFunctionProvider;
|
|
import com.ibm.wala.fixpoint.BitVectorVariable;
|
|
import com.ibm.wala.fixpoint.UnaryOperator;
|
|
import com.ibm.wala.util.CancelException;
|
|
import com.ibm.wala.util.MonitorUtil.IProgressMonitor;
|
|
import com.ibm.wala.util.collections.FilterIterator;
|
|
import com.ibm.wala.util.collections.Iterator2Collection;
|
|
import com.ibm.wala.util.debug.Assertions;
|
|
import com.ibm.wala.util.graph.impl.GraphInverter;
|
|
import com.ibm.wala.util.intset.MutableMapping;
|
|
import com.ibm.wala.util.intset.OrdinalSet;
|
|
import com.ibm.wala.util.intset.OrdinalSetMapping;
|
|
|
|
/**
|
|
* A dataflow system that computes, for each graph node, the set of "interesting" nodes that are reachable
|
|
*/
|
|
public class GraphReachability<T, S> {
|
|
|
|
/**
|
|
* Governing graph
|
|
*/
|
|
private final Graph<T> g;
|
|
|
|
/**
|
|
* Killdall-style dataflow solver
|
|
*/
|
|
private DataflowSolver<T, BitVectorVariable> solver;
|
|
|
|
/**
|
|
* set of "interesting" CGNodes
|
|
*/
|
|
final OrdinalSetMapping<S> domain;
|
|
|
|
/**
|
|
* @param g call graph to analyze
|
|
* @param filter "interesting" node definition
|
|
* @throws IllegalArgumentException if g is null
|
|
*/
|
|
public GraphReachability(Graph<T> g, Predicate<?> filter) {
|
|
if (g == null) {
|
|
throw new IllegalArgumentException("g is null");
|
|
}
|
|
this.g = g;
|
|
Iterator<S> i = new FilterIterator<>(g.iterator(), filter);
|
|
domain = new MutableMapping<>((Iterator2Collection.toSet(i)).toArray());
|
|
}
|
|
|
|
/**
|
|
* @param n
|
|
* @return the set of interesting nodes reachable from n
|
|
*/
|
|
public OrdinalSet<S> getReachableSet(Object n) throws IllegalStateException {
|
|
if (solver == null) {
|
|
throw new IllegalStateException("must call solve() before calling getReachableSet()");
|
|
}
|
|
BitVectorVariable v = solver.getOut(n);
|
|
assert v != null : "null variable for node " + n;
|
|
if (v.getValue() == null) {
|
|
return OrdinalSet.empty();
|
|
} else {
|
|
return new OrdinalSet<>(v.getValue(), domain);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return true iff the evaluation of some equation caused a change in the value of some variable.
|
|
*/
|
|
public boolean solve(IProgressMonitor monitor) throws CancelException {
|
|
|
|
ITransferFunctionProvider<T, BitVectorVariable> functions = new ITransferFunctionProvider<T, BitVectorVariable>() {
|
|
|
|
/*
|
|
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#getNodeTransferFunction(java.lang.Object)
|
|
*/
|
|
@Override
|
|
public UnaryOperator<BitVectorVariable> getNodeTransferFunction(T n) {
|
|
int index = domain.getMappedIndex(n);
|
|
if (index > -1) {
|
|
return new BitVectorUnionConstant(index);
|
|
} else {
|
|
return BitVectorIdentity.instance();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#hasNodeTransferFunctions()
|
|
*/
|
|
@Override
|
|
public boolean hasNodeTransferFunctions() {
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#getEdgeTransferFunction(java.lang.Object, java.lang.Object)
|
|
*/
|
|
@Override
|
|
public UnaryOperator<BitVectorVariable> getEdgeTransferFunction(Object from, Object to) {
|
|
Assertions.UNREACHABLE();
|
|
return null;
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#hasEdgeTransferFunctions()
|
|
*/
|
|
@Override
|
|
public boolean hasEdgeTransferFunctions() {
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* @see com.ibm.wala.dataflow.graph.ITransferFunctionProvider#getMeetOperator()
|
|
*/
|
|
@Override
|
|
public AbstractMeetOperator<BitVectorVariable> getMeetOperator() {
|
|
return BitVectorUnion.instance();
|
|
}
|
|
};
|
|
|
|
BitVectorFramework<T, S> f = new BitVectorFramework<>(GraphInverter.invert(g), functions, domain);
|
|
solver = new BitVectorSolver<>(f);
|
|
return solver.solve(monitor);
|
|
}
|
|
|
|
}
|