mapStackToLocal / removePush added

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@319 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 06af300a7e
commit a85885e603
  1. 35
      jode/jode/flow/IfThenElseBlock.java
  2. 44
      jode/jode/flow/InstructionBlock.java
  3. 68
      jode/jode/flow/LoopBlock.java
  4. 12
      jode/jode/flow/RetBlock.java
  5. 28
      jode/jode/flow/ReturnBlock.java
  6. 11
      jode/jode/flow/SequentialBlock.java
  7. 13
      jode/jode/flow/SpecialBlock.java
  8. 39
      jode/jode/flow/StructuredBlock.java
  9. 17
      jode/jode/flow/TryBlock.java

@ -16,8 +16,10 @@
* $Id$ * $Id$
*/ */
package jode.flow; package jode.flow;
import jode.decompiler.LocalInfo;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
import jode.expr.Expression; import jode.expr.Expression;
import jode.Type;
/** /**
* An IfThenElseBlock is the structured block representing an if * An IfThenElseBlock is the structured block representing an if
@ -29,6 +31,11 @@ public class IfThenElseBlock extends StructuredBlock {
* The condition. Must be of boolean type. * The condition. Must be of boolean type.
*/ */
Expression cond; Expression cond;
/**
* The loads that are on the stack before cond is executed.
*/
VariableStack condStack;
/** /**
* The then part. This is always a valid block and not null * The then part. This is always a valid block and not null
@ -88,6 +95,34 @@ public class IfThenElseBlock extends StructuredBlock {
return true; return true;
} }
/**
* This does take the instr into account and modifies stack
* accordingly. It then calls super.mapStackToLocal.
* @param stack the stack before the instruction is called
* @return stack the stack afterwards.
*/
public VariableStack mapStackToLocal(VariableStack stack) {
VariableStack newStack;
int params = cond.getOperandCount();
if (params > 0) {
condStack = stack.peek(params);
newStack = stack.pop(params);
} else
newStack = stack;
return VariableStack.merge(thenBlock.mapStackToLocal(newStack),
elseBlock == null ? newStack
: elseBlock.mapStackToLocal(newStack));
}
public void removePush() {
if (condStack != null)
cond = condStack.mergeIntoExpression(cond, used);
thenBlock.removePush();
if (elseBlock != null)
elseBlock.removePush();
}
/** /**
* Print the source code for this structured block. This may be * Print the source code for this structured block. This may be
* called only once, because it remembers which local variables * called only once, because it remembers which local variables

@ -16,6 +16,7 @@
* $Id$ * $Id$
*/ */
package jode.flow; package jode.flow;
import jode.Type;
import jode.decompiler.TabbedPrintWriter; import jode.decompiler.TabbedPrintWriter;
import jode.decompiler.LocalInfo; import jode.decompiler.LocalInfo;
import jode.expr.ComplexExpression; import jode.expr.ComplexExpression;
@ -26,6 +27,14 @@ import jode.expr.LocalStoreOperator;
* This is the structured block for atomic instructions. * This is the structured block for atomic instructions.
*/ */
public class InstructionBlock extends InstructionContainer { public class InstructionBlock extends InstructionContainer {
/**
* The loads that are on the stack before cond is executed.
*/
VariableStack stack;
/**
* The local to which we push to, if the instruction is non void
*/
LocalInfo pushedLocal = null;
public InstructionBlock(Expression instr) { public InstructionBlock(Expression instr) {
super(instr); super(instr);
@ -35,6 +44,41 @@ public class InstructionBlock extends InstructionContainer {
super(instr, jump); super(instr, jump);
} }
/**
* This does take the instr into account and modifies stack
* accordingly. It then calls super.mapStackToLocal.
* @param stack the stack before the instruction is called
* @return stack the stack afterwards.
*/
public VariableStack mapStackToLocal(VariableStack stack) {
VariableStack newStack;
int params = instr.getOperandCount();
if (params > 0)
this.stack = stack.peek(params);
if (instr.getType() != Type.tVoid) {
pushedLocal = new LocalInfo();
newStack = stack.poppush(params, pushedLocal);
} else if (params > 0) {
newStack = stack.pop(params);
} else
newStack = stack;
return super.mapStackToLocal(newStack);
}
public void removePush() {
if (stack != null)
instr = stack.mergeIntoExpression(instr, used);
if (pushedLocal != null) {
LocalStoreOperator store = new LocalStoreOperator
(pushedLocal.getType(), pushedLocal,
LocalStoreOperator.ASSIGN_OP);
instr = new ComplexExpression(store, new Expression[] { instr });
used.addElement(pushedLocal);
}
super.removePush();
}
/** /**
* Tells if this block needs braces when used in a if or while block. * Tells if this block needs braces when used in a if or while block.
* @return true if this block should be sorrounded by braces. * @return true if this block should be sorrounded by braces.

@ -45,6 +45,10 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
* The condition. Must be of boolean type. * The condition. Must be of boolean type.
*/ */
Expression cond; Expression cond;
/**
* The stack the condition eats.
*/
VariableStack condStack;
/** /**
* The init instruction, only valid if type == FOR or POSSFOR * The init instruction, only valid if type == FOR or POSSFOR
*/ */
@ -65,10 +69,20 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
int type; int type;
/** /**
* The body of this loop. This is always a valid block and not null * The body of this loop. This is always a valid block and not null.
*/ */
StructuredBlock bodyBlock; StructuredBlock bodyBlock;
/**
* The stack after the break.
*/
VariableStack breakedStack;
/**
* The stack at begin of the loop.
*/
VariableStack continueStack;
/*{ invariant { type != POSSFOR || /*{ invariant { type != POSSFOR ||
(incr != null (incr != null
&& incr.getInstruction().getOperator() && incr.getInstruction().getOperator()
@ -297,6 +311,58 @@ public class LoopBlock extends StructuredBlock implements BreakableBlock {
mayChangeJump = false; mayChangeJump = false;
} }
/**
* This is called after the analysis is completely done. It
* will remove all PUSH/stack_i expressions, (if the bytecode
* is correct).
* @param stack the stack at begin of the block
* @return null if there is no way to the end of this block,
* otherwise the stack after the block has executed.
*/
public VariableStack mapStackToLocal(VariableStack stack) {
continueStack = stack;
VariableStack newStack;
int params = cond.getOperandCount();
if (params > 0) {
condStack = stack.peek(params);
newStack = stack.pop(params);
} else
newStack = stack;
VariableStack afterBody = bodyBlock.mapStackToLocal(newStack);
if (afterBody != null)
mergeContinueStack(afterBody);
return breakedStack;
}
/**
* Is called by BreakBlock, to tell us what the stack can be after a
* break.
* @return false if the stack is inconsistent.
*/
public void mergeContinueStack(VariableStack stack) {
continueStack.merge(stack);
}
/**
* Is called by BreakBlock, to tell us what the stack can be after a
* break.
* @return false if the stack is inconsistent.
*/
public void mergeBreakedStack(VariableStack stack) {
if (breakedStack != null)
breakedStack.merge(stack);
else
breakedStack = stack;
}
public void removePush() {
if (condStack != null)
cond = condStack.mergeIntoExpression(cond, used);
bodyBlock.removePush();
}
/** /**
* Replace all breaks to block with a continue to this. * Replace all breaks to block with a continue to this.
* @param block the breakable block where the breaks originally * @param block the breakable block where the breaks originally

@ -46,6 +46,18 @@ public class RetBlock extends StructuredBlock {
gen.addElement(local); gen.addElement(local);
} }
/**
* This does take the instr into account and modifies stack
* accordingly. It then calls super.mapStackToLocal.
* @param stack the stack before the instruction is called
* @return stack the stack afterwards.
*/
public VariableStack mapStackToLocal(VariableStack stack) {
if (!stack.isEmpty())
throw new IllegalArgumentException("stack is not empty at RET");
return null;
}
public void dumpInstruction(jode.decompiler.TabbedPrintWriter writer) public void dumpInstruction(jode.decompiler.TabbedPrintWriter writer)
throws java.io.IOException throws java.io.IOException
{ {

@ -22,9 +22,13 @@ import jode.decompiler.TabbedPrintWriter;
import jode.expr.Expression; import jode.expr.Expression;
/** /**
* This is the structured block for an Return block. * This is the structured block for a Return block.
*/ */
public class ReturnBlock extends InstructionContainer { public class ReturnBlock extends InstructionContainer {
/**
* The loads that are on the stack before instr is executed.
*/
VariableStack stack;
public ReturnBlock() { public ReturnBlock() {
super(null); super(null);
@ -34,6 +38,28 @@ public class ReturnBlock extends InstructionContainer {
super(instr, new Jump(-1)); super(instr, new Jump(-1));
} }
/**
* This does take the instr into account and modifies stack
* accordingly. It then calls super.mapStackToLocal.
* @param stack the stack before the instruction is called
* @return stack the stack afterwards.
*/
public VariableStack mapStackToLocal(VariableStack stack) {
VariableStack newStack;
int params = instr.getOperandCount();
if (params > 0) {
this.stack = stack.peek(params);
newStack = stack.pop(params);
} else
newStack = stack;
return null;
}
public void removePush() {
if (stack != null)
instr = stack.mergeIntoExpression(instr, used);
}
/** /**
* Tells if this block needs braces when used in a if or while block. * Tells if this block needs braces when used in a if or while block.
* @return true if this block should be sorrounded by braces. * @return true if this block should be sorrounded by braces.

@ -52,6 +52,17 @@ public class SequentialBlock extends StructuredBlock {
throw new jode.AssertError("Inconsistency"); throw new jode.AssertError("Inconsistency");
} }
/**
* This does take the instr into account and modifies stack
* accordingly. It then calls super.mapStackToLocal.
* @param stack the stack before the instruction is called
* @return stack the stack afterwards.
*/
public VariableStack mapStackToLocal(VariableStack stack) {
return subBlocks[1].mapStackToLocal
(subBlocks[0].mapStackToLocal(stack));
}
/** /**
* Returns the block where the control will normally flow to, when * Returns the block where the control will normally flow to, when
* the given sub block is finished (<em>not</em> ignoring the jump * the given sub block is finished (<em>not</em> ignoring the jump

@ -52,6 +52,19 @@ public class SpecialBlock extends StructuredBlock {
setJump(jump); setJump(jump);
} }
/**
* This does take the instr into account and modifies stack
* accordingly. It then calls super.mapStackToLocal.
* @param stack the stack before the instruction is called
* @return stack the stack afterwards.
*/
public VariableStack mapStackToLocal(VariableStack stack) {
/* a SpecialBlock is special :-) */
VariableStack after = stack.executeSpecial(this);
return super.mapStackToLocal(after);
}
public void dumpInstruction(TabbedPrintWriter writer) public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException throws java.io.IOException
{ {

@ -351,6 +351,45 @@ public abstract class StructuredBlock {
return allUse; return allUse;
} }
/**
* This is called after the analysis is completely done. It
* will remove all PUSH/stack_i expressions, (if the bytecode
* is correct). <p>
* The default implementation merges the stack after each sub block.
* This may not be, what you want. <p>
*
* @param initialStack the stackmap at begin of the block
* @return the stack after the block has executed.
* @throw RuntimeException if something did get wrong.
*/
public VariableStack mapStackToLocal(VariableStack stack) {
StructuredBlock[] subBlocks = getSubBlocks();
VariableStack after;
if (subBlocks.length == 0)
after = stack;
else {
after = null;
for (int i=1; i< subBlocks.length; i++) {
after = VariableStack.merge
(after, subBlocks[i].mapStackToLocal(stack));
}
}
if (jump != null)
/* assert(after != null) */
jump.stackMap = after;
return after;
}
/**
* This is called after mapStackToLocal to do the stack to local
* transformation.
*/
public void removePush() {
StructuredBlock[] subBlocks = getSubBlocks();
for (int i=0; i< subBlocks.length; i++)
subBlocks[i].removePush();
}
/** /**
* Make the declarations, i.e. initialize the declare variable * Make the declarations, i.e. initialize the declare variable
* to correct values. This will declare every variable that * to correct values. This will declare every variable that

@ -90,6 +90,23 @@ public class TryBlock extends StructuredBlock {
return subBlocks; return subBlocks;
} }
/**
* This does take the instr into account and modifies stack
* accordingly. It then calls super.mapStackToLocal.
* @param stack the stack before the instruction is called
* @return stack the stack afterwards.
*/
public VariableStack mapStackToLocal(VariableStack stack) {
// first the try block.
VariableStack after = subBlocks[0].mapStackToLocal(stack);
for (int i = 1; i<subBlocks.length; i++) {
// now merge the catch blocks; they start on empty stack.
after = VariableStack.merge
(after, subBlocks[i].mapStackToLocal(VariableStack.EMPTY));
}
return after;
}
public void dumpInstruction(TabbedPrintWriter writer) public void dumpInstruction(TabbedPrintWriter writer)
throws java.io.IOException { throws java.io.IOException {
writer.print("try"); writer.print("try");

Loading…
Cancel
Save