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=null;
48 if (right!=null) rightfunctions=right.getfunctions();
49 if (leftfunctions!=null&&rightfunctions!=null) {
50 HashSet functions=new HashSet();
51 functions.addAll(leftfunctions);
52 functions.addAll(rightfunctions);
55 if (leftfunctions!=null)
57 return rightfunctions;
60 public void findmatch(Descriptor d, Set s) {
66 public static boolean isInt(Expr e) {
69 if ((e instanceof IntegerLiteralExpr)||
70 ((e instanceof OpExpr)&&(((OpExpr)e).opcode==Opcode.NOP)&&(((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr)))
75 public static int getInt(Expr e) {
76 if (e instanceof IntegerLiteralExpr)
77 return ((IntegerLiteralExpr)e).getValue();
78 else if ((e instanceof OpExpr) && (((OpExpr)e).getLeftExpr() instanceof IntegerLiteralExpr))
79 return ((IntegerLiteralExpr)((OpExpr)e).getLeftExpr()).getValue();
80 else throw new Error();
83 public OpExpr(Opcode opcode, Expr left, Expr right) {
84 if ((isInt(left)&&isInt(right))||
85 (isInt(left)&&(opcode==Opcode.NOT))||
86 (isInt(left)&&(opcode==Opcode.RND))) {
87 this.opcode=Opcode.NOP;
89 int lint=isInt(left)?getInt(left):0;
90 int rint=isInt(right)?getInt(right):0;
92 if (opcode==Opcode.ADD) {
94 } else if (opcode==Opcode.SUB) {
96 } else if (opcode==Opcode.SHL) {
98 } else if (opcode==Opcode.SHR) {
100 } else if (opcode==Opcode.MULT) {
102 } else if (opcode==Opcode.DIV) {
104 } else if (opcode==Opcode.GT) {
107 } else if (opcode==Opcode.GE) {
110 } else if (opcode==Opcode.LT) {
113 } else if (opcode==Opcode.LE) {
116 } else if (opcode==Opcode.EQ) {
119 } else if (opcode==Opcode.NE) {
122 } else if (opcode==Opcode.AND) {
123 if ((lint!=0)&&(rint!=0))
125 } else if (opcode==Opcode.OR) {
126 if ((lint!=0)||(rint!=0))
128 } else if (opcode==Opcode.NOT) {
131 } else if (opcode==Opcode.RND) {
132 value=((lint>>3)<<3);
135 } else throw new Error("Unrecognized Opcode");
136 this.left=new IntegerLiteralExpr(value);
137 } else if ((opcode==Opcode.MULT)&&
138 ((isInt(left)&&(getInt(left)==0))
139 ||(isInt(right)&&(getInt(right)==0)))) {
140 this.opcode=Opcode.NOP;
142 this.left=new IntegerLiteralExpr(0);
144 this.opcode = opcode;
147 assert (right == null && (opcode == Opcode.NOT||opcode==Opcode.RND)) || (right != null);
151 public Expr getRightExpr() {
155 public Expr getLeftExpr() {
159 public Set freeVars() {
160 Set lset=left.freeVars();
163 rset=right.freeVars();
171 public String name() {
172 if (opcode==Opcode.NOT)
173 return "!("+left.name()+")";
174 if (opcode==Opcode.NOP)
176 if (opcode==Opcode.RND)
177 return "Round("+left.name()+")";
178 String name=left.name()+opcode.toString();
184 public Opcode getOpcode() {
188 public boolean equals(Map remap, Expr e) {
189 if (e==null||!(e instanceof OpExpr))
192 if (opcode!=oe.opcode)
194 if (!left.equals(remap,oe.left))
196 if ((opcode!=Opcode.NOT)&&(opcode!=Opcode.RND)&&(opcode!=Opcode.NOP))
197 if (!right.equals(remap,oe.right))
202 public DNFRule constructDNF() {
203 if (opcode==Opcode.AND) {
204 DNFRule leftd=left.constructDNF();
205 DNFRule rightd=right.constructDNF();
206 return leftd.and(rightd);
207 } else if (opcode==Opcode.OR) {
208 DNFRule leftd=left.constructDNF();
209 DNFRule rightd=right.constructDNF();
210 return leftd.or(rightd);
211 } else if (opcode==Opcode.NOT) {
212 DNFRule leftd=left.constructDNF();
214 } else return new DNFRule(this);
217 public boolean usesDescriptor(Descriptor d) {
218 return left.usesDescriptor(d)||(right!=null&&right.usesDescriptor(d));
221 public Set useDescriptor(Descriptor d) {
222 HashSet newset=new HashSet();
223 newset.addAll(left.useDescriptor(d));
225 newset.addAll(right.useDescriptor(d));
229 public int[] getRepairs(boolean negated, Termination t) {
230 if (left instanceof RelationExpr)
231 return new int[] {AbstractRepair.MODIFYRELATION};
232 if (left instanceof SizeofExpr) {
235 /* remove negation through opcode translation */
238 else if (op==Opcode.GE)
240 else if (op==Opcode.EQ)
242 else if (op==Opcode.NE)
244 else if (op==Opcode.LT)
246 else if (op==Opcode.LE)
250 int maxsize=t.maxsize.getsize(getDescriptor());
251 int size=getInt(right);
254 boolean isRelation=((SizeofExpr)left).setexpr instanceof ImageSetExpr;
258 return new int[] {AbstractRepair.REMOVEFROMRELATION};
260 if ((maxsize!=-1)&&maxsize<=size)
261 return new int[] {AbstractRepair.ADDTORELATION};
262 return new int[] {AbstractRepair.ADDTORELATION,
263 AbstractRepair.REMOVEFROMRELATION};
265 } else if (op==Opcode.GE||op==Opcode.GT) {
266 return new int[]{AbstractRepair.ADDTORELATION};
267 } else if (op==Opcode.LE||op==Opcode.LT) {
268 if ((op==Opcode.LT&&maxsize!=-1&&maxsize<size)||(op==Opcode.LE&&maxsize!=-1&&maxsize<=size))
270 return new int[]{AbstractRepair.REMOVEFROMRELATION};
271 } else if (op==Opcode.NE) {
272 if (maxsize<size&&maxsize!=-1)
274 return new int[]{AbstractRepair.ADDTORELATION};
275 } else throw new Error();
279 return new int[] {AbstractRepair.REMOVEFROMSET};
281 if (maxsize<=size&&maxsize!=-1)
282 return new int[] {AbstractRepair.ADDTOSET};
283 return new int[] {AbstractRepair.ADDTOSET,
284 AbstractRepair.REMOVEFROMSET};
286 } else if (op==Opcode.GE||op==Opcode.GT) {
287 return new int[] {AbstractRepair.ADDTOSET};
288 } else if (op==Opcode.LE||op==Opcode.LT) {
289 if ((op==Opcode.LT&&maxsize<size&&maxsize!=-1)||(op==Opcode.LE&&maxsize<=size&&maxsize!=-1))
291 return new int[] {AbstractRepair.REMOVEFROMSET};
292 } else if (op==Opcode.NE) {
293 if (maxsize<size&&maxsize!=-1)
295 return new int[] {AbstractRepair.ADDTOSET};
296 } else throw new Error();
299 throw new Error("BAD");
302 public Descriptor getDescriptor() {
303 return left.getDescriptor();
306 public boolean inverted() {
307 return left.inverted();
310 public Set getInversedRelations() {
311 Set set = left.getInversedRelations();
313 set.addAll(right.getInversedRelations());
318 public Set getRequiredDescriptors() {
319 Set v = left.getRequiredDescriptors();
322 v.addAll(right.getRequiredDescriptors());
328 public void generate(CodeWriter writer, VarDescriptor dest) {
329 VarDescriptor ld = VarDescriptor.makeNew("leftop");
330 left.generate(writer, ld);
331 VarDescriptor rd = null;
332 VarDescriptor lm=VarDescriptor.makeNew("lm");
333 VarDescriptor rm=VarDescriptor.makeNew("rm");
336 if ((opcode==Opcode.OR)||
337 (opcode==Opcode.AND)) {
338 writer.outputline("int "+lm.getSafeSymbol()+"=maybe;");
339 writer.outputline("maybe=0;");
342 rd = VarDescriptor.makeNew("rightop");
343 right.generate(writer, rd);
347 if (opcode == Opcode.RND) {
348 writer.outputline("int " +dest.getSafeSymbol() + " = (" +
349 ld.getSafeSymbol() + ">>3)<<3; ");
350 writer.outputline("if ("+ld.getSafeSymbol()+" % 8) "+dest.getSafeSymbol()+"+=8;");
351 } else if (opcode == Opcode.NOP) {
352 writer.outputline("int " +dest.getSafeSymbol() + " = " +
353 ld.getSafeSymbol() +"; ");
354 } else if (opcode == Opcode.AND) {
355 writer.outputline("int "+rm.getSafeSymbol()+"=maybe;");
356 writer.outputline("maybe = (" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (" + rd.getSafeSymbol() + " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
357 writer.outputline("int "+dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " && " + rd.getSafeSymbol() + ";");
358 } else if (opcode == Opcode.OR) {
359 writer.outputline("int "+rm.getSafeSymbol()+"=maybe;");
360 writer.outputline("maybe = (!" + ld.getSafeSymbol() + " && " + rm.getSafeSymbol() + ") || (!" + rd.getSafeSymbol() +
361 " && " + lm.getSafeSymbol() + ") || (" + lm.getSafeSymbol() + " && " + rm.getSafeSymbol() + ");");
362 writer.outputline("int "+dest.getSafeSymbol() + " = " + ld.getSafeSymbol() + " || " + rd.getSafeSymbol() +
364 } else if (opcode != Opcode.NOT) { /* two operands */
366 writer.outputline("int " + dest.getSafeSymbol() + " = " +
367 ld.getSafeSymbol() + " " + opcode.toString() + " " + rd.getSafeSymbol() + ";");
368 } else if (opcode == Opcode.NOT) {
369 writer.outputline("int " + dest.getSafeSymbol() + " = !" + ld.getSafeSymbol() + ";");
373 public void prettyPrint(PrettyPrinter pp) {
375 if (opcode == Opcode.NOT) {
377 left.prettyPrint(pp);
378 } else if (opcode == Opcode.NOP) {
379 left.prettyPrint(pp);
380 } else if (opcode == Opcode.RND) {
382 left.prettyPrint(pp);
384 left.prettyPrint(pp);
385 pp.output(" " + opcode.toString() + " ");
386 assert right != null;
387 right.prettyPrint(pp);
392 public TypeDescriptor typecheck(SemanticAnalyzer sa) {
393 TypeDescriptor lt = left.typecheck(sa);
394 TypeDescriptor rt = right == null ? null : right.typecheck(sa);
398 } else if (right != null && rt == null) {
404 // #ATTN#: if we want node.next != literal(0) to represent a null check than we need to allow ptr arithmetic
405 // either that or we use a isvalid clause to check for null
408 if (lt != ReservedTypeDescriptor.INT) {
409 sa.getErrorReporter().report(null, "Left hand side of expression is of type '" + lt.getSymbol() + "' but must be type 'int'");
414 if (rt != ReservedTypeDescriptor.INT) {
415 sa.getErrorReporter().report(null, "Right hand side of expression is of type '" + rt.getSymbol() + "' but must be type 'int'");
425 this.td = ReservedTypeDescriptor.INT;