83d72576c8f50fe7aa2239b59b7a8b2ec67b7f7c
[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).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 {
87             this.opcode = opcode;
88             this.left = left;
89             this.right = right;
90             assert (right == null && (opcode == Opcode.NOT||opcode==Opcode.RND)) || (right != null);
91         }
92     }
93
94     public Expr getRightExpr() {
95         return right;
96     }
97
98     public Expr getLeftExpr() {
99         return left;
100     }
101
102     public Set freeVars() {
103         Set lset=left.freeVars();
104         Set rset=null;
105         if (right!=null)
106             rset=right.freeVars();
107         if (lset==null)
108             return rset;
109         if (rset!=null)
110             lset.addAll(rset);
111         return lset;
112     }
113
114     public String name() {
115         if (opcode==Opcode.NOT)
116             return "!("+left.name()+")";
117         if (opcode==Opcode.NOP)
118             return left.name();
119         if (opcode==Opcode.RND)
120             return "Round("+left.name()+")";
121         String name=left.name()+opcode.toString();
122         if (right!=null)
123             name+=right.name();
124         return name;
125     }
126
127     public Opcode getOpcode() {
128         return opcode;
129     }
130
131
132
133
134     public boolean equals(Map remap, Expr e) {
135         if (e==null||!(e instanceof OpExpr))
136             return false;
137         OpExpr oe=(OpExpr)e;
138         if (opcode!=oe.opcode)
139             return false;
140         if (!left.equals(remap,oe.left))
141             return false;
142         if ((opcode!=Opcode.NOT)&&(opcode!=Opcode.RND)&&(opcode!=Opcode.NOP))
143             if (!right.equals(remap,oe.right))
144                 return false;
145         return true;
146     }
147
148     public DNFRule constructDNF() {
149         if (opcode==Opcode.AND) {
150             DNFRule leftd=left.constructDNF();
151             DNFRule rightd=right.constructDNF();
152             return leftd.and(rightd);
153         } else if (opcode==Opcode.OR) {
154             DNFRule leftd=left.constructDNF();
155             DNFRule rightd=right.constructDNF();
156             return leftd.or(rightd);
157         } else if (opcode==Opcode.NOT) {
158             DNFRule leftd=left.constructDNF();
159             return leftd.not();
160         } else return new DNFRule(this);
161     }
162
163     public boolean usesDescriptor(Descriptor d) {
164         if (opcode==Opcode.GT||opcode==Opcode.GE||opcode==Opcode.LT||
165             opcode==Opcode.LE||opcode==Opcode.EQ||opcode==Opcode.NE)
166             return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
167             //      return right.usesDescriptor(d);
168         else
169             return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
170     }
171     
172
173     public int[] getRepairs(boolean negated) {
174         if (left instanceof RelationExpr)
175             return new int[] {AbstractRepair.MODIFYRELATION};
176         if (left instanceof SizeofExpr) {
177             Opcode op=opcode;
178             if (negated) {
179                 /* remove negation through opcode translation */
180                 if (op==Opcode.GT)
181                     op=Opcode.LE;
182                 else if (op==Opcode.GE)
183                     op=Opcode.LT;
184                 else if (op==Opcode.EQ)
185                     op=Opcode.NE;
186                 else if (op==Opcode.NE)
187                     op=Opcode.EQ;
188                 else if (op==Opcode.LT)
189                     op=Opcode.GE;
190                 else if (op==Opcode.LE)
191                     op=Opcode.GT;
192             }
193
194
195
196             boolean isRelation=((SizeofExpr)left).setexpr instanceof ImageSetExpr;
197             if (isRelation) {
198                 if (op==Opcode.EQ) {
199                     if (((IntegerLiteralExpr)right).getValue()==0)
200                         return new int[] {AbstractRepair.REMOVEFROMRELATION};
201                     else
202                         return new int[] {AbstractRepair.ADDTORELATION,
203                                           AbstractRepair.REMOVEFROMRELATION};
204                 } else if (op==Opcode.GE||op==Opcode.GT) {
205                     return new int[]{AbstractRepair.ADDTORELATION}; 
206                 } else if (op==Opcode.LE||op==Opcode.LT) {
207                     return new int[]{AbstractRepair.REMOVEFROMRELATION};
208                 } else if (op==Opcode.NE) {
209                     return new int[]{AbstractRepair.ADDTORELATION};
210                 } else throw new Error();
211             } else {
212                 if (op==Opcode.EQ) {
213                     if (((IntegerLiteralExpr)right).getValue()==0)
214                         return new int[] {AbstractRepair.REMOVEFROMSET};                        
215                     else
216                         return new int[] {AbstractRepair.ADDTOSET,
217                                               AbstractRepair.REMOVEFROMSET};
218                 } else if (op==Opcode.GE||op==Opcode.GT) {
219                     return new int[] {AbstractRepair.ADDTOSET}; 
220                 } else if (op==Opcode.LE||op==Opcode.LT) {
221                     return new int[] {AbstractRepair.REMOVEFROMSET};
222                 } else if (op==Opcode.NE) {
223                     return new int[] {AbstractRepair.ADDTOSET};
224                 } else throw new Error();
225             }
226         }
227         throw new Error("BAD");
228     }
229     
230     public Descriptor getDescriptor() {
231         return left.getDescriptor();
232     }
233
234     public boolean inverted() {
235         return left.inverted();
236     }
237
238     public Set getInversedRelations() {
239         Set set = left.getInversedRelations();
240         if (right != null) {
241             set.addAll(right.getInversedRelations());
242         }
243         return set;
244     }
245
246     public Set getRequiredDescriptors() {
247         Set v = left.getRequiredDescriptors();
248      
249         if (right != null) {
250             v.addAll(right.getRequiredDescriptors());
251         }
252
253         return v;
254     }   
255
256     public void generate(CodeWriter writer, VarDescriptor dest) {
257         VarDescriptor ld = VarDescriptor.makeNew("leftop");
258         left.generate(writer, ld);        
259         VarDescriptor rd = null;
260         VarDescriptor lm=VarDescriptor.makeNew("lm");
261         VarDescriptor rm=VarDescriptor.makeNew("rm");
262
263         if (right != null) {
264             if ((opcode==Opcode.OR)||
265                 (opcode==Opcode.AND)) {
266                 writer.outputline("int "+lm.getSafeSymbol()+"=maybe;");
267                 writer.outputline("int maybe=0;");
268             }
269
270             rd = VarDescriptor.makeNew("rightop");
271             right.generate(writer, rd);
272         }
273
274         String code;
275         if (opcode == Opcode.RND) {
276             writer.outputline("int " +dest.getSafeSymbol() + " = (" +
277                               ld.getSafeSymbol() + ">>3)<<3; ");
278             writer.outputline("if ("+ld.getSafeSymbol()+" % 8) "+dest.getSafeSymbol()+"+=8;");
279         } else if (opcode == Opcode.NOP) {
280             writer.outputline("int " +dest.getSafeSymbol() + " = " +
281                               ld.getSafeSymbol() +"; ");
282         } else if (opcode != Opcode.NOT) { /* two operands */
283             assert rd != null;
284             writer.outputline("int " + dest.getSafeSymbol() + " = " + 
285                               ld.getSafeSymbol() + " " + opcode.toString() + " " + rd.getSafeSymbol() + ";");
286         } else if (opcode == Opcode.AND) {
287             writer.outputline("int "+rm.getSafeSymbol()+"=maybe;");
288             writer.outputline("maybe = (" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (" + rd.getSafeSymbol() + " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
289             writer.outputline(dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " && " + rd.getSafeSymbol() + ";");
290         } else if (opcode == Opcode.OR) {
291             writer.outputline("int "+rm.getSafeSymbol()+"=maybe;");
292             writer.outputline("maybe = (!" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (!" + rd.getSafeSymbol() +
293                               " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
294             writer.outputline(dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " || " + rd.getSafeSymbol() +
295                               ";");
296         } else {
297             writer.outputline("int " + dest.getSafeSymbol() + " = !" + ld.getSafeSymbol() + ";");
298         }
299     }
300
301     public void prettyPrint(PrettyPrinter pp) {
302         pp.output("(");
303         if (opcode == Opcode.NOT) {
304             pp.output("!");
305             left.prettyPrint(pp);
306         } else if (opcode == Opcode.NOP) {
307             left.prettyPrint(pp);
308         } else if (opcode == Opcode.RND) {
309             pp.output("RND ");
310             left.prettyPrint(pp);
311         } else {           
312             left.prettyPrint(pp);
313             pp.output(" " + opcode.toString() + " ");
314             assert right != null;
315             right.prettyPrint(pp);
316         }
317         pp.output(")");
318     }
319
320     public TypeDescriptor typecheck(SemanticAnalyzer sa) {
321         TypeDescriptor lt = left.typecheck(sa);
322         TypeDescriptor rt = right == null ? null : right.typecheck(sa);
323
324         if (lt == null) {
325             return null;
326         } else if (right != null && rt == null) {
327             return null;
328         }
329
330         boolean ok = true;
331
332         // #ATTN#: if we want node.next != literal(0) to represent a null check than we need to allow ptr arithmetic
333         // either that or we use a isvalid clause to check for null
334
335         /*
336         if (lt != ReservedTypeDescriptor.INT) {
337             sa.getErrorReporter().report(null, "Left hand side of expression is of type '" + lt.getSymbol() + "' but must be type 'int'");
338             ok = false;
339         }
340
341         if (right != null) {
342             if (rt != ReservedTypeDescriptor.INT) {
343                 sa.getErrorReporter().report(null, "Right hand side of expression is of type '" + rt.getSymbol() + "' but must be type 'int'");
344                 ok = false;
345             }
346         }
347         */
348
349         if (!ok) {
350             return null;
351         }
352
353         this.td = ReservedTypeDescriptor.INT;
354         return this.td;
355     }
356
357 }
358
359
360
361
362