5 public class OpExpr extends Expr {
11 public boolean isSafe() {
14 return left.isSafe()&&right.isSafe();
17 public Set getfunctions() {
18 Set leftfunctions=left.getfunctions();
19 Set rightfunctions=right.getfunctions();
20 if (leftfunctions!=null&&rightfunctions!=null) {
21 HashSet functions=new HashSet();
22 functions.addAll(leftfunctions);
23 functions.addAll(rightfunctions);
26 if (leftfunctions!=null)
28 return rightfunctions;
31 public void findmatch(Descriptor d, Set s) {
37 public static boolean isInt(Expr e) {
40 if ((e instanceof IntegerLiteralExpr)||
41 ((e instanceof OpExpr)&&(((OpExpr)e).opcode==Opcode.NOP)&&(((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr)))
46 public static int getInt(Expr e) {
47 if (e instanceof IntegerLiteralExpr)
48 return ((IntegerLiteralExpr)e).getValue();
49 else if ((e instanceof OpExpr) && (((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr))
50 return ((IntegerLiteralExpr)((OpExpr)e).getLeftExpr()).getValue();
51 else throw new Error();
54 public OpExpr(Opcode opcode, Expr left, Expr right) {
55 if ((isInt(left)&&isInt(right))||
56 (isInt(left)&&(opcode==Opcode.NOT))||
57 (isInt(left)&&(opcode==Opcode.RND))) {
58 this.opcode=Opcode.NOP;
60 int lint=isInt(left)?getInt(left):0;
61 int rint=isInt(right)?getInt(right):0;
63 if (opcode==Opcode.ADD) {
65 } else if (opcode==Opcode.SUB) {
67 } else if (opcode==Opcode.SHL) {
69 } else if (opcode==Opcode.SHR) {
71 } else if (opcode==Opcode.MULT) {
73 } else if (opcode==Opcode.DIV) {
75 } else if (opcode==Opcode.GT) {
78 } else if (opcode==Opcode.GE) {
81 } else if (opcode==Opcode.LT) {
84 } else if (opcode==Opcode.LE) {
87 } else if (opcode==Opcode.EQ) {
90 } else if (opcode==Opcode.NE) {
93 } else if (opcode==Opcode.AND) {
94 if ((lint!=0)&&(rint!=0))
96 } else if (opcode==Opcode.OR) {
97 if ((lint!=0)||(rint!=0))
99 } else if (opcode==Opcode.NOT) {
102 } else if (opcode==Opcode.RND) {
103 value=((lint>>3)<<3);
106 } else throw new Error("Unrecognized Opcode");
107 this.left=new IntegerLiteralExpr(value);
108 } else if ((opcode==Opcode.MULT)&&
109 ((isInt(left)&&(getInt(left)==0))
110 ||(isInt(right)&&(getInt(right)==0)))) {
111 this.opcode=Opcode.NOP;
113 this.left=new IntegerLiteralExpr(0);
115 this.opcode = opcode;
118 assert (right == null && (opcode == Opcode.NOT||opcode==Opcode.RND)) || (right != null);
122 public Expr getRightExpr() {
126 public Expr getLeftExpr() {
130 public Set freeVars() {
131 Set lset=left.freeVars();
134 rset=right.freeVars();
142 public String name() {
143 if (opcode==Opcode.NOT)
144 return "!("+left.name()+")";
145 if (opcode==Opcode.NOP)
147 if (opcode==Opcode.RND)
148 return "Round("+left.name()+")";
149 String name=left.name()+opcode.toString();
155 public Opcode getOpcode() {
162 public boolean equals(Map remap, Expr e) {
163 if (e==null||!(e instanceof OpExpr))
166 if (opcode!=oe.opcode)
168 if (!left.equals(remap,oe.left))
170 if ((opcode!=Opcode.NOT)&&(opcode!=Opcode.RND)&&(opcode!=Opcode.NOP))
171 if (!right.equals(remap,oe.right))
176 public DNFRule constructDNF() {
177 if (opcode==Opcode.AND) {
178 DNFRule leftd=left.constructDNF();
179 DNFRule rightd=right.constructDNF();
180 return leftd.and(rightd);
181 } else if (opcode==Opcode.OR) {
182 DNFRule leftd=left.constructDNF();
183 DNFRule rightd=right.constructDNF();
184 return leftd.or(rightd);
185 } else if (opcode==Opcode.NOT) {
186 DNFRule leftd=left.constructDNF();
188 } else return new DNFRule(this);
191 public boolean usesDescriptor(Descriptor d) {
192 if (opcode==Opcode.GT||opcode==Opcode.GE||opcode==Opcode.LT||
193 opcode==Opcode.LE||opcode==Opcode.EQ||opcode==Opcode.NE)
194 return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
195 // return right.usesDescriptor(d);
197 return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
201 public int[] getRepairs(boolean negated, Termination t) {
202 if (left instanceof RelationExpr)
203 return new int[] {AbstractRepair.MODIFYRELATION};
204 if (left instanceof SizeofExpr) {
207 /* remove negation through opcode translation */
210 else if (op==Opcode.GE)
212 else if (op==Opcode.EQ)
214 else if (op==Opcode.NE)
216 else if (op==Opcode.LT)
218 else if (op==Opcode.LE)
222 int maxsize=t.maxsize.getsize(getDescriptor());
223 int size=getInt(right);
226 boolean isRelation=((SizeofExpr)left).setexpr instanceof ImageSetExpr;
230 return new int[] {AbstractRepair.REMOVEFROMRELATION};
232 if ((maxsize!=-1)&&maxsize<=size)
233 return new int[] {AbstractRepair.ADDTORELATION};
234 return new int[] {AbstractRepair.ADDTORELATION,
235 AbstractRepair.REMOVEFROMRELATION};
237 } else if (op==Opcode.GE||op==Opcode.GT) {
238 return new int[]{AbstractRepair.ADDTORELATION};
239 } else if (op==Opcode.LE||op==Opcode.LT) {
240 if ((op==Opcode.LT&&maxsize!=-1&&maxsize<size)||(op==Opcode.LE&&maxsize!=-1&&maxsize<=size))
242 return new int[]{AbstractRepair.REMOVEFROMRELATION};
243 } else if (op==Opcode.NE) {
244 if (maxsize<size&&maxsize!=-1)
246 return new int[]{AbstractRepair.ADDTORELATION};
247 } else throw new Error();
251 return new int[] {AbstractRepair.REMOVEFROMSET};
253 if (maxsize<=size&&maxsize!=-1)
254 return new int[] {AbstractRepair.ADDTOSET};
255 return new int[] {AbstractRepair.ADDTOSET,
256 AbstractRepair.REMOVEFROMSET};
258 } else if (op==Opcode.GE||op==Opcode.GT) {
259 return new int[] {AbstractRepair.ADDTOSET};
260 } else if (op==Opcode.LE||op==Opcode.LT) {
261 if ((op==Opcode.LT&&maxsize<size&&maxsize!=-1)||(op==Opcode.LE&&maxsize<=size&&maxsize!=-1))
263 return new int[] {AbstractRepair.REMOVEFROMSET};
264 } else if (op==Opcode.NE) {
265 if (maxsize<size&&maxsize!=-1)
267 return new int[] {AbstractRepair.ADDTOSET};
268 } else throw new Error();
271 throw new Error("BAD");
274 public Descriptor getDescriptor() {
275 return left.getDescriptor();
278 public boolean inverted() {
279 return left.inverted();
282 public Set getInversedRelations() {
283 Set set = left.getInversedRelations();
285 set.addAll(right.getInversedRelations());
290 public Set getRequiredDescriptors() {
291 Set v = left.getRequiredDescriptors();
294 v.addAll(right.getRequiredDescriptors());
300 public void generate(CodeWriter writer, VarDescriptor dest) {
301 VarDescriptor ld = VarDescriptor.makeNew("leftop");
302 left.generate(writer, ld);
303 VarDescriptor rd = null;
304 VarDescriptor lm=VarDescriptor.makeNew("lm");
305 VarDescriptor rm=VarDescriptor.makeNew("rm");
308 if ((opcode==Opcode.OR)||
309 (opcode==Opcode.AND)) {
310 writer.outputline("int "+lm.getSafeSymbol()+"=maybe;");
311 writer.outputline("int maybe=0;");
314 rd = VarDescriptor.makeNew("rightop");
315 right.generate(writer, rd);
319 if (opcode == Opcode.RND) {
320 writer.outputline("int " +dest.getSafeSymbol() + " = (" +
321 ld.getSafeSymbol() + ">>3)<<3; ");
322 writer.outputline("if ("+ld.getSafeSymbol()+" % 8) "+dest.getSafeSymbol()+"+=8;");
323 } else if (opcode == Opcode.NOP) {
324 writer.outputline("int " +dest.getSafeSymbol() + " = " +
325 ld.getSafeSymbol() +"; ");
326 } else if (opcode == Opcode.AND) {
327 writer.outputline("int "+rm.getSafeSymbol()+"=maybe;");
328 writer.outputline("maybe = (" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (" + rd.getSafeSymbol() + " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
329 writer.outputline(dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " && " + rd.getSafeSymbol() + ";");
330 } else if (opcode == Opcode.OR) {
331 writer.outputline("int "+rm.getSafeSymbol()+"=maybe;");
332 writer.outputline("maybe = (!" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (!" + rd.getSafeSymbol() +
333 " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
334 writer.outputline(dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " || " + rd.getSafeSymbol() +
336 } else if (opcode != Opcode.NOT) { /* two operands */
338 writer.outputline("int " + dest.getSafeSymbol() + " = " +
339 ld.getSafeSymbol() + " " + opcode.toString() + " " + rd.getSafeSymbol() + ";");
340 } else if (opcode == Opcode.NOT) {
341 writer.outputline("int " + dest.getSafeSymbol() + " = !" + ld.getSafeSymbol() + ";");
345 public void prettyPrint(PrettyPrinter pp) {
347 if (opcode == Opcode.NOT) {
349 left.prettyPrint(pp);
350 } else if (opcode == Opcode.NOP) {
351 left.prettyPrint(pp);
352 } else if (opcode == Opcode.RND) {
354 left.prettyPrint(pp);
356 left.prettyPrint(pp);
357 pp.output(" " + opcode.toString() + " ");
358 assert right != null;
359 right.prettyPrint(pp);
364 public TypeDescriptor typecheck(SemanticAnalyzer sa) {
365 TypeDescriptor lt = left.typecheck(sa);
366 TypeDescriptor rt = right == null ? null : right.typecheck(sa);
370 } else if (right != null && rt == null) {
376 // #ATTN#: if we want node.next != literal(0) to represent a null check than we need to allow ptr arithmetic
377 // either that or we use a isvalid clause to check for null
380 if (lt != ReservedTypeDescriptor.INT) {
381 sa.getErrorReporter().report(null, "Left hand side of expression is of type '" + lt.getSymbol() + "' but must be type 'int'");
386 if (rt != ReservedTypeDescriptor.INT) {
387 sa.getErrorReporter().report(null, "Right hand side of expression is of type '" + rt.getSymbol() + "' but must be type 'int'");
397 this.td = ReservedTypeDescriptor.INT;