332e58cd3932b2151e277e1be5a3b998ea8b35c6
[repair.git] / Repair / RepairCompiler / MCC / IR / RepairGenerator.java
1 package MCC.IR;
2
3 import java.io.*;
4 import java.util.*;
5 import MCC.State;
6 import MCC.Compiler;
7
8 public class RepairGenerator {
9     State state;
10     java.io.PrintWriter outputrepair = null;
11     java.io.PrintWriter outputaux = null;
12     java.io.PrintWriter outputhead = null;
13     String name="foo";
14     String headername;
15     static VarDescriptor oldmodel=null;
16     static VarDescriptor newmodel=null;
17     static VarDescriptor worklist=null;
18     static VarDescriptor repairtable=null;
19     static VarDescriptor goodflag=null;
20     Rule currentrule=null;
21     Hashtable updatenames;
22     HashSet usedupdates;
23     Termination termination;
24     Set removed;
25     HashSet togenerate;
26     static boolean DEBUG=false;
27     Cost cost;
28     ModelRuleDependence mrd;
29
30     public RepairGenerator(State state, Termination t) {
31         this.state = state;
32         updatenames=new Hashtable();
33         usedupdates=new HashSet();
34         termination=t;
35         removed=t.removedset;
36         togenerate=new HashSet();
37         togenerate.addAll(termination.conjunctions);
38         if (Compiler.REPAIR)
39             togenerate.removeAll(removed);
40         GraphNode.computeclosure(togenerate,removed);
41         cost=new Cost();
42         mrd=ModelRuleDependence.doAnalysis(state);
43         Repair.repairgenerator=this;
44     }
45
46     private void generatetypechecks(boolean flag) {
47         if (flag) {
48             DotExpr.DOTYPECHECKS=true;
49             VarExpr.DOTYPECHECKS=true;
50             DotExpr.DONULL=true;
51             VarExpr.DONULL=true;
52         } else {
53             VarExpr.DOTYPECHECKS=false;
54             DotExpr.DOTYPECHECKS=false;
55             VarExpr.DONULL=true;
56             DotExpr.DONULL=true;
57         }
58     }
59
60
61     private void name_updates() {
62         int count=0;
63         for(Iterator it=termination.updatenodes.iterator();it.hasNext();) {
64             GraphNode gn=(GraphNode) it.next();
65             TermNode tn=(TermNode) gn.getOwner();
66             MultUpdateNode mun=tn.getUpdate();
67             if (togenerate.contains(gn))
68             for (int i=0;i<mun.numUpdates();i++) {
69                 UpdateNode un=mun.getUpdate(i);
70                 String name="update"+String.valueOf(count++);
71                 updatenames.put(un,name);
72             }
73         }
74     }
75
76     public void generate(OutputStream outputrepair, OutputStream outputaux,OutputStream outputhead, String st) {
77         this.outputrepair = new java.io.PrintWriter(outputrepair, true);
78         this.outputaux = new java.io.PrintWriter(outputaux, true);
79         this.outputhead = new java.io.PrintWriter(outputhead, true);
80
81         headername=st;
82         name_updates();
83         generatetypechecks(true);
84         generate_tokentable();
85         RelationDescriptor.prefix = "thisvar->";
86         SetDescriptor.prefix = "thisvar->";
87
88         generate_hashtables();
89         generate_stateobject();
90
91
92         /* Rewrite globals */
93         CodeWriter craux = new StandardCodeWriter(this.outputaux);
94         for (Iterator it=this.state.stGlobals.descriptors();it.hasNext();) {
95             VarDescriptor vd=(VarDescriptor)it.next();
96             craux.outputline("#define "+vd.getSafeSymbol()+" thisvar->"+vd.getSafeSymbol());
97         }
98
99
100         generate_call();
101         generate_start();
102         generate_rules();
103         if (!Compiler.REPAIR||Compiler.GENERATEDEBUGPRINT) {
104             generate_print();
105         }
106         generate_checks();
107         generate_teardown();
108         CodeWriter crhead = new StandardCodeWriter(this.outputhead);
109         craux = new StandardCodeWriter(this.outputaux);
110         craux.outputline("}");
111
112         if (Compiler.GENERATEDEBUGHOOKS) {
113             crhead.outputline("void debughook();");
114             craux.outputline("void debughook() {}");
115         }
116         generatetypechecks(false);
117         generate_computesizes();
118         generatetypechecks(true);
119         generate_recomputesizes();
120         generatetypechecks(false);
121         generate_updates();
122         StructureGenerator sg=new StructureGenerator(state,this);
123         sg.buildall();
124         crhead.outputline("#endif");
125     }
126
127     String ststate="state";
128     String stmodel="model";
129     String strepairtable="repairtable";
130     String stleft="left";
131     String stright="right";
132     String stnew="newvalue";
133
134     private void generate_updates() {
135         int count=0;
136         CodeWriter crhead = new StandardCodeWriter(outputhead);
137         CodeWriter craux = new StandardCodeWriter(outputaux);
138         RelationDescriptor.prefix = "model->";
139         SetDescriptor.prefix = "model->";
140
141         /* Rewrite globals */
142
143         for (Iterator it=this.state.stGlobals.descriptors();it.hasNext();) {
144             VarDescriptor vd=(VarDescriptor)it.next();
145             craux.outputline("#undef "+vd.getSafeSymbol());
146             craux.outputline("#define "+vd.getSafeSymbol()+" "+ststate+"->"+vd.getSafeSymbol());
147         }
148
149         for(Iterator it=termination.updatenodes.iterator();it.hasNext();) {
150             GraphNode gn=(GraphNode) it.next();
151             TermNode tn=(TermNode) gn.getOwner();
152             MultUpdateNode mun=tn.getUpdate();
153             boolean isrelation=(mun.getDescriptor() instanceof RelationDescriptor);
154             if (togenerate.contains(gn))
155             for (int i=0;i<mun.numUpdates();i++) {
156                 UpdateNode un=mun.getUpdate(i);
157                 String methodname=(String)updatenames.get(un);
158
159                 switch(mun.op) {
160                 case MultUpdateNode.ADD:
161                     if (isrelation) {
162                         crhead.outputline("void "+methodname+"(struct "+name+"_state * " +ststate+",struct "+name+" * "+stmodel+", struct RepairHash * "+strepairtable+", int "+stleft+", int "+stright+");");
163                         craux.outputline("void "+methodname+"(struct "+name+"_state * "+ ststate+", struct "+name+" * "+stmodel+", struct RepairHash * "+strepairtable+", int "+stleft+", int "+stright+")");
164                     } else {
165                         crhead.outputline("void "+methodname+"(struct "+name+"_state * "+ ststate+", struct "+name+" * "+stmodel+", struct RepairHash * "+strepairtable+", int "+stleft+");");
166                         craux.outputline("void "+methodname+"(struct "+name+"_state * "+ststate+", struct "+name+" * "+stmodel+", struct RepairHash * "+strepairtable+", int "+stleft+")");
167                     }
168                     craux.startblock();
169                     craux.outputline("int maybe=0;");
170                     if (Compiler.GENERATEINSTRUMENT)
171                         craux.outputline("updatecount++;");
172
173                     final SymbolTable st = un.getRule().getSymbolTable();
174                     CodeWriter cr = new StandardCodeWriter(outputaux) {
175                         public SymbolTable getSymbolTable() { return st; }
176                     };
177                     un.generate(cr, false, false, stleft,stright, null,this);
178                     craux.outputline("if (maybe) printf(\"REALLY BAD\");");
179                     craux.endblock();
180                     break;
181                 case MultUpdateNode.REMOVE: {
182                     Rule r=un.getRule();
183                     String methodcall="void "+methodname+"(struct "+name+"_state * "+ststate+", struct "+name+" * "+stmodel+", struct RepairHash * "+strepairtable;
184                     for(int j=0;j<r.numQuantifiers();j++) {
185                         Quantifier q=r.getQuantifier(j);
186                         if (q instanceof SetQuantifier) {
187                             SetQuantifier sq=(SetQuantifier) q;
188                             methodcall+=","+sq.getVar().getType().getGenerateType().getSafeSymbol()+" "+sq.getVar().getSafeSymbol();
189                         } else if (q instanceof RelationQuantifier) {
190                             RelationQuantifier rq=(RelationQuantifier) q;
191
192                             methodcall+=","+rq.x.getType().getGenerateType().getSafeSymbol()+" "+rq.x.getSafeSymbol();
193                             methodcall+=","+rq.y.getType().getGenerateType().getSafeSymbol()+" "+rq.y.getSafeSymbol();
194                         } else if (q instanceof ForQuantifier) {
195                             ForQuantifier fq=(ForQuantifier) q;
196                             methodcall+=",int "+fq.getVar().getSafeSymbol();
197                         }
198                     }
199                     methodcall+=")";
200                     crhead.outputline(methodcall+";");
201                     craux.outputline(methodcall);
202                     craux.startblock();
203                     craux.outputline("int maybe=0;");
204                     if (Compiler.GENERATEINSTRUMENT)
205                         craux.outputline("updatecount++;");
206                     final SymbolTable st2 = un.getRule().getSymbolTable();
207                     CodeWriter cr2 = new StandardCodeWriter(outputaux) {
208                         public SymbolTable getSymbolTable() { return st2; }
209                     };
210                     un.generate(cr2, true, false, null,null, null,this);
211                     craux.outputline("if (maybe) printf(\"REALLY BAD\");");
212                     craux.endblock();
213                 }
214                     break;
215                 case MultUpdateNode.MODIFY: {
216                     Rule r=un.getRule();
217                     String methodcall="void "+methodname+"(struct "+name+"_state * "+ststate+", struct "+name+" * "+stmodel+", struct RepairHash * "+strepairtable;
218                     for(int j=0;j<r.numQuantifiers();j++) {
219                         Quantifier q=r.getQuantifier(j);
220                         if (q instanceof SetQuantifier) {
221                             SetQuantifier sq=(SetQuantifier) q;
222                             methodcall+=","+sq.getVar().getType().getGenerateType().getSafeSymbol()+" "+sq.getVar().getSafeSymbol();
223                         } else if (q instanceof RelationQuantifier) {
224                             RelationQuantifier rq=(RelationQuantifier) q;
225
226                             methodcall+=", "+rq.x.getType().getGenerateType().getSafeSymbol()+" "+rq.x.getSafeSymbol();
227                             methodcall+=", "+rq.y.getType().getGenerateType().getSafeSymbol()+" "+rq.y.getSafeSymbol();
228                         } else if (q instanceof ForQuantifier) {
229                             ForQuantifier fq=(ForQuantifier) q;
230                             methodcall+=", int "+fq.getVar().getSafeSymbol();
231                         }
232                     }
233                     methodcall+=", int "+stleft+", int "+stright+", int "+stnew;
234                     methodcall+=")";
235                     crhead.outputline(methodcall+";");
236                     craux.outputline(methodcall);
237                     craux.startblock();
238                     craux.outputline("int maybe=0;");
239                     if (Compiler.GENERATEINSTRUMENT)
240                         craux.outputline("updatecount++;");
241                     final SymbolTable st2 = un.getRule().getSymbolTable();
242                     CodeWriter cr2 = new StandardCodeWriter(outputaux) {
243                         public SymbolTable getSymbolTable() { return st2; }
244                     };
245                     un.generate(cr2, false, true, stleft, stright, stnew, this);
246                     craux.outputline("if (maybe) printf(\"REALLY BAD\");");
247                     craux.endblock();
248                 }
249                     break;
250
251                 default:
252                     throw new Error("Nonimplement Update");
253                 }
254             }
255         }
256     }
257
258     private void generate_call() {
259         CodeWriter cr = new StandardCodeWriter(outputrepair);
260         VarDescriptor vdstate=VarDescriptor.makeNew("repairstate");
261         cr.outputline("struct "+ name+"_state * "+vdstate.getSafeSymbol()+"=allocate"+name+"_state();");
262         Iterator globals=state.stGlobals.descriptors();
263         while (globals.hasNext()) {
264             VarDescriptor vd=(VarDescriptor) globals.next();
265             cr.outputline(vdstate.getSafeSymbol()+"->"+vd.getSafeSymbol()+"=("+vd.getType().getGenerateType().getSafeSymbol()+")"+vd.getSafeSymbol()+";");
266         }
267         /* Insert repair here */
268         cr.outputline("doanalysis("+vdstate.getSafeSymbol()+");");
269         globals=state.stGlobals.descriptors();
270         while (globals.hasNext()) {
271             VarDescriptor vd=(VarDescriptor) globals.next();
272             cr.outputline("*(("+vd.getType().getGenerateType().getSafeSymbol()+"*) &"+vd.getSafeSymbol()+")="+vdstate.getSafeSymbol()+"->"+vd.getSafeSymbol()+";");
273         }
274         cr.outputline("free"+name+"_state("+vdstate.getSafeSymbol()+");");
275     }
276
277     private void generate_tokentable() {
278         CodeWriter cr = new StandardCodeWriter(outputrepair);
279         Iterator tokens = TokenLiteralExpr.tokens.keySet().iterator();
280
281         cr.outputline("");
282         cr.outputline("/* Token values*/");
283         cr.outputline("");
284
285         while (tokens.hasNext()) {
286             Object token = tokens.next();
287             cr.outputline("/* " + token.toString() + " = " + TokenLiteralExpr.tokens.get(token).toString()+"*/");
288         }
289
290         cr.outputline("");
291         cr.outputline("");
292     }
293
294     private void generate_stateobject() {
295         CodeWriter crhead = new StandardCodeWriter(outputhead);
296         crhead.outputline("struct "+name+"_state {");
297         Iterator globals=state.stGlobals.descriptors();
298         while (globals.hasNext()) {
299             VarDescriptor vd=(VarDescriptor) globals.next();
300             crhead.outputline(vd.getType().getGenerateType().getSafeSymbol()+" "+vd.getSafeSymbol()+";");
301         }
302         crhead.outputline("};");
303         crhead.outputline("void "+name+"_statecomputesizes(struct "+name+"_state * ,int *,int **);");
304         crhead.outputline("void "+name+"_staterecomputesizes(struct "+name+"_state *);");
305     }
306
307     private void generate_computesizes() {
308         int max=TypeDescriptor.counter;
309         TypeDescriptor[] tdarray=new TypeDescriptor[max];
310         for(Iterator it=state.stTypes.descriptors();it.hasNext();) {
311             TypeDescriptor ttd=(TypeDescriptor)it.next();
312             tdarray[ttd.getId()]=ttd;
313         }
314         final SymbolTable st = state.stGlobals;
315         CodeWriter cr = new StandardCodeWriter(outputaux) {
316                 public SymbolTable getSymbolTable() { return st; }
317             };
318
319         cr.outputline("void "+name+"_statecomputesizes(struct "+name+"_state * thisvar,int *sizearray,int **numele) {");
320         cr.outputline("int maybe=0;");
321         for(int i=0;i<max;i++) {
322             TypeDescriptor td=tdarray[i];
323             Expr size=td.getSizeExpr();
324             VarDescriptor vd=VarDescriptor.makeNew("size");
325             size.generate(cr,vd);
326             cr.outputline("sizearray["+i+"]="+vd.getSafeSymbol()+";");
327         }
328         for(int i=0;i<max;i++) {
329             TypeDescriptor td=tdarray[i];
330             if (td instanceof StructureTypeDescriptor) {
331                 StructureTypeDescriptor std=(StructureTypeDescriptor) td;
332                 for(int j=0;j<std.fieldlist.size();j++) {
333                     FieldDescriptor fd=(FieldDescriptor)std.fieldlist.get(j);
334                     if (fd instanceof ArrayDescriptor) {
335                         ArrayDescriptor ad=(ArrayDescriptor)fd;
336                         Expr index=ad.getIndexBound();
337                         VarDescriptor vd=VarDescriptor.makeNew("index");
338                         index.generate(cr,vd);
339                         cr.outputline("numele["+i+"]["+j+"]="+vd.getSafeSymbol()+";");
340                     }
341                 }
342             }
343         }
344         cr.outputline("if (maybe) printf(\"BAD ERROR\");");
345         cr.outputline("}");
346     }
347
348     private void generate_recomputesizes() {
349         int max=TypeDescriptor.counter;
350         TypeDescriptor[] tdarray=new TypeDescriptor[max];
351         for(Iterator it=state.stTypes.descriptors();it.hasNext();) {
352             TypeDescriptor ttd=(TypeDescriptor)it.next();
353             tdarray[ttd.getId()]=ttd;
354         }
355         final SymbolTable st = state.stGlobals;
356         CodeWriter cr = new StandardCodeWriter(outputaux) {
357                 public SymbolTable getSymbolTable() { return st; }
358             };
359         cr.outputline("void "+name+"_staterecomputesizes(struct "+name+"_state * thisvar) {");
360         cr.outputline("int maybe=0;");
361         for(int i=0;i<max;i++) {
362             TypeDescriptor td=tdarray[i];
363             Expr size=td.getSizeExpr();
364             VarDescriptor vd=VarDescriptor.makeNew("size");
365             size.generate(cr,vd);
366         }
367         for(int i=0;i<max;i++) {
368             TypeDescriptor td=tdarray[i];
369             if (td instanceof StructureTypeDescriptor) {
370                 StructureTypeDescriptor std=(StructureTypeDescriptor) td;
371                 for(int j=0;j<std.fieldlist.size();j++) {
372                     FieldDescriptor fd=(FieldDescriptor)std.fieldlist.get(j);
373                     if (fd instanceof ArrayDescriptor) {
374                         ArrayDescriptor ad=(ArrayDescriptor)fd;
375                         Expr index=ad.getIndexBound();
376                         VarDescriptor vd=VarDescriptor.makeNew("index");
377                         index.generate(cr,vd);
378                     }
379                 }
380             }
381         }
382         cr.outputline("if (maybe) printf(\"BAD ERROR\");");
383         cr.outputline("}");
384     }
385
386
387     private void generate_hashtables() {
388         CodeWriter craux = new StandardCodeWriter(outputaux);
389         CodeWriter crhead = new StandardCodeWriter(outputhead);
390         crhead.outputline("#ifndef "+name+"_h");
391         crhead.outputline("#define "+name+"_h");
392         crhead.outputline("#include \"SimpleHash.h\"");
393         crhead.outputline("#include \"instrument.h\"");
394         crhead.outputline("#include <stdio.h>");
395         crhead.outputline("#include <stdlib.h>");
396         crhead.outputline("struct "+name+" * allocate"+name+"();");
397         crhead.outputline("void free"+name+"(struct "+name+" *);");
398         crhead.outputline("struct "+name+" {");
399         craux.outputline("#include \""+headername+"\"");
400         craux.outputline("#include \"size.h\"");
401         if (Compiler.TIME) {
402             craux.outputline("#include <sys/time.h>");
403         }
404         if (Compiler.ALLOCATECPLUSPLUS) {
405             for(Iterator it=state.stTypes.descriptors();it.hasNext();) {
406                 TypeDescriptor td=(TypeDescriptor)it.next();
407                 if (td instanceof StructureTypeDescriptor) {
408                     if (((StructureTypeDescriptor)td).size()>0) {
409                         FieldDescriptor fd=((StructureTypeDescriptor)td).get(0);
410                         if (fd.getSymbol().startsWith("_vptr_")) {
411                             String vtable="_ZTV";
412                             vtable+=td.getSymbol().length();
413                             vtable+=td.getSymbol();
414                             craux.outputline("extern void * "+vtable+";");
415                         }
416                     }
417                 }
418             }
419         }
420         craux.outputline("struct "+ name+"* "+name+"() {");
421         craux.outputline("/* creating hashtables */");
422
423         /* build sets */
424         Iterator sets = state.stSets.descriptors();
425         craux.outputline("struct "+name+"* thisvar=(struct "+name+"*) malloc(sizeof(struct "+name+"));");
426
427         /* first pass create all the hash tables */
428         while (sets.hasNext()) {
429             SetDescriptor set = (SetDescriptor) sets.next();
430             crhead.outputline("struct SimpleHash* " + set.getJustSafeSymbol() + "_hash;");
431             craux.outputline(set.getSafeSymbol() + "_hash = noargallocateSimpleHash();");
432         }
433
434         /* second pass build relationships between hashtables */
435         sets = state.stSets.descriptors();
436
437         while (sets.hasNext()) {
438             SetDescriptor set = (SetDescriptor) sets.next();
439             Iterator subsets = set.subsets();
440
441             while (subsets.hasNext()) {
442                 SetDescriptor subset = (SetDescriptor) subsets.next();
443                 craux.outputline("SimpleHashaddParent("+subset.getSafeSymbol() +"_hash ,"+ set.getSafeSymbol() + "_hash);");
444             }
445         }
446
447         /* build relations */
448         Iterator relations = state.stRelations.descriptors();
449
450         /* first pass create all the hash tables */
451         while (relations.hasNext()) {
452             RelationDescriptor relation = (RelationDescriptor) relations.next();
453
454             if (relation.testUsage(RelationDescriptor.IMAGE)) {
455                 crhead.outputline("struct SimpleHash* " + relation.getJustSafeSymbol() + "_hash;");
456                 craux.outputline(relation.getSafeSymbol() + "_hash = noargallocateSimpleHash();");
457             }
458
459             if (relation.testUsage(RelationDescriptor.INVIMAGE)) {
460                 crhead.outputline("struct SimpleHash* " + relation.getJustSafeSymbol() + "_hashinv;");
461                 craux.outputline(relation.getSafeSymbol() + "_hashinv = noargallocateSimpleHash();");
462             }
463         }
464
465         craux.outputline("}");
466         crhead.outputline("};");
467         craux.outputline("void free"+name+"(struct "+ name +"* thisvar) {");
468         craux.outputline("/* deleting hashtables */");
469
470         /* build destructor */
471         sets = state.stSets.descriptors();
472
473         /* first pass create all the hash tables */
474         while (sets.hasNext()) {
475             SetDescriptor set = (SetDescriptor) sets.next();
476             craux.outputline("freeSimpleHash("+set.getSafeSymbol() + "_hash);");
477         }
478
479         /* destroy relations */
480         relations = state.stRelations.descriptors();
481
482         /* first pass create all the hash tables */
483         while (relations.hasNext()) {
484             RelationDescriptor relation = (RelationDescriptor) relations.next();
485
486             if (relation.testUsage(RelationDescriptor.IMAGE)) {
487                 craux.outputline("freeSimpleHash("+relation.getSafeSymbol() + "_hash);");
488             }
489
490             if (relation.testUsage(RelationDescriptor.INVIMAGE)) {
491                 craux.outputline("freeSimpleHash(" + relation.getSafeSymbol() + "_hashinv);");
492             }
493         }
494         craux.outputline("free(thisvar);");
495         craux.outputline("}");
496     }
497
498     private void generate_start() {
499         CodeWriter crhead = new StandardCodeWriter(outputhead);
500         CodeWriter craux = new StandardCodeWriter(outputaux);
501         oldmodel=VarDescriptor.makeNew("oldmodel");
502         newmodel=VarDescriptor.makeNew("newmodel");
503         worklist=VarDescriptor.makeNew("worklist");
504         goodflag=VarDescriptor.makeNew("goodflag");
505         repairtable=VarDescriptor.makeNew("repairtable");
506
507         if (Compiler.GENERATEINSTRUMENT) {
508             craux.outputline("int updatecount;");
509             craux.outputline("int rebuildcount;");
510             craux.outputline("int abstractcount;");
511         }
512
513         crhead.outputline("void doanalysis(struct "+name+"_state *);");
514         craux.outputline("void doanalysis(struct "+name+"_state * thisvar)");
515         craux.startblock();
516         if (Compiler.TIME) {
517             craux.outputline("struct timeval _begin_time,_end_time;");
518             craux.outputline("gettimeofday(&_begin_time,NULL);");
519         }
520         if (Compiler.GENERATEINSTRUMENT) {
521             craux.outputline("updatecount=0;");
522             craux.outputline("rebuildcount=0;");
523             craux.outputline("abstractcount=0;");
524         }
525         craux.outputline("int highmark;");
526         craux.outputline("struct "+name+ " * "+oldmodel.getSafeSymbol()+"=0;");
527         craux.outputline("struct WorkList * "+worklist.getSafeSymbol()+" = allocateWorkList();");
528         craux.outputline("struct RepairHash * "+repairtable.getSafeSymbol()+"=0;");
529         craux.outputline("initializestack(&highmark);");
530         craux.outputline("computesizes(thisvar);");
531         craux.outputline(name+"_staterecomputesizes(thisvar);");
532         craux.outputline("while (1)");
533         craux.startblock();
534         craux.outputline("struct "+name+ " * "+newmodel.getSafeSymbol()+"=allocate"+name+"();");
535         craux.outputline("WorkListreset("+worklist.getSafeSymbol()+");");
536         if (Compiler.GENERATEINSTRUMENT)
537             craux.outputline("rebuildcount++;");
538     }
539
540     private void generate_teardown() {
541         CodeWriter cr = new StandardCodeWriter(outputaux);
542         cr.endblock();
543         if (Compiler.TIME) {
544             cr.outputline("gettimeofday(&_end_time,NULL);");
545             cr.outputline("printf(\"time=%ld uS\\n\",(_end_time.tv_sec-_begin_time.tv_sec)*1000000+_end_time.tv_usec-_begin_time.tv_usec);");
546         }
547
548         if (Compiler.GENERATEINSTRUMENT) {
549             cr.outputline("printf(\"updatecount=%d\\n\",updatecount);");
550             cr.outputline("printf(\"rebuildcount=%d\\n\",rebuildcount);");
551             cr.outputline("printf(\"abstractcount=%d\\n\",abstractcount);");
552         }
553
554     }
555
556     private void generate_print() {
557
558         final SymbolTable st = new SymbolTable();
559
560         CodeWriter cr = new StandardCodeWriter(outputaux) {
561                 public SymbolTable getSymbolTable() { return st; }
562             };
563
564         cr.outputline("/* printing sets!*/");
565         cr.outputline("printf(\"\\n\\nPRINTING SETS AND RELATIONS\\n\");");
566
567         Iterator setiterator = state.stSets.descriptors();
568         while (setiterator.hasNext()) {
569             SetDescriptor sd = (SetDescriptor) setiterator.next();
570             if (sd.getSymbol().equals("int") || sd.getSymbol().equals("token")) {
571                 continue;
572             }
573
574             String setname = sd.getSafeSymbol();
575
576             cr.startblock();
577             cr.outputline("/* printing set " + setname+"*/");
578             cr.outputline("printf(\"\\nPrinting set " + sd.getSymbol() + " - %d elements \\n\", SimpleHashcountset("+setname+"_hash));");
579             cr.outputline("struct SimpleIterator __setiterator;");
580             cr.outputline("SimpleHashiterator(&"+setname+"_hash,__setiterator);");
581             cr.outputline("while (hasNext(&__setiterator))");
582             cr.startblock();
583             cr.outputline("int __setval = (int) next(&__setiterator);");
584
585             TypeDescriptor td = sd.getType();
586             if (td instanceof StructureTypeDescriptor) {
587                 StructureTypeDescriptor std = (StructureTypeDescriptor) td;
588                 VarDescriptor vd = new VarDescriptor ("__setval", "__setval", td, false);
589                 std.generate_printout(cr, vd);
590             } else { // Missing type descriptor or reserved type, just print int
591                 cr.outputline("printf(\"<%d> \", __setval);");
592             }
593
594
595             cr.endblock();
596             cr.endblock();
597         }
598
599         cr.outputline("printf(\"\\n\\n------------------- END PRINTING\\n\");");
600     }
601
602     Set ruleset=null;
603     private void generate_rules() {
604         /* first we must sort the rules */
605         RelationDescriptor.prefix = newmodel.getSafeSymbol()+"->";
606         SetDescriptor.prefix = newmodel.getSafeSymbol()+"->";
607         System.out.println("SCC="+(mrd.numSCC()-1));
608         for(int sccindex=0;sccindex<mrd.numSCC();sccindex++) {
609             ruleset=mrd.getSCC(sccindex);
610             boolean needworklist=mrd.hasCycle(sccindex);
611
612             if (!needworklist) {
613                 Iterator iterator_rs = ruleset.iterator();
614                 while (iterator_rs.hasNext()) {
615                     Rule rule = (Rule) iterator_rs.next();
616                     if (rule.getnogenerate())
617                         continue;
618                     {
619                         final SymbolTable st = rule.getSymbolTable();
620                         CodeWriter cr = new StandardCodeWriter(outputaux) {
621                                 public SymbolTable getSymbolTable() { return st; }
622                             };
623                         InvariantValue ivalue=new InvariantValue();
624                         cr.setInvariantValue(ivalue);
625
626                         cr.outputline("/* build " +escape(rule.toString())+"*/");
627                         cr.startblock();
628                         cr.outputline("int maybe=0;");
629
630                         Expr ruleexpr=rule.getGuardExpr();
631                         HashSet invariantvars=new HashSet();
632                         Set invariants=ruleexpr.findInvariants(invariantvars);
633
634                         if ((ruleexpr instanceof BooleanLiteralExpr)&&
635                             ((BooleanLiteralExpr)ruleexpr).getValue()) {
636                             if (rule.getInclusion() instanceof SetInclusion) {
637                                 invariants.addAll(((SetInclusion)rule.getInclusion()).getExpr().findInvariants(invariantvars));
638                             } else if (rule.getInclusion() instanceof RelationInclusion) {
639                                 invariants.addAll(((RelationInclusion)rule.getInclusion()).getLeftExpr().findInvariants(invariantvars));
640                                 invariants.addAll(((RelationInclusion)rule.getInclusion()).getRightExpr().findInvariants(invariantvars));
641                             }
642                         }
643                         ListIterator quantifiers = rule.quantifiers();
644                         while (quantifiers.hasNext()) {
645                             Quantifier quantifier = (Quantifier) quantifiers.next();
646                             if (quantifier instanceof ForQuantifier) {
647                                 ForQuantifier fq=(ForQuantifier)quantifier;
648                                 invariants.addAll(fq.lower.findInvariants(invariantvars));
649                                 invariants.addAll(fq.upper.findInvariants(invariantvars));
650                             }
651                         }
652
653                         int openparencount=0;
654                         for(Iterator invit=invariants.iterator();invit.hasNext();) {
655                             Expr invexpr=(Expr)invit.next();
656                             VarDescriptor tmpvd=VarDescriptor.makeNew("tmpvar");
657                             VarDescriptor maybevd=VarDescriptor.makeNew("maybevar");
658                             invexpr.generate(cr,tmpvd);
659                             cr.outputline("int "+maybevd.getSafeSymbol()+"=maybe;");
660                             cr.outputline("maybe=0;");
661                             ivalue.assignPair(invexpr,tmpvd,maybevd);
662                             openparencount++;
663                             cr.startblock();
664                         }
665                         quantifiers = rule.quantifiers();
666                         while (quantifiers.hasNext()) {
667                             Quantifier quantifier = (Quantifier) quantifiers.next();
668                             quantifier.generate_open(cr);
669                         }
670
671                         /* pretty print! */
672                         cr.output("/*");
673                         rule.getGuardExpr().prettyPrint(cr);
674                         cr.outputline("*/");
675
676                         /* now we have to generate the guard test */
677                         VarDescriptor guardval = VarDescriptor.makeNew();
678                         rule.getGuardExpr().generate(cr, guardval);
679                         cr.outputline("if (" + guardval.getSafeSymbol() + ")");
680                         cr.startblock();
681
682                         /* now we have to generate the inclusion code */
683                         currentrule=rule;
684                         rule.getInclusion().generate(cr);
685                         cr.endblock();
686                         while (quantifiers.hasPrevious()) {
687                             Quantifier quantifier = (Quantifier) quantifiers.previous();
688                             cr.endblock();
689                         }
690                         cr.endblock();
691                         while((openparencount--)>0)
692                             cr.endblock();
693                         cr.outputline("");
694                         cr.outputline("");
695                     }
696                 }
697             } else {
698                 CodeWriter cr2 = new StandardCodeWriter(outputaux);
699
700                 for(Iterator initialworklist=ruleset.iterator();initialworklist.hasNext();) {
701                     /** Construct initial worklist set */
702                     Rule rule=(Rule)initialworklist.next();
703                     cr2.outputline("WorkListadd("+worklist.getSafeSymbol()+","+rule.getNum()+",-1,0,0);");
704                 }
705
706                 cr2.outputline("while (WorkListhasMoreElements("+worklist.getSafeSymbol()+"))");
707                 cr2.startblock();
708                 VarDescriptor idvar=VarDescriptor.makeNew("id");
709                 cr2.outputline("int "+idvar.getSafeSymbol()+"=WorkListgetid("+worklist.getSafeSymbol()+");");
710
711                 String elseladder = "if";
712
713                 Iterator iterator_rules = ruleset.iterator();
714                 while (iterator_rules.hasNext()) {
715
716                     Rule rule = (Rule) iterator_rules.next();
717                     int dispatchid = rule.getNum();
718
719                     {
720                         final SymbolTable st = rule.getSymbolTable();
721                         CodeWriter cr = new StandardCodeWriter(outputaux) {
722                                 public SymbolTable getSymbolTable() { return st; }
723                             };
724
725                         cr.indent();
726                         cr.outputline(elseladder + " ("+idvar.getSafeSymbol()+" == " + dispatchid + ")");
727                         cr.startblock();
728                         cr.outputline("int maybe=0;");
729                         VarDescriptor typevar=VarDescriptor.makeNew("type");
730                         VarDescriptor leftvar=VarDescriptor.makeNew("left");
731                         VarDescriptor rightvar=VarDescriptor.makeNew("right");
732                         cr.outputline("int "+typevar.getSafeSymbol()+"= WorkListgettype("+worklist.getSafeSymbol()+");");
733                         cr.outputline("int "+leftvar.getSafeSymbol()+"= WorkListgetlvalue("+worklist.getSafeSymbol()+");");
734                         cr.outputline("int "+rightvar.getSafeSymbol()+"= WorkListgetrvalue("+worklist.getSafeSymbol()+");");
735                         cr.outputline("/* build " +escape(rule.toString())+"*/");
736
737
738                         for (int j=0;j<rule.numQuantifiers();j++) {
739                             Quantifier quantifier = rule.getQuantifier(j);
740                             quantifier.generate_open(cr, typevar.getSafeSymbol(),j,leftvar.getSafeSymbol(),rightvar.getSafeSymbol());
741                         }
742
743                         /* pretty print! */
744                         cr.output("/*");
745
746                         rule.getGuardExpr().prettyPrint(cr);
747                         cr.outputline("*/");
748
749                         /* now we have to generate the guard test */
750
751                         VarDescriptor guardval = VarDescriptor.makeNew();
752                         rule.getGuardExpr().generate(cr, guardval);
753
754                         cr.outputline("if (" + guardval.getSafeSymbol() + ")");
755                         cr.startblock();
756
757                         /* now we have to generate the inclusion code */
758                         currentrule=rule;
759                         rule.getInclusion().generate(cr);
760                         cr.endblock();
761
762                         for (int j=0;j<rule.numQuantifiers();j++) {
763                             cr.endblock();
764                         }
765
766                         // close startblocks generated by DotExpr memory checks
767                         //DotExpr.generate_memory_endblocks(cr);
768
769                         cr.endblock(); // end else-if WORKLIST ladder
770
771                         elseladder = "else if";
772                     }
773                 }
774                 cr2.outputline("else");
775                 cr2.startblock();
776                 cr2.outputline("printf(\"VERY BAD !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\\n\\n\");");
777                 cr2.outputline("exit(1);");
778                 cr2.endblock();
779                 // end block created for worklist
780                 cr2.outputline("WorkListpop("+worklist.getSafeSymbol()+");");
781                 cr2.endblock();
782             }
783         }
784     }
785
786     public static String escape(String s) {
787         String newstring="";
788         for(int i=0;i<s.length();i++) {
789             char c=s.charAt(i);
790             if (c=='"')
791                 newstring+="\"";
792             else
793                 newstring+=c;
794         }
795         return newstring;
796     }
797
798     private void generate_checks() {
799         /* do constraint checks */
800         Iterator i;
801         if (Compiler.REPAIR)
802             i=termination.constraintdependence.computeOrdering().iterator();
803         else
804             i=state.vConstraints.iterator();
805         for (; i.hasNext();) {
806             Constraint constraint;
807             if (Compiler.REPAIR)
808                 constraint= (Constraint) ((GraphNode)i.next()).getOwner();
809             else
810                 constraint=(Constraint)i.next();
811
812             {
813                 final SymbolTable st = constraint.getSymbolTable();
814                 CodeWriter cr = new StandardCodeWriter(outputaux);
815                 cr.pushSymbolTable(constraint.getSymbolTable());
816
817                 cr.outputline("/* checking " + escape(constraint.toString())+"*/");
818                 cr.startblock();
819
820                 ListIterator quantifiers = constraint.quantifiers();
821
822                 while (quantifiers.hasNext()) {
823                     Quantifier quantifier = (Quantifier) quantifiers.next();
824                     quantifier.generate_open(cr);
825                 }
826
827                 cr.outputline("int maybe = 0;");
828
829                 /* now we have to generate the guard test */
830
831                 VarDescriptor constraintboolean = VarDescriptor.makeNew("constraintboolean");
832                 constraint.getLogicStatement().generate(cr, constraintboolean);
833
834                 cr.outputline("if (maybe)");
835                 cr.startblock();
836                 cr.outputline("printf(\"maybe fail " +  escape(constraint.toString()) + ". \\n\");");
837                 //cr.outputline("exit(1);");
838                 cr.endblock();
839
840                 cr.outputline("else if (!" + constraintboolean.getSafeSymbol() + ")");
841                 cr.startblock();
842                 if (!Compiler.REPAIR||Compiler.GENERATEDEBUGHOOKS)
843                     cr.outputline("printf(\"fail " + escape(constraint.toString()) + ". \\n\");");
844
845                 if (Compiler.REPAIR) {
846                 /* Do repairs */
847                 /* Build new repair table */
848
849                 cr.outputline("if ("+repairtable.getSafeSymbol()+")");
850                 cr.outputline("freeRepairHash("+repairtable.getSafeSymbol()+");");
851                 cr.outputline(repairtable.getSafeSymbol()+"=noargallocateRepairHash();");
852
853                 if (Compiler.GENERATEDEBUGHOOKS)
854                     cr.outputline("debughook();");
855                 /* Compute cost of each repair */
856                 VarDescriptor mincost=VarDescriptor.makeNew("mincost");
857                 VarDescriptor mincostindex=VarDescriptor.makeNew("mincostindex");
858                 Vector dnfconst=new Vector();
859                 dnfconst.addAll((Set)termination.conjunctionmap.get(constraint));
860
861                 if (dnfconst.size()<=1) {
862                     cr.outputline("int "+mincostindex.getSafeSymbol()+"=0;");
863                 }
864                 if (dnfconst.size()>1) {
865                     cr.outputline("int "+mincostindex.getSafeSymbol()+";");
866                     boolean first=true;
867                     for(int j=0;j<dnfconst.size();j++) {
868                         GraphNode gn=(GraphNode)dnfconst.get(j);
869                         Conjunction conj=((TermNode)gn.getOwner()).getConjunction();
870                         if (removed.contains(gn))
871                             continue;
872
873                         VarDescriptor costvar;
874                         if (first) {
875                             costvar=mincost;
876                         } else
877                             costvar=VarDescriptor.makeNew("cost");
878                         for(int k=0;k<conj.size();k++) {
879                             DNFPredicate dpred=conj.get(k);
880                             Predicate p=dpred.getPredicate();
881                             boolean negate=dpred.isNegated();
882                             VarDescriptor predvalue=VarDescriptor.makeNew("Predicatevalue");
883                             p.generate(cr,predvalue);
884                             if (k==0)
885                                 cr.outputline("int "+costvar.getSafeSymbol()+"=0;");
886
887                             if (negate)
888                                 cr.outputline("if (maybe||"+predvalue.getSafeSymbol()+")");
889                             else
890                                 cr.outputline("if (maybe||!"+predvalue.getSafeSymbol()+")");
891                             cr.outputline(costvar.getSafeSymbol()+"+="+cost.getCost(dpred)+";");
892                         }
893
894                         if(!first) {
895                             cr.outputline("if ("+costvar.getSafeSymbol()+"<"+mincost.getSafeSymbol()+")");
896                             cr.startblock();
897                             cr.outputline(mincost.getSafeSymbol()+"="+costvar.getSafeSymbol()+";");
898                             cr.outputline(mincostindex.getSafeSymbol()+"="+j+";");
899                             cr.endblock();
900                         } else
901                             cr.outputline(mincostindex.getSafeSymbol()+"="+j+";");
902                         first=false;
903                     }
904                 }
905                 cr.outputline("switch("+mincostindex.getSafeSymbol()+") {");
906                 for(int j=0;j<dnfconst.size();j++) {
907                     GraphNode gn=(GraphNode)dnfconst.get(j);
908                     Conjunction conj=((TermNode)gn.getOwner()).getConjunction();
909                     if (removed.contains(gn))
910                         continue;
911                     cr.outputline("case "+j+":");
912                     cr.startblock();
913                     for(int k=0;k<conj.size();k++) {
914                         DNFPredicate dpred=conj.get(k);
915                         Predicate p=dpred.getPredicate();
916                         boolean negate=dpred.isNegated();
917                         VarDescriptor predvalue=VarDescriptor.makeNew("Predicatevalue");
918                         p.generate(cr,predvalue);
919                         if (negate)
920                             cr.outputline("if (maybe||"+predvalue.getSafeSymbol()+")");
921                         else
922                             cr.outputline("if (maybe||!"+predvalue.getSafeSymbol()+")");
923                         cr.startblock();
924                         if (Compiler.GENERATEINSTRUMENT)
925                             cr.outputline("abstractcount++;");
926                         if (p instanceof InclusionPredicate)
927                             generateinclusionrepair(conj,dpred, cr);
928                         else if (p instanceof ExprPredicate) {
929                             ExprPredicate ep=(ExprPredicate)p;
930                             if (ep.getType()==ExprPredicate.SIZE)
931                                 generatesizerepair(conj,dpred,cr);
932                             else if (ep.getType()==ExprPredicate.COMPARISON)
933                                 generatecomparisonrepair(conj,dpred,cr);
934                         } else throw new Error("Unrecognized Predicate");
935                         cr.endblock();
936                     }
937                     /* Update model */
938                     cr.endblock();
939                     cr.outputline("break;");
940                 }
941                 cr.outputline("}");
942
943                 cr.outputline("if ("+oldmodel.getSafeSymbol()+")");
944                 cr.outputline("free"+name+"("+oldmodel.getSafeSymbol()+");");
945                 cr.outputline(oldmodel.getSafeSymbol()+"="+newmodel.getSafeSymbol()+";");
946                 cr.outputline("goto rebuild;");  /* Rebuild model and all */
947                 }
948                 cr.endblock();
949
950                 while (quantifiers.hasPrevious()) {
951                     Quantifier quantifier = (Quantifier) quantifiers.previous();
952                     cr.endblock();
953                 }
954                 cr.endblock();
955                 cr.outputline("");
956                 cr.outputline("");
957             }
958         }
959         CodeWriter cr = new StandardCodeWriter(outputaux);
960         cr.startblock();
961         cr.outputline("if ("+repairtable.getSafeSymbol()+")");
962         cr.outputline("freeRepairHash("+repairtable.getSafeSymbol()+");");
963         cr.outputline("if ("+oldmodel.getSafeSymbol()+")");
964         cr.outputline("free"+name+"("+oldmodel.getSafeSymbol()+");");
965         cr.outputline("free"+name+"("+newmodel.getSafeSymbol()+");");
966         cr.outputline("freeWorkList("+worklist.getSafeSymbol()+");");
967         cr.outputline("resettypemap();");
968         cr.outputline("break;");
969         cr.endblock();
970         cr.outputline("rebuild:");
971         cr.outputline(";");
972     }
973
974     private MultUpdateNode getmultupdatenode(Conjunction conj, DNFPredicate dpred, int repairtype) {
975         Set nodes=getmultupdatenodeset(conj,dpred,repairtype);
976         Iterator it=nodes.iterator();
977         if (it.hasNext())
978             return (MultUpdateNode)it.next();
979         else
980             return null;
981     }
982
983     private Set getmultupdatenodeset(Conjunction conj, DNFPredicate dpred, int repairtype) {
984         HashSet hs=new HashSet();
985         GraphNode gn=(GraphNode) termination.conjtonodemap.get(conj);
986         for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
987             GraphNode gn2=((GraphNode.Edge) edgeit.next()).getTarget();
988             TermNode tn2=(TermNode)gn2.getOwner();
989             if (tn2.getType()==TermNode.ABSTRACT) {
990                 AbstractRepair ar=tn2.getAbstract();
991                 if (((repairtype==-1)||(ar.getType()==repairtype))&&
992                     ar.getPredicate()==dpred) {
993                     for(Iterator edgeit2=gn2.edges();edgeit2.hasNext();) {
994                         GraphNode gn3=((GraphNode.Edge) edgeit2.next()).getTarget();
995                         if (!removed.contains(gn3)) {
996                             TermNode tn3=(TermNode)gn3.getOwner();
997                             if (tn3.getType()==TermNode.UPDATE) {
998                                 hs.add(tn3.getUpdate());
999                             }
1000                         }
1001                     }
1002                 }
1003             }
1004         }
1005         return hs;
1006     }
1007
1008     private AbstractRepair getabstractrepair(Conjunction conj, DNFPredicate dpred, int repairtype) {
1009         HashSet hs=new HashSet();
1010         MultUpdateNode mun=null;
1011         GraphNode gn=(GraphNode) termination.conjtonodemap.get(conj);
1012         for(Iterator edgeit=gn.edges();(mun==null)&&edgeit.hasNext();) {
1013             GraphNode gn2=((GraphNode.Edge) edgeit.next()).getTarget();
1014             TermNode tn2=(TermNode)gn2.getOwner();
1015             if (tn2.getType()==TermNode.ABSTRACT) {
1016                 AbstractRepair ar=tn2.getAbstract();
1017                 if (((repairtype==-1)||(ar.getType()==repairtype))&&
1018                     ar.getPredicate()==dpred) {
1019                     return ar;
1020                 }
1021             }
1022         }
1023         return null;
1024     }
1025
1026
1027     /** Generates abstract (and concrete) repair for a comparison */
1028
1029     private void generatecomparisonrepair(Conjunction conj, DNFPredicate dpred, CodeWriter cr){
1030         Set updates=getmultupdatenodeset(conj,dpred,AbstractRepair.MODIFYRELATION);
1031         AbstractRepair ar=getabstractrepair(conj,dpred,AbstractRepair.MODIFYRELATION);
1032         MultUpdateNode munmodify=null;
1033         MultUpdateNode munadd=null;
1034         MultUpdateNode munremove=null;
1035         for(Iterator it=updates.iterator();it.hasNext();) {
1036             MultUpdateNode mun=(MultUpdateNode)it.next();
1037             if (mun.getType()==MultUpdateNode.ADD) {
1038                 munadd=mun;
1039             } else if (mun.getType()==MultUpdateNode.REMOVE) {
1040                 munremove=mun;
1041             } else if (mun.getType()==MultUpdateNode.MODIFY) {
1042                 munmodify=mun;
1043             }
1044         }
1045
1046         ExprPredicate ep=(ExprPredicate)dpred.getPredicate();
1047         RelationDescriptor rd=(RelationDescriptor)ep.getDescriptor();
1048         boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1049         boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1050         boolean inverted=ep.inverted();
1051         boolean negated=dpred.isNegated();
1052         OpExpr expr=(OpExpr)ep.expr;
1053         Opcode opcode=expr.getOpcode();
1054         VarDescriptor leftside=VarDescriptor.makeNew("leftside");
1055         VarDescriptor rightside=VarDescriptor.makeNew("rightside");
1056         VarDescriptor newvalue=VarDescriptor.makeNew("newvalue");
1057         boolean needremoveloop=ar.mayNeedFunctionEnforcement(state)&&ar.needsRemoves(state);
1058
1059         if (needremoveloop&&((munadd==null)||(munremove==null))) {
1060             System.out.println("Warning:  need to have individual remove operations for"+dpred.name());
1061             needremoveloop=false;
1062         }
1063         if (needremoveloop)
1064             cr.outputline("while (1) {");
1065
1066         if (!inverted) {
1067             ((RelationExpr)expr.getLeftExpr()).getExpr().generate(cr,leftside);
1068             expr.getRightExpr().generate(cr,newvalue);
1069             cr.outputline(rd.getRange().getType().getGenerateType().getSafeSymbol()+" "+rightside.getSafeSymbol()+";");
1070             cr.outputline("SimpleHashget("+rd.getSafeSymbol()+"_hash,"+leftside.getSafeSymbol()+", &"+rightside.getSafeSymbol()+");");
1071         } else {
1072             ((RelationExpr)expr.getLeftExpr()).getExpr().generate(cr,rightside);
1073             expr.getRightExpr().generate(cr,newvalue);
1074             cr.outputline(rd.getDomain().getType().getGenerateType().getSafeSymbol()+" "+leftside.getSafeSymbol()+";");
1075             cr.outputline("SimpleHashget("+rd.getSafeSymbol()+"_hashinv,"+rightside.getSafeSymbol()+", &"+leftside.getSafeSymbol()+");");
1076         }
1077
1078         opcode=Opcode.translateOpcode(negated,opcode);
1079
1080         if (opcode==Opcode.GT) {
1081             cr.outputline(newvalue.getSafeSymbol()+"++;");
1082         } else if (opcode==Opcode.GE) {
1083             /* Equal */
1084         } else if (opcode==Opcode.LT) {
1085             cr.outputline(newvalue.getSafeSymbol()+"--;");
1086         } else if (opcode==Opcode.LE) {
1087             /* Equal */
1088         } else if (opcode==Opcode.EQ) {
1089             /* Equal */
1090         } else if (opcode==Opcode.NE) { /* search for FLAGNE if this is changed*/
1091             cr.outputline(newvalue.getSafeSymbol()+"++;");
1092         } else {
1093             throw new Error("Unrecognized Opcode");
1094         }
1095         /* Do abstract repairs */
1096         if (usageimage) {
1097             cr.outputline("SimpleHashremove("+rd.getSafeSymbol()+"_hash, "+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
1098         }
1099         if (usageinvimage) {
1100             cr.outputline("SimpleHashremove("+rd.getSafeSymbol()+"_hashinv, "+rightside.getSafeSymbol()+","+leftside.getSafeSymbol()+");");
1101         }
1102
1103         if (needremoveloop) {
1104             if (!inverted) {
1105                 cr.outputline("if (SimpleHashcontainskey("+rd.getSafeSymbol()+"_hash, "+leftside.getSafeSymbol()+")) {");
1106             } else {
1107                 cr.outputline("if (SimpleHashcontainskey("+rd.getSafeSymbol()+"_hashinv, "+rightside.getSafeSymbol()+")) {");
1108             }
1109             for(int i=0;i<state.vRules.size();i++) {
1110                 Rule r=(Rule)state.vRules.get(i);
1111                 if (r.getInclusion().getTargetDescriptors().contains(rd)) {
1112                     for(int j=0;j<munremove.numUpdates();j++) {
1113                         UpdateNode un=munremove.getUpdate(i);
1114                         if (un.getRule()==r) {
1115                                 /* Update for rule r */
1116                             String name=(String)updatenames.get(un);
1117                             cr.outputline("RepairHashaddrelation("+repairtable.getSafeSymbol()+","+rd.getNum()+","+r.getNum()+","+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+",(int) &"+name+");");
1118                         }
1119                     }
1120                 }
1121             }
1122             cr.outputline("continue;");
1123             cr.outputline("}");
1124         }
1125
1126         if (usageimage) {
1127             if (!inverted) {
1128                 cr.outputline("SimpleHashadd("+rd.getSafeSymbol()+"_hash,"+leftside.getSafeSymbol()+","+newvalue.getSafeSymbol()+");");
1129             } else {
1130                 cr.outputline("SimpleHashadd("+rd.getSafeSymbol()+"_hash, "+newvalue.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
1131             }
1132         }
1133         if (usageinvimage) {
1134             if (!inverted) {
1135                 cr.outputline("SimpleHashadd("+rd.getSafeSymbol()+"_hashinv, "+newvalue.getSafeSymbol()+","+leftside.getSafeSymbol()+");");
1136             } else {
1137                 cr.outputline("SimpleHashadd("+rd.getSafeSymbol()+"_hashinv,"+rightside.getSafeSymbol()+","+newvalue.getSafeSymbol()+");");
1138             }
1139         }
1140         /* Do concrete repairs */
1141         if (munmodify!=null&&(!ar.mayNeedFunctionEnforcement(state))||(munadd==null)||(ar.needsRemoves(state)&&(munremove==null))) {
1142             for(int i=0;i<state.vRules.size();i++) {
1143                 Rule r=(Rule)state.vRules.get(i);
1144                 if (r.getInclusion().getTargetDescriptors().contains(rd)) {
1145                     for(int j=0;j<munmodify.numUpdates();j++) {
1146                         UpdateNode un=munmodify.getUpdate(j);
1147                         if (un.getRule()==r) {
1148                             /* Update for rule r */
1149                             String name=(String)updatenames.get(un);
1150                             cr.outputline("RepairHashaddrelation2("+repairtable.getSafeSymbol()+","+rd.getNum()+","+r.getNum()+","+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+",(int) &"+name+","+newvalue.getSafeSymbol()+");");
1151                         }
1152                     }
1153                 }
1154             }
1155         } else {
1156             /* Start with scheduling removal */
1157             if (ar.needsRemoves(state))
1158                 for(int i=0;i<state.vRules.size();i++) {
1159                     Rule r=(Rule)state.vRules.get(i);
1160                     if (r.getInclusion().getTargetDescriptors().contains(rd)) {
1161                         for(int j=0;j<munremove.numUpdates();j++) {
1162                             UpdateNode un=munremove.getUpdate(i);
1163                             if (un.getRule()==r) {
1164                                 /* Update for rule r */
1165                                 String name=(String)updatenames.get(un);
1166                                 cr.outputline("RepairHashaddrelation("+repairtable.getSafeSymbol()+","+rd.getNum()+","+r.getNum()+","+leftside.getSafeSymbol()+","+rightside.getSafeSymbol()+",(int) &"+name+");");
1167                             }
1168                         }
1169                     }
1170                 }
1171             /* Now do addition */
1172             UpdateNode un=munadd.getUpdate(0);
1173             String name=(String)updatenames.get(un);
1174             if (!inverted) {
1175                 cr.outputline(name+"(thisvar,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+leftside.getSafeSymbol()+","+newvalue.getSafeSymbol()+");");
1176             } else {
1177                 cr.outputline(name+"(thisvar,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+newvalue.getSafeSymbol()+","+rightside.getSafeSymbol()+");");
1178             }
1179         }
1180         if (needremoveloop) {
1181             cr.outputline("break;");
1182             cr.outputline("}");
1183         }
1184     }
1185
1186     public void generatesizerepair(Conjunction conj, DNFPredicate dpred, CodeWriter cr) {
1187         ExprPredicate ep=(ExprPredicate)dpred.getPredicate();
1188         OpExpr expr=(OpExpr)ep.expr;
1189         Opcode opcode=expr.getOpcode();
1190         opcode=Opcode.translateOpcode(dpred.isNegated(),opcode);
1191
1192         MultUpdateNode munremove;
1193
1194         MultUpdateNode munadd;
1195         if (ep.getDescriptor() instanceof RelationDescriptor) {
1196             munremove=getmultupdatenode(conj,dpred,AbstractRepair.REMOVEFROMRELATION);
1197             munadd=getmultupdatenode(conj,dpred,AbstractRepair.ADDTORELATION);
1198         } else {
1199             munremove=getmultupdatenode(conj,dpred,AbstractRepair.REMOVEFROMSET);
1200             munadd=getmultupdatenode(conj,dpred,AbstractRepair.ADDTOSET);
1201         }
1202         int size=ep.rightSize();
1203         VarDescriptor sizevar=VarDescriptor.makeNew("size");
1204         ((OpExpr)expr).left.generate(cr, sizevar);
1205         VarDescriptor change=VarDescriptor.makeNew("change");
1206         cr.outputline("int "+change.getSafeSymbol()+";");
1207         boolean generateadd=false;
1208         boolean generateremove=false;
1209         if (opcode==Opcode.GT) {
1210             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size+1)+"-"+sizevar.getSafeSymbol()+";");
1211             generateadd=true;
1212             generateremove=false;
1213         } else if (opcode==Opcode.GE) {
1214             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size)+"-"+sizevar.getSafeSymbol()+";");
1215             generateadd=true;
1216             generateremove=false;
1217         } else if (opcode==Opcode.LT) {
1218             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size-1)+"-"+sizevar.getSafeSymbol()+";");
1219             generateadd=false;
1220             generateremove=true;
1221         } else if (opcode==Opcode.LE) {
1222             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size)+"-"+sizevar.getSafeSymbol()+";");
1223             generateadd=false;
1224             generateremove=true;
1225         } else if (opcode==Opcode.EQ) {
1226             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size)+"-"+sizevar.getSafeSymbol()+";");
1227             if (size==0)
1228                 generateadd=false;
1229             else
1230                 generateadd=true;
1231             generateremove=true;
1232         } else if (opcode==Opcode.NE) {
1233             cr.outputline(change.getSafeSymbol()+"="+String.valueOf(size+1)+"-"+sizevar.getSafeSymbol()+";");
1234             generateadd=true;
1235             generateremove=false;
1236         } else {
1237             throw new Error("Unrecognized Opcode");
1238         }
1239
1240 // In some cases the analysis has determined that generating removes
1241 // is unnecessary
1242         if (generateremove&&munremove==null)
1243             generateremove=false;
1244
1245         Descriptor d=ep.getDescriptor();
1246         if (generateremove) {
1247             cr.outputline("for(;"+change.getSafeSymbol()+"<0;"+change.getSafeSymbol()+"++)");
1248             cr.startblock();
1249             /* Find element to remove */
1250             VarDescriptor leftvar=VarDescriptor.makeNew("leftvar");
1251             VarDescriptor rightvar=VarDescriptor.makeNew("rightvar");
1252             if (d instanceof RelationDescriptor) {
1253                 if (ep.inverted()) {
1254                     ((ImageSetExpr)((SizeofExpr)expr.left).setexpr).generate_leftside(cr,rightvar);
1255                     cr.outputline("int "+leftvar.getSafeSymbol()+";");
1256                     cr.outputline("SimpleHashget("+d.getSafeSymbol()+"_hashinv,(int)"+rightvar.getSafeSymbol()+", &"+leftvar.getSafeSymbol()+");");
1257                 } else {
1258                     ((ImageSetExpr)((SizeofExpr)expr.left).setexpr).generate_leftside(cr,leftvar);
1259                     cr.outputline("int "+rightvar.getSafeSymbol()+"=0;");
1260                     cr.outputline("SimpleHashget("+d.getSafeSymbol()+"_hash ,(int)"+leftvar.getSafeSymbol()+", &"+rightvar.getSafeSymbol()+");");
1261                 }
1262             } else {
1263                 cr.outputline("int "+leftvar.getSafeSymbol()+"= SimpleHashfirstkey("+d.getSafeSymbol()+"_hash);");
1264             }
1265             /* Generate abstract remove instruction */
1266             if (d instanceof RelationDescriptor) {
1267                 RelationDescriptor rd=(RelationDescriptor) d;
1268                 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1269                 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1270                 if (usageimage)
1271                     cr.outputline("SimpleHashremove("+rd.getSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
1272                 if (usageinvimage)
1273                     cr.outputline("SimpleHashremove("+rd.getSafeSymbol()+"_hashinv ,(int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1274             } else {
1275                 cr.outputline("SimpleHashremove("+d.getSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1276             }
1277             /* Generate concrete remove instruction */
1278             for(int i=0;i<state.vRules.size();i++) {
1279                 Rule r=(Rule)state.vRules.get(i);
1280                 if (r.getInclusion().getTargetDescriptors().contains(d)) {
1281                     for(int j=0;j<munremove.numUpdates();j++) {
1282                         UpdateNode un=munremove.getUpdate(j);
1283                         if (un.getRule()==r) {
1284                                 /* Update for rule rule r */
1285                             String name=(String)updatenames.get(un);
1286                             if (d instanceof RelationDescriptor) {
1287                                 cr.outputline("RepairHashaddrelation("+repairtable.getSafeSymbol()+","+d.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+",(int) &"+name+");");
1288                             } else {
1289                                 cr.outputline("RepairHashaddset("+repairtable.getSafeSymbol()+","+d.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
1290                             }
1291                         }
1292                     }
1293                 }
1294             }
1295             cr.endblock();
1296         }
1297
1298 // In some cases the analysis has determined that generating removes
1299 // is unnecessary
1300         if (generateadd&&munadd==null)
1301             generateadd=false;
1302
1303         if (generateadd) {
1304
1305             cr.outputline("for(;"+change.getSafeSymbol()+">0;"+change.getSafeSymbol()+"--)");
1306             cr.startblock();
1307             VarDescriptor newobject=VarDescriptor.makeNew("newobject");
1308             if (d instanceof RelationDescriptor) {
1309                 VarDescriptor otherside=VarDescriptor.makeNew("otherside");
1310                 ((ImageSetExpr)((SizeofExpr)expr.left).setexpr).generate_leftside(cr,otherside);
1311
1312                 RelationDescriptor rd=(RelationDescriptor)d;
1313                 if (termination.sources.relsetSource(rd,!ep.inverted())) {
1314                     /* Set Source */
1315                     SetDescriptor sd=termination.sources.relgetSourceSet(rd,!ep.inverted());
1316                     VarDescriptor iterator=VarDescriptor.makeNew("iterator");
1317                     cr.outputline(sd.getType().getGenerateType().getSafeSymbol() +" "+newobject.getSafeSymbol()+";");
1318                     cr.outputline("struct SimpleIterator "+iterator.getSafeSymbol()+";");
1319                     cr.outputline("for(SimpleHashiterator(& "+sd.getSafeSymbol()+"_hash ,"+ iterator.getSafeSymbol() +");"+iterator.getSafeSymbol()+".hasNext();)");
1320                     cr.startblock();
1321                     if (ep.inverted()) {
1322                         cr.outputline("if (!SimpleHashcontainskeydata("+rd.getSafeSymbol()+"_hashinv,"+iterator.getSafeSymbol()+".key(),"+otherside.getSafeSymbol()+"))");
1323                     } else {
1324                         cr.outputline("if (!SimpleHashcontainskeydata("+rd.getSafeSymbol()+"_hash, "+otherside.getSafeSymbol()+","+iterator.getSafeSymbol()+".key()))");
1325                     }
1326                     cr.outputline(newobject.getSafeSymbol()+"=key("+iterator.getSafeSymbol()+");");
1327                     cr.outputline("next("+iterator.getSafeSymbol()+");");
1328                     cr.endblock();
1329                 } else if (termination.sources.relallocSource(rd,!ep.inverted())) {
1330                     /* Allocation Source*/
1331                     termination.sources.relgenerateSourceAlloc(cr,newobject,rd,!ep.inverted());
1332                 } else throw new Error("No source for adding to Relation");
1333                 if (ep.inverted()) {
1334                     boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1335                     boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1336                     if (usageimage)
1337                         cr.outputline("SimpleHashadd("+rd.getSafeSymbol()+"_hash, "+newobject.getSafeSymbol()+","+otherside.getSafeSymbol()+");");
1338                     if (usageinvimage)
1339                         cr.outputline("SimpleHashadd("+rd.getSafeSymbol()+"_hashinv, "+otherside.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
1340
1341                     UpdateNode un=munadd.getUpdate(0);
1342                     String name=(String)updatenames.get(un);
1343                     cr.outputline(name+"(thisvar,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+newobject.getSafeSymbol()+","+otherside.getSafeSymbol()+");");
1344                 } else {
1345                     boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1346                     boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1347                     if (usageimage)
1348                         cr.outputline("SimpleHashadd("+rd.getSafeSymbol()+"_hash, "+otherside.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
1349                     if (usageinvimage)
1350                         cr.outputline("SimpleHashadd("+rd.getSafeSymbol()+"_hashinv, "+newobject.getSafeSymbol()+","+otherside.getSafeSymbol()+");");
1351                     UpdateNode un=munadd.getUpdate(0);
1352                     String name=(String)updatenames.get(un);
1353                     cr.outputline(name+"(thisvar, "+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+otherside.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
1354                 }
1355             } else {
1356                 SetDescriptor sd=(SetDescriptor)d;
1357                 if (termination.sources.setSource(sd)) {
1358                     /* Set Source */
1359                     /* Set Source */
1360                     SetDescriptor sourcesd=termination.sources.getSourceSet(sd);
1361                     VarDescriptor iterator=VarDescriptor.makeNew("iterator");
1362                     cr.outputline(sourcesd.getType().getGenerateType().getSafeSymbol() +" "+newobject.getSafeSymbol()+";");
1363                     cr.outputline("SimpleIterator "+iterator.getSafeSymbol()+";");
1364                     cr.outputline("for(SimpleHashiterator("+sourcesd.getSafeSymbol()+"_hash, "+iterator.getSafeSymbol()+");"+iterator.getSafeSymbol()+".hasNext();)");
1365                     cr.startblock();
1366                     cr.outputline("if (!SimpleHashcontainskey("+sd.getSafeSymbol()+"_hash, key("+iterator.getSafeSymbol()+")))");
1367                     cr.outputline(newobject.getSafeSymbol()+"=key("+iterator.getSafeSymbol()+");");
1368                     cr.outputline("next("+iterator.getSafeSymbol()+");");
1369                     cr.endblock();
1370                 } else if (termination.sources.allocSource(sd)) {
1371                     /* Allocation Source*/
1372                     termination.sources.generateSourceAlloc(cr,newobject,sd);
1373                 } else throw new Error("No source for adding to Set");
1374                 cr.outputline("SimpleHashadd("+sd.getSafeSymbol()+"_hash, "+newobject.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
1375                 UpdateNode un=munadd.getUpdate(0);
1376                 String name=(String)updatenames.get(un);
1377                 cr.outputline(name+"(thisvar,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+newobject.getSafeSymbol()+");");
1378             }
1379             cr.endblock();
1380         }
1381     }
1382
1383     public void generateinclusionrepair(Conjunction conj, DNFPredicate dpred, CodeWriter cr){
1384         InclusionPredicate ip=(InclusionPredicate) dpred.getPredicate();
1385         boolean negated=dpred.isNegated();
1386         MultUpdateNode mun=getmultupdatenode(conj,dpred,-1);
1387         VarDescriptor leftvar=VarDescriptor.makeNew("left");
1388         ip.expr.generate(cr, leftvar);
1389
1390         if (negated) {
1391             if (ip.setexpr instanceof ImageSetExpr) {
1392                 ImageSetExpr ise=(ImageSetExpr) ip.setexpr;
1393                 VarDescriptor rightvar=ise.getVar();
1394                 boolean inverse=ise.inverted();
1395                 RelationDescriptor rd=ise.getRelation();
1396                 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1397                 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1398                 if (inverse) {
1399                     if (usageimage)
1400                         cr.outputline("SimpleHashremove("+rd.getSafeSymbol()+"_hash, (int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1401                     if (usageinvimage)
1402                         cr.outputline("SimpleHashremove("+rd.getSafeSymbol()+"_hashinv, (int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
1403                 } else {
1404                     if (usageimage)
1405                         cr.outputline("SimpleHashremove("+rd.getSafeSymbol()+"_hash ,(int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
1406                     if (usageinvimage)
1407                         cr.outputline("SimpleHashremove("+rd.getSafeSymbol()+"_hashinv, (int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1408                 }
1409                 for(int i=0;i<state.vRules.size();i++) {
1410                     Rule r=(Rule)state.vRules.get(i);
1411                     if (r.getInclusion().getTargetDescriptors().contains(rd)) {
1412                         for(int j=0;j<mun.numUpdates();j++) {
1413                             UpdateNode un=mun.getUpdate(j);
1414                             if (un.getRule()==r) {
1415                                 /* Update for rule rule r */
1416                                 String name=(String)updatenames.get(un);
1417                                 if (inverse) {
1418                                     cr.outputline("RepairHashaddrelation("+repairtable.getSafeSymbol()+","+rd.getNum()+","+r.getNum()+","+rightvar.getSafeSymbol()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
1419                                 } else {
1420                                     cr.outputline("RepairHashaddrelation("+repairtable.getSafeSymbol()+","+rd.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+",(int) &"+name+");");
1421                                 }
1422                             }
1423                         }
1424                     }
1425                 }
1426             } else {
1427                 SetDescriptor sd=ip.setexpr.sd;
1428                 cr.outputline("SimpleHashremove("+sd.getSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1429
1430                 for(int i=0;i<state.vRules.size();i++) {
1431                     Rule r=(Rule)state.vRules.get(i);
1432                     if (r.getInclusion().getTargetDescriptors().contains(sd)) {
1433                         for(int j=0;j<mun.numUpdates();j++) {
1434                             UpdateNode un=mun.getUpdate(j);
1435                             if (un.getRule()==r) {
1436                                 /* Update for rule rule r */
1437                                 String name=(String)updatenames.get(un);
1438                                 cr.outputline("RepairHashaddset("+repairtable.getSafeSymbol()+","+sd.getNum()+","+r.getNum()+","+leftvar.getSafeSymbol()+",(int) &"+name+");");
1439                             }
1440                         }
1441                     }
1442                 }
1443             }
1444         } else {
1445             /* Generate update */
1446             if (ip.setexpr instanceof ImageSetExpr) {
1447                 ImageSetExpr ise=(ImageSetExpr) ip.setexpr;
1448                 VarDescriptor rightvar=ise.getVar();
1449                 boolean inverse=ise.inverted();
1450                 RelationDescriptor rd=ise.getRelation();
1451                 boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1452                 boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1453                 if (inverse) {
1454                     if (usageimage)
1455                         cr.outputline("SimpleHashadd("+rd.getSafeSymbol()+"_hash, (int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1456                     if (usageinvimage)
1457                         cr.outputline("SimpleHashadd("+rd.getSafeSymbol()+"_hashinv, (int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
1458                 } else {
1459                     if (usageimage)
1460                         cr.outputline("SimpleHashadd("+rd.getSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + rightvar.getSafeSymbol() + ");");
1461                     if (usageinvimage)
1462                         cr.outputline("SimpleHashadd("+rd.getSafeSymbol()+"_hashinv, (int)" + rightvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1463                 }
1464                 UpdateNode un=mun.getUpdate(0);
1465                 String name=(String)updatenames.get(un);
1466                 if (inverse) {
1467                     cr.outputline(name+"(thisvar,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+rightvar.getSafeSymbol()+","+leftvar.getSafeSymbol()+");");
1468                 } else {
1469                     cr.outputline(name+"(thisvar,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+leftvar.getSafeSymbol()+","+rightvar.getSafeSymbol()+");");
1470                 }
1471             } else {
1472                 SetDescriptor sd=ip.setexpr.sd;
1473                 cr.outputline("SimpleHashadd("+sd.getSafeSymbol()+"_hash, (int)" + leftvar.getSafeSymbol() + ", (int)" + leftvar.getSafeSymbol() + ");");
1474
1475                 UpdateNode un=mun.getUpdate(0);
1476                 /* Update for rule rule r */
1477                 String name=(String)updatenames.get(un);
1478                 cr.outputline(name+"(thisvar,"+newmodel.getSafeSymbol()+","+repairtable.getSafeSymbol()+","+leftvar.getSafeSymbol()+");");
1479             }
1480         }
1481     }
1482
1483     public static Vector getrulelist(Descriptor d) {
1484         Vector dispatchrules = new Vector();
1485         Vector rules = State.currentState.vRules;
1486
1487         for (int i = 0; i < rules.size(); i++) {
1488             Rule rule = (Rule) rules.elementAt(i);
1489             Set requiredsymbols = rule.getRequiredDescriptors();
1490
1491             // #TBD#: in general this is wrong because these descriptors may contain descriptors
1492             // bound in "in?" expressions which need to be dealt with in a topologically sorted
1493             // fashion...
1494
1495             if (rule.getRequiredDescriptors().contains(d)) {
1496                 dispatchrules.addElement(rule);
1497             }
1498         }
1499         return dispatchrules;
1500     }
1501
1502     private boolean need_compensation(Rule r) {
1503         if (!Compiler.REPAIR)
1504             return false;
1505         GraphNode gn=(GraphNode)termination.scopefalsify.get(r);
1506         for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
1507             GraphNode.Edge edge=(GraphNode.Edge)edgeit.next();
1508             GraphNode gn2=edge.getTarget();
1509             if (!removed.contains(gn2)) {
1510                 TermNode tn2=(TermNode)gn2.getOwner();
1511                 if (tn2.getType()==TermNode.CONSEQUENCE)
1512                     return false;
1513             }
1514         }
1515         return true;
1516     }
1517
1518     private UpdateNode find_compensation(Rule r) {
1519         GraphNode gn=(GraphNode)termination.scopefalsify.get(r);
1520         for(Iterator edgeit=gn.edges();edgeit.hasNext();) {
1521             GraphNode.Edge edge=(GraphNode.Edge)edgeit.next();
1522             GraphNode gn2=edge.getTarget();
1523             if (!removed.contains(gn2)) {
1524                 TermNode tn2=(TermNode)gn2.getOwner();
1525                 if (tn2.getType()==TermNode.UPDATE) {
1526                     MultUpdateNode mun=tn2.getUpdate();
1527                     for(int i=0;i<mun.numUpdates();i++) {
1528                         UpdateNode un=mun.getUpdate(i);
1529                         if (un.getRule()==r)
1530                             return un;
1531                     }
1532                 }
1533             }
1534         }
1535         throw new Error("No Compensation Update could be found");
1536     }
1537
1538     public void generate_dispatch(CodeWriter cr, RelationDescriptor rd, String leftvar, String rightvar) {
1539         boolean usageimage=rd.testUsage(RelationDescriptor.IMAGE);
1540         boolean usageinvimage=rd.testUsage(RelationDescriptor.INVIMAGE);
1541
1542         if (!(usageinvimage||usageimage)) /* not used at all*/
1543             return;
1544
1545         cr.outputline("/* RELATION DISPATCH */");
1546         if (Compiler.REPAIR) {
1547             cr.outputline("if ("+oldmodel.getSafeSymbol()+"&&");
1548             if (usageimage)
1549                 cr.outputline("!SimpleHashcontainskeydata("+oldmodel.getSafeSymbol()+"->"+rd.getJustSafeSymbol() + "_hash, "+leftvar+","+rightvar+"))");
1550             else
1551                 cr.outputline("!SimpleHashcontainskeydata("+oldmodel.getSafeSymbol() +"->"+rd.getJustSafeSymbol()+"_hashinv, "+rightvar+","+leftvar+"))");
1552
1553             cr.startblock(); {
1554                 /* Adding new item */
1555                 /* Perform safety checks */
1556                 cr.outputline("if ("+repairtable.getSafeSymbol()+"&&");
1557                 cr.outputline("RepairHashcontainsrelation("+repairtable.getSafeSymbol()+","+rd.getNum()+","+currentrule.getNum()+","+leftvar+","+rightvar+"))");
1558                 cr.startblock(); {
1559                     /* Have update to call into */
1560                     VarDescriptor mdfyptr=VarDescriptor.makeNew("modifyptr");
1561                     VarDescriptor ismdfyptr=VarDescriptor.makeNew("ismodifyptr");
1562                     cr.outputline("int "+ismdfyptr.getSafeSymbol()+"=RepairHashismodify("+repairtable.getSafeSymbol()+","+rd.getNum()+","+currentrule.getNum()+","+leftvar+","+rightvar+");");
1563
1564
1565
1566
1567                     String parttype="";
1568                     for(int i=0;i<currentrule.numQuantifiers();i++) {
1569                         if (currentrule.getQuantifier(i) instanceof RelationQuantifier)
1570                             parttype=parttype+", int, int";
1571                         else
1572                             parttype=parttype+", int";
1573                     }
1574                     VarDescriptor funptr=VarDescriptor.makeNew("updateptr");
1575                     VarDescriptor tmpptr=VarDescriptor.makeNew("tempupdateptr");
1576
1577                     String methodcall="("+funptr.getSafeSymbol()+") (thisvar,"+oldmodel.getSafeSymbol()+","+repairtable.getSafeSymbol();
1578                     for(int i=0;i<currentrule.numQuantifiers();i++) {
1579                         Quantifier q=currentrule.getQuantifier(i);
1580                         if (q instanceof SetQuantifier) {
1581                             SetQuantifier sq=(SetQuantifier) q;
1582                             methodcall+=","+sq.getVar().getSafeSymbol();
1583                         } else if (q instanceof RelationQuantifier) {
1584                             RelationQuantifier rq=(RelationQuantifier) q;
1585                             methodcall+=","+rq.x.getSafeSymbol();
1586                             methodcall+=","+rq.y.getSafeSymbol();
1587                         } else if (q instanceof ForQuantifier) {
1588                             ForQuantifier fq=(ForQuantifier) q;
1589                             methodcall+=","+fq.getVar().getSafeSymbol();
1590                         }
1591                     }
1592
1593
1594
1595                     cr.outputline("void *"+tmpptr.getSafeSymbol()+"=");
1596                     cr.outputline("(void *) RepairHashgetrelation("+repairtable.getSafeSymbol()+","+rd.getNum()+","+currentrule.getNum()+","+leftvar+","+rightvar+");");
1597                     cr.outputline("if ("+ismdfyptr.getSafeSymbol()+")");
1598                     {
1599                         cr.startblock();
1600                         cr.outputline("int "+mdfyptr.getSafeSymbol()+"=RepairHashgetrelation2("+repairtable.getSafeSymbol()+","+rd.getNum()+","+currentrule.getNum()+","+leftvar+","+rightvar+");");
1601                         cr.outputline("void (*"+funptr.getSafeSymbol()+") (struct "+name+"_state *, struct "+name+"*, struct RepairHash *"+parttype+",int,int,int)="+"(void (*) (struct "+name+"_state *, struct "+name+"*, struct RepairHash *"+parttype+",int,int,int)) "+tmpptr.getSafeSymbol()+";");
1602                         cr.outputline(methodcall+","+leftvar+", "+rightvar+", "+mdfyptr.getSafeSymbol() +");");
1603                         cr.endblock();
1604                     }
1605                     cr.outputline("else ");
1606                     {
1607                         cr.startblock();
1608                         cr.outputline("void (*"+funptr.getSafeSymbol()+") (struct "+name+"_state *, struct "+name+"*,struct RepairHash *"+parttype+")="+"(void (*) (struct "+name+"_state *,struct "+name+"*,struct RepairHash *"+parttype+")) "+tmpptr.getSafeSymbol()+";");
1609                         cr.outputline(methodcall+");");
1610                         cr.endblock();
1611                     }
1612                     cr.outputline("free"+name+"("+newmodel.getSafeSymbol()+");");
1613                     cr.outputline("goto rebuild;");
1614                 }
1615                 cr.endblock();
1616
1617                 /* Build standard compensation actions */
1618                 if (need_compensation(currentrule)) {
1619                     UpdateNode un=find_compensation(currentrule);
1620                     String name=(String)updatenames.get(un);
1621                     usedupdates.add(un); /* Mark as used */
1622                     String methodcall=name+"(thisvar,"+oldmodel.getSafeSymbol()+","+repairtable.getSafeSymbol();
1623                     for(int i=0;i<currentrule.numQuantifiers();i++) {
1624                         Quantifier q=currentrule.getQuantifier(i);
1625                         if (q instanceof SetQuantifier) {
1626                             SetQuantifier sq=(SetQuantifier) q;
1627                             methodcall+=","+sq.getVar().getSafeSymbol();
1628                         } else if (q instanceof RelationQuantifier) {
1629                             RelationQuantifier rq=(RelationQuantifier) q;
1630                             methodcall+=","+rq.x.getSafeSymbol();
1631                             methodcall+=","+rq.y.getSafeSymbol();
1632                         } else if (q instanceof ForQuantifier) {
1633                             ForQuantifier fq=(ForQuantifier) q;
1634                             methodcall+=","+fq.getVar().getSafeSymbol();
1635                         }
1636                     }
1637                     methodcall+=");";
1638                     cr.outputline(methodcall);
1639                     cr.outputline("free"+name+"("+newmodel.getSafeSymbol()+");");
1640                     cr.outputline("goto rebuild;");
1641                 }
1642             }
1643             cr.endblock();
1644         }
1645
1646         String addeditem = (VarDescriptor.makeNew("addeditem")).getSafeSymbol();
1647         cr.startblock();
1648         cr.outputline("int " + addeditem + "=0;");
1649
1650         String ifstring="if (!maybe";
1651         if (rd.getDomain().getType() instanceof StructureTypeDescriptor)  {
1652             ifstring+="&&"+leftvar;
1653         }
1654
1655         if (rd.getRange().getType() instanceof StructureTypeDescriptor)  {
1656             ifstring+="&&"+rightvar;
1657         }
1658
1659         ifstring+=")";
1660
1661         if (rd.testUsage(RelationDescriptor.IMAGE)) {
1662             cr.outputline(ifstring);
1663             cr.outputline(addeditem + " = SimpleHashadd("+rd.getSafeSymbol()+"_hash, (int)" + leftvar + ", (int)" + rightvar+ ");");
1664         }
1665
1666         if (rd.testUsage(RelationDescriptor.INVIMAGE)) {
1667             cr.outputline(ifstring);
1668             cr.outputline(addeditem + " = SimpleHashadd("+rd.getSafeSymbol()+"_hashinv, (int)" + rightvar + ", (int)" + leftvar + ");");
1669         }
1670
1671
1672         Vector dispatchrules = getrulelist(rd);
1673
1674         Set toremove=new HashSet();
1675         for(int i=0;i<dispatchrules.size();i++) {
1676             Rule r=(Rule)dispatchrules.get(i);
1677             if (!ruleset.contains(r))
1678                 toremove.add(r);
1679         }
1680         dispatchrules.removeAll(toremove);
1681         if (dispatchrules.size() == 0) {
1682             cr.outputline("/* nothing to dispatch */");
1683             cr.endblock();
1684             return;
1685         }
1686
1687         cr.outputline("if (" + addeditem + ")");
1688         cr.startblock();
1689
1690         for(int i = 0; i < dispatchrules.size(); i++) {
1691             Rule rule = (Rule) dispatchrules.elementAt(i);
1692             if (rule.getGuardExpr().getRequiredDescriptors().contains(rd)) {
1693                 /* Guard depends on this relation, so we recomput everything */
1694                 cr.outputline("WorkListadd("+worklist.getSafeSymbol()+","+rule.getNum()+",-1,0,0);");
1695             } else {
1696                 for (int j=0;j<rule.numQuantifiers();j++) {
1697                     Quantifier q=rule.getQuantifier(j);
1698                     if (q.getRequiredDescriptors().contains(rd)) {
1699                         /* Generate add */
1700                         cr.outputline("WorkListadd("+worklist.getSafeSymbol()+","+rule.getNum()+","+j+","+leftvar+","+rightvar+");");
1701                     }
1702                 }
1703             }
1704         }
1705         cr.endblock();
1706         cr.endblock();
1707     }
1708
1709
1710     public void generate_dispatch(CodeWriter cr, SetDescriptor sd, String setvar) {
1711         cr.outputline("/* SET DISPATCH */");
1712         if (Compiler.REPAIR) {
1713             cr.outputline("if ("+oldmodel.getSafeSymbol()+"&&");
1714             cr.outputline("!SimpleHashcontainskey("+oldmodel.getSafeSymbol() +"->"+sd.getJustSafeSymbol()+"_hash, "+setvar+"))");
1715             cr.startblock(); {
1716                 /* Adding new item */
1717                 /* See if there is an outstanding update in the repairtable */
1718                 cr.outputline("if ("+repairtable.getSafeSymbol()+"&&");
1719                 cr.outputline("RepairHashcontainsset("+repairtable.getSafeSymbol()+","+sd.getNum()+","+currentrule.getNum()+","+setvar+"))");
1720                 cr.startblock(); {
1721                     /* Have update to call into */
1722                     VarDescriptor funptr=VarDescriptor.makeNew("updateptr");
1723                     String parttype="";
1724                     for(int i=0;i<currentrule.numQuantifiers();i++) {
1725                         if (currentrule.getQuantifier(i) instanceof RelationQuantifier)
1726                             parttype=parttype+", int, int";
1727                         else
1728                             parttype=parttype+", int";
1729                     }
1730                     cr.outputline("void (*"+funptr.getSafeSymbol()+") (struct "+name+"_state *,struct "+name+"*,struct RepairHash *"+parttype+")=");
1731                     cr.outputline("(void (*) (struct "+name+"_state *,struct "+name+"*,struct RepairHash *"+parttype+")) RepairHashgetset("+repairtable.getSafeSymbol()+","+sd.getNum()+","+currentrule.getNum()+","+setvar+");");
1732                     String methodcall="("+funptr.getSafeSymbol()+") (thisvar,"+oldmodel.getSafeSymbol()+","+
1733                         repairtable.getSafeSymbol();
1734                     for(int i=0;i<currentrule.numQuantifiers();i++) {
1735                         Quantifier q=currentrule.getQuantifier(i);
1736                         if (q instanceof SetQuantifier) {
1737                             SetQuantifier sq=(SetQuantifier) q;
1738                             methodcall+=","+sq.getVar().getSafeSymbol();
1739                         } else if (q instanceof RelationQuantifier) {
1740                             RelationQuantifier rq=(RelationQuantifier) q;
1741                             methodcall+=","+rq.x.getSafeSymbol();
1742                             methodcall+=","+rq.y.getSafeSymbol();
1743                         } else if (q instanceof ForQuantifier) {
1744                             ForQuantifier fq=(ForQuantifier) q;
1745                             methodcall+=","+fq.getVar().getSafeSymbol();
1746                         }
1747                     }
1748                     methodcall+=");";
1749                     cr.outputline(methodcall);
1750                     cr.outputline("free"+name+"("+newmodel.getSafeSymbol()+");");
1751                     cr.outputline("goto rebuild;");
1752                 }
1753                 cr.endblock();
1754                 /* Build standard compensation actions */
1755                 Vector ruleset=new Vector();
1756                 ruleset.add(currentrule);
1757                 if (state.implicitruleinv.containsKey(currentrule))
1758                     ruleset.addAll((Set)state.implicitruleinv.get(currentrule));
1759                 for(int i=0;i<ruleset.size();i++) {
1760                     Rule itrule=(Rule)ruleset.get(i);
1761
1762                     if (need_compensation(itrule)) {
1763                         UpdateNode un=find_compensation(itrule);
1764                         String name=(String)updatenames.get(un);
1765                         usedupdates.add(un); /* Mark as used */
1766
1767                         String methodcall=name+"(thisvar,"+oldmodel.getSafeSymbol()+","+
1768                             repairtable.getSafeSymbol();
1769                         for(int j=0;j<currentrule.numQuantifiers();j++) {
1770                             Quantifier q=currentrule.getQuantifier(j);
1771                             if (q instanceof SetQuantifier) {
1772                                 SetQuantifier sq=(SetQuantifier) q;
1773                                 methodcall+=","+sq.getVar().getSafeSymbol();
1774                             } else if (q instanceof RelationQuantifier) {
1775                                 RelationQuantifier rq=(RelationQuantifier) q;
1776                                 methodcall+=","+rq.x.getSafeSymbol();
1777                                 methodcall+=","+rq.y.getSafeSymbol();
1778                             } else if (q instanceof ForQuantifier) {
1779                                 ForQuantifier fq=(ForQuantifier) q;
1780                                 methodcall+=","+fq.getVar().getSafeSymbol();
1781                             }
1782                         }
1783                         methodcall+=");";
1784                         if (currentrule!=itrule) {
1785                             SetDescriptor sdrule=((SetInclusion)itrule.getInclusion()).getSet();
1786                             cr.outputline("if ("+oldmodel.getSafeSymbol()+"&&");
1787                             cr.outputline("!SimpleHashcontainskey("+ oldmodel.getSafeSymbol() +"->"+sdrule.getJustSafeSymbol() +"_hash,"+setvar+"))");
1788                             cr.startblock();
1789                         }
1790                         cr.outputline(methodcall);
1791                         cr.outputline("free"+name+"("+newmodel.getSafeSymbol()+");");
1792                         cr.outputline("goto rebuild;");
1793                         cr.endblock();
1794                     }
1795                     if (currentrule==itrule)
1796                         cr.endblock();
1797                 }
1798             }
1799         }
1800
1801         cr.startblock();
1802         String addeditem = (VarDescriptor.makeNew("addeditem")).getSafeSymbol();
1803         cr.outputline("int " + addeditem + " = 0;");
1804         if (sd.getType() instanceof StructureTypeDescriptor)  {
1805             cr.outputline("if (!maybe&&"+setvar+")");
1806         } else
1807             cr.outputline("if (!maybe)");
1808         cr.outputline(addeditem + " = SimpleHashadd("+sd.getSafeSymbol()+"_hash, (int)" + setvar +  ", (int)" + setvar + ");");
1809         cr.startblock();
1810         Vector dispatchrules = getrulelist(sd);
1811
1812         Set toremove=new HashSet();
1813         for(int i=0;i<dispatchrules.size();i++) {
1814             Rule r=(Rule)dispatchrules.get(i);
1815             if (!ruleset.contains(r))
1816                 toremove.add(r);
1817         }
1818         dispatchrules.removeAll(toremove);
1819
1820         if (dispatchrules.size() == 0) {
1821             cr.outputline("/* nothing to dispatch */");
1822             cr.endblock();
1823             cr.endblock();
1824             return;
1825         }
1826         /* Add item to worklist if new */
1827         cr.outputline("if ("+addeditem+")");
1828         cr.startblock();
1829         for(int i = 0; i < dispatchrules.size(); i++) {
1830             Rule rule = (Rule) dispatchrules.elementAt(i);
1831             if (SetDescriptor.expand(rule.getGuardExpr().getRequiredDescriptors()).contains(sd)) {
1832                 /* Guard depends on this relation, so we recompute everything */
1833                 cr.outputline("WorkListadd("+worklist.getSafeSymbol()+","+rule.getNum()+",-1,0,0);");
1834             } else {
1835                 for (int j=0;j<rule.numQuantifiers();j++) {
1836                     Quantifier q=rule.getQuantifier(j);
1837                     if (SetDescriptor.expand(q.getRequiredDescriptors()).contains(sd)) {
1838                         /* Generate add */
1839                         cr.outputline("WorkListadd("+worklist.getSafeSymbol()+","+rule.getNum()+","+j+","+setvar+",0);");
1840                     }
1841                 }
1842             }
1843         }
1844         cr.endblock();
1845         cr.endblock();
1846         cr.endblock();
1847     }
1848 }