diff --git a/jode/jode/flow/VariableStack.java b/jode/jode/flow/VariableStack.java new file mode 100644 index 0000000..bc63a27 --- /dev/null +++ b/jode/jode/flow/VariableStack.java @@ -0,0 +1,155 @@ +package jode.flow; +import jode.decompiler.LocalInfo; +import jode.expr.ComplexExpression; +import jode.expr.Expression; +import jode.expr.LocalLoadOperator; +import jode.expr.Operator; + +/** + * This class represents the state of the stack at various points in + * the program. Each entry is a anonymous local, which is used instead + * of the PUSH / stack_i statements.

+ * + * This class is immutable, but note, that the local infos can get merged. + * @see FlowBlock.mapStackToLocal + * @see FlowBlock.removePush + */ +public class VariableStack { + public final static VariableStack EMPTY = + new VariableStack(new LocalInfo[0]); + + final LocalInfo[] stackMap; + + private VariableStack(LocalInfo[] stack) { + stackMap = stack; + } + + public boolean isEmpty() { + return stackMap.length == 0; + } + + public VariableStack pop(int count) { + LocalInfo[] newStack = new LocalInfo[stackMap.length - count]; + System.arraycopy(stackMap, 0, newStack, 0, stackMap.length - count); + return new VariableStack(newStack); + } + + public VariableStack push(LocalInfo li) { + return poppush(0, li); + } + + public VariableStack poppush(int count, LocalInfo li) { + LocalInfo[] newStack = new LocalInfo[stackMap.length - count + 1]; + System.arraycopy(stackMap, 0, newStack, 0, stackMap.length - count); + newStack[stackMap.length - count] = li; + return new VariableStack(newStack); + } + + public VariableStack peek(int count) { + LocalInfo[] peeked = new LocalInfo[count]; + System.arraycopy(stackMap, stackMap.length - count, peeked, 0, count); + return new VariableStack(peeked); + } + + public void merge(VariableStack other) { + if (stackMap.length != other.stackMap.length) + throw new IllegalArgumentException("stack length differs"); + for (int i=0; i