stack overflow checking
[org.ibex.classgen.git] / src / org / ibex / classgen / JSSA.java
index b8e57ca..c16f5e6 100644 (file)
@@ -73,12 +73,22 @@ public class JSSA extends MethodGen implements CGConst {
     /** 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-1) throw new IllegalStateException("stack overflow");
+        return stack[sp++] = e;
+    }
+    private Expr pop() {
+        if(sp == 0) throw new IllegalStateException("stack underflow");
+        return stack[--sp];
+    }
 
 
     // SSA-node classes /////////////////////////////////////////////////////////////////////////////////////////
 
+    public final Expr VOID_EXPR = new Expr() {
+        public Type getType() { return Type.VOID; }
+    };
+    
     /** an purely imperative operation which does not generate data */
     public abstract class Op {
         //public abstract Op[] predecessors();  // not implemented yet
@@ -187,20 +197,33 @@ public class JSSA extends MethodGen implements CGConst {
     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 {
@@ -240,9 +263,9 @@ public class JSSA extends MethodGen implements CGConst {
 
     public class Return extends Op {
         final Expr e;
-        public Return() { this(null); }
+        public Return() { this(VOID_EXPR); }
         public Return(Expr e) { this.e = e; }
-        public String toString() { return e==null?"return":("return "+e.toString()); }
+        public String toString() { return e.getType() == Type.VOID ? "return" : ("return "+e.toString()); }
     }
 
     /** GETFIELD and GETSTATIC */
@@ -523,8 +546,8 @@ public class JSSA extends MethodGen implements CGConst {
 
                 // 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;