allow control flow in induced cfgs, and various related fixes

This commit is contained in:
Julian Dolby 2014-07-08 14:44:06 -04:00
parent d6ffcdc3bb
commit dd3124479e
19 changed files with 207 additions and 22000 deletions

View File

@ -664,7 +664,9 @@ public class RhinoToAstTranslator {
}
}
return Ast.makeNode(CAstNode.OBJECT_LITERAL, eltNodes.toArray(new CAstNode[eltNodes.size()]));
CAstNode lit = Ast.makeNode(CAstNode.OBJECT_LITERAL, eltNodes.toArray(new CAstNode[eltNodes.size()]));
arg.cfg().map(node, lit);
return lit;
}
@Override
@ -787,9 +789,12 @@ public class RhinoToAstTranslator {
result = get = Ast.makeNode(CAstNode.OBJECT_REF, obj, elt);
}
if (get != null && context.getCatchTarget() != null) {
if (get != null) {
context.cfg().map(get, get);
context.cfg().add(get, context.getCatchTarget(), JavaScriptTypes.TypeError);
context.cfg().add(
get,
context.getCatchTarget() != null? context.getCatchTarget(): CAstControlFlowMap.EXCEPTION_TO_EXIT,
JavaScriptTypes.TypeError);
}
return result;
@ -1178,7 +1183,10 @@ public class RhinoToAstTranslator {
visit(label, context);
args[i++] = visit(prop, context);
}
return Ast.makeNode(CAstNode.OBJECT_LITERAL, args);
CAstNode lit = Ast.makeNode(CAstNode.OBJECT_LITERAL, args);
context.cfg().map(n, lit);
return lit;
}
@Override

View File

@ -1,4 +1,10 @@
function f() {
lbl:
break lbl;
function dead_code() {
}
function f() {
lbl: {
break lbl;
dead_code();
}
}

View File

@ -81,6 +81,15 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
verifyGraphAssertions(CG, assertionsForObjects);
}
private static final Object[][] cfgAssertionsForInherit = new Object[][] {
new Object[]{"ctor:tests/inherit.js/objectMasquerading/Rectangle",
new int[][]{{1,7},{2},{3,7},{4,7},{5,6},{7},{7}}
},
new Object[]{"ctor:tests/inherit.js/sharedClassObject/Rectangle",
new int[][]{{1,7},{2},{3,7},{4,7},{5,6},{7},{7}}
}
};
private static final Object[][] assertionsForInherit = new Object[][] {
new Object[] { ROOT, new String[] { "tests/inherit.js" } },
new Object[] {
@ -88,18 +97,26 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape {
new String[] { "tests/inherit.js/objectMasquerading", "tests/inherit.js/objectMasquerading/Rectangle/area",
"tests/inherit.js/Polygon/shape", "tests/inherit.js/sharedClassObject",
"tests/inherit.js/sharedClassObject/Rectangle/area" } },
/*
* new Object[]{"tests/inherit.js/objectMasquerading", new
* String[]{"ctor:tests/inherit.js/objectMasquerading/Rectangle"}}, new
* Object[]{"tests/inherit.js/sharedClassObject", new
* String[]{"ctor:tests/inherit.js/sharedClassObject/Rectangle"}},
*/
new Object[]{
"tests/inherit.js/objectMasquerading",
new String[]{"ctor:tests/inherit.js/objectMasquerading/Rectangle"}},
new Object[]{
"ctor:tests/inherit.js/objectMasquerading/Rectangle" ,
new String[]{"tests/inherit.js/objectMasquerading/Rectangle"}},
new Object[]{"tests/inherit.js/objectMasquerading/Rectangle",
new String[]{"tests/inherit.js/Polygon"}},
new Object[]{
"tests/inherit.js/sharedClassObject",
new String[]{"ctor:tests/inherit.js/sharedClassObject/Rectangle"}},
new Object[]{"ctor:tests/inherit.js/sharedClassObject/Rectangle",
new String[]{"tests/inherit.js/sharedClassObject/Rectangle"}}
};
@Test
public void testInherit() throws IOException, IllegalArgumentException, CancelException, WalaException {
CallGraph CG = JSCallGraphBuilderUtil.makeScriptCG("tests", "inherit.js");
verifyGraphAssertions(CG, assertionsForInherit);
verifyCFGAssertions(CG, cfgAssertionsForInherit);
}
private static final Object[][] assertionsForNewfn = new Object[][] {

View File

@ -69,13 +69,15 @@ public class WebPageLoaderFactory extends JavaScriptLoaderFactory {
translateConditionOpcode(CAstOperator.OP_NE),
null,
isDefined,
context.currentScope().getConstantValue(new Integer(0))));
context.currentScope().getConstantValue(new Integer(0)),
-1));
PreBasicBlock srcB = context.cfg().getCurrentBlock();
// field lookup of value
context.cfg().newBlock(true);
context.cfg().addInstruction(((JSInstructionFactory) insts).GetInstruction(result, windowVal, name));
context.cfg().addInstruction(insts.GotoInstruction());
context.cfg().newBlock(true);
context.cfg().addInstruction(insts.GotoInstruction(-1));
PreBasicBlock trueB = context.cfg().getCurrentBlock();
// read global

View File

@ -295,16 +295,16 @@ public class ClosureExtractor extends CAstRewriterExt {
epos.addGotoTarget(root.getChildCount() > 0 ? (String)root.getChild(0).getValue(): null, target);
int label = labeller.addNode(target);
// return { type: 'goto', target: <label> }
CAstNode newNode =
Ast.makeNode(RETURN,
Ast.makeNode(OBJECT_LITERAL,
addExnFlow(Ast.makeNode(CALL,
addExnFlow(makeVarRef("Object"), JavaScriptTypes.ReferenceError, getCurrentEntity(), context),
Ast.makeConstant("ctor")), null, getCurrentEntity(), context),
Ast.makeConstant("type"),
Ast.makeConstant("goto"),
Ast.makeConstant("target"),
Ast.makeConstant(((double)label)+"")));
CAstNode returnLit = Ast.makeNode(OBJECT_LITERAL,
addExnFlow(Ast.makeNode(CALL,
addExnFlow(makeVarRef("Object"), JavaScriptTypes.ReferenceError, getCurrentEntity(), context),
Ast.makeConstant("ctor")), null, getCurrentEntity(), context),
Ast.makeConstant("type"),
Ast.makeConstant("goto"),
Ast.makeConstant("target"),
Ast.makeConstant(((double)label)+""));
addNode(returnLit, getCurrentEntity().getControlFlow());
CAstNode newNode = Ast.makeNode(RETURN, returnLit);
// remove outgoing cfg edges of the old node
deleteFlow(root, getCurrentEntity());
nodeMap.put(Pair.make(root, context.key()), newNode);

View File

@ -19,6 +19,8 @@ import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.classLoader.NewSiteReference;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.ipa.summaries.MethodSummary;
import com.ibm.wala.shrikeBT.IConditionalBranchInstruction.IOperator;
import com.ibm.wala.shrikeBT.IConditionalBranchInstruction.Operator;
import com.ibm.wala.ssa.ConstantValue;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
@ -459,8 +461,6 @@ public class JavaScriptConstructorFunctions {
Object key = Pair.make(cls, new Integer(nargs));
if (constructors.containsKey(key))
return constructors.get(key);
System.err.println(cls);
MethodReference ref = JavaScriptMethods.makeCtorReference(cls.getReference());
JavaScriptSummary S = new JavaScriptSummary(ref, nargs + 1);
@ -473,7 +473,6 @@ public class JavaScriptConstructorFunctions {
JavaScriptTypes.Object)));
S.addStatement(insts.SetPrototype(nargs + 5, nargs + 4));
//S.addStatement(insts.PutInstruction(nargs + 5, nargs + 4, "__proto__"));
S.getNextProgramCounter();
CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter());
@ -482,15 +481,18 @@ public class JavaScriptConstructorFunctions {
for (int i = 0; i < nargs; i++)
args[i + 1] = i + 2;
S.addStatement(insts.Invoke(1, nargs + 7, args, nargs + 8, cs));
int pc = S.getNextProgramCounter();
S.addConstant(nargs + 9, null);
S.addStatement(insts.ConditionalBranchInstruction(Operator.EQ, JavaScriptTypes.Root, nargs + 7, nargs + 9, pc+2));
S.getNextProgramCounter();
S.addStatement(insts.ReturnInstruction(nargs + 7, false));
S.getNextProgramCounter();
S.addStatement(insts.ReturnInstruction(nargs + 5, false));
S.getNextProgramCounter();
//S.addConstant(nargs + 9, new ConstantValue("__proto__"));
return record(key, new JavaScriptConstructor(ref, S, cls, cls));
}

View File

@ -421,8 +421,8 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
@Override
public SSAConditionalBranchInstruction ConditionalBranchInstruction(
com.ibm.wala.shrikeBT.IConditionalBranchInstruction.IOperator operator, TypeReference type, int val1, int val2) {
return new SSAConditionalBranchInstruction(operator, type, val1, val2);
com.ibm.wala.shrikeBT.IConditionalBranchInstruction.IOperator operator, TypeReference type, int val1, int val2, int target) {
return new SSAConditionalBranchInstruction(operator, type, val1, val2, target);
}
@Override
@ -462,8 +462,8 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader {
}
@Override
public SSAGotoInstruction GotoInstruction() {
return new SSAGotoInstruction();
public SSAGotoInstruction GotoInstruction(int target) {
return new SSAGotoInstruction(target);
}
@Override

View File

@ -258,17 +258,15 @@ public class JSAstTranslator extends AstTranslator {
context.cfg().addInstruction(((JSInstructionFactory) insts).PropertyRead(result, x, context.getValue(elt)));
}
// generate code to handle read of non-existent property
if (context.getControlFlow().getMappedNodes().contains(readNode)) {
context.cfg().addPreNode(readNode, context.getUnwindState());
// generate code to handle read of property from null or undefined
context.cfg().addPreNode(readNode, context.getUnwindState());
context.cfg().newBlock(true);
context.cfg().newBlock(true);
if (context.getControlFlow().getTarget(readNode, JavaScriptTypes.TypeError) != null)
context.cfg().addPreEdge(readNode, context.getControlFlow().getTarget(readNode, JavaScriptTypes.TypeError), true);
else
context.cfg().addPreEdgeToExit(readNode, true);
}
if (context.getControlFlow().getTarget(readNode, JavaScriptTypes.TypeError) != null)
context.cfg().addPreEdge(readNode, context.getControlFlow().getTarget(readNode, JavaScriptTypes.TypeError), true);
else
context.cfg().addPreEdgeToExit(readNode, true);
}
@Override
@ -293,9 +291,18 @@ public class JSAstTranslator extends AstTranslator {
context.cfg().addInstruction(put);
}
} else {
*/
*/
context.cfg().addInstruction(((JSInstructionFactory) insts).PropertyWrite(receiver, context.getValue(elt), rval));
// }
context.cfg().addPreNode(parent, context.getUnwindState());
// generate code to handle read of property from null or undefined
context.cfg().newBlock(true);
if (context.getControlFlow().getTarget(parent, JavaScriptTypes.TypeError) != null)
context.cfg().addPreEdge(parent, context.getControlFlow().getTarget(parent, JavaScriptTypes.TypeError), true);
else
context.cfg().addPreEdgeToExit(parent, true);
// }
}
private void doPrimitiveNew(WalkContext context, int resultVal, String typeName) {

View File

@ -22,11 +22,29 @@ import com.ibm.wala.core.tests.util.WalaTestCase;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.ssa.SSACFG;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.util.collections.NonNullSingletonIterator;
public abstract class TestCallGraphShape extends WalaTestCase {
protected void verifyCFGAssertions(CallGraph CG, Object[][] assertionData) {
for(Object[] dat : assertionData) {
String function = (String) dat[0];
for(CGNode N : getNodes(CG, function)) {
int[][] edges = (int[][]) dat[1];
SSACFG cfg = N.getIR().getControlFlowGraph();
for (int i = 0; i < edges.length; i++) {
SSACFG.BasicBlock bb = cfg.getNode(i);
Assert.assertEquals("basic block " + i, edges[i].length, cfg.getSuccNodeCount(bb));
for (int j = 0; j < edges[i].length; j++) {
Assert.assertTrue(cfg.hasEdge(bb, cfg.getNode(edges[i][j])));
}
}
}
}
}
protected void verifySourceAssertions(CallGraph CG, Object[][] assertionData) {
for(Object[] dat : assertionData) {
String function = (String) dat[0];

View File

@ -22,6 +22,7 @@ import com.ibm.wala.cast.ir.ssa.analysis.LiveAnalysis;
import com.ibm.wala.cast.loader.AstMethod;
import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation;
import com.ibm.wala.cast.loader.AstMethod.LexicalInformation;
import com.ibm.wala.cast.tree.CAstType.Array;
import com.ibm.wala.ssa.IR.SSA2LocalMap;
import com.ibm.wala.ssa.SSACFG;
import com.ibm.wala.ssa.SSAInstruction;
@ -34,6 +35,7 @@ import com.ibm.wala.util.collections.Pair;
import com.ibm.wala.util.intset.BitVector;
import com.ibm.wala.util.intset.BitVectorIntSet;
import com.ibm.wala.util.intset.IntSet;
import com.ibm.wala.util.intset.IntSetUtil;
import com.ibm.wala.util.intset.MutableIntSet;
/**
@ -264,22 +266,30 @@ public class SSAConversion extends AbstractSSAConversion {
// SSA2LocalMap implementation for SSAConversion
//
private class SSAInformation implements com.ibm.wala.ssa.IR.SSA2LocalMap {
private final String[][] computedNames = new String[valueMap.length][];
@Override
public String[] getLocalNames(int pc, int vn) {
if (computedNames[vn] != null) {
return computedNames[vn];
}
int v = skip(vn) || vn >= valueMap.length ? vn : valueMap[vn];
String[][] namesData = debugInfo.getSourceNamesForValues();
String[] vNames = namesData[v];
Set<String> x = HashSetFactory.make();
x.addAll(Arrays.asList(vNames));
while (assignments.containsKey(v)) {
MutableIntSet vals = IntSetUtil.make();
while (assignments.containsKey(v) && !vals.contains(v)) {
vals.add(v);
v = assignments.get(v);
vNames = namesData[v];
x.addAll(Arrays.asList(vNames));
}
return x.toArray(new String[x.size()]);
return computedNames[vn] = x.toArray(new String[x.size()]);
}
private void undoCopyPropagation(int instructionIndex, int useNumber) {

View File

@ -68,6 +68,7 @@ import com.ibm.wala.shrikeBT.IConditionalBranchInstruction;
import com.ibm.wala.shrikeBT.IUnaryOpInstruction;
import com.ibm.wala.shrikeBT.ShiftInstruction;
import com.ibm.wala.ssa.SSAAbstractInvokeInstruction;
import com.ibm.wala.ssa.SSAConditionalBranchInstruction;
import com.ibm.wala.ssa.SSAGetCaughtExceptionInstruction;
import com.ibm.wala.ssa.SSAGotoInstruction;
import com.ibm.wala.ssa.SSAInstruction;
@ -698,6 +699,7 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
* holds the control-flow graph as it is being constructed. When construction
* is complete, information is stored in an {@link AstCFG}
*/
@SuppressWarnings("javadoc")
public final class IncipientCFG extends SparseNumberedGraph<PreBasicBlock> {
protected class Unwind {
@ -751,7 +753,7 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
int e = -1;
PreBasicBlock currentBlock = getCurrentBlock();
if (!isDeadBlock(currentBlock)) {
addInstruction(insts.GotoInstruction());
addInstruction(insts.GotoInstruction(-1));
newBlock(false);
}
PreBasicBlock startBlock = getCurrentBlock();
@ -795,7 +797,7 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
addPreNode(dummy);
doThrow(astContext, e);
} else {
addInstruction(insts.GotoInstruction());
addInstruction(insts.GotoInstruction(-1));
}
newBlock(false);
@ -1277,7 +1279,35 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
if (ci.getBasicBlockNumber() != blocks.get(i).getNumber()) {
inst = insts.GetCaughtExceptionInstruction(blocks.get(i).getNumber(), ci.getException());
}
} else if (inst instanceof SSAGotoInstruction) {
Iterator<PreBasicBlock> succs = this.getNormalSuccessors(blocks.get(i)).iterator();
if (succs.hasNext()) {
PreBasicBlock target = succs.next();
assert !succs.hasNext() : "unexpected successors for block " + blocks.get(i) + ": " + target + " and " + succs.next();
inst = insts.GotoInstruction(target.firstIndex);
} else {
// goto to the end of the method, so the instruction is unnecessary
inst = null;
}
} else if (inst instanceof SSAConditionalBranchInstruction) {
Iterator<PreBasicBlock> succs = this.getNormalSuccessors(blocks.get(i)).iterator();
assert succs.hasNext();
int target;
int t1 = succs.next().firstIndex;
if (succs.hasNext()) {
int t2 = succs.next().firstIndex;
if (t1 == x+1) {
target = t2;
} else {
target = t1;
}
} else {
target = t1;
}
SSAConditionalBranchInstruction branch = (SSAConditionalBranchInstruction) inst;
inst = insts.ConditionalBranchInstruction(branch.getOperator(), branch.getType(), branch.getUse(0), branch.getUse(1), target);
}
instructions[x++] = inst;
}
}
@ -3451,14 +3481,14 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
+ " of loop " + CAstPrinter.print(n, context.top().getSourceMap());
context.cfg().addInstruction(
insts.ConditionalBranchInstruction(translateConditionOpcode(CAstOperator.OP_EQ), null, c.getValue(n.getChild(0)), context
.currentScope().getConstantValue(new Integer(0))));
.currentScope().getConstantValue(new Integer(0)), -1));
PreBasicBlock branchB = context.cfg().getCurrentBlock();
// loop body
context.cfg().newBlock(true);
visitor.visit(n.getChild(1), context, visitor);
if (!context.cfg().isDeadBlock(context.cfg().getCurrentBlock())) {
context.cfg().addInstruction(insts.GotoInstruction());
context.cfg().addInstruction(insts.GotoInstruction(-1));
PreBasicBlock bodyB = context.cfg().getCurrentBlock();
context.cfg().addEdge(bodyB, headerB);
@ -3727,11 +3757,11 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
if (n.getChildCount() == 1) {
context.cfg().addInstruction(
insts.ConditionalBranchInstruction(translateConditionOpcode(CAstOperator.OP_NE), null, c.getValue(n.getChild(0)), context
.currentScope().getConstantValue(new Integer(0))));
.currentScope().getConstantValue(new Integer(0)), -1));
} else if (n.getChildCount() == 3) {
context.cfg().addInstruction(
insts.ConditionalBranchInstruction(translateConditionOpcode(n.getChild(0)), null, c.getValue(n.getChild(1)),
c.getValue(n.getChild(2))));
c.getValue(n.getChild(2)), -1));
} else {
Assertions.UNREACHABLE();
}
@ -3752,7 +3782,7 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
if (!context.cfg().isDeadBlock(context.cfg().getCurrentBlock())) {
context.cfg().addPreNode(n, context.getUnwindState());
context.cfg().addPreEdge(n, context.getControlFlow().getTarget(n, null), false);
context.cfg().addInstruction(insts.GotoInstruction());
context.cfg().addInstruction(insts.GotoInstruction(-1));
if (context.getControlFlow().getTarget(n, null) == null) {
assert context.getControlFlow().getTarget(n, null) != null : context.getControlFlow() + " does not map " + n + " ("
+ context.getSourceMap().getPosition(n) + ")";
@ -3783,7 +3813,7 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
visitor.visit(l, context, visitor);
context.cfg().addInstruction(
insts.ConditionalBranchInstruction(translateConditionOpcode(CAstOperator.OP_EQ), null, c.getValue(l), context.currentScope()
.getConstantValue(new Integer(0))));
.getConstantValue(new Integer(0)), -1));
PreBasicBlock srcB = context.cfg().getCurrentBlock();
// true clause
context.cfg().newBlock(true);
@ -3793,7 +3823,7 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
context.cfg().addInstruction(new AssignInstruction(c.getValue(n), c.getValue(r)));
if (n.getChildCount() == 3) {
if (!context.cfg().isDeadBlock(context.cfg().getCurrentBlock())) {
context.cfg().addInstruction(insts.GotoInstruction());
context.cfg().addInstruction(insts.GotoInstruction(-1));
trueB = context.cfg().getCurrentBlock();
// false clause
@ -4184,7 +4214,7 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
// PreBasicBlock switchB = context.cfg().getCurrentBlock();
context.cfg().newBlock(true);
context.cfg().addInstruction(insts.GotoInstruction());
context.cfg().addInstruction(insts.GotoInstruction(-1));
defaultHackBlock = context.cfg().getCurrentBlock();
context.cfg().newBlock(false);
@ -4228,14 +4258,14 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
if (x != CAstControlFlowMap.SWITCH_DEFAULT) {
visitor.visit((CAstNode) x, context, visitor);
context.cfg().addInstruction(
insts.ConditionalBranchInstruction(translateConditionOpcode(CAstOperator.OP_EQ), null, v, context.getValue((CAstNode) x)));
insts.ConditionalBranchInstruction(translateConditionOpcode(CAstOperator.OP_EQ), null, v, context.getValue((CAstNode) x), -1));
labelToBlock.put(x, context.cfg().getCurrentBlock());
context.cfg().newBlock(true);
}
}
PreBasicBlock defaultGotoBlock = context.cfg().getCurrentBlock();
context.cfg().addInstruction(insts.GotoInstruction());
context.cfg().addInstruction(insts.GotoInstruction(-1));
context.cfg().newBlock(false);
CAstNode switchBody = n.getChild(1);
@ -4381,7 +4411,7 @@ public abstract class AstTranslator extends CAstVisitor<AstTranslator.WalkContex
if (!context.cfg().isDeadBlock(context.cfg().getCurrentBlock())) {
addSkipCatchGoto = true;
context.cfg().addInstruction(insts.GotoInstruction());
context.cfg().addInstruction(insts.GotoInstruction(-1));
context.cfg().newBlock(false);
}

View File

@ -78,7 +78,7 @@ public class CAstImpl implements CAst {
@Override
public int hashCode() {
int code = getKind() * (getChildCount() + 13);
for (int i = 0; i < getChildCount(); i++) {
for (int i = 0; i < getChildCount() && i < 15; i++) {
code *= getChild(i).getKind();
}

View File

@ -234,24 +234,21 @@ public class InducedCFG extends AbstractCFG<SSAInstruction, InducedCFG.BasicBloc
@Override
public void visitGoto(SSAGotoInstruction instruction) {
Assertions.UNREACHABLE("haven't implemented logic for goto yet.");
breakBasicBlock(index);
}
@Override
public void visitConditionalBranch(SSAConditionalBranchInstruction instruction) {
Assertions.UNREACHABLE("haven't implemented logic for cbranch yet.");
breakBasicBlock(index);
}
@Override
public void visitSwitch(SSASwitchInstruction instruction) {
Assertions.UNREACHABLE("haven't implemented logic for switch yet.");
// breakBasicBlock();
// int[] targets = instruction.getTargets();
// for (int i = 0; i < targets.length; i++) {
// r[targets[i]] = true;
// }
breakBasicBlock(index);
int[] targets = instruction.getCasesAndLabels();
for (int i = 1; i < targets.length; i+=2) {
r[targets[i]] = true;
}
}
@Override
@ -448,20 +445,30 @@ public class InducedCFG extends AbstractCFG<SSAInstruction, InducedCFG.BasicBloc
SSAInstruction last = getInstructions()[getLastInstructionIndex()];
addExceptionalEdges(last);
// this CFG is odd in that we assume fallthru might always
// happen .. this is because I'm too lazy to code control
// flow in all method summaries yet.
int normalSuccNodeNumber = getGraphNodeId() + 1;
if (true) {
// if (last.isFallThrough()) {
if (last.isFallThrough()) {
if (DEBUG) {
System.err.println(("Add fallthru to " + getNode(getGraphNodeId() + 1)));
}
addNormalEdgeTo(getNode(normalSuccNodeNumber));
}
if (last instanceof SSAGotoInstruction) {
addNormalEdgeTo(getBlockForInstruction(((SSAGotoInstruction)last).getTarget()));
} else if (last instanceof SSAConditionalBranchInstruction) {
addNormalEdgeTo(getBlockForInstruction(((SSAConditionalBranchInstruction)last).getTarget()));
} else if (last instanceof SSASwitchInstruction) {
int[] targets = ((SSASwitchInstruction) last).getCasesAndLabels();
for (int i = 1; i < targets.length; i+=2) {
addNormalEdgeTo(getBlockForInstruction(targets[i]));
}
}
if (pis != null) {
updatePiInstrs(normalSuccNodeNumber);
}
if (last instanceof SSAReturnInstruction) {
// link each return instrution to the exit block.
BasicBlock exit = exit();

View File

@ -168,8 +168,8 @@ public class JavaLanguage extends LanguageImpl implements BytecodeLanguage, Cons
@Override
public SSAConditionalBranchInstruction ConditionalBranchInstruction(IConditionalBranchInstruction.IOperator operator,
TypeReference type, int val1, int val2) {
return new SSAConditionalBranchInstruction(operator, type, val1, val2);
TypeReference type, int val1, int val2, int target) {
return new SSAConditionalBranchInstruction(operator, type, val1, val2, target);
}
@Override
@ -210,8 +210,8 @@ public class JavaLanguage extends LanguageImpl implements BytecodeLanguage, Cons
}
@Override
public SSAGotoInstruction GotoInstruction() {
return new SSAGotoInstruction();
public SSAGotoInstruction GotoInstruction(int target) {
return new SSAGotoInstruction(target);
}
@Override

View File

@ -480,7 +480,7 @@ public class SSABuilder extends AbstractIntStackMachine {
int val1 = workingState.pop();
TypeReference t = ShrikeUtil.makeTypeReference(loader, instruction.getType());
emitInstruction(insts.ConditionalBranchInstruction(instruction.getOperator(), t, val1, val2));
emitInstruction(insts.ConditionalBranchInstruction(instruction.getOperator(), t, val1, val2, instruction.getTarget()));
}
/**
@ -560,7 +560,7 @@ public class SSABuilder extends AbstractIntStackMachine {
*/
@Override
public void visitGoto(com.ibm.wala.shrikeBT.GotoInstruction instruction) {
emitInstruction(insts.GotoInstruction());
emitInstruction(insts.GotoInstruction(instruction.getLabel()));
}
/**

View File

@ -26,9 +26,12 @@ public class SSAConditionalBranchInstruction extends SSAInstruction {
private final TypeReference type;
public SSAConditionalBranchInstruction(IConditionalBranchInstruction.IOperator operator, TypeReference type, int val1, int val2)
final private int target;
public SSAConditionalBranchInstruction(IConditionalBranchInstruction.IOperator operator, TypeReference type, int val1, int val2, int target)
throws IllegalArgumentException {
super();
this.target = target;
this.operator = operator;
this.val1 = val1;
this.val2 = val2;
@ -41,12 +44,16 @@ public class SSAConditionalBranchInstruction extends SSAInstruction {
}
}
public int getTarget() {
return target;
}
@Override
public SSAInstruction copyForSSA(SSAInstructionFactory insts, int[] defs, int[] uses) throws IllegalArgumentException {
if (uses != null && uses.length < 2) {
throw new IllegalArgumentException("(uses != null) and (uses.length < 2)");
}
return insts.ConditionalBranchInstruction(operator, type, uses == null ? val1 : uses[0], uses == null ? val2 : uses[1]);
return insts.ConditionalBranchInstruction(operator, type, uses == null ? val1 : uses[0], uses == null ? val2 : uses[1], target);
}
public IConditionalBranchInstruction.IOperator getOperator() {

View File

@ -14,14 +14,18 @@ package com.ibm.wala.ssa;
* Unconditional branch instruction for SSA form.
*/
public class SSAGotoInstruction extends SSAInstruction {
private final int target;
public SSAGotoInstruction(int target) {
this.target = target;
}
public SSAGotoInstruction() {
super();
public int getTarget() {
return target;
}
@Override
public SSAInstruction copyForSSA(SSAInstructionFactory insts, int[] defs, int[] uses) {
return insts.GotoInstruction();
return insts.GotoInstruction(target);
}
@Override

View File

@ -51,7 +51,7 @@ public interface SSAInstructionFactory {
SSAComparisonInstruction ComparisonInstruction(IComparisonInstruction.Operator operator, int result, int val1, int val2);
SSAConditionalBranchInstruction ConditionalBranchInstruction(IConditionalBranchInstruction.IOperator operator,
TypeReference type, int val1, int val2);
TypeReference type, int val1, int val2, int target);
SSAConversionInstruction ConversionInstruction(int result, int val, TypeReference fromType, TypeReference toType, boolean overflow);
@ -61,7 +61,7 @@ public interface SSAInstructionFactory {
SSAGetInstruction GetInstruction(int result, int ref, FieldReference field);
SSAGotoInstruction GotoInstruction();
SSAGotoInstruction GotoInstruction(int target);
SSAInstanceofInstruction InstanceofInstruction(int result, int ref, TypeReference checkedType);