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