You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
5.4 KiB
218 lines
5.4 KiB
/* Flow Copyright (C) 1999 Jochen Hoenicke.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
* $Id$
|
|
*/
|
|
|
|
|
|
public abstract class Flow {
|
|
int g;
|
|
int[] ain;
|
|
|
|
void skip() {
|
|
for (int i=0; i<3; i++) {
|
|
if (g > 5) {
|
|
for (int j=0; j<5; j++) {
|
|
g++;
|
|
}
|
|
}
|
|
i--;
|
|
}
|
|
}
|
|
|
|
/* This tests the while in a switch problem.
|
|
*/
|
|
public void switchWhileTest() {
|
|
int dir = g;
|
|
int x = 0;
|
|
int y = 0;
|
|
boolean done = false;
|
|
g = 5;
|
|
switch (dir) {
|
|
case 1:
|
|
while (!done) {
|
|
done = true;
|
|
if (g > 7)
|
|
g = g - 4;
|
|
x = g;
|
|
y = g;
|
|
if (x > 7)
|
|
x = x - 4;
|
|
for (int i=0; i<4; i++) {
|
|
for (int j=0; j<5; j++) {
|
|
if (ain[j] == x + i && ain[j] == y)
|
|
done = false;
|
|
}
|
|
}
|
|
}
|
|
for (int i=0; i<5; i++) {
|
|
ain[g] = x + i;
|
|
ain[g] = y;
|
|
g += 1;
|
|
}
|
|
break;
|
|
case 2:
|
|
while (!done) {
|
|
done = true;
|
|
x = g;
|
|
y = g;
|
|
if (y > 7)
|
|
y = y - 4;
|
|
for (int i=0; i<4; i++) {
|
|
for (int j=0; j<4; j++) {
|
|
if (ain[j] == x && ain[j] == y + i)
|
|
done = false;
|
|
}
|
|
}
|
|
}
|
|
for (int i = 0; i<4; i++) {
|
|
ain[g] = x;
|
|
ain[g] = y + i;
|
|
g += 1;
|
|
}
|
|
break;
|
|
case 3: // Same code as case 2 slightly optimized
|
|
big:
|
|
for (;;) {
|
|
x = g;
|
|
y = g;
|
|
if (y > 7)
|
|
y = y - 4;
|
|
for (int i=0; i<4; i++) {
|
|
for (int j=0; j<4; j++) {
|
|
if (ain[j] == x && ain[j] == y + i)
|
|
continue big;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
for (int i = 0; i<4; i++) {
|
|
ain[g] = x;
|
|
ain[g] = y + i;
|
|
g += 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This was an example where our flow analysis didn't find an
|
|
* elegant solution. The reason is, that we try to make
|
|
* while(true)-loops as small as possible (you can't see the real
|
|
* end of the loop, if it is breaked there like here).
|
|
*
|
|
* Look at the assembler code and you know why my Decompiler had
|
|
* problems with this. But the decompiler did produce compilable
|
|
* code which produces the same assembler code.
|
|
*
|
|
* The solution was, to make switches as big as possible, the whole
|
|
* analyze methods were overworked.
|
|
*/
|
|
void WhileTrueSwitch() {
|
|
int i = 1;
|
|
while (true) {
|
|
switch (i) {
|
|
case 0:
|
|
return;
|
|
case 1:
|
|
i = 5;
|
|
continue;
|
|
case 2:
|
|
i = 6;
|
|
continue;
|
|
case 3:
|
|
throw new RuntimeException();
|
|
default:
|
|
i = 7;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
abstract int test();
|
|
|
|
/**
|
|
* This tests shorts and empty ifs. Especially the no op ifs can
|
|
* be optimized to very unusual code.
|
|
*/
|
|
public void shortIf() {
|
|
while(g != 7) {
|
|
if (g == 5)
|
|
return;
|
|
else if (g != 4)
|
|
break;
|
|
else if (g == 2)
|
|
shortIf();
|
|
else
|
|
return;
|
|
|
|
if (g!= 7)
|
|
shortIf();
|
|
else {
|
|
shortIf();
|
|
return;
|
|
}
|
|
|
|
if (g != 1)
|
|
break;
|
|
else if (g == 3)
|
|
shortIf();
|
|
else
|
|
break;
|
|
|
|
// javac optimizes this instruction to
|
|
// test();
|
|
// jikes reproduces this statement as one would expect
|
|
if (g + 5 == test()) {
|
|
}
|
|
|
|
// javac -O optimizes this to the following weired statements
|
|
// PUSH g;
|
|
// PUSH test();
|
|
// POP2;
|
|
// This cannot be decompiled correctly, since the == is lost.
|
|
if (g == test())
|
|
continue;
|
|
}
|
|
while(g == 3) {
|
|
// javac:
|
|
// PUSH test() == 4 || test() == 3 && test() == 2;
|
|
// POP;
|
|
if (test() == 4 || test() == 3 && test() == 2);
|
|
// javac -O:
|
|
// if (test() != 4 && test() == 3) {
|
|
// PUSH test()+test() - test();
|
|
// PUSH g-4;
|
|
// POP2;
|
|
// }
|
|
if (test() == 4 || test() == 3 && test() == 2)
|
|
continue;
|
|
}
|
|
while (g==2) {
|
|
// javac:
|
|
// test();
|
|
// test();
|
|
// test();
|
|
if ((long) (test() + test() - test()) == (long)(g-4));
|
|
// javac -O:
|
|
// PUSH (long)(test() + test() - test()) <=> (long)(g-4)
|
|
// POP;
|
|
if ((long) (test() + test() - test()) == (long)(g-4))
|
|
continue;
|
|
}
|
|
System.err.println("Hallo");
|
|
}
|
|
}
|
|
|