for(int i=0; i<size(); i++) {
int op = get(i);
Object arg = getArg(i);
- Object o = addOp(op, arg);
- if (o != null) {
- ops[numOps] = o;
- ofs[numOps++] = i;
+ try {
+ Object o = addOp(op, arg);
+ if (o != null) {
+ ops[numOps] = o;
+ ofs[numOps++] = i;
+ }
+ } catch(RuntimeException e) {
+ System.err.println("Had a problem at PC: " + i + " of " + method);
+ e.printStackTrace();
+ throw new IOException("invalid class file");
}
}
}
/** JVM stack pointer */
private int sp = 0;
- private Expr push(Expr e) { return stack[sp++] = e; }
- private Expr pop() { return stack[--sp]; }
+ private Expr push(Expr e) {
+ if(sp == stack.length) {
+ for(int i=0;i<stack.length;i++) System.err.println("Stack " + i + ": " + stack[i]);
+ throw new IllegalStateException("stack overflow (" + stack.length + ")");
+ }
+ if(e.getType() == Type.VOID) throw new IllegalArgumentException("can't push a void");
+ return stack[sp++] = e;
+ }
+ private Expr pop() {
+ if(sp == 0) throw new IllegalStateException("stack underflow");
+ return stack[--sp];
+ }
// SSA-node classes /////////////////////////////////////////////////////////////////////////////////////////
public String toString() { return name; }
public Type getType() { return t; }
}
-
+
+ // Unary Operations
+ public class Not extends Expr {
+ public final Expr e;
+ public Not(Expr e) {
+ if(e.getType() != Type.BOOLEAN) throw new IllegalArgumentException("not needs a boolean expression");
+ this.e = e;
+ }
+ public Type getType() { return Type.BOOLEAN; }
+ public String toString() { return "!(" + e + ")"; }
+ }
+
+ public class Neg extends Expr {
+ public final Expr e;
+ public Neg(Expr e) {
+ if(!e.getType().isPrimitive()) throw new IllegalArgumentException("can only negate a primitive");
+ this.e = e;
+ }
+ public Type getType() { return e.getType(); }
+ public String toString() { return "- (" + e + ")"; }
+ }
+
// Binary Operations //////////////////////////////////////////////////////////////////////////////
public abstract class BinExpr extends Expr {
public final Expr e1;
public final Expr e2;
- public BinExpr(Expr e1, Expr e2) { this.e1 = e1; this.e2 = e2; }
+ private final String show;
+ public BinExpr(Expr e1, Expr e2, String show) { this.e1 = e1; this.e2 = e2; this.show = show; }
public String toString() {
- return name() + "("+e1+", "+e2+")";
+ // FEATURE: should we be doing some precedence stuff here? probably no worth it for debugging output
+ return "(" + e1 + show + e2 + ")";
}
}
public class Comparison extends BinExpr {
- public Comparison(Expr e1, Expr e2) { super(e1, e2); }
+ public Comparison(Expr e1, Expr e2, String show) { super(e1, e2, show); }
public Type getType() { return Type.BOOLEAN; }
}
- public class Gt extends Comparison { public Gt(Expr e1, Expr e2) { super(e1, e2); } }
- public class Lt extends Comparison { public Lt(Expr e1, Expr e2) { super(e1, e2); } }
- public class Eq extends Comparison { public Eq(Expr e1, Expr e2) { super(e1, e2); } }
- public class Not extends Expr {
- public final Expr e;
- public Not(Expr e) { this.e = e; }
- public Type getType() { return Type.BOOLEAN; }
+
+ public class Eq extends Comparison {
+ public Eq(Expr e1, Expr e2) {
+ super(e1, e2, "==");
+ if(e1.getType().isPrimitive() != e2.getType().isPrimitive())
+ throw new IllegalArgumentException("type mismatch");
+ if(e1.getType().isPrimitive() && e1.getType() != e2.getType())
+ throw new IllegalArgumentException("type mismatch");
+ // FEATURE: Check if we can compare these classes
+ }
}
+
+ public class PrimitiveComparison extends Comparison {
+ public PrimitiveComparison(Expr e1, Expr e2, String show) {
+ super(e1, e2, show);
+ if(!e1.getType().isPrimitive() || e1.getType() != e2.getType()) throw new IllegalArgumentException("type mismatch");
+ }
+ }
+
+ public class Gt extends PrimitiveComparison { public Gt(Expr e1, Expr e2) { super(e1, e2, ">"); } }
+ public class Lt extends PrimitiveComparison { public Lt(Expr e1, Expr e2) { super(e1, e2, "<"); } }
+ public class Ge extends PrimitiveComparison { public Ge(Expr e1, Expr e2) { super(e1, e2, ">="); } }
+ public class Le extends PrimitiveComparison { public Le(Expr e1, Expr e2) { super(e1, e2, "<="); } }
+
// Math Operations //////////////////////////////////////////////////////////////////////////////
- public class Math extends BinExpr {
- private final String show;
- public Math(Expr e1, Expr e2, String show) { super(e2, e1); this.show = show; }
- public String toString() { return e1+" "+show+" "+e2; }
- public Type getType() {
+ public class BinMath extends BinExpr {
+ public BinMath(Expr e1, Expr e2, String show) {
+ super(e2, e1, show);
+ if(e1.getType() != e2.getType()) throw new IllegalArgumentException("types disagree");
+ }
+ public Type getType() { return e1.getType(); }
+ }
+
+ public class Add extends BinMath { public Add(Expr e, Expr e2) { super(e, e2, "+"); } }
+ public class Sub extends BinMath { public Sub(Expr e, Expr e2) { super(e, e2, "-"); } }
+ public class Mul extends BinMath { public Mul(Expr e, Expr e2) { super(e, e2, "*"); } }
+ public class Rem extends BinMath { public Rem(Expr e, Expr e2) { super(e, e2, "%"); } }
+ public class Div extends BinMath { public Div(Expr e, Expr e2) { super(e, e2, "/"); } }
+ public class And extends BinMath { public And(Expr e, Expr e2) { super(e, e2, "&"); } }
+ public class Or extends BinMath { public Or(Expr e, Expr e2) { super(e, e2, "|"); } }
+ public class Xor extends BinMath { public Xor(Expr e, Expr e2) { super(e, e2, "^"); } }
+
+ public class BitShiftExpr extends BinExpr {
+ public BitShiftExpr(Expr e1, Expr e2, String show) {
+ super(e1,e2,show);
Type t = e1.getType();
- if (t != e2.getType()) throw new Error("types disagree");
- return t;
+ if(t != Type.INT && t != Type.LONG) throw new IllegalArgumentException("type mismatch");
+ if(e2.getType() != Type.INT) throw new IllegalArgumentException("type mismatch");
}
+ public Type getType() { return e1.getType(); }
}
- public class Add extends Math { public Add(Expr e, Expr e2) { super(e, e2, "+"); } }
- public class Sub extends Math { public Sub(Expr e, Expr e2) { super(e, e2, "-"); } }
- public class Mul extends Math { public Mul(Expr e, Expr e2) { super(e, e2, "*"); } }
- public class Rem extends Math { public Rem(Expr e, Expr e2) { super(e, e2, "%"); } }
- //public class Neg extends Math { public Neg(Expr e) { super(e, "-"); } }
- public class Div extends Math { public Div(Expr e, Expr e2) { super(e, e2, "/"); } }
- public class Shl extends Math { public Shl(Expr e, Expr e2) { super(e, e2, "<<"); } }
- public class Shr extends Math { public Shr(Expr e, Expr e2) { super(e, e2, ">>"); } }
- public class Ushr extends Math { public Ushr(Expr e, Expr e2) { super(e, e2, ">>>"); } }
- public class And extends Math { public And(Expr e, Expr e2) { super(e, e2, "&"); } }
- public class Or extends Math { public Or(Expr e, Expr e2) { super(e, e2, "|"); } }
- public class Xor extends Math { public Xor(Expr e, Expr e2) { super(e, e2, "^"); } }
+ public class Shl extends BitShiftExpr { public Shl(Expr e, Expr e2) { super(e, e2, "<<"); } }
+ public class Shr extends BitShiftExpr { public Shr(Expr e, Expr e2) { super(e, e2, ">>"); } }
+ public class Ushr extends BitShiftExpr { public Ushr(Expr e, Expr e2) { super(e, e2, ">>>"); } }
// Other operations //////////////////////////////////////////////////////////////////////////////
public class Cast extends Expr {
final Expr e;
final Type t;
- public Cast(Expr e, Type t) { this.e = e; this.t = t; }
+ public Cast(Expr e, Type t) {
+ if(e.getType().isRef() != t.isRef()) throw new IllegalArgumentException("invalid cast");
+ // FEATURE: Check that one is a subclass of the other if it is a ref
+ this.e = e;
+ this.t = t;
+ }
public Type getType() { return t; }
}
public class InstanceOf extends Expr {
final Expr e;
- final Type t;
- public InstanceOf(Expr e, Type t) { this.e = e; this.t = t; }
+ final Type.Ref t;
+ public InstanceOf(Expr e, Type.Ref t) {
+ if(!e.getType().isRef()) throw new IllegalArgumentException("can't do an instanceof check on a non-ref");
+ this.e = e;
+ this.t = t;
+ }
public Type getType() { return Type.BOOLEAN; }
}
public class Throw extends Op {
public final Expr e;
- public Throw(Expr e) { this.e = e; }
+ public Throw(Expr e) {
+ if(!e.getType().isRef()) throw new IllegalArgumentException("can't throw a non ref");
+ // FEATURE: CHeck that it is a subclass of Throwable
+ this.e = e;
+ }
}
public class Branch extends Op {
public Type getType() { return t; }
}
- // FEATURE: Array stuff
-
public class Return extends Op {
final Expr e;
public Return() { this(VOID_EXPR); }
// Runtime Type information //////////////////////////////////////////////////////////////////////////////
- case CHECKCAST: push(new Cast(pop(), (Type)arg)); return null;
- case INSTANCEOF: push(new InstanceOf(pop(), (Type)arg)); return null;
+ case CHECKCAST: push(new Cast(pop(), (Type.Ref)arg)); return null;
+ case INSTANCEOF: push(new InstanceOf(pop(), (Type.Ref)arg)); return null;
case LDC: case LDC_W: case LDC2_W: push(new Constant(arg)); return null;