replace broken ExpandedControlFlowGraph with hopefully somewhat less broken ExplodedControlFlowGraph
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@1499 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
2c4fd1fc93
commit
b9465e1bcc
|
@ -40,8 +40,8 @@ import com.ibm.wala.ipa.slicer.Statement.Kind;
|
||||||
import com.ibm.wala.ssa.IR;
|
import com.ibm.wala.ssa.IR;
|
||||||
import com.ibm.wala.ssa.SSAInstruction;
|
import com.ibm.wala.ssa.SSAInstruction;
|
||||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||||
import com.ibm.wala.ssa.analysis.ExpandedControlFlowGraph;
|
import com.ibm.wala.ssa.analysis.ExplodedControlFlowGraph;
|
||||||
import com.ibm.wala.ssa.analysis.ExpandedControlFlowGraph.SingleInstructionBasicBlock;
|
import com.ibm.wala.ssa.analysis.ExplodedControlFlowGraph.ExplodedBasicBlock;
|
||||||
import com.ibm.wala.util.collections.Filter;
|
import com.ibm.wala.util.collections.Filter;
|
||||||
import com.ibm.wala.util.collections.FilterIterator;
|
import com.ibm.wala.util.collections.FilterIterator;
|
||||||
import com.ibm.wala.util.collections.HashMapFactory;
|
import com.ibm.wala.util.collections.HashMapFactory;
|
||||||
|
@ -104,12 +104,11 @@ public class HeapReachingDefs {
|
||||||
}
|
}
|
||||||
System.err.println("Reaching Defs " + node);
|
System.err.println("Reaching Defs " + node);
|
||||||
if (VERBOSE) {
|
if (VERBOSE) {
|
||||||
// System.err.println("Reaching Defs " + node);
|
|
||||||
System.err.println(statements.size());
|
System.err.println(statements.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a control flow graph with one instruction per basic block.
|
// create a control flow graph with one instruction per basic block.
|
||||||
ExpandedControlFlowGraph cfg = new ExpandedControlFlowGraph(ir);
|
ExplodedControlFlowGraph cfg = ExplodedControlFlowGraph.make(ir);
|
||||||
|
|
||||||
// create a mapping between statements and integers, used in bit vectors
|
// create a mapping between statements and integers, used in bit vectors
|
||||||
// shortly
|
// shortly
|
||||||
|
@ -141,7 +140,7 @@ public class HeapReachingDefs {
|
||||||
private final CallGraph cg;
|
private final CallGraph cg;
|
||||||
|
|
||||||
RDMap(BitVectorSolver<IBasicBlock> solver, OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h,
|
RDMap(BitVectorSolver<IBasicBlock> solver, OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h,
|
||||||
PointerAnalysis pa, Map<CGNode, OrdinalSet<PointerKey>> mod, ExpandedControlFlowGraph cfg,
|
PointerAnalysis pa, Map<CGNode, OrdinalSet<PointerKey>> mod, ExplodedControlFlowGraph cfg,
|
||||||
Map<Integer, NormalStatement> ssaInstructionIndex2Statement, HeapExclusions exclusions, CallGraph cg) {
|
Map<Integer, NormalStatement> ssaInstructionIndex2Statement, HeapExclusions exclusions, CallGraph cg) {
|
||||||
if (VERBOSE) {
|
if (VERBOSE) {
|
||||||
System.err.println("Init pointer Key mod ");
|
System.err.println("Init pointer Key mod ");
|
||||||
|
@ -160,7 +159,7 @@ public class HeapReachingDefs {
|
||||||
|
|
||||||
private void eagerPopulate(Map<PointerKey, MutableIntSet> pointerKeyMod, BitVectorSolver<IBasicBlock> solver,
|
private void eagerPopulate(Map<PointerKey, MutableIntSet> pointerKeyMod, BitVectorSolver<IBasicBlock> solver,
|
||||||
OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h, PointerAnalysis pa,
|
OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h, PointerAnalysis pa,
|
||||||
Map<CGNode, OrdinalSet<PointerKey>> mod, ExpandedControlFlowGraph cfg,
|
Map<CGNode, OrdinalSet<PointerKey>> mod, ExplodedControlFlowGraph cfg,
|
||||||
Map<Integer, NormalStatement> ssaInstruction2Statement) {
|
Map<Integer, NormalStatement> ssaInstruction2Statement) {
|
||||||
for (Statement s : domain) {
|
for (Statement s : domain) {
|
||||||
delegate.put(s, computeResult(s, pointerKeyMod, solver, domain, node, h, pa, mod, cfg, ssaInstruction2Statement));
|
delegate.put(s, computeResult(s, pointerKeyMod, solver, domain, node, h, pa, mod, cfg, ssaInstruction2Statement));
|
||||||
|
@ -169,11 +168,6 @@ public class HeapReachingDefs {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For each pointerKey, which statements may def it
|
* For each pointerKey, which statements may def it
|
||||||
*
|
|
||||||
* @param domain
|
|
||||||
* @param node
|
|
||||||
* @param h
|
|
||||||
* @param pa
|
|
||||||
*/
|
*/
|
||||||
private Map<PointerKey, MutableIntSet> initPointerKeyMod(OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h,
|
private Map<PointerKey, MutableIntSet> initPointerKeyMod(OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h,
|
||||||
PointerAnalysis pa) {
|
PointerAnalysis pa) {
|
||||||
|
@ -285,7 +279,7 @@ public class HeapReachingDefs {
|
||||||
*/
|
*/
|
||||||
private OrdinalSet<Statement> computeResult(Statement s, Map<PointerKey, MutableIntSet> pointerKeyMod,
|
private OrdinalSet<Statement> computeResult(Statement s, Map<PointerKey, MutableIntSet> pointerKeyMod,
|
||||||
BitVectorSolver<IBasicBlock> solver, OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h,
|
BitVectorSolver<IBasicBlock> solver, OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h,
|
||||||
PointerAnalysis pa, Map<CGNode, OrdinalSet<PointerKey>> mod, ExpandedControlFlowGraph cfg,
|
PointerAnalysis pa, Map<CGNode, OrdinalSet<PointerKey>> mod, ExplodedControlFlowGraph cfg,
|
||||||
Map<Integer, NormalStatement> ssaInstructionIndex2Statement) {
|
Map<Integer, NormalStatement> ssaInstructionIndex2Statement) {
|
||||||
switch (s.getKind()) {
|
switch (s.getKind()) {
|
||||||
case NORMAL:
|
case NORMAL:
|
||||||
|
@ -367,7 +361,7 @@ public class HeapReachingDefs {
|
||||||
*/
|
*/
|
||||||
private static Map<Statement, OrdinalSet<Statement>> makeResult(BitVectorSolver<IBasicBlock> solver,
|
private static Map<Statement, OrdinalSet<Statement>> makeResult(BitVectorSolver<IBasicBlock> solver,
|
||||||
OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h, PointerAnalysis pa,
|
OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h, PointerAnalysis pa,
|
||||||
Map<CGNode, OrdinalSet<PointerKey>> mod, ExpandedControlFlowGraph cfg,
|
Map<CGNode, OrdinalSet<PointerKey>> mod, ExplodedControlFlowGraph cfg,
|
||||||
Map<Integer, NormalStatement> ssaInstructionIndex2Statement, HeapExclusions exclusions, CallGraph cg) {
|
Map<Integer, NormalStatement> ssaInstructionIndex2Statement, HeapExclusions exclusions, CallGraph cg) {
|
||||||
|
|
||||||
return new RDMap(solver, domain, node, h, pa, mod, cfg, ssaInstructionIndex2Statement, exclusions, cg);
|
return new RDMap(solver, domain, node, h, pa, mod, cfg, ssaInstructionIndex2Statement, exclusions, cg);
|
||||||
|
@ -447,7 +441,7 @@ public class HeapReachingDefs {
|
||||||
|
|
||||||
private final CGNode node;
|
private final CGNode node;
|
||||||
|
|
||||||
private final ExpandedControlFlowGraph cfg;
|
private final ExplodedControlFlowGraph cfg;
|
||||||
|
|
||||||
private final OrdinalSetMapping<Statement> domain;
|
private final OrdinalSetMapping<Statement> domain;
|
||||||
|
|
||||||
|
@ -466,7 +460,7 @@ public class HeapReachingDefs {
|
||||||
*/
|
*/
|
||||||
private final IBinaryNaturalRelation heapReturnCaller = new BasicNaturalRelation();
|
private final IBinaryNaturalRelation heapReturnCaller = new BasicNaturalRelation();
|
||||||
|
|
||||||
public RD(CGNode node, ExpandedControlFlowGraph cfg, PointerAnalysis pa, OrdinalSetMapping<Statement> domain,
|
public RD(CGNode node, ExplodedControlFlowGraph cfg, PointerAnalysis pa, OrdinalSetMapping<Statement> domain,
|
||||||
Map<Integer, NormalStatement> ssaInstructionIndex2Statement, HeapExclusions exclusions) {
|
Map<Integer, NormalStatement> ssaInstructionIndex2Statement, HeapExclusions exclusions) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
this.cfg = cfg;
|
this.cfg = cfg;
|
||||||
|
@ -491,7 +485,7 @@ public class HeapReachingDefs {
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnaryOperator getEdgeTransferFunction(IBasicBlock src, IBasicBlock dst) {
|
public UnaryOperator getEdgeTransferFunction(IBasicBlock src, IBasicBlock dst) {
|
||||||
SingleInstructionBasicBlock s = (SingleInstructionBasicBlock) src;
|
ExplodedBasicBlock s = (ExplodedBasicBlock) src;
|
||||||
if (s.getInstruction() != null && !(s.getInstruction() instanceof SSAInvokeInstruction)
|
if (s.getInstruction() != null && !(s.getInstruction() instanceof SSAInvokeInstruction)
|
||||||
&& !cfg.getNormalSuccessors(src).contains(dst)) {
|
&& !cfg.getNormalSuccessors(src).contains(dst)) {
|
||||||
// if the edge only happens due to exceptional control flow, then no
|
// if the edge only happens due to exceptional control flow, then no
|
||||||
|
@ -538,7 +532,7 @@ public class HeapReachingDefs {
|
||||||
* @return int set representing the heap def statements that are gen'ed by
|
* @return int set representing the heap def statements that are gen'ed by
|
||||||
* the basic block. null if none.
|
* the basic block. null if none.
|
||||||
*/
|
*/
|
||||||
IntSet gen(SingleInstructionBasicBlock b) {
|
IntSet gen(ExplodedBasicBlock b) {
|
||||||
if (b.isEntryBlock()) {
|
if (b.isEntryBlock()) {
|
||||||
return heapEntryStatements();
|
return heapEntryStatements();
|
||||||
} else {
|
} else {
|
||||||
|
@ -588,7 +582,7 @@ public class HeapReachingDefs {
|
||||||
* @return int set representing the heap def statements that are killed by
|
* @return int set representing the heap def statements that are killed by
|
||||||
* the basic block. null if none.
|
* the basic block. null if none.
|
||||||
*/
|
*/
|
||||||
BitVector kill(SingleInstructionBasicBlock b) {
|
BitVector kill(ExplodedBasicBlock b) {
|
||||||
SSAInstruction s = b.getInstruction();
|
SSAInstruction s = b.getInstruction();
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -28,8 +28,7 @@ import com.ibm.wala.util.collections.HashSetFactory;
|
||||||
import com.ibm.wala.util.debug.Trace;
|
import com.ibm.wala.util.debug.Trace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Eliminate dead assignments (phis) from an SSA IR.
|
||||||
* Eliminate dead assignnments (phis) from an SSA IR.
|
|
||||||
*
|
*
|
||||||
* @author sfink
|
* @author sfink
|
||||||
*/
|
*/
|
||||||
|
@ -84,8 +83,6 @@ public class DeadAssignmentElimination {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author sfink
|
|
||||||
*
|
|
||||||
* A dataflow system which computes whether or not a value is dead
|
* A dataflow system which computes whether or not a value is dead
|
||||||
*/
|
*/
|
||||||
private static class DeadValueSystem extends DefaultFixedPointSolver {
|
private static class DeadValueSystem extends DefaultFixedPointSolver {
|
||||||
|
|
|
@ -1,144 +0,0 @@
|
||||||
/*******************************************************************************
|
|
||||||
* 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.ssa.analysis;
|
|
||||||
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import com.ibm.wala.ssa.SSACFG;
|
|
||||||
import com.ibm.wala.ssa.SSACFG.BasicBlock;
|
|
||||||
import com.ibm.wala.ssa.analysis.ExpandedControlFlowGraph.SingleInstructionBasicBlock;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Eran Yahav (yahave)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class ExpandedCFGDotWriter {
|
|
||||||
|
|
||||||
public static void write(String fileName, ExpandedControlFlowGraph cfg) throws IllegalArgumentException {
|
|
||||||
if (cfg == null) {
|
|
||||||
throw new IllegalArgumentException("cfg cannot be null");
|
|
||||||
}
|
|
||||||
StringBuffer result = new StringBuffer();
|
|
||||||
result.append(dotOutput(cfg));
|
|
||||||
try {
|
|
||||||
FileWriter fw = new FileWriter(fileName, false);
|
|
||||||
fw.write(result.toString());
|
|
||||||
fw.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Error writing dot file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void write(String fileName, SSACFG cfg) {
|
|
||||||
if (cfg == null) {
|
|
||||||
throw new IllegalArgumentException("cfg cannot be null");
|
|
||||||
}
|
|
||||||
StringBuffer result = new StringBuffer();
|
|
||||||
result.append(dotOutput(cfg));
|
|
||||||
try {
|
|
||||||
FileWriter fw = new FileWriter(fileName, false);
|
|
||||||
fw.write(result.toString());
|
|
||||||
fw.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Error writing dot file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static StringBuffer dotOutput(ExpandedControlFlowGraph cfg) {
|
|
||||||
StringBuffer result = new StringBuffer("digraph \"ExpandedControlFlowGraph:\" {\n");
|
|
||||||
result.append("center=true;fontsize=12;node [fontsize=12];edge [fontsize=12]; \n");
|
|
||||||
|
|
||||||
// create nodes for basic-blocks
|
|
||||||
for (Iterator it = cfg.iterator(); it.hasNext();) {
|
|
||||||
|
|
||||||
SingleInstructionBasicBlock bb = (SingleInstructionBasicBlock) it.next();
|
|
||||||
result.append(dotOutput(bb));
|
|
||||||
if (bb.isEntryBlock()) {
|
|
||||||
result.append(" [color=green]\n");
|
|
||||||
} else if (bb.isExitBlock()) {
|
|
||||||
result.append(" [color=red]\n");
|
|
||||||
} else {
|
|
||||||
result.append("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// create edges
|
|
||||||
for (Iterator it = cfg.iterator(); it.hasNext();) {
|
|
||||||
SingleInstructionBasicBlock bb = (SingleInstructionBasicBlock) it.next();
|
|
||||||
for (Iterator succIt = cfg.getSuccNodes(bb); succIt.hasNext();) {
|
|
||||||
SingleInstructionBasicBlock succ = (SingleInstructionBasicBlock) succIt.next();
|
|
||||||
result.append(dotOutput(bb));
|
|
||||||
result.append(" -> ");
|
|
||||||
result.append(dotOutput(succ));
|
|
||||||
|
|
||||||
result.append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// close digraph
|
|
||||||
result.append("}");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static StringBuffer dotOutput(SSACFG cfg) {
|
|
||||||
StringBuffer result = new StringBuffer("digraph \"ControlFlowGraph:\" {\n");
|
|
||||||
result.append("center=true;fontsize=12;node [fontsize=12];edge [fontsize=12]; \n");
|
|
||||||
|
|
||||||
// create nodes for basic-blocks
|
|
||||||
for (Iterator it = cfg.iterator(); it.hasNext();) {
|
|
||||||
|
|
||||||
BasicBlock bb = (BasicBlock) it.next();
|
|
||||||
result.append(dotOutput(bb));
|
|
||||||
if (bb.isEntryBlock()) {
|
|
||||||
result.append(" [color=green]\n");
|
|
||||||
} else if (bb.isExitBlock()) {
|
|
||||||
result.append(" [color=red]\n");
|
|
||||||
} else {
|
|
||||||
result.append("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// create edges
|
|
||||||
for (Iterator it = cfg.iterator(); it.hasNext();) {
|
|
||||||
BasicBlock bb = (BasicBlock) it.next();
|
|
||||||
for (Iterator succIt = cfg.getSuccNodes(bb); succIt.hasNext();) {
|
|
||||||
BasicBlock succ = (BasicBlock) succIt.next();
|
|
||||||
result.append(dotOutput(bb));
|
|
||||||
result.append(" -> ");
|
|
||||||
result.append(dotOutput(succ));
|
|
||||||
result.append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// close digraph
|
|
||||||
result.append("}");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static StringBuffer dotOutput(BasicBlock bb) {
|
|
||||||
StringBuffer result = new StringBuffer();
|
|
||||||
result.append("\"");
|
|
||||||
result.append(bb.getNumber());
|
|
||||||
result.append("\"");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static StringBuffer dotOutput(SingleInstructionBasicBlock bb) {
|
|
||||||
StringBuffer result = new StringBuffer();
|
|
||||||
result.append("\"");
|
|
||||||
result.append(bb.getNumber());
|
|
||||||
result.append("-");
|
|
||||||
result.append(bb.getInstruction());
|
|
||||||
result.append("\"");
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,418 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* 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.ssa.analysis;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.ibm.wala.cfg.ControlFlowGraph;
|
||||||
|
import com.ibm.wala.cfg.IBasicBlock;
|
||||||
|
import com.ibm.wala.classLoader.IMethod;
|
||||||
|
import com.ibm.wala.shrikeBT.IInstruction;
|
||||||
|
import com.ibm.wala.ssa.IR;
|
||||||
|
import com.ibm.wala.ssa.SSAInstruction;
|
||||||
|
import com.ibm.wala.util.collections.EmptyIterator;
|
||||||
|
import com.ibm.wala.util.collections.HashSetFactory;
|
||||||
|
import com.ibm.wala.util.collections.NonNullSingletonIterator;
|
||||||
|
import com.ibm.wala.util.debug.Assertions;
|
||||||
|
import com.ibm.wala.util.intset.BitVector;
|
||||||
|
import com.ibm.wala.util.intset.IntSet;
|
||||||
|
import com.ibm.wala.util.intset.SimpleVector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A view of a control flow graph where each basic block corresponds to exactly
|
||||||
|
* one SSA instruction index.
|
||||||
|
*
|
||||||
|
* Prototype: Not terribly efficient.
|
||||||
|
*/
|
||||||
|
public class ExplodedControlFlowGraph implements ControlFlowGraph {
|
||||||
|
|
||||||
|
private final IR ir;
|
||||||
|
|
||||||
|
private final SimpleVector<IBasicBlock> normalNodes = new SimpleVector<IBasicBlock>();
|
||||||
|
|
||||||
|
private final Collection<IBasicBlock> allNodes = HashSetFactory.make();
|
||||||
|
|
||||||
|
private final ExplodedBasicBlock entry;
|
||||||
|
|
||||||
|
private final ExplodedBasicBlock exit;
|
||||||
|
|
||||||
|
private ExplodedControlFlowGraph(IR ir) {
|
||||||
|
this.ir = ir;
|
||||||
|
this.entry = new ExplodedBasicBlock(-2, ir.getControlFlowGraph().entry());
|
||||||
|
this.exit = new ExplodedBasicBlock(-2, ir.getControlFlowGraph().exit());
|
||||||
|
createNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createNodes() {
|
||||||
|
allNodes.add(entry);
|
||||||
|
allNodes.add(exit);
|
||||||
|
for (IBasicBlock b : ir.getControlFlowGraph()) {
|
||||||
|
for (int i = b.getFirstInstructionIndex(); i <= b.getLastInstructionIndex(); i++) {
|
||||||
|
ExplodedBasicBlock bb = new ExplodedBasicBlock(i, b);
|
||||||
|
normalNodes.set(i, bb);
|
||||||
|
allNodes.add(bb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ExplodedControlFlowGraph make(IR ir) {
|
||||||
|
return new ExplodedControlFlowGraph(ir);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBasicBlock entry() {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBasicBlock exit() {
|
||||||
|
return exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBasicBlock getBlockForInstruction(int index) {
|
||||||
|
return normalNodes.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BitVector getCatchBlocks() {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<IBasicBlock> getExceptionalPredecessors(IBasicBlock b) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<IBasicBlock> getExceptionalSuccessors(IBasicBlock b) {
|
||||||
|
assert b != null;
|
||||||
|
if (b.equals(exit)) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
ExplodedBasicBlock eb = (ExplodedBasicBlock) b;
|
||||||
|
if (eb.isEntryBlock() || eb.instructionIndex == eb.original.getLastInstructionIndex()) {
|
||||||
|
List<IBasicBlock> result = new ArrayList<IBasicBlock>();
|
||||||
|
for (IBasicBlock s : ir.getControlFlowGraph().getExceptionalSuccessors(eb.original)) {
|
||||||
|
if (s.equals(ir.getControlFlowGraph().exit())) {
|
||||||
|
result.add(exit());
|
||||||
|
} else {
|
||||||
|
assert normalNodes.get(s.getFirstInstructionIndex()) != null;
|
||||||
|
result.add(normalNodes.get(s.getFirstInstructionIndex()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IInstruction[] getInstructions() {
|
||||||
|
return ir.getInstructions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMethod getMethod() {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<IBasicBlock> getNormalPredecessors(IBasicBlock b) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<IBasicBlock> getNormalSuccessors(IBasicBlock b) {
|
||||||
|
assert b != null;
|
||||||
|
if (b.equals(exit)) {
|
||||||
|
return Collections.emptySet();
|
||||||
|
}
|
||||||
|
ExplodedBasicBlock eb = (ExplodedBasicBlock) b;
|
||||||
|
if (eb.isEntryBlock() || eb.instructionIndex == eb.original.getLastInstructionIndex()) {
|
||||||
|
List<IBasicBlock> result = new ArrayList<IBasicBlock>();
|
||||||
|
for (IBasicBlock s : ir.getControlFlowGraph().getNormalSuccessors(eb.original)) {
|
||||||
|
if (s.equals(ir.getControlFlowGraph().exit())) {
|
||||||
|
result.add(exit());
|
||||||
|
} else {
|
||||||
|
assert normalNodes.get(s.getFirstInstructionIndex()) != null;
|
||||||
|
result.add(normalNodes.get(s.getFirstInstructionIndex()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
assert normalNodes.get(eb.instructionIndex + 1) != null;
|
||||||
|
return Collections.singleton(normalNodes.get(eb.instructionIndex + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getProgramCounter(int index) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeNodeAndEdges(IBasicBlock N) throws UnsupportedOperationException {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addNode(IBasicBlock n) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean containsNode(IBasicBlock N) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberOfNodes() {
|
||||||
|
return allNodes.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<IBasicBlock> iterator() {
|
||||||
|
return allNodes.iterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeNode(IBasicBlock n) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addEdge(IBasicBlock src, IBasicBlock dst) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPredNodeCount(IBasicBlock N) {
|
||||||
|
ExplodedBasicBlock b = (ExplodedBasicBlock) N;
|
||||||
|
if (b.isEntryBlock()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (b.equals(exit) || b.instructionIndex == b.original.getFirstInstructionIndex()) {
|
||||||
|
return ir.getControlFlowGraph().getPredNodeCount(b.original);
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<? extends IBasicBlock> getPredNodes(IBasicBlock N) {
|
||||||
|
ExplodedBasicBlock b = (ExplodedBasicBlock) N;
|
||||||
|
if (b.isEntryBlock()) {
|
||||||
|
return EmptyIterator.instance();
|
||||||
|
}
|
||||||
|
if (b.equals(exit) || b.instructionIndex == b.original.getFirstInstructionIndex()) {
|
||||||
|
List<IBasicBlock> result = new ArrayList<IBasicBlock>();
|
||||||
|
for (Iterator<IBasicBlock> it = ir.getControlFlowGraph().getPredNodes(b.original); it.hasNext();) {
|
||||||
|
IBasicBlock s = it.next();
|
||||||
|
if (s.isEntryBlock()) {
|
||||||
|
result.add(entry);
|
||||||
|
} else {
|
||||||
|
assert normalNodes.get(s.getLastInstructionIndex()) != null;
|
||||||
|
result.add(normalNodes.get(s.getLastInstructionIndex()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.iterator();
|
||||||
|
} else {
|
||||||
|
assert normalNodes.get(b.instructionIndex - 1) != null;
|
||||||
|
return NonNullSingletonIterator.make(normalNodes.get(b.instructionIndex - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSuccNodeCount(IBasicBlock N) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<? extends IBasicBlock> getSuccNodes(IBasicBlock N) {
|
||||||
|
assert N != null;
|
||||||
|
if (N.equals(exit)) {
|
||||||
|
return EmptyIterator.instance();
|
||||||
|
}
|
||||||
|
ExplodedBasicBlock b = (ExplodedBasicBlock) N;
|
||||||
|
if (b.isEntryBlock() || b.instructionIndex == b.original.getLastInstructionIndex()) {
|
||||||
|
List<IBasicBlock> result = new ArrayList<IBasicBlock>();
|
||||||
|
for (Iterator<IBasicBlock> it = ir.getControlFlowGraph().getSuccNodes(b.original); it.hasNext();) {
|
||||||
|
IBasicBlock s = it.next();
|
||||||
|
if (s.equals(ir.getControlFlowGraph().exit())) {
|
||||||
|
result.add(exit());
|
||||||
|
} else {
|
||||||
|
assert normalNodes.get(s.getFirstInstructionIndex()) != null;
|
||||||
|
result.add(normalNodes.get(s.getFirstInstructionIndex()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.iterator();
|
||||||
|
} else {
|
||||||
|
assert normalNodes.get(b.instructionIndex + 1) != null;
|
||||||
|
return NonNullSingletonIterator.make(normalNodes.get(b.instructionIndex + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasEdge(IBasicBlock src, IBasicBlock dst) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAllIncidentEdges(IBasicBlock node) throws UnsupportedOperationException {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeEdge(IBasicBlock src, IBasicBlock dst) throws UnsupportedOperationException {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeIncomingEdges(IBasicBlock node) throws UnsupportedOperationException {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeOutgoingEdges(IBasicBlock node) throws UnsupportedOperationException {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxNumber() {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBasicBlock getNode(int number) {
|
||||||
|
if (number == 0) {
|
||||||
|
return entry();
|
||||||
|
} else if (number == getNumberOfNodes() -1) {
|
||||||
|
return exit();
|
||||||
|
} else {
|
||||||
|
return normalNodes.get(number);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumber(IBasicBlock N) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<IBasicBlock> iterateNodes(IntSet s) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntSet getPredNodeNumbers(IBasicBlock node) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntSet getSuccNodeNumbers(IBasicBlock node) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExplodedBasicBlock implements IBasicBlock {
|
||||||
|
|
||||||
|
private final int instructionIndex;
|
||||||
|
|
||||||
|
private final IBasicBlock original;
|
||||||
|
|
||||||
|
public ExplodedBasicBlock(int instructionIndex, IBasicBlock original) {
|
||||||
|
this.instructionIndex = instructionIndex;
|
||||||
|
this.original = original;
|
||||||
|
assert original != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFirstInstructionIndex() {
|
||||||
|
return instructionIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLastInstructionIndex() {
|
||||||
|
return instructionIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IMethod getMethod() {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumber() {
|
||||||
|
if (isEntryBlock()) {
|
||||||
|
return 0;
|
||||||
|
} else if (isExitBlock()) {
|
||||||
|
return getNumberOfNodes() -1;
|
||||||
|
} else {
|
||||||
|
return instructionIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCatchBlock() {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEntryBlock() {
|
||||||
|
return original.isEntryBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isExitBlock() {
|
||||||
|
return original.isExitBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGraphNodeId() {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGraphNodeId(int number) {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterator<IInstruction> iterator() {
|
||||||
|
Assertions.UNREACHABLE();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + instructionIndex;
|
||||||
|
result = prime * result + ((original == null) ? 0 : original.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
final ExplodedBasicBlock other = (ExplodedBasicBlock) obj;
|
||||||
|
if (instructionIndex != other.instructionIndex)
|
||||||
|
return false;
|
||||||
|
if (original == null) {
|
||||||
|
if (other.original != null)
|
||||||
|
return false;
|
||||||
|
} else if (!original.equals(other.original))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SSAInstruction getInstruction() {
|
||||||
|
if (isEntryBlock() || isExitBlock()) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return ir.getInstructions()[instructionIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue