X-Git-Url: http://git.megacz.com/?p=org.ibex.classgen.git;a=blobdiff_plain;f=src%2Forg%2Fibex%2Fclassgen%2FJSSA.java;h=2fc521ace03c227e2eec2ee45040f42d2af51988;hp=5161a4187c062e853831a6e63ca8122ad6a79e75;hb=7b7d64efd6761d48aabe652945e907e9309bccd0;hpb=0af18e327981bdae42ca0753ca05b4030bbdc848 diff --git a/src/org/ibex/classgen/JSSA.java b/src/org/ibex/classgen/JSSA.java index 5161a41..2fc521a 100644 --- a/src/org/ibex/classgen/JSSA.java +++ b/src/org/ibex/classgen/JSSA.java @@ -13,58 +13,50 @@ public class JSSA extends MethodGen implements CGConst { public JSSA(Type.Class c, DataInput in, ConstantPool cp) throws IOException { super(c, in, cp); - local = new Expr[maxLocals]; - stack = new Expr[maxStack]; - int n=0; - if (!isStatic()) - local[n++] = new Argument("this",method.getDeclaringClass()); - for(int i=0;i="); } } public class Le extends PrimitiveComparison { public Le(Expr e1, Expr e2) { super(e1, e2, "<="); } } + + // Math Operations ////////////////////////////////////////////////////////////////////////////// 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"); + if (e1.getType() != null && e2.getType() != null && e1.getType() != e2.getType()) + throw new IllegalArgumentException("types disagree"); } public Type getType() { return e1.getType(); } } @@ -242,8 +313,8 @@ public class JSSA extends MethodGen implements CGConst { public BitShiftExpr(Expr e1, Expr e2, String show) { super(e1,e2,show); Type t = e1.getType(); - if(t != Type.INT && t != Type.LONG) throw new IllegalArgumentException("type mismatch"); - if(e2.getType() != Type.INT) throw new IllegalArgumentException("type mismatch"); + 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(); } } @@ -251,13 +322,14 @@ public class JSSA extends MethodGen implements CGConst { 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) { - if(e.getType().isRef() != t.isRef()) throw new IllegalArgumentException("invalid cast"); + 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; @@ -269,46 +341,83 @@ public class JSSA extends MethodGen implements CGConst { final Expr e; 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"); + 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 class Branch extends Op { + Expr destination = null; + public Branch(Expr destination) { this.destination = destination; } + public Branch(MethodGen.Switch s) { /* FIXME */ } + public Branch() { } + public void branchTo() { if (destination != null) branchTo(destination); } + private void branchTo(Expr e) { + if (e instanceof Phi) { + Phi phi = (Phi)e; + for(int i=0; i>"; } } public class New extends Expr { 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 String _toString() { return "new " + t + "()"; } } public class NewArray extends Expr { @@ -317,15 +426,20 @@ public class JSSA extends MethodGen implements CGConst { public NewArray(Type.Array t, Expr[] dims) { this.t = t; this.dims = dims; } public NewArray(Type.Array t, Expr dim) { this(t,new Expr[]{dim}); } public Type getType() { return t; } + public String _toString() { + Type base = t; + int totalDims = 0; + while(base.isArray()) { + totalDims++; + base = base.asArray().getElementType(); + } + StringBuffer sb = new StringBuffer("new " + base); + for(int i=0;i") ? method.getDeclaringClass().getName() : method.name); } + public String _toString() { return _toString(method.name.equals("") + ? 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 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() { return toString(method.name); } - protected String toString(String name) { + public String _toString() { return _toString(method.name); } + protected String _toString(String name) { StringBuffer sb = new StringBuffer(); sb.append(instance+"."); sb.append(name); @@ -424,8 +543,9 @@ public class JSSA extends MethodGen implements CGConst { private final Object o; public Constant(int i) { this(new Integer(i)); } public Constant(Object o) { this.o = o; } - public String toString() { return o instanceof String ? "\"" + o + "\"" : o.toString(); } + public String toString() { return o == null ? "null" : o instanceof String ? "\"" + o + "\"" : o.toString(); } public Type getType() { + if (o == null) return Type.NULL; if (o instanceof Byte) return Type.BYTE; if (o instanceof Short) return Type.SHORT; if (o instanceof Character) return Type.CHAR; @@ -458,34 +578,41 @@ public class JSSA extends MethodGen implements CGConst { i1 = p.i1; i2 = p.i2; } + if (arg instanceof Number) i1 = ((Integer)arg).intValue(); + Label label = (arg instanceof Label) ? (Label)arg : null; switch(op) { case NOP: return null; // Stack manipulations ////////////////////////////////////////////////////////////////////////////// - case ACONST_NULL: return stack[sp++] = new Constant(null); - case ICONST_M1: return stack[sp++] = new Constant(-1); - case ICONST_0: case LCONST_0: case FCONST_0: case DCONST_0: push(new Constant(0)); return null; - case ICONST_1: case LCONST_1: case FCONST_1: case DCONST_1: push(new Constant(1)); return null; - case ICONST_2: case FCONST_2: push(new Constant(2)); return null; - case ICONST_3: push(new Constant(3)); return null; - case ICONST_4: push(new Constant(4)); return null; - case ICONST_5: push(new Constant(5)); return null; - case ILOAD: case LLOAD: case FLOAD: case DLOAD: case ALOAD: return push(local[i1]); - case ILOAD_0: case LLOAD_0: case FLOAD_0: case DLOAD_0: case ALOAD_0: return push(local[0]); - case ILOAD_1: case LLOAD_1: case FLOAD_1: case DLOAD_1: case ALOAD_1: return push(local[1]); - case ALOAD_2: case DLOAD_2: case FLOAD_2: case LLOAD_2: case ILOAD_2: return push(local[2]); - case ILOAD_3: case LLOAD_3: case FLOAD_3: case DLOAD_3: case ALOAD_3: return push(local[3]); - case ISTORE: case LSTORE: case FSTORE: case DSTORE: case ASTORE: local[i1] = pop(); return null; - case ISTORE_0: case LSTORE_0: case FSTORE_0: case DSTORE_0: case ASTORE_0: local[0] = pop(); return null; - 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: 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; + case ACONST_NULL: push(new Constant(null)); return null; + case ICONST_M1: push(new Constant(-1)); return null; + case ICONST_0: case LCONST_0: case FCONST_0: case DCONST_0: push(new Constant(0)); return null; + case ICONST_1: case LCONST_1: case FCONST_1: case DCONST_1: push(new Constant(1)); return null; + case ICONST_2: case FCONST_2: push(new Constant(2)); return null; + case ICONST_3: push(new Constant(3)); return null; + case ICONST_4: push(new Constant(4)); return null; + case ICONST_5: push(new Constant(5)); return null; + case ILOAD: case LLOAD: case FLOAD: case DLOAD: case ALOAD: push(locals[pc][i1]); return null; + case ILOAD_0: case LLOAD_0: case FLOAD_0: case DLOAD_0: case ALOAD_0: push(locals[pc][0]); return null; + case ILOAD_1: case LLOAD_1: case FLOAD_1: case DLOAD_1: case ALOAD_1: push(locals[pc][1]); return null; + case ALOAD_2: case DLOAD_2: case FLOAD_2: case LLOAD_2: case ILOAD_2: push(locals[pc][2]); return null; + case ILOAD_3: case LLOAD_3: case FLOAD_3: case DLOAD_3: case ALOAD_3: push(locals[pc][3]); return null; + case ISTORE: case LSTORE: case FSTORE: case DSTORE: case ASTORE: + locals[pc+1][i1].merge(pop()); return null; + case ISTORE_0: case LSTORE_0: case FSTORE_0: case DSTORE_0: case ASTORE_0: + locals[pc+1][0].merge(pop()); return null; + case ISTORE_1: case LSTORE_1: case FSTORE_1: case DSTORE_1: case ASTORE_1: + locals[pc+1][1].merge(pop()); return null; + case ASTORE_2: case DSTORE_2: case FSTORE_2: case LSTORE_2: case ISTORE_2: + locals[pc+1][2].merge(pop()); return null; + case ISTORE_3: case LSTORE_3: case FSTORE_3: case DSTORE_3: case ASTORE_3: + locals[pc+1][3].merge(pop()); return null; + 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-1]); return null; // Conversions ////////////////////////////////////////////////////////////////////////////// @@ -503,52 +630,54 @@ public class JSSA extends MethodGen implements CGConst { // Math ////////////////////////////////////////////////////////////////////////////// - case IADD: case LADD: case FADD: case DADD: push(new Add(pop(), pop())); return null; - case ISUB: case LSUB: case FSUB: case DSUB: push(new Sub(pop(), pop())); return null; - case IMUL: case LMUL: case FMUL: case DMUL: push(new Mul(pop(), pop())); return null; - case IREM: case LREM: case FREM: case DREM: push(new Rem(pop(), pop())); return null; - //case INEG: case LNEG: case FNEG: case DNEG: push(new Neg(pop())); return null; - case IDIV: case LDIV: case FDIV: case DDIV: push(new Div(pop(), pop())); return null; - case ISHL: case LSHL: push(new Shl(pop(), pop())); return null; - case ISHR: case LSHR: push(new Shr(pop(), pop())); return null; + case IADD: case LADD: case FADD: case DADD: push(new Add(pop(), pop())); return null; + case ISUB: case LSUB: case FSUB: case DSUB: push(new Sub(pop(), pop())); return null; + case IMUL: case LMUL: case FMUL: case DMUL: push(new Mul(pop(), pop())); return null; + case IREM: case LREM: case FREM: case DREM: push(new Rem(pop(), pop())); return null; + case INEG: case LNEG: case FNEG: case DNEG: push(new Neg(pop())); return null; + case IDIV: case LDIV: case FDIV: case DDIV: push(new Div(pop(), pop())); return null; + case ISHL: case LSHL: push(new Shl(pop(), pop())); return null; + case ISHR: case LSHR: push(new Shr(pop(), pop())); return null; case IUSHR: case LUSHR: push(new Ushr(pop(), pop())); return null; - case IAND: case LAND: push(new And(pop(), pop())); return null; - case IOR: case LOR: push(new Or(pop(), pop())); return null; - case IXOR: case LXOR: push(new Xor(pop(), pop())); return null; - case IINC: return local[i1] = new Add(local[i1], new Constant(i2)); + case IAND: case LAND: push(new And(pop(), pop())); return null; + case IOR: case LOR: push(new Or(pop(), pop())); return null; + case IXOR: case LXOR: push(new Xor(pop(), pop())); return null; + case IINC: return locals[pc+1][i1] = phi(new Add(locals[pc][i1], new Constant(i2))); // Control and branching ////////////////////////////////////////////////////////////////////////////// - case IFNULL: return new Branch(new Eq(pop(), new Constant(null)), new Label(i1)); - case IFNONNULL: return new Branch(new Not(new Eq(pop(),new Constant(null))),new Label(i1)); - case IFEQ: return new Branch( new Eq(new Constant(0), pop()), arg); - case IFNE: return new Branch(new Not(new Eq(new Constant(0), pop())), arg); - case IFLT: return new Branch( new Lt(new Constant(0), pop()), arg); - case IFGE: return new Branch(new Not(new Lt(new Constant(0), pop())), arg); - case IFGT: return new Branch( new Gt(new Constant(0), pop()), arg); - case IFLE: return new Branch(new Not(new Gt(new Constant(0), pop())), arg); - case IF_ICMPEQ: return new Branch( new Eq(pop(), pop()), arg); - case IF_ICMPNE: return new Branch(new Not(new Eq(pop(), pop())), arg); - case IF_ICMPLT: return new Branch( new Lt(pop(), pop()), arg); - case IF_ICMPGE: return new Branch(new Not(new Lt(pop(), pop())), arg); - case IF_ICMPGT: return new Branch( new Gt(pop(), pop()), arg); - case IF_ICMPLE: return new Branch(new Not(new Gt(pop(), pop())), arg); - case IF_ACMPEQ: return new Branch( new Eq(pop(), pop()), arg); - case IF_ACMPNE: return new Branch(new Not(new Eq(pop(), pop())), arg); - case ATHROW: return new Throw(pop()); - case GOTO: return new Branch(new Label(i1)); - case JSR: return new JSR(new Label(i1)); - case RET: return new RET(); - case RETURN: return new Return(); + case IFNULL: return new If(new Eq(pop(), new Constant(null)), new Label(i1)); + case IFNONNULL: return new If(new Not(new Eq(pop(),new Constant(null))),new Label(i1)); + case IFEQ: return new If( new Eq(new Constant(0), pop()), new Label(i1)); + case IFNE: return new If(new Not(new Eq(new Constant(0), pop())), new Label(i1)); + case IFLT: return new If( new Lt(new Constant(0), pop()), new Label(i1)); + case IFGE: return new If(new Not(new Lt(new Constant(0), pop())), new Label(i1)); + case IFGT: return new If( new Gt(new Constant(0), pop()), new Label(i1)); + case IFLE: return new If(new Not(new Gt(new Constant(0), pop())), new Label(i1)); + case IF_ICMPEQ: return new If( new Eq(pop(), pop()), new Label(i1)); + case IF_ICMPNE: return new If(new Not(new Eq(pop(), pop())), new Label(i1)); + case IF_ICMPLT: return new If( new Lt(pop(), pop()), new Label(i1)); + case IF_ICMPGE: return new If(new Not(new Lt(pop(), pop())), new Label(i1)); + case IF_ICMPGT: return new If( new Gt(pop(), pop()), new Label(i1)); + case IF_ICMPLE: return new If(new Not(new Gt(pop(), pop())), new Label(i1)); + case IF_ACMPEQ: return new If( new Eq(pop(), pop()), new Label(i1)); + case IF_ACMPNE: return new If(new Not(new Eq(pop(), pop())), new Label(i1)); + case ATHROW: return new Throw(pop()); + case GOTO: return new Goto(locals[pc][i1]); + case JSR: push(new Label(pc)); return new JSR(new Label(i1)); + case RET: return new RET(pop()); + case RETURN: return new Return(); case IRETURN: case LRETURN: case FRETURN: case DRETURN: case ARETURN: return new Return(pop()); // 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 ////////////////////////////////////////////////////////////////////////////// @@ -564,60 +693,44 @@ public class JSSA extends MethodGen implements CGConst { case INVOKESTATIC: ret = new InvokeStatic(method, args); break; default: throw new Error("should never happen"); } - if(ret.getType() != Type.VOID) push(ret); - return ret; + 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 NEW: push(new New((Type.Class)arg)); return null; - case NEWARRAY: { - Type base; - switch(((Integer)arg).intValue()) { - case 4: base = Type.BOOLEAN; break; - case 5: base = Type.CHAR; break; - case 6: base = Type.FLOAT; break; - case 7: base = Type.DOUBLE; break; - case 8: base = Type.BYTE; break; - case 9: base = Type.SHORT; break; - case 10: base = Type.INT; break; - case 11: base = Type.LONG; break; - default: throw new IllegalStateException("invalid array type"); - } - push(new NewArray(base.makeArray(),pop())); - return null; - } + case NEWARRAY: return seqPush(new NewArray(Type.fromArraySpec(((Integer)arg).intValue()).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