Bug fixes to make Cristian happy...
[repair.git] / Repair / RepairCompiler / MCC / IR / OpExpr.java
1 package MCC.IR;
2
3 import java.util.*;
4
5 public class OpExpr extends Expr {
6
7     Expr left;
8     Expr right;
9     Opcode opcode;
10
11     public void findmatch(Descriptor d, Set  s) {
12         left.findmatch(d,s);
13         if (right!=null)
14             right.findmatch(d,s);
15     }
16
17     public static boolean isInt(Expr e) {
18         if ((e instanceof IntegerLiteralExpr)||
19             ((e instanceof OpExpr)&&(((OpExpr)e).opcode==Opcode.NOP)&&(((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr)))
20             return true;
21         return false;
22     }
23
24     public static int getInt(Expr e) {
25         if (e instanceof IntegerLiteralExpr)
26             return ((IntegerLiteralExpr)e).getValue();
27         else if ((e instanceof OpExpr) && (((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr))
28             return ((IntegerLiteralExpr)((OpExpr)e).getLeftExpr()).getValue();
29         else throw new Error();
30     }
31
32     public OpExpr(Opcode opcode, Expr left, Expr right) {
33         if ((isInt(left)&&isInt(right))||
34             (isInt(left)&&(opcode==Opcode.NOT))||
35             (isInt(left)&&(opcode==Opcode.RND))) {
36             this.opcode=Opcode.NOP;
37             this.right=null;
38             int lint=getInt(left);
39             int rint=getInt(right);
40             int value=0;
41             if (opcode==Opcode.ADD) {
42                 value=lint+rint;
43             } else if (opcode==Opcode.SUB) {
44                 value=lint-rint;
45             } else if (opcode==Opcode.SHL) {
46                 value=lint<<rint;
47             } else if (opcode==Opcode.SHR) {
48                 value=lint>>rint;
49             } else if (opcode==Opcode.MULT) {
50                 value=lint*rint;
51             } else if (opcode==Opcode.DIV) {
52                 value=lint/rint;
53             } else if (opcode==Opcode.GT) {
54                 if (lint>rint)
55                     value=1;
56             } else if (opcode==Opcode.GE) {
57                 if (lint>=rint)
58                     value=1;
59             } else if (opcode==Opcode.LT) {
60                 if (lint<rint)
61                     value=1;
62             } else if (opcode==Opcode.LE) {
63                 if (lint<=rint)
64                     value=1;
65             } else if (opcode==Opcode.EQ) {
66                 if (lint==rint)
67                     value=1;
68             } else if (opcode==Opcode.NE) {
69                 if (lint!=rint)
70                     value=1;
71             } else if (opcode==Opcode.AND) {
72                 if ((lint!=0)&&(rint!=0))
73                     value=1;
74             } else if (opcode==Opcode.OR) {
75                 if ((lint!=0)||(rint!=0))
76                     value=1;
77             } else if (opcode==Opcode.NOT) {
78                 if (lint==0)
79                     value=1;
80             } else if (opcode==Opcode.RND) {
81                 value=((lint>>3)<<3);
82                 if ((lint % 8)!=0)
83                     value+=8;
84             } else throw new Error("Unrecognized Opcode");
85             this.left=new IntegerLiteralExpr(value);
86         } else if ((opcode==Opcode.MULT)&&
87                    ((isInt(left)&&(getInt(left)==0))
88                     ||(isInt(right)&&(getInt(right)==0)))) {
89             this.opcode=Opcode.NOP;
90             this.right=null;
91             this.left=new IntegerLiteralExpr(0);
92         } else {
93             this.opcode = opcode;
94             this.left = left;
95             this.right = right;
96             assert (right == null && (opcode == Opcode.NOT||opcode==Opcode.RND)) || (right != null);
97         }
98     }
99
100     public Expr getRightExpr() {
101         return right;
102     }
103
104     public Expr getLeftExpr() {
105         return left;
106     }
107
108     public Set freeVars() {
109         Set lset=left.freeVars();
110         Set rset=null;
111         if (right!=null)
112             rset=right.freeVars();
113         if (lset==null)
114             return rset;
115         if (rset!=null)
116             lset.addAll(rset);
117         return lset;
118     }
119
120     public String name() {
121         if (opcode==Opcode.NOT)
122             return "!("+left.name()+")";
123         if (opcode==Opcode.NOP)
124             return left.name();
125         if (opcode==Opcode.RND)
126             return "Round("+left.name()+")";
127         String name=left.name()+opcode.toString();
128         if (right!=null)
129             name+=right.name();
130         return name;
131     }
132
133     public Opcode getOpcode() {
134         return opcode;
135     }
136
137
138
139
140     public boolean equals(Map remap, Expr e) {
141         if (e==null||!(e instanceof OpExpr))
142             return false;
143         OpExpr oe=(OpExpr)e;
144         if (opcode!=oe.opcode)
145             return false;
146         if (!left.equals(remap,oe.left))
147             return false;
148         if ((opcode!=Opcode.NOT)&&(opcode!=Opcode.RND)&&(opcode!=Opcode.NOP))
149             if (!right.equals(remap,oe.right))
150                 return false;
151         return true;
152     }
153
154     public DNFRule constructDNF() {
155         if (opcode==Opcode.AND) {
156             DNFRule leftd=left.constructDNF();
157             DNFRule rightd=right.constructDNF();
158             return leftd.and(rightd);
159         } else if (opcode==Opcode.OR) {
160             DNFRule leftd=left.constructDNF();
161             DNFRule rightd=right.constructDNF();
162             return leftd.or(rightd);
163         } else if (opcode==Opcode.NOT) {
164             DNFRule leftd=left.constructDNF();
165             return leftd.not();
166         } else return new DNFRule(this);
167     }
168
169     public boolean usesDescriptor(Descriptor d) {
170         if (opcode==Opcode.GT||opcode==Opcode.GE||opcode==Opcode.LT||
171             opcode==Opcode.LE||opcode==Opcode.EQ||opcode==Opcode.NE)
172             return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
173             //      return right.usesDescriptor(d);
174         else
175             return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
176     }
177     
178
179     public int[] getRepairs(boolean negated) {
180         if (left instanceof RelationExpr)
181             return new int[] {AbstractRepair.MODIFYRELATION};
182         if (left instanceof SizeofExpr) {
183             Opcode op=opcode;
184             if (negated) {
185                 /* remove negation through opcode translation */
186                 if (op==Opcode.GT)
187                     op=Opcode.LE;
188                 else if (op==Opcode.GE)
189                     op=Opcode.LT;
190                 else if (op==Opcode.EQ)
191                     op=Opcode.NE;
192                 else if (op==Opcode.NE)
193                     op=Opcode.EQ;
194                 else if (op==Opcode.LT)
195                     op=Opcode.GE;
196                 else if (op==Opcode.LE)
197                     op=Opcode.GT;
198             }
199
200
201
202             boolean isRelation=((SizeofExpr)left).setexpr instanceof ImageSetExpr;
203             if (isRelation) {
204                 if (op==Opcode.EQ) {
205                     if (((IntegerLiteralExpr)right).getValue()==0)
206                         return new int[] {AbstractRepair.REMOVEFROMRELATION};
207                     else
208                         return new int[] {AbstractRepair.ADDTORELATION,
209                                           AbstractRepair.REMOVEFROMRELATION};
210                 } else if (op==Opcode.GE||op==Opcode.GT) {
211                     return new int[]{AbstractRepair.ADDTORELATION}; 
212                 } else if (op==Opcode.LE||op==Opcode.LT) {
213                     return new int[]{AbstractRepair.REMOVEFROMRELATION};
214                 } else if (op==Opcode.NE) {
215                     return new int[]{AbstractRepair.ADDTORELATION};
216                 } else throw new Error();
217             } else {
218                 if (op==Opcode.EQ) {
219                     if (((IntegerLiteralExpr)right).getValue()==0)
220                         return new int[] {AbstractRepair.REMOVEFROMSET};                        
221                     else
222                         return new int[] {AbstractRepair.ADDTOSET,
223                                               AbstractRepair.REMOVEFROMSET};
224                 } else if (op==Opcode.GE||op==Opcode.GT) {
225                     return new int[] {AbstractRepair.ADDTOSET}; 
226                 } else if (op==Opcode.LE||op==Opcode.LT) {
227                     return new int[] {AbstractRepair.REMOVEFROMSET};
228                 } else if (op==Opcode.NE) {
229                     return new int[] {AbstractRepair.ADDTOSET};
230                 } else throw new Error();
231             }
232         }
233         throw new Error("BAD");
234     }
235     
236     public Descriptor getDescriptor() {
237         return left.getDescriptor();
238     }
239
240     public boolean inverted() {
241         return left.inverted();
242     }
243
244     public Set getInversedRelations() {
245         Set set = left.getInversedRelations();
246         if (right != null) {
247             set.addAll(right.getInversedRelations());
248         }
249         return set;
250     }
251
252     public Set getRequiredDescriptors() {
253         Set v = left.getRequiredDescriptors();
254      
255         if (right != null) {
256             v.addAll(right.getRequiredDescriptors());
257         }
258
259         return v;
260     }   
261
262     public void generate(CodeWriter writer, VarDescriptor dest) {
263         VarDescriptor ld = VarDescriptor.makeNew("leftop");
264         left.generate(writer, ld);        
265         VarDescriptor rd = null;
266         VarDescriptor lm=VarDescriptor.makeNew("lm");
267         VarDescriptor rm=VarDescriptor.makeNew("rm");
268
269         if (right != null) {
270             if ((opcode==Opcode.OR)||
271                 (opcode==Opcode.AND)) {
272                 writer.outputline("int "+lm.getSafeSymbol()+"=maybe;");
273                 writer.outputline("int maybe=0;");
274             }
275
276             rd = VarDescriptor.makeNew("rightop");
277             right.generate(writer, rd);
278         }
279
280         String code;
281         if (opcode == Opcode.RND) {
282             writer.outputline("int " +dest.getSafeSymbol() + " = (" +
283                               ld.getSafeSymbol() + ">>3)<<3; ");
284             writer.outputline("if ("+ld.getSafeSymbol()+" % 8) "+dest.getSafeSymbol()+"+=8;");
285         } else if (opcode == Opcode.NOP) {
286             writer.outputline("int " +dest.getSafeSymbol() + " = " +
287                               ld.getSafeSymbol() +"; ");
288         } else if (opcode == Opcode.AND) {
289             writer.outputline("int "+rm.getSafeSymbol()+"=maybe;");
290             writer.outputline("maybe = (" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (" + rd.getSafeSymbol() + " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
291             writer.outputline(dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " && " + rd.getSafeSymbol() + ";");
292         } else if (opcode == Opcode.OR) {
293             writer.outputline("int "+rm.getSafeSymbol()+"=maybe;");
294             writer.outputline("maybe = (!" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (!" + rd.getSafeSymbol() +
295                               " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
296             writer.outputline(dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " || " + rd.getSafeSymbol() +
297                               ";");
298         } else if (opcode != Opcode.NOT) { /* two operands */
299             assert rd != null;
300             writer.outputline("int " + dest.getSafeSymbol() + " = " + 
301                               ld.getSafeSymbol() + " " + opcode.toString() + " " + rd.getSafeSymbol() + ";");
302         } else if (opcode == Opcode.NOT) {
303             writer.outputline("int " + dest.getSafeSymbol() + " = !" + ld.getSafeSymbol() + ";");
304         }
305     }
306
307     public void prettyPrint(PrettyPrinter pp) {
308         pp.output("(");
309         if (opcode == Opcode.NOT) {
310             pp.output("!");
311             left.prettyPrint(pp);
312         } else if (opcode == Opcode.NOP) {
313             left.prettyPrint(pp);
314         } else if (opcode == Opcode.RND) {
315             pp.output("RND ");
316             left.prettyPrint(pp);
317         } else {           
318             left.prettyPrint(pp);
319             pp.output(" " + opcode.toString() + " ");
320             assert right != null;
321             right.prettyPrint(pp);
322         }
323         pp.output(")");
324     }
325
326     public TypeDescriptor typecheck(SemanticAnalyzer sa) {
327         TypeDescriptor lt = left.typecheck(sa);
328         TypeDescriptor rt = right == null ? null : right.typecheck(sa);
329
330         if (lt == null) {
331             return null;
332         } else if (right != null && rt == null) {
333             return null;
334         }
335
336         boolean ok = true;
337
338         // #ATTN#: if we want node.next != literal(0) to represent a null check than we need to allow ptr arithmetic
339         // either that or we use a isvalid clause to check for null
340
341         /*
342         if (lt != ReservedTypeDescriptor.INT) {
343             sa.getErrorReporter().report(null, "Left hand side of expression is of type '" + lt.getSymbol() + "' but must be type 'int'");
344             ok = false;
345         }
346
347         if (right != null) {
348             if (rt != ReservedTypeDescriptor.INT) {
349                 sa.getErrorReporter().report(null, "Right hand side of expression is of type '" + rt.getSymbol() + "' but must be type 'int'");
350                 ok = false;
351             }
352         }
353         */
354
355         if (!ok) {
356             return null;
357         }
358
359         this.td = ReservedTypeDescriptor.INT;
360         return this.td;
361     }
362
363 }