5 public class OpExpr extends Expr {
11 public Expr getUpper() {
12 Expr lupper=left.getUpper();
16 Expr rupper=right.getUpper();
19 OpExpr oe=new OpExpr(this.opcode,lupper,rupper);
20 oe.td = ReservedTypeDescriptor.INT;
25 public Expr getLower() {
26 Expr llower=left.getLower();
30 Expr rlower=right.getLower();
33 OpExpr oe=new OpExpr(this.opcode,llower,rlower);
34 oe.td = ReservedTypeDescriptor.INT;
39 public boolean isSafe() {
42 return left.isSafe()&&right.isSafe();
45 public Set getfunctions() {
46 Set leftfunctions=left.getfunctions();
47 Set rightfunctions=right.getfunctions();
48 if (leftfunctions!=null&&rightfunctions!=null) {
49 HashSet functions=new HashSet();
50 functions.addAll(leftfunctions);
51 functions.addAll(rightfunctions);
54 if (leftfunctions!=null)
56 return rightfunctions;
59 public void findmatch(Descriptor d, Set s) {
65 public static boolean isInt(Expr e) {
68 if ((e instanceof IntegerLiteralExpr)||
69 ((e instanceof OpExpr)&&(((OpExpr)e).opcode==Opcode.NOP)&&(((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr)))
74 public static int getInt(Expr e) {
75 if (e instanceof IntegerLiteralExpr)
76 return ((IntegerLiteralExpr)e).getValue();
77 else if ((e instanceof OpExpr) && (((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr))
78 return ((IntegerLiteralExpr)((OpExpr)e).getLeftExpr()).getValue();
79 else throw new Error();
82 public OpExpr(Opcode opcode, Expr left, Expr right) {
83 if ((isInt(left)&&isInt(right))||
84 (isInt(left)&&(opcode==Opcode.NOT))||
85 (isInt(left)&&(opcode==Opcode.RND))) {
86 this.opcode=Opcode.NOP;
88 int lint=isInt(left)?getInt(left):0;
89 int rint=isInt(right)?getInt(right):0;
91 if (opcode==Opcode.ADD) {
93 } else if (opcode==Opcode.SUB) {
95 } else if (opcode==Opcode.SHL) {
97 } else if (opcode==Opcode.SHR) {
99 } else if (opcode==Opcode.MULT) {
101 } else if (opcode==Opcode.DIV) {
103 } else if (opcode==Opcode.GT) {
106 } else if (opcode==Opcode.GE) {
109 } else if (opcode==Opcode.LT) {
112 } else if (opcode==Opcode.LE) {
115 } else if (opcode==Opcode.EQ) {
118 } else if (opcode==Opcode.NE) {
121 } else if (opcode==Opcode.AND) {
122 if ((lint!=0)&&(rint!=0))
124 } else if (opcode==Opcode.OR) {
125 if ((lint!=0)||(rint!=0))
127 } else if (opcode==Opcode.NOT) {
130 } else if (opcode==Opcode.RND) {
131 value=((lint>>3)<<3);
134 } else throw new Error("Unrecognized Opcode");
135 this.left=new IntegerLiteralExpr(value);
136 } else if ((opcode==Opcode.MULT)&&
137 ((isInt(left)&&(getInt(left)==0))
138 ||(isInt(right)&&(getInt(right)==0)))) {
139 this.opcode=Opcode.NOP;
141 this.left=new IntegerLiteralExpr(0);
143 this.opcode = opcode;
146 assert (right == null && (opcode == Opcode.NOT||opcode==Opcode.RND)) || (right != null);
150 public Expr getRightExpr() {
154 public Expr getLeftExpr() {
158 public Set freeVars() {
159 Set lset=left.freeVars();
162 rset=right.freeVars();
170 public String name() {
171 if (opcode==Opcode.NOT)
172 return "!("+left.name()+")";
173 if (opcode==Opcode.NOP)
175 if (opcode==Opcode.RND)
176 return "Round("+left.name()+")";
177 String name=left.name()+opcode.toString();
183 public Opcode getOpcode() {
187 public boolean equals(Map remap, Expr e) {
188 if (e==null||!(e instanceof OpExpr))
191 if (opcode!=oe.opcode)
193 if (!left.equals(remap,oe.left))
195 if ((opcode!=Opcode.NOT)&&(opcode!=Opcode.RND)&&(opcode!=Opcode.NOP))
196 if (!right.equals(remap,oe.right))
201 public DNFRule constructDNF() {
202 if (opcode==Opcode.AND) {
203 DNFRule leftd=left.constructDNF();
204 DNFRule rightd=right.constructDNF();
205 return leftd.and(rightd);
206 } else if (opcode==Opcode.OR) {
207 DNFRule leftd=left.constructDNF();
208 DNFRule rightd=right.constructDNF();
209 return leftd.or(rightd);
210 } else if (opcode==Opcode.NOT) {
211 DNFRule leftd=left.constructDNF();
213 } else return new DNFRule(this);
216 public boolean usesDescriptor(Descriptor d) {
217 return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
220 public Set useDescriptor(Descriptor d) {
221 HashSet newset=new HashSet();
222 newset.addAll(left.useDescriptor(d));
224 newset.addAll(right.useDescriptor(d));
228 public int[] getRepairs(boolean negated, Termination t) {
229 if (left instanceof RelationExpr)
230 return new int[] {AbstractRepair.MODIFYRELATION};
231 if (left instanceof SizeofExpr) {
234 /* remove negation through opcode translation */
237 else if (op==Opcode.GE)
239 else if (op==Opcode.EQ)
241 else if (op==Opcode.NE)
243 else if (op==Opcode.LT)
245 else if (op==Opcode.LE)
249 int maxsize=t.maxsize.getsize(getDescriptor());
250 int size=getInt(right);
253 boolean isRelation=((SizeofExpr)left).setexpr instanceof ImageSetExpr;
257 return new int[] {AbstractRepair.REMOVEFROMRELATION};
259 if ((maxsize!=-1)&&maxsize<=size)
260 return new int[] {AbstractRepair.ADDTORELATION};
261 return new int[] {AbstractRepair.ADDTORELATION,
262 AbstractRepair.REMOVEFROMRELATION};
264 } else if (op==Opcode.GE||op==Opcode.GT) {
265 return new int[]{AbstractRepair.ADDTORELATION};
266 } else if (op==Opcode.LE||op==Opcode.LT) {
267 if ((op==Opcode.LT&&maxsize!=-1&&maxsize<size)||(op==Opcode.LE&&maxsize!=-1&&maxsize<=size))
269 return new int[]{AbstractRepair.REMOVEFROMRELATION};
270 } else if (op==Opcode.NE) {
271 if (maxsize<size&&maxsize!=-1)
273 return new int[]{AbstractRepair.ADDTORELATION};
274 } else throw new Error();
278 return new int[] {AbstractRepair.REMOVEFROMSET};
280 if (maxsize<=size&&maxsize!=-1)
281 return new int[] {AbstractRepair.ADDTOSET};
282 return new int[] {AbstractRepair.ADDTOSET,
283 AbstractRepair.REMOVEFROMSET};
285 } else if (op==Opcode.GE||op==Opcode.GT) {
286 return new int[] {AbstractRepair.ADDTOSET};
287 } else if (op==Opcode.LE||op==Opcode.LT) {
288 if ((op==Opcode.LT&&maxsize<size&&maxsize!=-1)||(op==Opcode.LE&&maxsize<=size&&maxsize!=-1))
290 return new int[] {AbstractRepair.REMOVEFROMSET};
291 } else if (op==Opcode.NE) {
292 if (maxsize<size&&maxsize!=-1)
294 return new int[] {AbstractRepair.ADDTOSET};
295 } else throw new Error();
298 throw new Error("BAD");
301 public Descriptor getDescriptor() {
302 return left.getDescriptor();
305 public boolean inverted() {
306 return left.inverted();
309 public Set getInversedRelations() {
310 Set set = left.getInversedRelations();
312 set.addAll(right.getInversedRelations());
317 public Set getRequiredDescriptors() {
318 Set v = left.getRequiredDescriptors();
321 v.addAll(right.getRequiredDescriptors());
327 public void generate(CodeWriter writer, VarDescriptor dest) {
328 VarDescriptor ld = VarDescriptor.makeNew("leftop");
329 left.generate(writer, ld);
330 VarDescriptor rd = null;
331 VarDescriptor lm=VarDescriptor.makeNew("lm");
332 VarDescriptor rm=VarDescriptor.makeNew("rm");
335 if ((opcode==Opcode.OR)||
336 (opcode==Opcode.AND)) {
337 writer.outputline("int "+lm.getSafeSymbol()+"=maybe;");
338 writer.outputline("maybe=0;");
341 rd = VarDescriptor.makeNew("rightop");
342 right.generate(writer, rd);
346 if (opcode == Opcode.RND) {
347 writer.outputline("int " +dest.getSafeSymbol() + " = (" +
348 ld.getSafeSymbol() + ">>3)<<3; ");
349 writer.outputline("if ("+ld.getSafeSymbol()+" % 8) "+dest.getSafeSymbol()+"+=8;");
350 } else if (opcode == Opcode.NOP) {
351 writer.outputline("int " +dest.getSafeSymbol() + " = " +
352 ld.getSafeSymbol() +"; ");
353 } else if (opcode == Opcode.AND) {
354 writer.outputline("int "+rm.getSafeSymbol()+"=maybe;");
355 writer.outputline("maybe = (" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (" + rd.getSafeSymbol() + " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
356 writer.outputline("int "+dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " && " + rd.getSafeSymbol() + ";");
357 } else if (opcode == Opcode.OR) {
358 writer.outputline("int "+rm.getSafeSymbol()+"=maybe;");
359 writer.outputline("maybe = (!" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (!" + rd.getSafeSymbol() +
360 " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
361 writer.outputline("int "+dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " || " + rd.getSafeSymbol() +
363 } else if (opcode != Opcode.NOT) { /* two operands */
365 writer.outputline("int " + dest.getSafeSymbol() + " = " +
366 ld.getSafeSymbol() + " " + opcode.toString() + " " + rd.getSafeSymbol() + ";");
367 } else if (opcode == Opcode.NOT) {
368 writer.outputline("int " + dest.getSafeSymbol() + " = !" + ld.getSafeSymbol() + ";");
372 public void prettyPrint(PrettyPrinter pp) {
374 if (opcode == Opcode.NOT) {
376 left.prettyPrint(pp);
377 } else if (opcode == Opcode.NOP) {
378 left.prettyPrint(pp);
379 } else if (opcode == Opcode.RND) {
381 left.prettyPrint(pp);
383 left.prettyPrint(pp);
384 pp.output(" " + opcode.toString() + " ");
385 assert right != null;
386 right.prettyPrint(pp);
391 public TypeDescriptor typecheck(SemanticAnalyzer sa) {
392 TypeDescriptor lt = left.typecheck(sa);
393 TypeDescriptor rt = right == null ? null : right.typecheck(sa);
397 } else if (right != null && rt == null) {
403 // #ATTN#: if we want node.next != literal(0) to represent a null check than we need to allow ptr arithmetic
404 // either that or we use a isvalid clause to check for null
407 if (lt != ReservedTypeDescriptor.INT) {
408 sa.getErrorReporter().report(null, "Left hand side of expression is of type '" + lt.getSymbol() + "' but must be type 'int'");
413 if (rt != ReservedTypeDescriptor.INT) {
414 sa.getErrorReporter().report(null, "Right hand side of expression is of type '" + rt.getSymbol() + "' but must be type 'int'");
424 this.td = ReservedTypeDescriptor.INT;