/*******************************************************************************
* Copyright (c) 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.ipa.modref;
import java.util.Collection;
import java.util.Map;
import com.ibm.wala.dataflow.graph.AbstractMeetOperator;
import com.ibm.wala.dataflow.graph.BitVectorFramework;
import com.ibm.wala.dataflow.graph.BitVectorUnion;
import com.ibm.wala.dataflow.graph.BitVectorUnionVector;
import com.ibm.wala.dataflow.graph.ITransferFunctionProvider;
import com.ibm.wala.fixpoint.BitVectorVariable;
import com.ibm.wala.fixpoint.UnaryOperator;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.graph.Graph;
import com.ibm.wala.util.intset.BitVector;
import com.ibm.wala.util.intset.MutableMapping;
import com.ibm.wala.util.intset.OrdinalSetMapping;
/**
* Generic dataflow framework to accumulate reachable gen'ned values in a graph.
*/
public class GenReach<T, L> extends BitVectorFramework<T, L> {
@SuppressWarnings("unchecked")
public GenReach(Graph<T> flowGraph, Map<T, Collection<L>> gen) {
super(flowGraph, new GenFunctions<T, L>(gen), makeDomain(gen));
// ugly but necessary, in order to avoid computing the domain twice.
GenReach.GenFunctions<T, L> g = (GenReach.GenFunctions<T, L>) getTransferFunctionProvider();
g.domain = getLatticeValues();
}
private static <T, L> OrdinalSetMapping<L> makeDomain(Map<T, Collection<L>> gen) {
MutableMapping<L> result = MutableMapping.make();
if (gen == null) {
throw new IllegalArgumentException("null gen");
}
for (Collection<L> c : gen.values()) {
for (L p : c) {
result.add(p);
}
}
return result;
}
static class GenFunctions<T, L> implements ITransferFunctionProvider<T, BitVectorVariable> {
private final Map<T, Collection<L>> gen;
private OrdinalSetMapping<L> domain;
public GenFunctions(Map<T, Collection<L>> gen) {
this.gen = gen;
}
@Override
public AbstractMeetOperator<BitVectorVariable> getMeetOperator() {
return BitVectorUnion.instance();
}
@Override
public UnaryOperator<BitVectorVariable> getNodeTransferFunction(T node) {
BitVector v = getGen(node);
return new BitVectorUnionVector(v);
}
private BitVector getGen(T node) {
Collection<L> g = gen.get(node);
if (g == null) {
return new BitVector();
} else {
BitVector result = new BitVector();
for (L p : g) {
result.set(domain.getMappedIndex(p));
}
return result;
}
}
@Override
public boolean hasEdgeTransferFunctions() {
return false;
}
@Override
public boolean hasNodeTransferFunctions() {
return true;
}
@Override
public UnaryOperator<BitVectorVariable> getEdgeTransferFunction(T src, T dst) {
Assertions.UNREACHABLE();
return null;
}
}
}