added documentation
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@3824 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
2e724aac3e
commit
e25b29ed48
|
@ -45,28 +45,37 @@ import com.ibm.wala.util.intset.OrdinalSetMapping;
|
|||
public class ContextInsensitiveReachingDefs {
|
||||
|
||||
/**
|
||||
* the exploded control-flow graph on which to compute the analysis
|
||||
* the exploded interprocedural control-flow graph on which to compute the analysis
|
||||
*/
|
||||
private final ExplodedInterproceduralCFG icfg;
|
||||
|
||||
/**
|
||||
* maps method and instruction index of putstatic to more compact numbering for bitvectors
|
||||
* maps call graph node and instruction index of putstatic instructions to more compact numbering for bitvectors
|
||||
*/
|
||||
private final OrdinalSetMapping<Pair<CGNode, Integer>> putInstrNumbering;
|
||||
|
||||
/**
|
||||
* for resolving field references in putstatic instructions
|
||||
*/
|
||||
private final IClassHierarchy cha;
|
||||
|
||||
/**
|
||||
* maps each static field to the numbers of the statements that define it
|
||||
* maps each static field to the numbers of the statements (in {@link #putInstrNumbering}) that define it; used for kills in flow
|
||||
* functions
|
||||
*/
|
||||
private final Map<IField, BitVector> staticField2DefStatements = HashMapFactory.make();
|
||||
|
||||
private static final boolean VERBOSE = true;
|
||||
|
||||
public ContextInsensitiveReachingDefs(ExplodedInterproceduralCFG icfg, IClassHierarchy cha) {
|
||||
this.icfg = icfg;
|
||||
this.cha = cha;
|
||||
this.putInstrNumbering = numberPutStatics();
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a numbering of the putstatic instructions
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private OrdinalSetMapping<Pair<CGNode, Integer>> numberPutStatics() {
|
||||
ArrayList<Pair<CGNode, Integer>> putInstrs = new ArrayList<Pair<CGNode, Integer>>();
|
||||
|
@ -80,8 +89,10 @@ public class ContextInsensitiveReachingDefs {
|
|||
SSAInstruction instruction = instructions[i];
|
||||
if (instruction instanceof SSAPutInstruction && ((SSAPutInstruction) instruction).isStatic()) {
|
||||
SSAPutInstruction putInstr = (SSAPutInstruction) instruction;
|
||||
// instrNum is the number that will be assigned to this putstatic
|
||||
int instrNum = putInstrs.size();
|
||||
putInstrs.add(Pair.make(node, i));
|
||||
// also update the mapping of static fields to def'ing statements
|
||||
IField field = cha.resolveField(putInstr.getDeclaredField());
|
||||
assert field != null;
|
||||
BitVector bv = staticField2DefStatements.get(field);
|
||||
|
@ -98,8 +109,10 @@ public class ContextInsensitiveReachingDefs {
|
|||
|
||||
private class TransferFunctions implements ITransferFunctionProvider<BasicBlockInContext<IExplodedBasicBlock>, BitVectorVariable> {
|
||||
|
||||
/**
|
||||
* our meet operator is set union
|
||||
*/
|
||||
public AbstractMeetOperator<BitVectorVariable> getMeetOperator() {
|
||||
// meet is union
|
||||
return BitVectorUnion.instance();
|
||||
}
|
||||
|
||||
|
@ -109,7 +122,7 @@ public class ContextInsensitiveReachingDefs {
|
|||
int instructionIndex = ebb.getFirstInstructionIndex();
|
||||
CGNode cgNode = node.getNode();
|
||||
if (instruction instanceof SSAPutInstruction && ((SSAPutInstruction) instruction).isStatic()) {
|
||||
// kill all defs of the same static field
|
||||
// kill all defs of the same static field, and gen this instruction
|
||||
final SSAPutInstruction putInstr = (SSAPutInstruction) instruction;
|
||||
final IField field = cha.resolveField(putInstr.getDeclaredField());
|
||||
assert field != null;
|
||||
|
@ -118,11 +131,15 @@ public class ContextInsensitiveReachingDefs {
|
|||
gen.set(putInstrNumbering.getMappedIndex(Pair.make(cgNode, instructionIndex)));
|
||||
return new BitVectorKillGen(kill, gen);
|
||||
} else {
|
||||
// nothing defined
|
||||
// identity function for non-putstatic instructions
|
||||
return BitVectorIdentity.instance();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* here we need an edge transfer function for call-to-return edges (see
|
||||
* {@link #getEdgeTransferFunction(BasicBlockInContext, BasicBlockInContext)})
|
||||
*/
|
||||
public boolean hasEdgeTransferFunctions() {
|
||||
return true;
|
||||
}
|
||||
|
@ -131,9 +148,13 @@ public class ContextInsensitiveReachingDefs {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* for direct call-to-return edges at a call site, the edge transfer function will kill all facts, since we only want to
|
||||
* consider facts that arise from going through the callee
|
||||
*/
|
||||
public UnaryOperator<BitVectorVariable> getEdgeTransferFunction(BasicBlockInContext<IExplodedBasicBlock> src,
|
||||
BasicBlockInContext<IExplodedBasicBlock> dst) {
|
||||
if (isCallToReturnEdge(src,dst)) {
|
||||
if (isCallToReturnEdge(src, dst)) {
|
||||
return BitVectorKillAll.instance();
|
||||
} else {
|
||||
return BitVectorIdentity.instance();
|
||||
|
@ -147,7 +168,13 @@ public class ContextInsensitiveReachingDefs {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* run the analysis
|
||||
*
|
||||
* @return the solver used for the analysis, which contains the analysis result
|
||||
*/
|
||||
public BitVectorSolver<BasicBlockInContext<IExplodedBasicBlock>> analyze() {
|
||||
// the framework describes the dataflow problem, in particular the underlying graph and the transfer functions
|
||||
BitVectorFramework<BasicBlockInContext<IExplodedBasicBlock>, Pair<CGNode, Integer>> framework = new BitVectorFramework<BasicBlockInContext<IExplodedBasicBlock>, Pair<CGNode, Integer>>(
|
||||
icfg, new TransferFunctions(), putInstrNumbering);
|
||||
BitVectorSolver<BasicBlockInContext<IExplodedBasicBlock>> solver = new BitVectorSolver<BasicBlockInContext<IExplodedBasicBlock>>(
|
||||
|
@ -155,18 +182,23 @@ public class ContextInsensitiveReachingDefs {
|
|||
try {
|
||||
solver.solve(null);
|
||||
} catch (CancelException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
// this shouldn't happen
|
||||
assert false;
|
||||
}
|
||||
for (BasicBlockInContext<IExplodedBasicBlock> ebb : icfg) {
|
||||
System.out.println(ebb);
|
||||
System.out.println(ebb.getDelegate().getInstruction());
|
||||
System.out.println(solver.getIn(ebb));
|
||||
System.out.println(solver.getOut(ebb));
|
||||
if (VERBOSE) {
|
||||
for (BasicBlockInContext<IExplodedBasicBlock> ebb : icfg) {
|
||||
System.out.println(ebb);
|
||||
System.out.println(ebb.getDelegate().getInstruction());
|
||||
System.out.println(solver.getIn(ebb));
|
||||
System.out.println(solver.getOut(ebb));
|
||||
}
|
||||
}
|
||||
return solver;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets putstatic instruction corresponding to some fact number from a bitvector in the analysis result
|
||||
*/
|
||||
public Pair<CGNode, Integer> getNodeAndInstrForNumber(int num) {
|
||||
return putInstrNumbering.getMappedObject(num);
|
||||
}
|
||||
|
|
|
@ -48,17 +48,30 @@ import com.ibm.wala.util.intset.MutableSparseIntSet;
|
|||
*/
|
||||
public class ContextSensitiveReachingDefs {
|
||||
|
||||
/**
|
||||
* used for resolving field references in putstatic instructions
|
||||
*/
|
||||
private final IClassHierarchy cha;
|
||||
|
||||
private final ISupergraph<BasicBlockInContext<IExplodedBasicBlock>, CGNode> supergraph;
|
||||
/**
|
||||
* the supergraph over which tabulation is performed
|
||||
*/
|
||||
private final ISupergraph<BasicBlockInContext<IExplodedBasicBlock>, CGNode> supergraph;
|
||||
|
||||
private ReachingDefsDomain domain = new ReachingDefsDomain();
|
||||
/**
|
||||
* the tabulation domain
|
||||
*/
|
||||
private final ReachingDefsDomain domain = new ReachingDefsDomain();
|
||||
|
||||
public ContextSensitiveReachingDefs(CallGraph cg, AnalysisCache cache) {
|
||||
this.cha = cg.getClassHierarchy();
|
||||
// we use an ICFGSupergraph, which basically adapts ExplodedInterproceduralCFG to the ISupergraph interface
|
||||
this.supergraph = ICFGSupergraph.make(cg, cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* controls numbering of putstatic instructions for use in tabulation
|
||||
*/
|
||||
private class ReachingDefsDomain extends MutableMapping<Pair<CGNode, Integer>> implements
|
||||
TabulationDomain<Pair<CGNode, Integer>, BasicBlockInContext<IExplodedBasicBlock>> {
|
||||
|
||||
|
@ -78,29 +91,45 @@ public class ContextSensitiveReachingDefs {
|
|||
this.domain = domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* the flow function for flow from a callee to caller where there was no flow from caller to callee; just the identity function
|
||||
*
|
||||
* @see ReachingDefsProblem
|
||||
*/
|
||||
public IFlowFunction getUnbalancedReturnFlowFunction(BasicBlockInContext<IExplodedBasicBlock> src,
|
||||
BasicBlockInContext<IExplodedBasicBlock> dest) {
|
||||
return IdentityFlowFunction.identity();
|
||||
}
|
||||
|
||||
/**
|
||||
* flow function from caller to callee; just the identity function
|
||||
*/
|
||||
public IUnaryFlowFunction getCallFlowFunction(BasicBlockInContext<IExplodedBasicBlock> src,
|
||||
BasicBlockInContext<IExplodedBasicBlock> dest, BasicBlockInContext<IExplodedBasicBlock> ret) {
|
||||
// just send the fact into the callee
|
||||
return IdentityFlowFunction.identity();
|
||||
}
|
||||
|
||||
/**
|
||||
* flow function from call node to return node when there are no targets for the call site; not a case we are expecting
|
||||
*/
|
||||
public IUnaryFlowFunction getCallNoneToReturnFlowFunction(BasicBlockInContext<IExplodedBasicBlock> src,
|
||||
BasicBlockInContext<IExplodedBasicBlock> dest) {
|
||||
// if we're missing callees, just give up and kill everything
|
||||
return KillEverything.singleton();
|
||||
}
|
||||
|
||||
/**
|
||||
* flow function from call node to return node at a call site when callees exist. We kill everything; surviving facts should
|
||||
* flow out of the callee
|
||||
*/
|
||||
public IUnaryFlowFunction getCallToReturnFlowFunction(BasicBlockInContext<IExplodedBasicBlock> src,
|
||||
BasicBlockInContext<IExplodedBasicBlock> dest) {
|
||||
// kill everything; surviving facts should flow out of the callee
|
||||
return KillEverything.singleton();
|
||||
}
|
||||
|
||||
/**
|
||||
* flow function for normal intraprocedural edges
|
||||
*/
|
||||
public IUnaryFlowFunction getNormalFlowFunction(final BasicBlockInContext<IExplodedBasicBlock> src,
|
||||
BasicBlockInContext<IExplodedBasicBlock> dest) {
|
||||
final IExplodedBasicBlock ebb = src.getDelegate();
|
||||
|
@ -111,15 +140,16 @@ public class ContextSensitiveReachingDefs {
|
|||
return new IUnaryFlowFunction() {
|
||||
|
||||
public IntSet getTargets(int d1) {
|
||||
// first, gen this statement
|
||||
int factNum = domain.getMappedIndex(Pair.make(src.getNode(), ebb.getFirstInstructionIndex()));
|
||||
IField staticField = cha.resolveField(putInstr.getDeclaredField());
|
||||
assert staticField != null;
|
||||
assert factNum != -1;
|
||||
MutableSparseIntSet result = MutableSparseIntSet.makeEmpty();
|
||||
result.add(factNum);
|
||||
// if incoming statement is some different statement that defs the same static field, kill it; otherwise, keep it
|
||||
if (d1 != factNum) {
|
||||
IField staticField = cha.resolveField(putInstr.getDeclaredField());
|
||||
assert staticField != null;
|
||||
Pair<CGNode, Integer> otherPutInstrAndNode = domain.getMappedObject(d1);
|
||||
// if it writes the same field, kill it
|
||||
SSAPutInstruction otherPutInstr = (SSAPutInstruction) otherPutInstrAndNode.fst.getIR().getInstructions()[otherPutInstrAndNode.snd];
|
||||
IField otherStaticField = cha.resolveField(otherPutInstr.getDeclaredField());
|
||||
if (!staticField.equals(otherStaticField)) {
|
||||
|
@ -135,9 +165,13 @@ public class ContextSensitiveReachingDefs {
|
|||
};
|
||||
}
|
||||
}
|
||||
// identity function when src block isn't for a putstatic
|
||||
return IdentityFlowFunction.identity();
|
||||
}
|
||||
|
||||
/**
|
||||
* standard flow function from callee to caller; just identity
|
||||
*/
|
||||
public IFlowFunction getReturnFlowFunction(BasicBlockInContext<IExplodedBasicBlock> call,
|
||||
BasicBlockInContext<IExplodedBasicBlock> src, BasicBlockInContext<IExplodedBasicBlock> dest) {
|
||||
return IdentityFlowFunction.identity();
|
||||
|
@ -145,11 +179,24 @@ public class ContextSensitiveReachingDefs {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Definition of the reaching definitions tabulation problem. Note that we choose to make the problem a <em>partially</em>
|
||||
* balanced tabulation problem, where the solver is seeded with the putstatic instructions themselves. The problem is partially
|
||||
* balanced since a definition in a callee used as a seed for the analysis may then reach a caller, yielding a "return" without a
|
||||
* corresponding "call." An alternative to this approach, used in the Reps-Horwitz-Sagiv POPL95 paper, would be to "lift" the
|
||||
* domain of putstatic instructions with a 0 (bottom) element, have a 0->0 transition in all transfer functions, and then seed the
|
||||
* analysis with the path edge (main_entry, 0) -> (main_entry, 0). We choose the partially-balanced approach to avoid pollution of
|
||||
* the flow functions.
|
||||
*
|
||||
*/
|
||||
private class ReachingDefsProblem implements
|
||||
PartiallyBalancedTabulationProblem<BasicBlockInContext<IExplodedBasicBlock>, CGNode, Pair<CGNode, Integer>> {
|
||||
|
||||
private ReachingDefsFlowFunctions flowFunctions = new ReachingDefsFlowFunctions(domain);
|
||||
|
||||
/**
|
||||
* path edges corresponding to all putstatic instructions, used as seeds for the analysis
|
||||
*/
|
||||
private Collection<PathEdge<BasicBlockInContext<IExplodedBasicBlock>>> initialSeeds = collectInitialSeeds();
|
||||
|
||||
/**
|
||||
|
@ -161,7 +208,7 @@ public class ContextSensitiveReachingDefs {
|
|||
}
|
||||
|
||||
/**
|
||||
* we use the entry block of the CGNode as the fake entry when propagating from callee to caller with unbalanced parens
|
||||
* we use the entry block of the CGNode as the "fake" entry when propagating from callee to caller with unbalanced parens
|
||||
*/
|
||||
private BasicBlockInContext<IExplodedBasicBlock> getFakeEntry(final CGNode cgNode) {
|
||||
BasicBlockInContext<IExplodedBasicBlock>[] entriesForProcedure = supergraph.getEntriesForProcedure(cgNode);
|
||||
|
@ -169,6 +216,9 @@ public class ContextSensitiveReachingDefs {
|
|||
return entriesForProcedure[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* collect the putstatic instructions in the call graph as {@link PathEdge} seeds for the analysis
|
||||
*/
|
||||
private Collection<PathEdge<BasicBlockInContext<IExplodedBasicBlock>>> collectInitialSeeds() {
|
||||
Collection<PathEdge<BasicBlockInContext<IExplodedBasicBlock>>> result = HashSetFactory.make();
|
||||
for (BasicBlockInContext<IExplodedBasicBlock> bb : supergraph) {
|
||||
|
@ -181,6 +231,7 @@ public class ContextSensitiveReachingDefs {
|
|||
Pair<CGNode, Integer> fact = Pair.make(cgNode, ebb.getFirstInstructionIndex());
|
||||
int factNum = domain.add(fact);
|
||||
BasicBlockInContext<IExplodedBasicBlock> fakeEntry = getFakeEntry(cgNode);
|
||||
// note that the fact number used for the source of this path edge doesn't really matter
|
||||
result.add(PathEdge.createPathEdge(fakeEntry, factNum, bb, factNum));
|
||||
|
||||
}
|
||||
|
@ -197,6 +248,9 @@ public class ContextSensitiveReachingDefs {
|
|||
return domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* we don't need a merge function; the default unioning of tabulation works fine
|
||||
*/
|
||||
public IMergeFunction getMergeFunction() {
|
||||
return null;
|
||||
}
|
||||
|
@ -211,19 +265,28 @@ public class ContextSensitiveReachingDefs {
|
|||
|
||||
}
|
||||
|
||||
public TabulationResult<BasicBlockInContext<IExplodedBasicBlock>, CGNode, Pair<CGNode, Integer>> analyze() throws CancelException {
|
||||
/**
|
||||
* perform the tabulation analysis and return the {@link TabulationResult}
|
||||
*/
|
||||
public TabulationResult<BasicBlockInContext<IExplodedBasicBlock>, CGNode, Pair<CGNode, Integer>> analyze() {
|
||||
PartiallyBalancedTabulationSolver<BasicBlockInContext<IExplodedBasicBlock>, CGNode, Pair<CGNode, Integer>> solver = PartiallyBalancedTabulationSolver
|
||||
.createPartiallyBalancedTabulationSolver(new ReachingDefsProblem(), null);
|
||||
TabulationResult<BasicBlockInContext<IExplodedBasicBlock>, CGNode, Pair<CGNode, Integer>> result = solver.solve();
|
||||
TabulationResult<BasicBlockInContext<IExplodedBasicBlock>, CGNode, Pair<CGNode, Integer>> result = null;
|
||||
try {
|
||||
result = solver.solve();
|
||||
} catch (CancelException e) {
|
||||
// this shouldn't happen
|
||||
assert false;
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public ISupergraph<BasicBlockInContext<IExplodedBasicBlock>, CGNode> getSupergraph() {
|
||||
return supergraph;
|
||||
}
|
||||
|
||||
public TabulationDomain<Pair<CGNode,Integer>, BasicBlockInContext<IExplodedBasicBlock>> getDomain() {
|
||||
|
||||
public TabulationDomain<Pair<CGNode, Integer>, BasicBlockInContext<IExplodedBasicBlock>> getDomain() {
|
||||
return domain;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,23 +47,32 @@ public class IntraprocReachingDefs {
|
|||
private final ExplodedControlFlowGraph ecfg;
|
||||
|
||||
/**
|
||||
* maps instruction index of putstatic to more compact numbering for bitvectors
|
||||
* maps the index of a putstatic IR instruction to a more compact numbering for use in bitvectors
|
||||
*/
|
||||
private final OrdinalSetMapping<Integer> putInstrNumbering;
|
||||
|
||||
/**
|
||||
* used to resolve references to fields in putstatic instructions
|
||||
*/
|
||||
private final IClassHierarchy cha;
|
||||
|
||||
/**
|
||||
* maps each static field to the numbers of the statements that define it
|
||||
* maps each static field to the numbers of the statements (in {@link #putInstrNumbering}) that define it; used for kills in flow
|
||||
* functions
|
||||
*/
|
||||
private final Map<IField, BitVector> staticField2DefStatements = HashMapFactory.make();
|
||||
|
||||
private static final boolean VERBOSE = true;
|
||||
|
||||
public IntraprocReachingDefs(ExplodedControlFlowGraph ecfg, IClassHierarchy cha) {
|
||||
this.ecfg = ecfg;
|
||||
this.cha = cha;
|
||||
this.putInstrNumbering = numberPutStatics();
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a numbering of the putstatic instructions
|
||||
*/
|
||||
private OrdinalSetMapping<Integer> numberPutStatics() {
|
||||
ArrayList<Integer> putInstrs = new ArrayList<Integer>();
|
||||
IR ir = ecfg.getIR();
|
||||
|
@ -72,8 +81,10 @@ public class IntraprocReachingDefs {
|
|||
SSAInstruction instruction = instructions[i];
|
||||
if (instruction instanceof SSAPutInstruction && ((SSAPutInstruction) instruction).isStatic()) {
|
||||
SSAPutInstruction putInstr = (SSAPutInstruction) instruction;
|
||||
// instrNum is the number that will be assigned to this putstatic
|
||||
int instrNum = putInstrs.size();
|
||||
putInstrs.add(i);
|
||||
// also update the mapping of static fields to def'ing statements
|
||||
IField field = cha.resolveField(putInstr.getDeclaredField());
|
||||
assert field != null;
|
||||
BitVector bv = staticField2DefStatements.get(field);
|
||||
|
@ -93,8 +104,10 @@ public class IntraprocReachingDefs {
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* our meet operator is set union
|
||||
*/
|
||||
public AbstractMeetOperator<BitVectorVariable> getMeetOperator() {
|
||||
// meet is union
|
||||
return BitVectorUnion.instance();
|
||||
}
|
||||
|
||||
|
@ -102,7 +115,7 @@ public class IntraprocReachingDefs {
|
|||
SSAInstruction instruction = node.getInstruction();
|
||||
int instructionIndex = node.getFirstInstructionIndex();
|
||||
if (instruction instanceof SSAPutInstruction && ((SSAPutInstruction) instruction).isStatic()) {
|
||||
// kill all defs of the same static field
|
||||
// kill all defs of the same static field, and gen this instruction
|
||||
final SSAPutInstruction putInstr = (SSAPutInstruction) instruction;
|
||||
final IField field = cha.resolveField(putInstr.getDeclaredField());
|
||||
assert field != null;
|
||||
|
@ -111,12 +124,13 @@ public class IntraprocReachingDefs {
|
|||
gen.set(putInstrNumbering.getMappedIndex(instructionIndex));
|
||||
return new BitVectorKillGen(kill, gen);
|
||||
} else {
|
||||
// nothing defined
|
||||
// identity function for non-putstatic instructions
|
||||
return BitVectorIdentity.instance();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasEdgeTransferFunctions() {
|
||||
// we only need transfer functions on nodes
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -126,21 +140,29 @@ public class IntraprocReachingDefs {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* run the analysis
|
||||
*
|
||||
* @return the solver used for the analysis, which contains the analysis result
|
||||
*/
|
||||
public BitVectorSolver<IExplodedBasicBlock> analyze() {
|
||||
BitVectorFramework<IExplodedBasicBlock, Integer> framework = new BitVectorFramework<IExplodedBasicBlock, Integer>(
|
||||
ecfg, new TransferFunctions(), putInstrNumbering);
|
||||
// the framework describes the dataflow problem, in particular the underlying graph and the transfer functions
|
||||
BitVectorFramework<IExplodedBasicBlock, Integer> framework = new BitVectorFramework<IExplodedBasicBlock, Integer>(ecfg,
|
||||
new TransferFunctions(), putInstrNumbering);
|
||||
BitVectorSolver<IExplodedBasicBlock> solver = new BitVectorSolver<IExplodedBasicBlock>(framework);
|
||||
try {
|
||||
solver.solve(null);
|
||||
} catch (CancelException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
// this shouldn't happen
|
||||
assert false;
|
||||
}
|
||||
for (IExplodedBasicBlock ebb : ecfg) {
|
||||
System.out.println(ebb);
|
||||
System.out.println(ebb.getInstruction());
|
||||
System.out.println(solver.getIn(ebb));
|
||||
System.out.println(solver.getOut(ebb));
|
||||
if (VERBOSE) {
|
||||
for (IExplodedBasicBlock ebb : ecfg) {
|
||||
System.out.println(ebb);
|
||||
System.out.println(ebb.getInstruction());
|
||||
System.out.println(solver.getIn(ebb));
|
||||
System.out.println(solver.getOut(ebb));
|
||||
}
|
||||
}
|
||||
return solver;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue