private void verifyLiveVariableAnalysis(String body) { verifyLiveVariableAnalysis("", body); }
private void verifyLiveVariableAnalysis(String argsList, String body) { CompilationUnitTree cut = parse("<?php function f(" + argsList + ") { " + body + " }", PHPLexicalGrammar.COMPILATION_UNIT); SymbolTableImpl symbolTable = SymbolTableImpl.create(cut); FunctionDeclarationTree functionTree = (FunctionDeclarationTree) cut.script().statements().get(0); ControlFlowGraph cfg = ControlFlowGraph.build(functionTree.body()); LiveVariablesAnalysis analysis = LiveVariablesAnalysis.analyze(cfg, symbolTable); Validator.assertLiveVariables(cfg, analysis); }
@Test public void read_symbols() { String body = "" + "$foo = 1;" + "$bar = bar();" + "$bar += bar();" + "read($bar);" + "$qix += 1 + 2;"; CompilationUnitTree cut = parse("<?php function f() { " + body + " }", PHPLexicalGrammar.COMPILATION_UNIT); SymbolTableImpl symbolTable = SymbolTableImpl.create(cut); FunctionDeclarationTree functionTree = (FunctionDeclarationTree) cut.script().statements().get(0); ControlFlowGraph cfg = ControlFlowGraph.build(functionTree.body()); LiveVariablesAnalysis analysis = LiveVariablesAnalysis.analyze(cfg, symbolTable); Set<Symbol> readSymbols = analysis.getReadSymbols(); assertThat(readSymbols).extracting("name").containsExactlyInAnyOrder("$bar", "$qix"); }
@Test public void test_gen_kill() { verifyLiveVariableAnalysis("" + "condition( succ = [body, END], liveIn = [x], liveOut = [], gen = [x], kill = [a]);" + "$a = $x + 1;" + "foo($a);" + "if (true) {" + " body( succ = [END], liveIn = [], liveOut = [], gen = [], kill = [x]);" + " $x = 1;" + "}"); verifyLiveVariableAnalysis("" + "condition( succ = [body, END], liveIn = [x,a], liveOut = [], gen = [a,x], kill = [a]);" + "foo($a);" + "$a = $x + 1;" + "if (true) {" + " body( succ = [END], liveIn = [], liveOut = [], gen = [], kill = [x]);" + " $x = 1;" + "}"); }
@Test public void test_complex_reads_and_writes() { verifyLiveVariableAnalysis("" + "block( succ = [END], liveIn = [a,b], liveOut = [], gen = [a,b], kill = []);" + "$a[$b] = 1;"); verifyLiveVariableAnalysis("" + "block( succ = [END], liveIn = [a], liveOut = [], gen = [a], kill = []);" + "read($a);" + verifyLiveVariableAnalysis("" + "block( succ = [END], liveIn = [a], liveOut = [], gen = [a], kill = [a]);" + "$a = read($a);" + verifyLiveVariableAnalysis("" + "block( succ = [END], liveIn = [a], liveOut = [], gen = [a], kill = [a]);" + "$a = read($a);" + verifyLiveVariableAnalysis("" + "block( succ = [END], liveIn = [a], liveOut = [], gen = [a], kill = [a]);" + "read($a);" + verifyLiveVariableAnalysis("" + "block( succ = [END], liveIn = [], liveOut = [], gen = [], kill = [a]);" + "$a = 1;" + verifyLiveVariableAnalysis("" + "block( succ = [END], liveIn = [], liveOut = [], gen = [], kill = [a]);" + "$a = 1;" +
@Test public void test_with_array_assignment() { verifyLiveVariableAnalysis("" + "condition( succ = [insideIf], liveIn = [], liveOut = [x], gen = [], kill = [x,y]);" + "list($x, $y) = array();" + "if ($y) {" + " insideIf (succ = [END], liveIn = [x], liveOut = [], gen = [x]);" + " foo($x);" + "}"); }
@Test public void test_simple_kill() { verifyLiveVariableAnalysis("" + "block( succ = [END], liveIn = [], liveOut = [], gen = [], kill = [foo, bar, qix]);" + "$foo = 1;" + "$bar = bar();" + "$qix = 1 + 2;"); }
@Test public void test_do_while() { verifyLiveVariableAnalysis("" + "beforeDo( succ = [body], liveIn = [x], liveOut = [a], gen = [x], kill = [a]);" + "$a = $x + 1;" + "do {" + " body( succ = [cond], liveIn = [a], liveOut = [a], gen = [a], kill = []);" + " foo ($a);" + "} while(cond( succ = [body, afterDo], liveIn = [a], liveOut = [a], gen = [], kill = []) );" + "afterDo( succ = [END], liveIn = [], liveOut = [], gen = [], kill = [a]);" + "$a = 0;"); }
@Test public void test_simple_gen() { verifyLiveVariableAnalysis("" + "block( succ = [END], liveIn = [foo, bar], liveOut = [], gen = [foo, bar]);" + "foo($foo, $bar);"); }
@Test public void test_write_before_read() { verifyLiveVariableAnalysis("" + "condition( succ = [body, END], liveIn = [], liveOut = [], gen = [], kill = [a]);" + "$a = 1;" + "foo($a);" + "if (true) {" + " body( succ = [END], liveIn = [], liveOut = [], gen = [], kill = [a]);" + " $a = 1;" + " foo($a);" + "}"); }
@Test public void compound_assignments() { verifyLiveVariableAnalysis("" + "condition( succ = [insideIf], liveIn = [y], liveOut = [x,y], gen = [y], kill = [x,y]);" + "$x = 0;" + "$x += 20;" + "$y += 20;" + "if ($y) {" + " insideIf (succ = [END], liveIn = [x,y], liveOut = [], gen = [x,y]);" + " foo($x, $y);" + "}"); }
@Test public void unary_minus_plus_expression() { verifyLiveVariableAnalysis("" + "condition( succ = [insideIf], liveIn = [a], liveOut = [a], gen = [a], kill = []);" + "foo($a);" + "-$a;" + "+$a;" + "if (cond) {" + " insideIf (succ = [END], liveIn = [a], liveOut = [], gen = [a]);" + " foo($a);" + "}"); }
@Test public void prefix_postfix_increment_decrement_expressions() { verifyLiveVariableAnalysis("" + "condition( succ = [insideIf], liveIn = [a, a1, a2], liveOut = [a], gen = [a, a1, a2], kill = [a]);" + "--$a;" + "++$a;" + "++$a1[$a2];" + "$a++;" + "$a--;" + "if ($a) {" + " insideIf (succ = [END], liveIn = [a], liveOut = [], gen = [a]);" + " foo($a);" + "}"); }
@Test public void test_with_ignored_param() { verifyLiveVariableAnalysis("$a", "" + "condition( succ = [insideIf], liveIn = [foo, bar], liveOut = [x], gen = [foo, bar], kill = [x,y,z,w]);" + "$a = 42;" + "foo($a);" + "list(, , $x, $y) = array();" + "list(foo()) = array();" + "list($z => $w ) = array('a' => 32);" + "foo($foo, $bar, $x);" + "if ($y) {" + " insideIf (succ = [END], liveIn = [x], liveOut = [], gen = [x]);" + " foo($a, $x);" + "}"); }