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