Some embarrassing erros. The DNF conversion for negation wasn't
[repair.git] / Repair / RepairCompiler / MCC / IR / OpExpr.java
index 83d72576c8f50fe7aa2239b59b7a8b2ec67b7f7c..e9cde37d174b730ca782e0f1a07cc603ac505afc 100755 (executable)
@@ -8,15 +8,81 @@ public class OpExpr extends Expr {
     Expr right;
     Opcode opcode;
 
-    public void findmatch(Descriptor d, Set  s) {
-       left.findmatch(d,s);
-       if (right!=null)
-           right.findmatch(d,s);
+    public Expr getUpper() {
+       Expr lupper=left.getUpper();
+       if (lupper==null)
+           return null;
+       if (right!=null) {
+           Expr rupper=right.getUpper();
+           if (rupper==null)
+               return null;
+           OpExpr oe=new OpExpr(this.opcode,lupper,rupper);
+           oe.td = ReservedTypeDescriptor.INT;
+           return oe;
+       } else return lupper;
+    }
+
+    public Expr getLower() {
+       Expr llower=left.getLower();
+       if (llower==null)
+           return null;
+       if (right!=null) {
+           Expr rlower=right.getLower();
+           if (rlower==null)
+               return null;
+           OpExpr oe=new OpExpr(this.opcode,llower,rlower);
+           oe.td = ReservedTypeDescriptor.INT;
+           return oe;
+       } else return llower;
+    }
+
+
+    public boolean isSafe() {
+       if (right==null)
+           return left.isSafe();
+       return left.isSafe()&&right.isSafe();
+    }
+
+    public boolean isInvariant(Set vars) {
+       return left.isInvariant(vars)&&((right==null)||right.isInvariant(vars));
+    }
+
+    public Set findInvariants(Set vars) {
+       if (isInt(this)) {
+           /* Don't hoist ints */
+           return new HashSet();
+       } else if (isInvariant(vars)) {
+           Set s=new HashSet();
+           s.add(this);
+           return s;
+       } else {
+           Set ls=left.findInvariants(vars);
+           if (right!=null)
+               ls.addAll(right.findInvariants(vars));
+           return ls;
+       }
+    }
+
+    public Set getfunctions() {
+       Set leftfunctions=left.getfunctions();
+       Set rightfunctions=null;
+       if (right!=null) rightfunctions=right.getfunctions();
+       if (leftfunctions!=null&&rightfunctions!=null) {
+           HashSet functions=new HashSet();
+           functions.addAll(leftfunctions);
+           functions.addAll(rightfunctions);
+           return functions;
+       }
+       if (leftfunctions!=null)
+           return leftfunctions;
+       return rightfunctions;
     }
 
     public static boolean isInt(Expr e) {
+       if (e==null)
+           return false;
        if ((e instanceof IntegerLiteralExpr)||
-           ((e instanceof OpExpr)&&(((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr)))
+           ((e instanceof OpExpr)&&(((OpExpr)e).opcode==Opcode.NOP)&&(((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr)))
            return true;
        return false;
     }
@@ -35,8 +101,8 @@ public class OpExpr extends Expr {
            (isInt(left)&&(opcode==Opcode.RND))) {
            this.opcode=Opcode.NOP;
            this.right=null;
-           int lint=getInt(left);
-           int rint=getInt(right);
+           int lint=isInt(left)?getInt(left):0;
+           int rint=isInt(right)?getInt(right):0;
            int value=0;
            if (opcode==Opcode.ADD) {
                value=lint+rint;
@@ -83,7 +149,13 @@ public class OpExpr extends Expr {
                    value+=8;
            } else throw new Error("Unrecognized Opcode");
            this.left=new IntegerLiteralExpr(value);
-           } else {
+       } else if ((opcode==Opcode.MULT)&&
+                  ((isInt(left)&&(getInt(left)==0))
+                   ||(isInt(right)&&(getInt(right)==0)))) {
+           this.opcode=Opcode.NOP;
+           this.right=null;
+           this.left=new IntegerLiteralExpr(0);
+       } else {
            this.opcode = opcode;
            this.left = left;
            this.right = right;
@@ -119,8 +191,10 @@ public class OpExpr extends Expr {
        if (opcode==Opcode.RND)
            return "Round("+left.name()+")";
        String name=left.name()+opcode.toString();
-       if (right!=null)
+       if (right!=null) {
            name+=right.name();
+            name="("+name+")";
+        }
        return name;
     }
 
@@ -128,9 +202,6 @@ public class OpExpr extends Expr {
        return opcode;
     }
 
-
-
-
     public boolean equals(Map remap, Expr e) {
        if (e==null||!(e instanceof OpExpr))
            return false;
@@ -161,16 +232,24 @@ public class OpExpr extends Expr {
     }
 
     public boolean usesDescriptor(Descriptor d) {
-       if (opcode==Opcode.GT||opcode==Opcode.GE||opcode==Opcode.LT||
-           opcode==Opcode.LE||opcode==Opcode.EQ||opcode==Opcode.NE)
-           return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
-           //      return right.usesDescriptor(d);
-       else
-           return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
+       return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
+    }
+
+    public void findmatch(Descriptor d, Set  s) {
+       left.findmatch(d,s);
+       if (right!=null)
+           right.findmatch(d,s);
     }
-    
 
-    public int[] getRepairs(boolean negated) {
+    public Set useDescriptor(Descriptor d) {
+       HashSet newset=new HashSet();
+       newset.addAll(left.useDescriptor(d));
+       if (right!=null)
+           newset.addAll(right.useDescriptor(d));
+       return newset;
+    }
+
+    public int[] getRepairs(boolean negated, Termination t) {
        if (left instanceof RelationExpr)
            return new int[] {AbstractRepair.MODIFYRELATION};
        if (left instanceof SizeofExpr) {
@@ -191,42 +270,58 @@ public class OpExpr extends Expr {
                    op=Opcode.GT;
            }
 
+           int maxsize=t.maxsize.getsize(getDescriptor());
+           int size=getInt(right);
 
 
            boolean isRelation=((SizeofExpr)left).setexpr instanceof ImageSetExpr;
            if (isRelation) {
                if (op==Opcode.EQ) {
-                   if (((IntegerLiteralExpr)right).getValue()==0)
+                   if (size==0)
                        return new int[] {AbstractRepair.REMOVEFROMRELATION};
-                   else
+                   else {
+                       if ((maxsize!=-1)&&maxsize<=size)
+                           return new int[] {AbstractRepair.ADDTORELATION};
                        return new int[] {AbstractRepair.ADDTORELATION,
                                          AbstractRepair.REMOVEFROMRELATION};
+                   }
                } else if (op==Opcode.GE||op==Opcode.GT) {
-                   return new int[]{AbstractRepair.ADDTORELATION}; 
+                   return new int[]{AbstractRepair.ADDTORELATION};
                } else if (op==Opcode.LE||op==Opcode.LT) {
+                   if ((op==Opcode.LT&&maxsize!=-1&&maxsize<size)||(op==Opcode.LE&&maxsize!=-1&&maxsize<=size))
+                       return new int[0];
                    return new int[]{AbstractRepair.REMOVEFROMRELATION};
                } else if (op==Opcode.NE) {
+                   if (maxsize<size&&maxsize!=-1)
+                       return new int[0];
                    return new int[]{AbstractRepair.ADDTORELATION};
                } else throw new Error();
            } else {
                if (op==Opcode.EQ) {
-                   if (((IntegerLiteralExpr)right).getValue()==0)
-                       return new int[] {AbstractRepair.REMOVEFROMSET};                        
-                   else
+                   if (size==0)
+                       return new int[] {AbstractRepair.REMOVEFROMSET};
+                   else {
+                       if (maxsize<=size&&maxsize!=-1)
+                           return new int[] {AbstractRepair.ADDTOSET};
                        return new int[] {AbstractRepair.ADDTOSET,
                                              AbstractRepair.REMOVEFROMSET};
+                   }
                } else if (op==Opcode.GE||op==Opcode.GT) {
-                   return new int[] {AbstractRepair.ADDTOSET}; 
+                   return new int[] {AbstractRepair.ADDTOSET};
                } else if (op==Opcode.LE||op==Opcode.LT) {
+                   if ((op==Opcode.LT&&maxsize<size&&maxsize!=-1)||(op==Opcode.LE&&maxsize<=size&&maxsize!=-1))
+                       return new int[0];
                    return new int[] {AbstractRepair.REMOVEFROMSET};
                } else if (op==Opcode.NE) {
+                   if (maxsize<size&&maxsize!=-1)
+                       return new int[0];
                    return new int[] {AbstractRepair.ADDTOSET};
                } else throw new Error();
            }
        }
        throw new Error("BAD");
     }
-    
+
     public Descriptor getDescriptor() {
        return left.getDescriptor();
     }
@@ -245,17 +340,26 @@ public class OpExpr extends Expr {
 
     public Set getRequiredDescriptors() {
         Set v = left.getRequiredDescriptors();
-     
+
         if (right != null) {
             v.addAll(right.getRequiredDescriptors());
         }
 
         return v;
-    }   
+    }
 
     public void generate(CodeWriter writer, VarDescriptor dest) {
         VarDescriptor ld = VarDescriptor.makeNew("leftop");
-        left.generate(writer, ld);        
+       /* Check for loop invariant hoisting. */
+       if (writer.getInvariantValue()!=null&&
+           writer.getInvariantValue().isInvariant(this)) {
+           writer.addDeclaration("int",dest.getSafeSymbol());
+           writer.outputline(dest.getSafeSymbol()+"="+writer.getInvariantValue().getValue(this).getSafeSymbol()+";");
+           writer.outputline("maybe="+writer.getInvariantValue().getMaybe(this).getSafeSymbol()+";");
+           return;
+       }
+
+       left.generate(writer, ld);
         VarDescriptor rd = null;
        VarDescriptor lm=VarDescriptor.makeNew("lm");
        VarDescriptor rm=VarDescriptor.makeNew("rm");
@@ -263,8 +367,9 @@ public class OpExpr extends Expr {
         if (right != null) {
            if ((opcode==Opcode.OR)||
                (opcode==Opcode.AND)) {
-               writer.outputline("int "+lm.getSafeSymbol()+"=maybe;");
-               writer.outputline("int maybe=0;");
+               writer.addDeclaration("int",lm.getSafeSymbol());
+               writer.outputline(lm.getSafeSymbol()+"=maybe;");
+               writer.outputline("maybe=0;");
            }
 
             rd = VarDescriptor.makeNew("rightop");
@@ -273,42 +378,50 @@ public class OpExpr extends Expr {
 
         String code;
        if (opcode == Opcode.RND) {
-           writer.outputline("int " +dest.getSafeSymbol() + " = (" +
+           writer.addDeclaration("int",dest.getSafeSymbol());
+           writer.outputline(dest.getSafeSymbol() + " = (" +
                              ld.getSafeSymbol() + ">>3)<<3; ");
            writer.outputline("if ("+ld.getSafeSymbol()+" % 8) "+dest.getSafeSymbol()+"+=8;");
        } else if (opcode == Opcode.NOP) {
-           writer.outputline("int " +dest.getSafeSymbol() + " = " +
+           writer.addDeclaration("int", dest.getSafeSymbol());
+           writer.outputline(dest.getSafeSymbol() + " = " +
                              ld.getSafeSymbol() +"; ");
-       } else if (opcode != Opcode.NOT) { /* two operands */
-            assert rd != null;
-            writer.outputline("int " + dest.getSafeSymbol() + " = " + 
-                              ld.getSafeSymbol() + " " + opcode.toString() + " " + rd.getSafeSymbol() + ";");
         } else if (opcode == Opcode.AND) {
-           writer.outputline("int "+rm.getSafeSymbol()+"=maybe;");
+           writer.addDeclaration("int",rm.getSafeSymbol());
+           writer.outputline(rm.getSafeSymbol()+"=maybe;");
            writer.outputline("maybe = (" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (" + rd.getSafeSymbol() + " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
+           writer.addDeclaration("int",dest.getSafeSymbol());
            writer.outputline(dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " && " + rd.getSafeSymbol() + ";");
        } else if (opcode == Opcode.OR) {
-           writer.outputline("int "+rm.getSafeSymbol()+"=maybe;");
+           writer.addDeclaration("int",rm.getSafeSymbol());
+           writer.outputline(rm.getSafeSymbol()+"=maybe;");
            writer.outputline("maybe = (!" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (!" + rd.getSafeSymbol() +
                              " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
-           writer.outputline(dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " || " + rd.getSafeSymbol() +
-                             ";");
-       } else {
-            writer.outputline("int " + dest.getSafeSymbol() + " = !" + ld.getSafeSymbol() + ";");
+           writer.addDeclaration("int",dest.getSafeSymbol());
+           writer.outputline(dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " || " + rd.getSafeSymbol() + ";");
+       } else if (opcode != Opcode.NOT) { /* two operands */
+            assert rd != null;
+           writer.addDeclaration("int", dest.getSafeSymbol());
+           writer.outputline(dest.getSafeSymbol() + " = " +
+                             ld.getSafeSymbol() + " " + opcode.toString() + " " + rd.getSafeSymbol() + ";");
+        } else if (opcode == Opcode.NOT) {
+            writer.addDeclaration("int", dest.getSafeSymbol());
+            writer.outputline(dest.getSafeSymbol() + " = !" + ld.getSafeSymbol() + ";");
         }
     }
 
     public void prettyPrint(PrettyPrinter pp) {
         pp.output("(");
         if (opcode == Opcode.NOT) {
-           pp.output("!");
+           pp.output("!(");
             left.prettyPrint(pp);
+           pp.output(")");
        } else if (opcode == Opcode.NOP) {
             left.prettyPrint(pp);
        } else if (opcode == Opcode.RND) {
            pp.output("RND ");
             left.prettyPrint(pp);
-        } else {           
+        } else {
             left.prettyPrint(pp);
             pp.output(" " + opcode.toString() + " ");
             assert right != null;
@@ -329,23 +442,6 @@ public class OpExpr extends Expr {
 
         boolean ok = true;
 
-        // #ATTN#: if we want node.next != literal(0) to represent a null check than we need to allow ptr arithmetic
-        // either that or we use a isvalid clause to check for null
-
-        /*
-        if (lt != ReservedTypeDescriptor.INT) {
-            sa.getErrorReporter().report(null, "Left hand side of expression is of type '" + lt.getSymbol() + "' but must be type 'int'");
-            ok = false;
-        }
-
-        if (right != null) {
-            if (rt != ReservedTypeDescriptor.INT) {
-                sa.getErrorReporter().report(null, "Right hand side of expression is of type '" + rt.getSymbol() + "' but must be type 'int'");
-                ok = false;
-            }
-        }
-        */
-
         if (!ok) {
             return null;
         }
@@ -355,8 +451,3 @@ public class OpExpr extends Expr {
     }
 
 }
-
-
-
-
-