|
|
|
/*
|
|
|
|
* CreateIfStatements (c) 1998 Jochen Hoenicke
|
|
|
|
*
|
|
|
|
* You may distribute under the terms of the GNU General Public License.
|
|
|
|
*
|
|
|
|
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT,
|
|
|
|
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
|
|
|
|
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE
|
|
|
|
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
|
|
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
|
|
|
|
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
|
|
|
|
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
|
|
|
*
|
|
|
|
* $Id$
|
|
|
|
*/
|
|
|
|
|
|
|
|
package jode;
|
|
|
|
|
|
|
|
public class CreateIfStatements extends FlowTransformation
|
|
|
|
implements Transformation {
|
|
|
|
|
|
|
|
public InstructionHeader transform(InstructionHeader ifgoto) {
|
|
|
|
|
|
|
|
if (ifgoto.getFlowType() != ifgoto.IFGOTO ||
|
|
|
|
ifgoto.nextInstruction == null ||
|
|
|
|
ifgoto.getSuccessors()[1].getAddress() <=
|
|
|
|
ifgoto.getSuccessors()[0].getAddress())
|
|
|
|
return null;
|
|
|
|
|
|
|
|
/* elseBlock points to the first instruction of the
|
|
|
|
* elseBlock or is null if the else block is empty.
|
|
|
|
* next points to the next instruction after this block
|
|
|
|
* or is null, if this if is the last instruction in
|
|
|
|
* this block.
|
|
|
|
*/
|
|
|
|
|
|
|
|
InstructionHeader elseBlock = null, next = null;
|
|
|
|
|
|
|
|
if (ifgoto.outer != ifgoto.successors[1].outer) {
|
|
|
|
if (ifgoto.outer.getEndBlock() != ifgoto.successors[1].getShadow())
|
|
|
|
/* This doesn't seem to be an if but a if-break
|
|
|
|
*/
|
|
|
|
return null;
|
|
|
|
|
|
|
|
/* This is an if without else that goes to the end
|
|
|
|
* of the current block. May be this was a continue,
|
|
|
|
* but who would know it?
|
|
|
|
*
|
|
|
|
* If you like breaks and continues more than ifs,
|
|
|
|
* simply do the break transformation before the
|
|
|
|
* if transformation.
|
|
|
|
*/
|
|
|
|
next = null;
|
|
|
|
} else {
|
|
|
|
/* This is a normal if, let us first assume, that there is
|
|
|
|
* no else part. Then end is successors[1], but that may
|
|
|
|
* be a while loop, so unoptimized it...
|
|
|
|
*/
|
|
|
|
next = UnoptimizeWhileLoops(ifgoto.successors[1]);
|
|
|
|
if (next != ifgoto.successors[1]) {
|
|
|
|
ifgoto.successors[1].predecessors.removeElement(ifgoto);
|
|
|
|
ifgoto.successors[1] = next;
|
|
|
|
ifgoto.successors[1].predecessors.addElement(ifgoto);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* next.prevInstruction is the end of the `then' block.
|
|
|
|
* If this a goto statement that jumps downward, this is
|
|
|
|
* probably an `if-then-else'.
|
|
|
|
*/
|
|
|
|
InstructionHeader thenEnd = next.prevInstruction;
|
|
|
|
if (thenEnd.flowType == thenEnd.GOTO) {
|
|
|
|
if (thenEnd.successors[0].outer == next.outer &&
|
|
|
|
thenEnd.successors[0].addr >= next.addr) {
|
|
|
|
|
|
|
|
/* this is a normal if-then-else that is
|
|
|
|
* fully contained in this block.
|
|
|
|
*/
|
|
|
|
elseBlock = next;
|
|
|
|
next = UnoptimizeWhileLoops(thenEnd.successors[0]);
|
|
|
|
|
|
|
|
} else if (thenEnd.successors[0].getShadow() ==
|
|
|
|
ifgoto.outer.getEndBlock()) {
|
|
|
|
/* this is a normal if-then-else that goes
|
|
|
|
* to the end of the block.
|
|
|
|
*
|
|
|
|
* Again this may also be a continue/break statement,
|
|
|
|
* but again, who knows.
|
|
|
|
*/
|
|
|
|
elseBlock = next;
|
|
|
|
next = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This was all, the rest is done in the constructor of
|
|
|
|
* IfInstructionHeader.
|
|
|
|
*/
|
|
|
|
if(Decompiler.isVerbose)
|
|
|
|
System.err.print("i");
|
|
|
|
return new IfInstructionHeader
|
|
|
|
(ifgoto, elseBlock, next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|