git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@36 379699f6-c40d-0410-875b-85095c16579estable
parent
674d865943
commit
704a534731
@ -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 |
||||||
|
* } |
||||||
|
* ->IF (stack_0 == 0) |
||||||
|
* GOTO flow_1_ |
||||||
|
* GOTO flow_2_ |
||||||
|
* </pre> |
||||||
|
* is transformed to |
||||||
|
* <pre> |
||||||
|
* push cond ? e1 : c2 |
||||||
|
* ->IF (stack_0 == 0) |
||||||
|
* GOTO flow_1_ |
||||||
|
* GOTO flow_2_ |
||||||
|
* </pre> |
||||||
|
* |
||||||
|
* The <code>-></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_ |
||||||
|
* ->push e2 |
||||||
|
* GOTO flow_2 |
||||||
|
* </pre> |
||||||
|
* is transformed to |
||||||
|
* <pre> |
||||||
|
* ->push cond ? e1 : e2 |
||||||
|
* </pre> |
||||||
|
* The <code>-></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…
Reference in new issue