Initial revision

git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@324 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 9a5ccb5a86
commit c3320ae555
  1. 155
      jode/jode/flow/VariableStack.java
  2. 53
      jode/test/ConstantTypes.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. <p>
*
* 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<stackMap.length; i++) {
if (stackMap[i].getType().stackSize()
!= other.stackMap[i].getType().stackSize())
throw new IllegalArgumentException
("stack element length differs at "+i);
stackMap[i].combineWith(other.stackMap[i]);
}
}
/**
* Merge to VariableStacks. Either one may be null, in which case
* the other is returned.
*/
public static VariableStack merge(VariableStack first,
VariableStack second) {
if (first == null)
return second;
else if (second == null)
return first;
first.merge(second);
return first;
}
public Expression mergeIntoExpression(Expression expr, VariableSet used) {
/* assert expr.getOperandCount() == stackMap.length */
ComplexExpression parent = null;
Expression inner = expr;
while (inner instanceof ComplexExpression) {
parent = (ComplexExpression)inner;
inner = parent.getSubExpressions()[0];
}
Expression[] loads = new Expression[stackMap.length];
for (int i=0; i< stackMap.length; i++) {
used.addElement(stackMap[i]);
loads[i] = new LocalLoadOperator(stackMap[i].getType(),
stackMap[i]);
}
Expression newExpr = new ComplexExpression((Operator)inner, loads);
if (parent != null)
parent.setSubExpressions(0, newExpr);
else
expr = newExpr;
return expr;
}
public VariableStack executeSpecial(SpecialBlock special) {
if (special.type == special.POP) {
int popped = 0;
int newLength = stackMap.length;
while (popped < special.count) {
newLength--;
popped += stackMap[newLength].getType().stackSize();
}
if (popped != special.count)
throw new IllegalArgumentException("wrong POP");
LocalInfo[] newStack = new LocalInfo[newLength];
System.arraycopy(stackMap, 0, newStack, 0, newLength);
return new VariableStack(newStack);
} else if (special.type == special.DUP) {
int popped = 0;
int numDup = 0;
int startDup = stackMap.length;
while (popped < special.count) {
startDup--;
numDup++;
popped += stackMap[startDup].getType().stackSize();
}
if (popped != special.count)
throw new IllegalArgumentException("wrong DUP");
int destDup = startDup;
int depth = 0;
while (depth < special.depth) {
destDup--;
depth += stackMap[destDup].getType().stackSize();
}
if (depth != special.depth)
throw new IllegalArgumentException("wrong DUP");
LocalInfo[] newStack = new LocalInfo[stackMap.length + numDup];
System.arraycopy(stackMap, 0, newStack, 0, destDup);
System.arraycopy(stackMap, startDup, newStack, destDup, numDup);
System.arraycopy(stackMap, destDup, newStack, destDup + numDup,
startDup - destDup);
System.arraycopy(stackMap, startDup, newStack, startDup + numDup,
numDup);
return new VariableStack(newStack);
} else if (special.type == special.SWAP) {
LocalInfo[] newStack = new LocalInfo[stackMap.length];
System.arraycopy(stackMap, 0, newStack, 0, stackMap.length - 2);
if (stackMap[stackMap.length-2].getType().stackSize() != 1
|| stackMap[stackMap.length-1].getType().stackSize() != 1)
throw new IllegalArgumentException("wrong SWAP");
newStack[stackMap.length-2] = stackMap[stackMap.length-1];
newStack[stackMap.length-1] = stackMap[stackMap.length-2];
return new VariableStack(newStack);
} else
throw new jode.AssertError("Unknown SpecialBlock");
}
}

@ -0,0 +1,53 @@
package jode.test;
public class ConstantTypes {
static boolean bool = true;
static byte b = (byte) 0x80;
static char c = '\u0080';
static short s = (short)'\u8234';
static int i = '\uffff';
static void intFunc(int i){}
static void shortFunc(short s){}
static void charFunc(char c){}
static void byteFunc(byte b){}
static {
/* All casts are necessaray */
intFunc(25);
shortFunc((short) 25);
charFunc((char) 25);
byteFunc((byte) 25);
intFunc('\u0019');
shortFunc((short) '\u0019');
charFunc('\u0019');
byteFunc((byte) '\u0019');
intFunc(b);
intFunc(c);
intFunc(s);
intFunc(i);
shortFunc(b);
shortFunc((short)c);
shortFunc(s);
shortFunc((short)i);
charFunc((char)b);
charFunc(c);
charFunc((char)s);
charFunc((char)i);
byteFunc(b);
byteFunc((byte)c);
byteFunc((byte)s);
byteFunc((byte)i);
b = 42;
c = 42;
s = 42;
i = 42;
i = c;
s = b;
i = s;
c = (char) s;
s = (short) c;
c = (char) b;
b = (byte) c;
}
}
Loading…
Cancel
Save