super(c, in, cp);
local = new Expr[maxLocals];
stack = new Expr[maxStack];
- for(int i=0; i<this.method.getNumArgs(); i++)
- local[i] = new Argument("arg"+i, this.method.getArgType(i));
+ int n=0;
+ if (!isStatic())
+ local[n++] = new Argument("this",method.getDeclaringClass());
+ for(int i=0;i<this.method.getNumArgs(); i++)
+ local[n++] = new Argument("arg"+i, this.method.getArgType(i));
for(int i=0; i<size(); i++) {
int op = get(i);
Object arg = getArg(i);
if(sp == 0) throw new IllegalStateException("stack underflow");
return stack[--sp];
}
+
+ private Op seqPush(Expr e) {
+ push(e);
+ return new Seq(e);
+ }
// SSA-node classes /////////////////////////////////////////////////////////////////////////////////////////
return name;
}
}
-
+
+ /** A sequence point. expr is evaluated for side effects at this point, this does not generate data
+ Expressions that haven't been evaluated with Seq are evaluated when they are first encountered
+ */
+ public class Seq extends Op {
+ private final Expr expr;
+ public String toString() { return expr.toString(); }
+ public Seq(Expr expr) { this.expr = expr; }
+ }
+
/** an operation which generates data */
public abstract class Expr extends Op {
//public abstract Expr[] contributors(); // not implemented yet
public final Type.Class t;
public Type getType() { return t; }
public New(Type.Class t) { this.t = t; }
+ public String toString() { return "new " + t + "(...)"; }
}
public class NewArray extends Expr {
public class InvokeStatic extends Invoke { public InvokeStatic(Type.Class.Method m, Expr[] a) { super(m,a); } }
public class InvokeSpecial extends InvokeVirtual {
public InvokeSpecial(Type.Class.Method m, Expr[] a, Expr e) { super(m,a,e); }
- public String toString() {
- StringBuffer sb = new StringBuffer();
- sb.append(method.name.equals("<init>") ? "super" : method.name);
- args(sb);
- return sb.toString();
- }
+ public String toString() { return toString(method.name.equals("<init>") ? method.getDeclaringClass().getName() : method.name); }
}
public class InvokeInterface extends InvokeVirtual{public InvokeInterface(Type.Class.Method m, Expr[] a, Expr e){super(m,a,e);}}
public class InvokeVirtual extends Invoke {
public final Expr instance;
public InvokeVirtual(Type.Class.Method m, Expr[] a, Expr e) { super(m, a); instance = e; }
- public String toString() {
+ public String toString() { return toString(method.name); }
+ protected String toString(String name) {
StringBuffer sb = new StringBuffer();
- sb.append(method.name);
+ sb.append(instance+".");
+ sb.append(name);
args(sb);
return sb.toString();
}
private final Object o;
public Constant(int i) { this(new Integer(i)); }
public Constant(Object o) { this.o = o; }
- public String toString() { return o.toString(); }
+ public String toString() { return o instanceof String ? "\"" + o + "\"" : o.toString(); }
public Type getType() {
if (o instanceof Byte) return Type.BYTE;
if (o instanceof Short) return Type.SHORT;
if (o instanceof Long) return Type.LONG;
if (o instanceof Double) return Type.DOUBLE;
if (o instanceof Float) return Type.FLOAT;
- if (o instanceof ConstantPool.Ent) throw new Error("unimplemented");
- throw new Error("this should not happen");
+ if (o instanceof Integer) return Type.INT;
+ if (o instanceof String) return Type.STRING;
+ throw new IllegalStateException("unknown constant type");
}
}
case ISTORE_1: case LSTORE_1: case FSTORE_1: case DSTORE_1: case ASTORE_1: local[1] = pop(); return null;
case ASTORE_2: case DSTORE_2: case FSTORE_2: case LSTORE_2: case ISTORE_2: local[2] = pop(); return null;
case ISTORE_3: case LSTORE_3: case FSTORE_3: case DSTORE_3: case ASTORE_3: local[3] = pop(); return null;
- case POP: stack[--sp] = null;
- case POP2: stack[--sp] = null; stack[--sp] = null; /** fixme: pops a WORD, not an item */
- case DUP: stack[sp] = stack[sp-1]; sp++;
- case DUP2: stack[sp] = stack[sp-2]; stack[sp+1] = stack[sp-1]; sp+=2;
+ case POP: pop(); return null;
+ case POP2: pop(); pop(); return null;
+ case DUP: push(stack[sp-1]); return null;
+ case DUP2: push(stack[sp-2]); push(stack[sp-2]); return null;
// Conversions //////////////////////////////////////////////////////////////////////////////
// Array manipulations //////////////////////////////////////////////////////////////////////////////
case IALOAD: case LALOAD: case FALOAD: case DALOAD: case AALOAD:
- case BALOAD: case CALOAD: case SALOAD: push(new ArrayGet(pop(), pop())); return null;
+ case BALOAD: case CALOAD: case SALOAD:
+ return seqPush(new ArrayGet(pop(), pop()));
case IASTORE: case LASTORE: case FASTORE: case DASTORE: case AASTORE:
- case BASTORE: case CASTORE: case SASTORE: return new ArrayPut(pop(), pop(), pop());
+ case BASTORE: case CASTORE: case SASTORE:
+ return new ArrayPut(pop(), pop(), pop());
// Invocation //////////////////////////////////////////////////////////////////////////////
Type.Class.Method method = (Type.Class.Method)arg;
Expr args[] = new Expr[method.getNumArgs()];
for(int i=0; i<args.length; i++) args[args.length-i-1] = pop();
+ Expr ret;
switch(op) {
- case INVOKEVIRTUAL: return push(new InvokeVirtual(method, args, pop()));
- case INVOKEINTERFACE: return push(new InvokeInterface(method, args, pop()));
- case INVOKESPECIAL: return push(new InvokeSpecial(method, args, pop()));
- case INVOKESTATIC: return push(new InvokeStatic(method, args));
+ case INVOKEVIRTUAL: ret = new InvokeVirtual(method, args, pop()); break;
+ case INVOKEINTERFACE: ret = new InvokeInterface(method, args, pop()); break;
+ case INVOKESPECIAL: ret = new InvokeSpecial(method, args, pop()); break;
+ case INVOKESTATIC: ret = new InvokeStatic(method, args); break;
+ default: throw new Error("should never happen");
}
+ if(ret.getType() != Type.VOID) push(ret);
+ return new Seq(ret);
}
// Field Access //////////////////////////////////////////////////////////////////////////////
- case GETSTATIC: push(new Get((Type.Class.Field)arg, null)); return null;
+ case GETSTATIC: return seqPush(new Get((Type.Class.Field)arg, null));
case PUTSTATIC: return new Put((Type.Class.Field)arg, pop(), null);
- case GETFIELD: push(new Get((Type.Class.Field)arg, pop())); return null;
+ case GETFIELD: return seqPush(new Get((Type.Class.Field)arg, pop()));
case PUTFIELD: return new Put((Type.Class.Field)arg, pop(), pop());
// Allocation //////////////////////////////////////////////////////////////////////////////
case 11: base = Type.LONG; break;
default: throw new IllegalStateException("invalid array type");
}
- push(new NewArray(base.makeArray(),pop()));
- return null;
+ return seqPush(new NewArray(base.makeArray(),pop()));
}
case ANEWARRAY: push(new NewArray(((Type.Ref)arg).makeArray(), pop())); return null;
case MULTIANEWARRAY: {
MethodGen.MultiANewArray mana = (MethodGen.MultiANewArray) arg;
Expr[] dims = new Expr[mana.dims];
for(int i=0;i<dims.length;i++) dims[i] = pop();
- push(new NewArray(mana.type, dims));
- return null;
+ return seqPush(new NewArray(mana.type, dims));
}
- case ARRAYLENGTH: push(new ArrayLength(pop())); return null;
+ case ARRAYLENGTH: return seqPush(new ArrayLength(pop()));
// Runtime Type information //////////////////////////////////////////////////////////////////////////////
- case CHECKCAST: push(new Cast(pop(), (Type.Ref)arg)); return null;
+ case CHECKCAST: return seqPush(new Cast(pop(), (Type.Ref)arg));
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;
- case BIPUSH: push(new Constant(i1)); // FIXME return null;
- case SIPUSH: push(new Constant(i1)); // FIXME return null;
+ case BIPUSH: push(new Constant((Integer)arg)); return null;
+ case SIPUSH: push(new Constant((Integer)arg)); return null;
case TABLESWITCH: new Branch((MethodGen.Switch)arg);
case LOOKUPSWITCH: new Branch((MethodGen.Switch)arg);