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