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;
40 public boolean isSafe() {
43 return left.isSafe()&&right.isSafe();
46 public boolean isInvariant(Set vars) {
47 return left.isInvariant(vars)&&((right==null)||right.isInvariant(vars));
50 public Set findInvariants(Set vars) {
52 /* Don't hoist ints */
54 } else if (isInvariant(vars)) {
59 Set ls=left.findInvariants(vars);
61 ls.addAll(right.findInvariants(vars));
66 public Set getfunctions() {
67 Set leftfunctions=left.getfunctions();
68 Set rightfunctions=null;
69 if (right!=null) rightfunctions=right.getfunctions();
70 if (leftfunctions!=null&&rightfunctions!=null) {
71 HashSet functions=new HashSet();
72 functions.addAll(leftfunctions);
73 functions.addAll(rightfunctions);
76 if (leftfunctions!=null)
78 return rightfunctions;
81 public static boolean isInt(Expr e) {
84 if ((e instanceof IntegerLiteralExpr)||
85 ((e instanceof OpExpr)&&(((OpExpr)e).opcode==Opcode.NOP)&&(((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr)))
90 public static int getInt(Expr e) {
91 if (e instanceof IntegerLiteralExpr)
92 return ((IntegerLiteralExpr)e).getValue();
93 else if ((e instanceof OpExpr) && (((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr))
94 return ((IntegerLiteralExpr)((OpExpr)e).getLeftExpr()).getValue();
95 else throw new Error();
98 public OpExpr(Opcode opcode, Expr left, Expr right) {
99 if ((isInt(left)&&isInt(right))||
100 (isInt(left)&&(opcode==Opcode.NOT))||
101 (isInt(left)&&(opcode==Opcode.RND))) {
102 this.opcode=Opcode.NOP;
104 int lint=isInt(left)?getInt(left):0;
105 int rint=isInt(right)?getInt(right):0;
107 if (opcode==Opcode.ADD) {
109 } else if (opcode==Opcode.SUB) {
111 } else if (opcode==Opcode.SHL) {
113 } else if (opcode==Opcode.SHR) {
115 } else if (opcode==Opcode.MULT) {
117 } else if (opcode==Opcode.DIV) {
119 } else if (opcode==Opcode.GT) {
122 } else if (opcode==Opcode.GE) {
125 } else if (opcode==Opcode.LT) {
128 } else if (opcode==Opcode.LE) {
131 } else if (opcode==Opcode.EQ) {
134 } else if (opcode==Opcode.NE) {
137 } else if (opcode==Opcode.AND) {
138 if ((lint!=0)&&(rint!=0))
140 } else if (opcode==Opcode.OR) {
141 if ((lint!=0)||(rint!=0))
143 } else if (opcode==Opcode.NOT) {
146 } else if (opcode==Opcode.RND) {
147 value=((lint>>3)<<3);
150 } else throw new Error("Unrecognized Opcode");
151 this.left=new IntegerLiteralExpr(value);
152 } else if ((opcode==Opcode.MULT)&&
153 ((isInt(left)&&(getInt(left)==0))
154 ||(isInt(right)&&(getInt(right)==0)))) {
155 this.opcode=Opcode.NOP;
157 this.left=new IntegerLiteralExpr(0);
159 this.opcode = opcode;
162 assert (right == null && (opcode == Opcode.NOT||opcode==Opcode.RND)) || (right != null);
166 public Expr getRightExpr() {
170 public Expr getLeftExpr() {
174 public Set freeVars() {
175 Set lset=left.freeVars();
178 rset=right.freeVars();
186 public String name() {
187 if (opcode==Opcode.NOT)
188 return "!("+left.name()+")";
189 if (opcode==Opcode.NOP)
191 if (opcode==Opcode.RND)
192 return "Round("+left.name()+")";
193 String name=left.name()+opcode.toString();
199 public Opcode getOpcode() {
203 public boolean equals(Map remap, Expr e) {
204 if (e==null||!(e instanceof OpExpr))
207 if (opcode!=oe.opcode)
209 if (!left.equals(remap,oe.left))
211 if ((opcode!=Opcode.NOT)&&(opcode!=Opcode.RND)&&(opcode!=Opcode.NOP))
212 if (!right.equals(remap,oe.right))
217 public DNFRule constructDNF() {
218 if (opcode==Opcode.AND) {
219 DNFRule leftd=left.constructDNF();
220 DNFRule rightd=right.constructDNF();
221 return leftd.and(rightd);
222 } else if (opcode==Opcode.OR) {
223 DNFRule leftd=left.constructDNF();
224 DNFRule rightd=right.constructDNF();
225 return leftd.or(rightd);
226 } else if (opcode==Opcode.NOT) {
227 DNFRule leftd=left.constructDNF();
229 } else return new DNFRule(this);
232 public boolean usesDescriptor(Descriptor d) {
233 return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
236 public void findmatch(Descriptor d, Set s) {
239 right.findmatch(d,s);
242 public Set useDescriptor(Descriptor d) {
243 HashSet newset=new HashSet();
244 newset.addAll(left.useDescriptor(d));
246 newset.addAll(right.useDescriptor(d));
250 public int[] getRepairs(boolean negated, Termination t) {
251 if (left instanceof RelationExpr)
252 return new int[] {AbstractRepair.MODIFYRELATION};
253 if (left instanceof SizeofExpr) {
256 /* remove negation through opcode translation */
259 else if (op==Opcode.GE)
261 else if (op==Opcode.EQ)
263 else if (op==Opcode.NE)
265 else if (op==Opcode.LT)
267 else if (op==Opcode.LE)
271 int maxsize=t.maxsize.getsize(getDescriptor());
272 int size=getInt(right);
275 boolean isRelation=((SizeofExpr)left).setexpr instanceof ImageSetExpr;
279 return new int[] {AbstractRepair.REMOVEFROMRELATION};
281 if ((maxsize!=-1)&&maxsize<=size)
282 return new int[] {AbstractRepair.ADDTORELATION};
283 return new int[] {AbstractRepair.ADDTORELATION,
284 AbstractRepair.REMOVEFROMRELATION};
286 } else if (op==Opcode.GE||op==Opcode.GT) {
287 return new int[]{AbstractRepair.ADDTORELATION};
288 } else if (op==Opcode.LE||op==Opcode.LT) {
289 if ((op==Opcode.LT&&maxsize!=-1&&maxsize<size)||(op==Opcode.LE&&maxsize!=-1&&maxsize<=size))
291 return new int[]{AbstractRepair.REMOVEFROMRELATION};
292 } else if (op==Opcode.NE) {
293 if (maxsize<size&&maxsize!=-1)
295 return new int[]{AbstractRepair.ADDTORELATION};
296 } else throw new Error();
300 return new int[] {AbstractRepair.REMOVEFROMSET};
302 if (maxsize<=size&&maxsize!=-1)
303 return new int[] {AbstractRepair.ADDTOSET};
304 return new int[] {AbstractRepair.ADDTOSET,
305 AbstractRepair.REMOVEFROMSET};
307 } else if (op==Opcode.GE||op==Opcode.GT) {
308 return new int[] {AbstractRepair.ADDTOSET};
309 } else if (op==Opcode.LE||op==Opcode.LT) {
310 if ((op==Opcode.LT&&maxsize<size&&maxsize!=-1)||(op==Opcode.LE&&maxsize<=size&&maxsize!=-1))
312 return new int[] {AbstractRepair.REMOVEFROMSET};
313 } else if (op==Opcode.NE) {
314 if (maxsize<size&&maxsize!=-1)
316 return new int[] {AbstractRepair.ADDTOSET};
317 } else throw new Error();
320 throw new Error("BAD");
323 public Descriptor getDescriptor() {
324 return left.getDescriptor();
327 public boolean inverted() {
328 return left.inverted();
331 public Set getInversedRelations() {
332 Set set = left.getInversedRelations();
334 set.addAll(right.getInversedRelations());
339 public Set getRequiredDescriptors() {
340 Set v = left.getRequiredDescriptors();
343 v.addAll(right.getRequiredDescriptors());
349 public void generate(CodeWriter writer, VarDescriptor dest) {
350 VarDescriptor ld = VarDescriptor.makeNew("leftop");
351 /* Check for loop invariant hoisting. */
352 if (writer.getInvariantValue()!=null&&
353 writer.getInvariantValue().isInvariant(this)) {
354 writer.addDeclaration("int",dest.getSafeSymbol());
355 writer.outputline(dest.getSafeSymbol()+"="+writer.getInvariantValue().getValue(this).getSafeSymbol()+";");
356 writer.outputline("maybe="+writer.getInvariantValue().getMaybe(this).getSafeSymbol()+";");
360 left.generate(writer, ld);
361 VarDescriptor rd = null;
362 VarDescriptor lm=VarDescriptor.makeNew("lm");
363 VarDescriptor rm=VarDescriptor.makeNew("rm");
366 if ((opcode==Opcode.OR)||
367 (opcode==Opcode.AND)) {
368 writer.addDeclaration("int",lm.getSafeSymbol());
369 writer.outputline(lm.getSafeSymbol()+"=maybe;");
370 writer.outputline("maybe=0;");
373 rd = VarDescriptor.makeNew("rightop");
374 right.generate(writer, rd);
378 if (opcode == Opcode.RND) {
379 writer.addDeclaration("int",dest.getSafeSymbol());
380 writer.outputline(dest.getSafeSymbol() + " = (" +
381 ld.getSafeSymbol() + ">>3)<<3; ");
382 writer.outputline("if ("+ld.getSafeSymbol()+" % 8) "+dest.getSafeSymbol()+"+=8;");
383 } else if (opcode == Opcode.NOP) {
384 writer.addDeclaration("int", dest.getSafeSymbol());
385 writer.outputline(dest.getSafeSymbol() + " = " +
386 ld.getSafeSymbol() +"; ");
387 } else if (opcode == Opcode.AND) {
388 writer.addDeclaration("int",rm.getSafeSymbol());
389 writer.outputline(rm.getSafeSymbol()+"=maybe;");
390 writer.outputline("maybe = (" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (" + rd.getSafeSymbol() + " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
391 writer.addDeclaration("int",dest.getSafeSymbol());
392 writer.outputline(dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " && " + rd.getSafeSymbol() + ";");
393 } else if (opcode == Opcode.OR) {
394 writer.addDeclaration("int",rm.getSafeSymbol());
395 writer.outputline(rm.getSafeSymbol()+"=maybe;");
396 writer.outputline("maybe = (!" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (!" + rd.getSafeSymbol() +
397 " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
398 writer.addDeclaration("int",dest.getSafeSymbol());
399 writer.outputline(dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " || " + rd.getSafeSymbol() + ";");
400 } else if (opcode != Opcode.NOT) { /* two operands */
402 writer.addDeclaration("int", dest.getSafeSymbol());
403 writer.outputline(dest.getSafeSymbol() + " = " +
404 ld.getSafeSymbol() + " " + opcode.toString() + " " + rd.getSafeSymbol() + ";");
405 } else if (opcode == Opcode.NOT) {
406 writer.addDeclaration("int", dest.getSafeSymbol());
407 writer.outputline(dest.getSafeSymbol() + " = !" + ld.getSafeSymbol() + ";");
411 public void prettyPrint(PrettyPrinter pp) {
413 if (opcode == Opcode.NOT) {
415 left.prettyPrint(pp);
416 } else if (opcode == Opcode.NOP) {
417 left.prettyPrint(pp);
418 } else if (opcode == Opcode.RND) {
420 left.prettyPrint(pp);
422 left.prettyPrint(pp);
423 pp.output(" " + opcode.toString() + " ");
424 assert right != null;
425 right.prettyPrint(pp);
430 public TypeDescriptor typecheck(SemanticAnalyzer sa) {
431 TypeDescriptor lt = left.typecheck(sa);
432 TypeDescriptor rt = right == null ? null : right.typecheck(sa);
436 } else if (right != null && rt == null) {
446 this.td = ReservedTypeDescriptor.INT;