JSSA.Seq to for evaluation of an expr
[org.ibex.classgen.git] / src / org / ibex / classgen / JSSA.java
index d01aa06..d43008b 100644 (file)
@@ -94,6 +94,11 @@ public class JSSA extends MethodGen implements CGConst {
         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 /////////////////////////////////////////////////////////////////////////////////////////
@@ -114,7 +119,16 @@ public class JSSA extends MethodGen implements CGConst {
             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
@@ -308,6 +322,7 @@ public class JSSA extends MethodGen implements CGConst {
         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 {
@@ -403,20 +418,17 @@ public class JSSA extends MethodGen implements CGConst {
     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();
         }
@@ -426,7 +438,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.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;
@@ -436,6 +448,7 @@ public class JSSA extends MethodGen implements CGConst {
             if (o instanceof Double) return Type.DOUBLE;
             if (o instanceof Float) return Type.FLOAT;
             if (o instanceof Integer) return Type.INT;
+            if (o instanceof String) return Type.STRING;
             throw new IllegalStateException("unknown constant type");
         }
     }
@@ -483,10 +496,10 @@ public class JSSA extends MethodGen implements CGConst {
             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 //////////////////////////////////////////////////////////////////////////////
 
@@ -547,9 +560,11 @@ public class JSSA extends MethodGen implements CGConst {
                 // 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 //////////////////////////////////////////////////////////////////////////////
 
@@ -566,14 +581,14 @@ public class JSSA extends MethodGen implements CGConst {
                     default: throw new Error("should never happen");
                 }
                 if(ret.getType() != Type.VOID) push(ret);
-                return 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 //////////////////////////////////////////////////////////////////////////////
@@ -592,22 +607,20 @@ public class JSSA extends MethodGen implements CGConst {
                     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;