13 public UpdateNode(Rule r) {
15 bindings=new Vector();
16 invariants=new Vector();
17 binding=new Hashtable();
21 public Rule getRule() {
25 public String toString() {
28 for(int i=0;i<bindings.size();i++)
29 st+=bindings.get(i).toString()+"\n";
30 st+="---------------------\n";
32 for(int i=0;i<updates.size();i++)
33 st+=updates.get(i).toString()+"\n";
34 st+="---------------------\n";
36 for(int i=0;i<invariants.size();i++)
37 st+=((Expr)invariants.get(i)).name()+"\n";
38 st+="---------------------\n";
42 public void addBindings(Vector v) {
43 for (int i=0;i<v.size();i++) {
44 addBinding((Binding)v.get(i));
48 public boolean checkupdates(State state) {
49 if (!checkconflicts()) /* Do we have conflicting concrete updates */
51 if (!checknoupdates(state))
53 if (computeordering()) /* Ordering exists */
59 private boolean checknoupdates(State state) {
60 Set noupdate=state.noupdate;
61 for(int i=0;i<updates.size();i++) {
62 Updates u=(Updates)updates.get(i);
64 continue; /* Abstract updates don't change fields */
65 Descriptor d=u.getDescriptor();
66 if (noupdate.contains(d))
72 private boolean computeordering() {
73 /* Build dependency graph between updates */
74 HashSet graph=new HashSet();
75 Hashtable mapping=new Hashtable();
76 for(int i=0;i<updates.size();i++) {
77 Updates u=(Updates)updates.get(i);
78 GraphNode gn=new GraphNode(String.valueOf(i),u);
82 for(int i=0;i<updates.size();i++) {
83 Updates u1=(Updates)updates.get(i);
86 for(int j=0;j<updates.size();j++) {
87 Updates u2=(Updates)updates.get(j);
90 Descriptor d=u1.getDescriptor();
95 subexpr=((DotExpr)u2.getLeftExpr()).getExpr();
96 intindex=((DotExpr)u2.getLeftExpr()).getIndex();
98 if (u2.getRightExpr().usesDescriptor(d)||
99 (subexpr!=null&&subexpr.usesDescriptor(d))||
100 (intindex!=null&&intindex.usesDescriptor(d))) {
101 /* Add edge for dependency */
102 GraphNode gn1=(GraphNode) mapping.get(u1);
103 GraphNode gn2=(GraphNode) mapping.get(u2);
104 GraphNode.Edge e=new GraphNode.Edge("dependency",gn2);
110 if (!GraphNode.DFS.depthFirstSearch(graph)) /* DFS & check for acyclicity */
113 TreeSet topologicalsort = new TreeSet(new Comparator() {
114 public boolean equals(Object obj) { return false; }
115 public int compare(Object o1, Object o2) {
116 GraphNode g1 = (GraphNode) o1;
117 GraphNode g2 = (GraphNode) o2;
118 return g2.getFinishingTime() - g1.getFinishingTime();
121 topologicalsort.addAll(graph);
122 Vector sortedvector=new Vector();
123 for(Iterator sort=topologicalsort.iterator();sort.hasNext();) {
124 GraphNode gn=(GraphNode)sort.next();
125 sortedvector.add(gn.getOwner());
127 updates=sortedvector; //replace updates with the sorted array
131 private boolean checkconflicts() {
132 Set toremove=new HashSet();
133 for(int i=0;i<updates.size();i++) {
134 Updates u1=(Updates)updates.get(i);
135 if (!u1.isAbstract()) {
136 Descriptor d=u1.getDescriptor();
137 for(int j=0;j<invariants.size();j++) {
138 Expr invariant=(Expr)invariants.get(j);
139 if (invariant.usesDescriptor(d))
143 for(int j=0;j<updates.size();j++) {
144 Updates u2=(Updates)updates.get(j);
147 if (u1.isAbstract()||u2.isAbstract())
148 continue; /* Abstract updates are already accounted for by graph */
149 if (u1.getDescriptor()!=u2.getDescriptor())
150 continue; /* No interference - different descriptors */
152 if ((u1.getOpcode()==Opcode.GT||u1.getOpcode()==Opcode.GE)&&
153 (u2.getOpcode()==Opcode.GT||u2.getOpcode()==Opcode.GE))
154 continue; /* Can be satisfied simultaneously */
156 if ((u1.getOpcode()==Opcode.LT||u1.getOpcode()==Opcode.LE)&&
157 (u2.getOpcode()==Opcode.LT||u2.getOpcode()==Opcode.LE))
159 if ((u1.getOpcode()==u2.getOpcode())&&
160 u1.isExpr()&&u2.isExpr()&&
161 u1.getRightExpr().equals(null, u2.getRightExpr())) {
162 /*We'll remove the second occurence*/
170 /* Handle = or != NULL */
171 if ((((u1.getOpcode()==Opcode.EQ)&&(u2.getOpcode()==Opcode.NE))||
172 ((u1.getOpcode()==Opcode.NE)&&(u2.getOpcode()==Opcode.EQ)))&&
173 (((u1.isExpr()&&u1.getRightExpr().isNull())&&(!u2.isExpr()||u2.getRightExpr().isNonNull()))
174 ||((!u1.isExpr()||u1.getRightExpr().isNonNull())&&(u2.isExpr()&&u2.getRightExpr().isNull())))) {
175 if (u1.getOpcode()==Opcode.NE)
182 /* Handle = and != to different constants */
183 if ((((u1.getOpcode()==Opcode.EQ)&&(u2.getOpcode()==Opcode.NE))||
184 ((u1.getOpcode()==Opcode.NE)&&(u2.getOpcode()==Opcode.EQ)))&&
185 (u1.isExpr()&&u1.getRightExpr() instanceof LiteralExpr)&&
186 (u2.isExpr()&&u2.getRightExpr() instanceof LiteralExpr)&&
187 !u1.getRightExpr().equals(u2.getRightExpr())) {
188 if (u1.getOpcode()==Opcode.NE)
195 /* Compatible operations < & <= */
196 if (((u1.getOpcode()==Opcode.LT)||(u1.getOpcode()==Opcode.LE))&&
197 ((u2.getOpcode()==Opcode.LT)||(u2.getOpcode()==Opcode.LE)))
200 /* Compatible operations > & >= */
201 if (((u1.getOpcode()==Opcode.GT)||(u1.getOpcode()==Opcode.GE))&&
202 ((u2.getOpcode()==Opcode.GT)||(u2.getOpcode()==Opcode.GE)))
207 /* Equality & Comparisons */
210 return false; /* They interfere */
213 updates.removeAll(toremove);
217 public void addBinding(Binding b) {
219 binding.put(b.getVar(),b);
222 public int numBindings() {
223 return bindings.size();
226 public Binding getBinding(int i) {
227 return (Binding)bindings.get(i);
230 public Binding getBinding(VarDescriptor vd) {
231 if (binding.containsKey(vd))
232 return (Binding)binding.get(vd);
237 public void addInvariant(Expr e) {
241 public int numInvariants() {
242 return invariants.size();
245 public Expr getInvariant(int i) {
246 return (Expr)invariants.get(i);
249 public void addUpdate(Updates u) {
253 public int numUpdates() {
254 return updates.size();
256 public Updates getUpdate(int i) {
257 return (Updates)updates.get(i);
260 private MultUpdateNode getMultUpdateNode(boolean negate, Descriptor d, RepairGenerator rg) {
261 Termination termination=rg.termination;
262 MultUpdateNode mun=null;
265 gn=(GraphNode)termination.abstractremove.get(d);
267 gn=(GraphNode)termination.abstractadd.get(d);
268 TermNode tn=(TermNode)gn.getOwner();
269 for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
270 GraphNode gn2=((GraphNode.Edge) edgeit.next()).getTarget();
271 if (!rg.removed.contains(gn2)) {
272 TermNode tn2=(TermNode)gn2.getOwner();
273 if (tn2.getType()==TermNode.UPDATE) {
280 throw new Error("Can't find update node!");
284 public void generate_abstract(CodeWriter cr, Updates u, RepairGenerator rg) {
285 State state=rg.state;
286 Expr abstractexpr=u.getLeftExpr();
287 boolean negated=u.negate;
291 boolean istuple=false;
292 if (abstractexpr instanceof TupleOfExpr) {
293 TupleOfExpr toe=(TupleOfExpr) abstractexpr;
298 } else if (abstractexpr instanceof ElementOfExpr) {
299 ElementOfExpr eoe=(ElementOfExpr) abstractexpr;
304 throw new Error("Unsupported Expr");
306 MultUpdateNode mun=getMultUpdateNode(negated,d,rg);
307 VarDescriptor leftvar=VarDescriptor.makeNew("leftvar");
308 VarDescriptor rightvar=VarDescriptor.makeNew("rightvar");
309 left.generate(cr, leftvar);
311 right.generate(cr,rightvar);
315 RelationDescriptor rd=(RelationDescriptor)d;
316 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
317 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
319 cr.outputline("SimpleHashremove("+rg.stmodel+"->"+rd.getJustSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
321 cr.outputline("SimpleHashremove("+rg.stmodel+"->"+rd.getJustSafeSymbol()+"_hashinv, (int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
323 for(int i=0;i<state.vRules.size();i++) {
324 Rule r=(Rule)state.vRules.get(i);
325 if (r.getInclusion().getTargetDescriptors().contains(rd)) {
326 for(int j=0;j<mun.numUpdates();j++) {
327 UpdateNode un=mun.getUpdate(i);
328 if (un.getRule()==r) {
329 /* Update for rule rule r */
330 String name=(String)rg.updatenames.get(un);
331 cr.outputline("RepairHashaddrelation("+rg.strepairtable+","+rd.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+",(int) &"+name+");");
337 SetDescriptor sd=(SetDescriptor) d;
338 cr.outputline("SimpleHashremove("+rg.stmodel+"->"+sd.getJustSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
340 for(int i=0;i<state.vRules.size();i++) {
341 Rule r=(Rule)state.vRules.get(i);
342 if (r.getInclusion().getTargetDescriptors().contains(sd)) {
343 for(int j=0;j<mun.numUpdates();j++) {
344 UpdateNode un=mun.getUpdate(j);
345 if (un.getRule()==r) {
346 /* Update for rule rule r */
347 String name=(String)rg.updatenames.get(un);
348 cr.outputline("RepairHashaddset("+rg.strepairtable+","+sd.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
355 /* Generate update */
357 RelationDescriptor rd=(RelationDescriptor) d;
358 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
359 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
361 cr.outputline("SimpleHashadd("+rg.stmodel+"->"+rd.getJustSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
363 cr.outputline("SimpleHashadd("+rg.stmodel+"->"+rd.getJustSafeSymbol()+"_hashinv, (int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
365 UpdateNode un=mun.getUpdate(0);
366 String name=(String)rg.updatenames.get(un);
367 cr.outputline(name+"(this,"+rg.stmodel+","+rg.strepairtable+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+");");
369 SetDescriptor sd=(SetDescriptor)d;
370 cr.outputline("SimpleHashadd("+rg.stmodel+"->"+sd.getJustSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
372 UpdateNode un=mun.getUpdate(0);
373 /* Update for rule rule r */
374 String name=(String)rg.updatenames.get(un);
375 cr.outputline(name+"(this,"+rg.stmodel+","+rg.strepairtable+","+leftvar.getSafeSymbol()+");");
380 public void generate(CodeWriter cr, boolean removal, boolean modify, String slot0, String slot1, String slot2, RepairGenerator rg) {
381 if (!removal&&!modify)
382 generate_bindings(cr, slot0,slot1);
383 for(int i=0;i<updates.size();i++) {
384 Updates u=(Updates)updates.get(i);
385 VarDescriptor right=VarDescriptor.makeNew("right");
386 if (u.getType()==Updates.ABSTRACT) {
387 generate_abstract(cr, u, rg);
391 switch(u.getType()) {
393 u.getRightExpr().generate(cr,right);
395 case Updates.POSITION:
396 case Updates.ACCESSPATH:
397 if (u.getRightPos()==0) {
398 cr.addDeclaration("int", right.getSafeSymbol());
399 cr.outputline(right.getSafeSymbol()+"="+slot0+";");
400 } else if (u.getRightPos()==1) {
401 cr.addDeclaration("int", right.getSafeSymbol());
402 cr.outputline(right.getSafeSymbol()+"="+slot1+";");
403 } else if (u.getRightPos()==2) {
404 cr.addDeclaration("int", right.getSafeSymbol());
405 cr.outputline(right.getSafeSymbol()+"="+slot2+";");
406 } else throw new Error("Error w/ Position");
412 if (u.getType()==Updates.ACCESSPATH) {
413 VarDescriptor newright=VarDescriptor.makeNew("right");
414 generate_accesspath(cr, right,newright,u);
417 VarDescriptor left=VarDescriptor.makeNew("left");
418 u.getLeftExpr().generate(cr,left);
419 Opcode op=u.getOpcode();
420 cr.outputline("if (!("+left.getSafeSymbol()+op+right.getSafeSymbol()+"))");
424 cr.outputline(right.getSafeSymbol()+"++;");
425 else if (op==Opcode.GE)
427 else if (op==Opcode.EQ)
429 else if (op==Opcode.NE)
430 cr.outputline(right.getSafeSymbol()+"++;");
431 else if (op==Opcode.LT)
432 cr.outputline(right.getSafeSymbol()+"--;");
433 else if (op==Opcode.LE)
435 else throw new Error();
438 VarDescriptor vd=((VarExpr)u.getLeftExpr()).getVar();
439 cr.outputline(vd.getSafeSymbol()+"="+right.getSafeSymbol()+";");
440 if (Compiler.PRINTREPAIRS) {
441 cr.outputline("printf(\""+u.getLeftExpr().toString()+"=%d\\n\","+right.getSafeSymbol()+");");
443 } else if (u.isField()) {
445 Expr subexpr=((DotExpr)u.getLeftExpr()).getExpr();
446 Expr intindex=((DotExpr)u.getLeftExpr()).getIndex();
447 VarDescriptor subvd=VarDescriptor.makeNew("subexpr");
448 VarDescriptor indexvd=VarDescriptor.makeNew("index");
449 subexpr.generate(cr,subvd);
452 intindex.generate(cr,indexvd);
453 FieldDescriptor fd=(FieldDescriptor)u.getDescriptor();
454 if (Compiler.PRINTREPAIRS) {
455 if (intindex==null) {
456 cr.outputline("printf(\"0x%x."+fd.toString()+
457 "=%d\\n\","+subvd.getSafeSymbol()+","+right.getSafeSymbol()+");");
459 cr.outputline("printf(\"0x%x."+fd.toString()+
460 "[%d]=%d\\n\","+subvd.getSafeSymbol()+
461 ","+indexvd.getSafeSymbol()+","+right.getSafeSymbol()+");");
466 StructureTypeDescriptor std=(StructureTypeDescriptor)subexpr.getType();
467 Expr offsetbits = std.getOffsetExpr(fd);
468 if (fd instanceof ArrayDescriptor) {
469 fd = ((ArrayDescriptor) fd).getField();
472 if (intindex != null) {
473 Expr basesize = fd.getBaseSizeExpr();
474 offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex));
476 Expr offsetbytes = new OpExpr(Opcode.SHR, offsetbits,new IntegerLiteralExpr(3));
477 Expr byteaddress=new OpExpr(Opcode.ADD, offsetbytes, subexpr);
478 VarDescriptor addr=VarDescriptor.makeNew("byteaddress");
479 byteaddress.generate(cr,addr);
481 if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) {
482 ReservedTypeDescriptor rtd=(ReservedTypeDescriptor)fd.getType();
483 if (rtd==ReservedTypeDescriptor.INT) {
484 cr.outputline("*((int *) "+addr.getSafeSymbol()+")="+right.getSafeSymbol()+";");
485 } else if (rtd==ReservedTypeDescriptor.SHORT) {
486 cr.outputline("*((short *) "+addr.getSafeSymbol()+")="+right.getSafeSymbol()+";");
487 } else if (rtd==ReservedTypeDescriptor.BYTE) {
488 cr.outputline("*((char *) "+addr.getSafeSymbol()+")="+right.getSafeSymbol()+";");
489 } else if (rtd==ReservedTypeDescriptor.BIT) {
490 Expr tmp = new OpExpr(Opcode.SHL, offsetbytes, new IntegerLiteralExpr(3));
491 Expr offset=new OpExpr(Opcode.SUB, offsetbits, tmp);
492 Expr mask=new OpExpr(Opcode.SHL, new IntegerLiteralExpr(1), offset);
493 VarDescriptor maskvar=VarDescriptor.makeNew("mask");
494 mask.generate(cr,maskvar);
495 cr.outputline("*((char *) "+addr.getSafeSymbol()+")|="+maskvar.getSafeSymbol()+";");
496 cr.outputline("if (!"+right.getSafeSymbol()+")");
497 cr.outputline("*((char *) "+addr.getSafeSymbol()+")^="+maskvar.getSafeSymbol()+";");
498 } else throw new Error();
501 cr.outputline("*((int *) "+addr.getSafeSymbol()+")="+right.getSafeSymbol()+";");
509 private void generate_accesspath(CodeWriter cr, VarDescriptor right, VarDescriptor newright, Updates u) {
510 Vector dotvector=new Vector();
511 Expr ptr=u.getRightExpr();
512 VarExpr rightve=new VarExpr(right);
513 right.td=ReservedTypeDescriptor.INT;
516 /* Does something other than a dereference? */
518 if (ptr instanceof DotExpr)
519 ptr=((DotExpr)ptr).left;
520 else if (ptr instanceof CastExpr)
521 ptr=((CastExpr)ptr).getExpr();
522 if (ptr instanceof VarExpr) {
523 /* Finished constructing vector */
527 ArrayAnalysis.AccessPath ap=u.getAccessPath();
528 VarDescriptor init=VarDescriptor.makeNew("init");
530 cr.addDeclaration("int", init.getSafeSymbol());
531 cr.outputline(init.getSafeSymbol()+"= SimpleHashfirstkey("+ap.getSet().getSafeSymbol()+"_hash);");
532 init.td=ap.getSet().getType();
536 Expr newexpr=new VarExpr(init);
538 for(int i=dotvector.size()-1;i>=0;i--) {
539 Expr e=(Expr)dotvector.get(i);
540 if (e instanceof CastExpr) {
542 newexpr=new CastExpr(((CastExpr)e).getType(),newexpr);
543 } else if (e instanceof DotExpr) {
544 DotExpr de=(DotExpr)e;
545 if (de.getField() instanceof ArrayDescriptor) {
546 DotExpr de2=new DotExpr(newexpr,de.field,new IntegerLiteralExpr(0));
548 de2.fieldtype=de.fieldtype;
550 OpExpr offset=new OpExpr(Opcode.SUB,rightve,de2);
551 OpExpr index=new OpExpr(Opcode.DIV,offset,de.fieldtype.getSizeExpr());
552 if (u.getRightPos()==apindex) {
553 index.generate(cr,newright);
556 DotExpr de3=new DotExpr(newexpr,de.field,index);
559 de3.fieldtype=de.fieldtype;
563 DotExpr de2=new DotExpr(newexpr,de.field,null);
565 de2.fieldtype=de.fieldtype;
570 } else throw new Error();
575 private void generate_bindings(CodeWriter cr, String slot0, String slot1) {
576 for(int i=0;i<bindings.size();i++) {
577 Binding b=(Binding)bindings.get(i);
579 if (b.getType()==Binding.SEARCH) {
580 VarDescriptor vd=b.getVar();
581 cr.addDeclaration(vd.getType().getGenerateType().getSafeSymbol(), vd.getSafeSymbol());
582 cr.outputline(vd.getSafeSymbol()+"=SimpleHashfirstkey("+b.getSet().getSafeSymbol()+"_hash);");
583 } else if (b.getType()==Binding.CREATE) {
584 throw new Error("Creation not supported");
585 // source.generateSourceAlloc(cr,vd,b.getSet());
587 VarDescriptor vd=b.getVar();
588 switch(b.getPosition()) {
590 cr.addDeclaration(vd.getType().getGenerateType().getSafeSymbol(), vd.getSafeSymbol());
591 cr.outputline(vd.getSafeSymbol()+"="+slot0+";");
594 cr.addDeclaration(vd.getType().getGenerateType().getSafeSymbol(), vd.getSafeSymbol());
595 cr.outputline(vd.getSafeSymbol()+"="+slot1+";");
598 throw new Error("Slot >1 doesn't exist.");