Initial revision

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@36 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 674d865943
commit 704a534731
  1. 147
      jode/jode/flow/CatchBlock.java
  2. 115
      jode/jode/flow/CreateAssignExpression.java
  3. 221
      jode/jode/flow/CreateIfThenElseOperator.java
  4. 149
      jode/jode/flow/CreatePostIncExpression.java

@ -0,0 +1,147 @@
/* CatchBlock Copyright (C) 1997-1998 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$
*/
package jode.flow;
import jode.LocalInfo;
import sun.tools.java.Identifier;
/**
*
* @author Jochen Hoenicke
*/
public class CatchBlock extends StructuredBlock {
/**
* The try block. This may be another CatchBlock!
*/
StructuredBlock tryBlock;
/**
* The catch block.
*/
StructuredBlock catchBlock;
/**
* The type of the exception.
*/
sun.tools.java.Type exceptionType;
/**
* The local containing the exception.
*/
LocalInfo exceptionLocal;
public CatchBlock(RawTryCatchBlock rawBlock) {
exceptionType = rawBlock.type;
this.tryBlock = rawBlock.tryBlock;
tryBlock.outer = this;
}
static int serialno=0;
/**
* Sets the catch block.
* @param catchBlock the catch block.
*/
public void setCatchBlock(StructuredBlock catchBlock) {
if (catchBlock instanceof SequentialBlock
&& catchBlock.getSubBlocks()[0] instanceof InstructionBlock) {
InstructionBlock localBlock =
(InstructionBlock) catchBlock.getSubBlocks()[0];
jode.Instruction instr = localBlock.getInstruction();
if (instr instanceof jode.PopOperator) {
exceptionLocal = new LocalInfo(99);
exceptionLocal.setName
(Identifier.lookup("exception_"+(serialno++)+"_"));
catchBlock = catchBlock.getSubBlocks()[1];
} else if (instr instanceof jode.LocalStoreOperator) {
exceptionLocal =
((jode.LocalStoreOperator) instr).getLocalInfo();
catchBlock = catchBlock.getSubBlocks()[1];
}
}
if (exceptionLocal == null) {
exceptionLocal = new LocalInfo(99);
exceptionLocal.setName(Identifier.lookup("ERROR!!!"));
}
this.catchBlock = catchBlock;
catchBlock.outer = this;
catchBlock.setFlowBlock(flowBlock);
}
/* The implementation of getNext[Flow]Block is the standard
* implementation */
/**
* Replaces the given sub block with a new block.
* @param oldBlock the old sub block.
* @param newBlock the new sub block.
* @return false, if oldBlock wasn't a direct sub block.
*/
public boolean replaceSubBlock(StructuredBlock oldBlock,
StructuredBlock newBlock) {
if (tryBlock == oldBlock)
tryBlock = newBlock;
else if (catchBlock == oldBlock)
catchBlock = newBlock;
else
return false;
return true;
}
/**
* Returns all sub block of this structured block.
*/
public StructuredBlock[] getSubBlocks() {
StructuredBlock[] result = { tryBlock, catchBlock };
return result;
}
/**
* Determines if there is a sub block, that flows through to the end
* of this block. If this returns true, you know that jump is null.
* @return true, if the jump may be safely changed.
*/
public boolean jumpMayBeChanged() {
return ( tryBlock.jump != null || tryBlock.jumpMayBeChanged())
&& (catchBlock.jump != null || catchBlock.jumpMayBeChanged());
}
public void dumpInstruction(jode.TabbedPrintWriter writer)
throws java.io.IOException {
/* avoid ugly nested tries */
if (!(outer instanceof CatchBlock
/* XXX || outer instanceof FinallyBlock*/)) {
writer.println("try {");
writer.tab();
}
tryBlock.dumpInstruction(writer);
writer.untab();
writer.println("} catch ("+/*XXX*/exceptionType.typeString
(exceptionLocal.getName().toString())+") {");
writer.tab();
catchBlock.dumpSource(writer);
if (!(outer instanceof CatchBlock
/* XXX || outer instanceof FinallyBlock*/)) {
writer.untab();
writer.println("}");
}
}
}

@ -0,0 +1,115 @@
/*
* CreateAssignExpression (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.flow;
import jode.*;
public class CreateAssignExpression implements Transformation{
public boolean transform(FlowBlock flow) {
return (createAssignOp(flow) || createAssignExpression(flow));
}
public boolean createAssignOp(FlowBlock flow) {
Expression rightHandSide;
StoreInstruction store;
BinaryOperator binop;
InstructionContainer lastBlock;
SequentialBlock rhsBlock;
SequentialBlock sequBlock;
try {
InstructionBlock ib;
lastBlock = (InstructionContainer) flow.lastModified;
store = (StoreInstruction) lastBlock.getInstruction();
sequBlock = (SequentialBlock) lastBlock.outer;
if (sequBlock.subBlocks[1] != lastBlock)
return false;
ib = (InstructionBlock) sequBlock.subBlocks[0];
binop = (BinaryOperator) ib.getInstruction();
if (binop.getOperator() < binop.ADD_OP ||
binop.getOperator() >= binop.ASSIGN_OP)
return false;
sequBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
rightHandSide = (Expression) ib.getInstruction();
if (rightHandSide.isVoid())
return false; /* XXX */
rhsBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) rhsBlock.subBlocks[0];
Operator load = (Operator) ib.getInstruction();
if (!store.matches(load))
return false;
sequBlock = (SequentialBlock) rhsBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
DupOperator dup = (DupOperator) ib.getInstruction();
if (dup.getDepth() != 0 &&
dup.getCount() != store.getLValueOperandCount())
return false;
} catch (ClassCastException ex) {
return false;
} catch (NullPointerException ex) {
return false;
}
((InstructionBlock)rhsBlock.subBlocks[0])
.setInstruction(rightHandSide);
rhsBlock.replace(sequBlock, rhsBlock);
store.setOperator(store.OPASSIGN_OP+binop.getOperator());
store.setLValueType(MyType.intersection(binop.getType(),
store.getLValueType()));
lastBlock.setInstruction(store);
lastBlock.replace(rhsBlock.subBlocks[1], lastBlock);
return true;
}
public boolean createAssignExpression(FlowBlock flow) {
StoreInstruction store;
InstructionContainer lastBlock;
SequentialBlock sequBlock;
try {
lastBlock = (InstructionContainer) flow.lastModified;
store = (StoreInstruction) lastBlock.getInstruction();
sequBlock = (SequentialBlock) lastBlock.outer;
InstructionBlock ib = (InstructionBlock) sequBlock.subBlocks[0];
DupOperator dup = (DupOperator) ib.getInstruction();
if (dup.getDepth() != store.getLValueOperandCount() &&
dup.getCount() != store.getLValueType().stackSize())
return false;
} catch (NullPointerException ex) {
return false;
} catch (ClassCastException ex) {
return false;
}
lastBlock.setInstruction
(new AssignOperator(Operator.ASSIGN_OP, store));
lastBlock.replace(sequBlock, lastBlock);
return true;
}
}

@ -0,0 +1,221 @@
/*
* CreateIfThenElseOperator (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.flow;
import jode.Expression;
import jode.IfThenElseOperator;
import jode.MyType;
import jode.CompareUnaryOperator;
import java.util.Enumeration;
import java.util.Vector;
public class CreateIfThenElseOperator implements Transformation {
/**
* This handles the more complicated form of the ?-:-operator used
* in a conditional block. The simplest case is:
* <pre>
* if (cond)
* push e1
* else {
* IF (c2)
* GOTO flow_2_
* push 0
* }
* -&gt;IF (stack_0 == 0)
* GOTO flow_1_
* GOTO flow_2_
* </pre>
* is transformed to
* <pre>
* push cond ? e1 : c2
* -&gt;IF (stack_0 == 0)
* GOTO flow_1_
* GOTO flow_2_
* </pre>
*
* The <code>-&gt;</code> points to the lastModified block. Note
* that both the if and the then part may contain this
* condition+push0-block. There may be even stack if-then-else-blocks
* for very complicated nested ?-:-Operators. <p>
*
* Also note that the produced code is suboptimal: The push-0 could
* sometimes be better replaced with a correct jump.
* @param flow The FlowBlock that is transformed
*/
public boolean createFunny(FlowBlock flow) {
Expression[] e = new Expression[3];
IfThenElseBlock ifBlock;
try {
ConditionalBlock conditional =
(ConditionalBlock) flow.lastModified;
if (!(conditional.trueBlock instanceof EmptyBlock)
|| conditional.trueBlock.jump == null
|| conditional.jump == null)
return false;
CompareUnaryOperator compare =
(CompareUnaryOperator) conditional.getInstruction();
FlowBlock trueDestination;
if (compare.getOperator() == compare.EQUALS_OP)
trueDestination = conditional.jump.destination;
else if (compare.getOperator() == compare.NOTEQUALS_OP)
trueDestination = conditional.trueBlock.jump.destination;
else
return false;
SequentialBlock sequBlock =
(SequentialBlock) conditional.outer;
ifBlock = (IfThenElseBlock) sequBlock.subBlocks[0];
while (true) {
if (ifBlock.thenBlock instanceof IfThenElseBlock)
ifBlock = (IfThenElseBlock) ifBlock.thenBlock;
else if (ifBlock.elseBlock instanceof IfThenElseBlock)
ifBlock = (IfThenElseBlock) ifBlock.elseBlock;
else
break;
}
e[0] = (Expression) ifBlock.cond;
StructuredBlock[] subBlocks = ifBlock.getSubBlocks();
if (subBlocks.length != 2)
return false;
for (int i=0; i< 2; i++) {
if (subBlocks[i] instanceof InstructionBlock) {
e[i+1] = (Expression)
((InstructionBlock)subBlocks[i]).getInstruction();
continue;
}
sequBlock = (SequentialBlock) subBlocks[i];
ConditionalBlock condBlock =
(ConditionalBlock) sequBlock.subBlocks[0];
InstructionBlock pushBlock =
(InstructionBlock) sequBlock.subBlocks[1];
Expression zeroExpr =
(Expression) pushBlock.getInstruction();
jode.ConstOperator zero =
(jode.ConstOperator) zeroExpr.getOperator();
if (!zero.getValue().equals("0"))
return false;
if (!(condBlock.trueBlock instanceof EmptyBlock)
|| condBlock.trueBlock.jump == null
|| condBlock.jump != null
|| condBlock.trueBlock.jump.destination
!= trueDestination)
return false;
Expression cond = (Expression) condBlock.getInstruction();
condBlock.trueBlock.removeJump();
pushBlock.setInstruction(cond);
pushBlock.replace(sequBlock, pushBlock);
e[i+1] = cond;
}
} catch (ClassCastException ex) {
return false;
} catch (NullPointerException ex) {
return false;
}
if (jode.Decompiler.isVerbose)
System.err.print("?");
IfThenElseOperator iteo = new IfThenElseOperator
(MyType.intersection(e[1].getType(),e[2].getType()));
((InstructionBlock)ifBlock.thenBlock).
setInstruction(new Expression(iteo, e));
ifBlock.thenBlock.replace(ifBlock, ifBlock.thenBlock);
return true;
}
/**
* This handles the normal form of the ?-:-operator:
* <pre>
* if (cond)
* push e1
* GOTO flow_1_
* -&gt;push e2
* GOTO flow_2
* </pre>
* is transformed to
* <pre>
* -&gt;push cond ? e1 : e2
* </pre>
* The <code>-&gt;</code> points to the lastModified block.
* @param flow The FlowBlock that is transformed
*/
public boolean create(FlowBlock flow) {
Expression e[] = new Expression[3];
try {
InstructionBlock elseBlock = (InstructionBlock) flow.lastModified;
SequentialBlock sequBlock = (SequentialBlock)elseBlock.outer;
if (sequBlock.subBlocks[1] != elseBlock)
return false;
IfThenElseBlock ifBlock = (IfThenElseBlock)sequBlock.subBlocks[0];
if (ifBlock.elseBlock != null)
return false;
InstructionBlock thenBlock = (InstructionBlock) ifBlock.thenBlock;
if (thenBlock.jump.destination != elseBlock.jump.destination)
return false;
e[1] = (Expression) thenBlock.getInstruction();
if (e[1].isVoid())
return false;
e[2] = (Expression) elseBlock.getInstruction();
if (e[2].isVoid())
return false;
e[0] = (Expression) ifBlock.cond;
thenBlock.removeJump();
} catch (ClassCastException ex) {
return false;
} catch (NullPointerException ex) {
return false;
}
if (jode.Decompiler.isVerbose)
System.err.print("?");
IfThenElseOperator iteo = new IfThenElseOperator
(MyType.intersection(e[1].getType(),e[2].getType()));
((InstructionBlock)flow.lastModified).
setInstruction(new Expression(iteo, e));
flow.lastModified.replace(flow.lastModified.outer, flow.lastModified);
return true;
}
public boolean transform(FlowBlock flow) {
return createFunny(flow) || create(flow);
}
}

@ -0,0 +1,149 @@
/*
* CreatePostIncExpression (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.flow;
import sun.tools.java.Type;
import jode.*;
public class CreatePostIncExpression implements Transformation {
public boolean transform(FlowBlock flow)
{
return (createLocalPostInc(flow) || createPostInc(flow));
}
public boolean createLocalPostInc(FlowBlock flow) {
IIncOperator iinc;
int op;
InstructionContainer lastBlock;
Type type;
try {
lastBlock = (InstructionContainer) flow.lastModified;
Expression iincExpr = (Expression) lastBlock.getInstruction();
iinc = (IIncOperator) iincExpr.getOperator();
if (iinc.getOperator() == iinc.ADD_OP + iinc.OPASSIGN_OP)
op = Operator.INC_OP;
else if (iinc.getOperator() == iinc.NEG_OP + iinc.OPASSIGN_OP)
op = Operator.DEC_OP;
else
return false;
if (!iinc.getValue().equals("1") &&
!iinc.getValue().equals("-1"))
return false;
if (iinc.getValue().equals("-1"))
op ^= 1;
SequentialBlock sequBlock = (SequentialBlock)lastBlock.outer;
if (sequBlock.subBlocks[1] != lastBlock)
return false;
InstructionBlock ib = (InstructionBlock) sequBlock.subBlocks[0];
Expression loadExpr = (Expression) ib.getInstruction();
LocalLoadOperator load =
(LocalLoadOperator)loadExpr.getOperator();
if (!iinc.matches(load))
return false;
type = MyType.intersection(load.getType(), MyType.tUInt);
} catch (NullPointerException ex) {
return false;
} catch (ClassCastException ex) {
return false;
}
Operator postop = new LocalPostFixOperator(type, op, iinc);
lastBlock.setInstruction(postop);
lastBlock.replace(lastBlock.outer, lastBlock);
return true;
}
public boolean createPostInc(FlowBlock flow) {
StoreInstruction store;
int op;
Type type;
InstructionBlock lastBlock;
SequentialBlock sequBlock;
try {
lastBlock = (InstructionBlock) flow.lastModified;
store = (StoreInstruction) lastBlock.getInstruction();
sequBlock = (SequentialBlock) lastBlock.outer;
if (sequBlock.subBlocks[1] != lastBlock)
return false;
InstructionBlock ib = (InstructionBlock) sequBlock.subBlocks[0];
BinaryOperator binOp = (BinaryOperator) ib.getInstruction();
if (binOp.getOperator() == store.ADD_OP)
op = Operator.INC_OP;
else if (store.getOperator() == store.NEG_OP)
op = Operator.DEC_OP;
else
return false;
sequBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
Expression expr = (Expression) ib.getInstruction();
ConstOperator constOp = (ConstOperator) expr.getOperator();
if (!constOp.getValue().equals("1") &&
!constOp.getValue().equals("-1"))
return false;
if (constOp.getValue().equals("-1"))
op ^= 1;
sequBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
DupOperator dup = (DupOperator) ib.getInstruction();
if (dup.getCount() != store.getLValueType().stackSize() ||
dup.getDepth() != store.getLValueOperandCount())
return false;
sequBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
Instruction instr = ib.getInstruction();
if (instr instanceof Expression
&& ((Expression)instr).getSubExpressions().length == 0)
instr = ((Expression)instr).getOperator();
Operator load = (Operator) instr;
if (!store.matches(load))
return false;
if (store.getLValueOperandCount() > 0) {
sequBlock = (SequentialBlock) sequBlock.outer;
ib = (InstructionBlock) sequBlock.subBlocks[0];
DupOperator dup2 = (DupOperator) ib.getInstruction();
if (dup2.getCount() != store.getLValueOperandCount() ||
dup2.getDepth() != 0)
return false;
}
type = MyType.intersection(load.getType(), store.getLValueType());
} catch (NullPointerException ex) {
return false;
} catch (ClassCastException ex) {
return false;
}
Operator postop = new PostFixOperator(type, op, store);
lastBlock.setInstruction(postop);
lastBlock.replace(sequBlock, lastBlock);
return true;
}
}
Loading…
Cancel
Save