From: adam Date: Mon, 4 Jul 2005 22:24:54 +0000 (+0000) Subject: initial support for branching: phi() function, track stack/locals for every pc-position X-Git-Url: http://git.megacz.com/?p=org.ibex.classgen.git;a=commitdiff_plain;h=4b586655926ec3807715ede09e642f050c336f79 initial support for branching: phi() function, track stack/locals for every pc-position added in preliminary support for branching. It consisted of: - we have to track the state of the stack and localvars separately for each instruction-position - I introduced a phi() function that "merges" two expressions - whenever you branch _to_ an instruction, you have to "map" the merge() function over the target stack, passing the source stack as an argument (and likewise for locals). Note that Phis are mutable (see the javadoc comment at the head of "class Phi"), and you can't "collapse" nested Phi's, even though it's tempting. darcs-hash:20050704222454-5007d-64bd5ec518540efe8c9cc47421ae002777bcc687.gz --- diff --git a/src/org/ibex/classgen/JSSA.java b/src/org/ibex/classgen/JSSA.java index 6cf8d07..16af019 100644 --- a/src/org/ibex/classgen/JSSA.java +++ b/src/org/ibex/classgen/JSSA.java @@ -13,24 +13,34 @@ 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]; + locals = new Phi[size()][maxLocals]; + stacks = new Phi[size()][maxStack]; + sps = new int [size()]; + sps[0] = 0; int n=0; + locals[0] = new Phi[maxLocals]; if (!isStatic()) - local[n++] = new Argument("this",method.getDeclaringClass()); + locals[0][n++] = phi(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 ////////////////////////////////////////////////////////////////////////////// @@ -434,7 +499,7 @@ 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 == null ? "null" : 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; @@ -483,20 +548,25 @@ public class JSSA extends MethodGen implements CGConst { 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(local[i1]); return null; - case ILOAD_0: case LLOAD_0: case FLOAD_0: case DLOAD_0: case ALOAD_0: push(local[0]); return null; - case ILOAD_1: case LLOAD_1: case FLOAD_1: case DLOAD_1: case ALOAD_1: push(local[1]); return null; - case ALOAD_2: case DLOAD_2: case FLOAD_2: case LLOAD_2: case ILOAD_2: push(local[2]); return null; - case ILOAD_3: case LLOAD_3: case FLOAD_3: case DLOAD_3: case ALOAD_3: push(local[3]); return null; - 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 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-2]); return null; + case DUP: push(stacks[pc][sps[pc]-1]); return null; + case DUP2: push(stacks[pc][sps[pc]-2]); push(stacks[pc][sps[pc]-1]); return null; // Conversions ////////////////////////////////////////////////////////////////////////////// @@ -526,7 +596,7 @@ public class JSSA extends MethodGen implements CGConst { 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 IINC: return locals[pc+1][i1] = phi(new Add(locals[pc][i1], new Constant(i2))); // Control and branching ////////////////////////////////////////////////////////////////////////////// @@ -671,20 +741,6 @@ public class JSSA extends MethodGen implements CGConst { private Map bindingMap; private int nextVar; - String exprToString(Expr e) { - if (e instanceof Constant) return e._toString(); - String s = (String)bindingMap.get(e); - if (s != null) return s; - String prefix; - if (e.getType() == Type.VOID) return e._toString(); - else if (e.getType() == Type.DOUBLE || e.getType() == Type.FLOAT) prefix = "f"; - else if (e.getType().isPrimitive()) prefix = "i"; - else if (e.getType().isArray()) prefix = "a"; - else prefix = "o"; - s = prefix + (nextVar++); - bindingMap.put(e,s); - return "(" + s + " = " + e._toString() + ")"; - } public static void main(String[] args) throws Exception { InputStream is = Class.forName(args[0]).getClassLoader().getResourceAsStream(args[0].replace('.', '/')+".class");