code formatting changes..it is getting hard to read this
[IRC.git] / Robust / src / IR / Flat / BuildCode.java
1 package IR.Flat;
2 import IR.Tree.FlagExpressionNode;
3 import IR.Tree.DNFFlag;
4 import IR.Tree.DNFFlagAtom;
5 import IR.Tree.TagExpressionList;
6 import IR.*;
7 import java.util.*;
8 import java.io.*;
9 import Util.Relation;
10 import Analysis.TaskStateAnalysis.FlagState;
11 import Analysis.TaskStateAnalysis.OptionalTaskDescriptor;
12 import Analysis.TaskStateAnalysis.Predicate;
13
14 public class BuildCode {
15     State state;
16     Hashtable temptovar;
17     Hashtable paramstable;
18     Hashtable tempstable;
19     Hashtable fieldorder;
20     Hashtable flagorder;
21     int tag=0;
22     String localsprefix="___locals___";
23     String paramsprefix="___params___";
24     public static boolean GENERATEPRECISEGC=false;
25     public static String PREFIX="";
26     public static String arraytype="ArrayObject";
27     Virtual virtualcalls;
28     TypeUtil typeutil;
29     private int maxtaskparams=0;
30     private int maxcount=0;
31     ClassDescriptor[] cdarray;
32     TypeDescriptor[] arraytable;
33    
34     public BuildCode(State st, Hashtable temptovar, TypeUtil typeutil) {
35         state=st;
36         this.temptovar=temptovar;
37         paramstable=new Hashtable();    
38         tempstable=new Hashtable();
39         fieldorder=new Hashtable();
40         flagorder=new Hashtable();
41         this.typeutil=typeutil;
42         virtualcalls=new Virtual(state);
43     }
44
45     /** The buildCode method outputs C code for all the methods.  The Flat
46      * versions of the methods must already be generated and stored in
47      * the State object. */
48
49     public void buildCode() {
50         /* Create output streams to write to */
51         PrintWriter outclassdefs=null;
52         PrintWriter outstructs=null;
53         PrintWriter outrepairstructs=null;
54         PrintWriter outmethodheader=null;
55         PrintWriter outmethod=null;
56         PrintWriter outvirtual=null;
57         PrintWriter outtask=null;
58         PrintWriter outtaskdefs=null;
59         PrintWriter outoptionalarrays=null;
60         PrintWriter optionalheaders=null;
61
62         try {
63             outstructs=new PrintWriter(new FileOutputStream(PREFIX+"structdefs.h"), true);
64             outmethodheader=new PrintWriter(new FileOutputStream(PREFIX+"methodheaders.h"), true);
65             outclassdefs=new PrintWriter(new FileOutputStream(PREFIX+"classdefs.h"), true);
66             outmethod=new PrintWriter(new FileOutputStream(PREFIX+"methods.c"), true);
67             outvirtual=new PrintWriter(new FileOutputStream(PREFIX+"virtualtable.h"), true);
68             if (state.TASK) {
69                 outtask=new PrintWriter(new FileOutputStream(PREFIX+"task.h"), true);
70                 outtaskdefs=new PrintWriter(new FileOutputStream(PREFIX+"taskdefs.c"), true);
71                 if (state.OPTIONAL){
72                     outoptionalarrays=new PrintWriter(new FileOutputStream(PREFIX+"optionalarrays.c"), true);
73                     optionalheaders=new PrintWriter(new FileOutputStream(PREFIX+"optionalstruct.h"), true);
74                 } 
75             }
76             if (state.structfile!=null) {
77                 outrepairstructs=new PrintWriter(new FileOutputStream(PREFIX+state.structfile+".struct"), true);
78             }
79         } catch (Exception e) {
80             e.printStackTrace();
81             System.exit(-1);
82         }
83
84         /* Build the virtual dispatch tables */
85         buildVirtualTables(outvirtual);
86
87         /* Output includes */
88         outmethodheader.println("#ifndef METHODHEADERS_H");
89         outmethodheader.println("#define METHODHEADERS_H");
90         outmethodheader.println("#include \"structdefs.h\"");
91
92         /* Output Structures */
93         outputStructs(outstructs);
94
95         // Output the C class declarations
96         // These could mutually reference each other
97         outputClassDeclarations(outclassdefs);
98
99         /* Outputs task structures if this is a task program */
100         if (state.TASK)
101             outputTaskTypes(outtask);
102
103         // Output function prototypes and structures for parameters
104         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
105         while(it.hasNext()) {
106             ClassDescriptor cn=(ClassDescriptor)it.next();
107             generateCallStructs(cn, outclassdefs, outstructs, outmethodheader);
108         }
109         outclassdefs.close();
110
111         if (state.TASK) {
112             /* Map flags to integers */
113             /* The runtime keeps track of flags using these integers */
114             it=state.getClassSymbolTable().getDescriptorsIterator();
115             while(it.hasNext()) {
116                 ClassDescriptor cn=(ClassDescriptor)it.next();
117                 mapFlags(cn);
118             }
119             /* Generate Tasks */
120             generateTaskStructs(outstructs, outmethodheader);
121         }
122
123         /* Build the actual methods */
124         outputMethods(outmethod);
125
126         if (state.TASK) {
127             outputTaskCode(outtaskdefs, outmethod);
128             outtaskdefs.close();
129         } else if (state.main!=null) {
130             /* Generate main method */
131             outputMainMethod(outmethod);
132         }
133         outmethodheader.println("#endif");
134         outmethodheader.close();
135         outmethod.close();
136         
137         if (state.TASK)
138             outstructs.println("#define MAXTASKPARAMS "+maxtaskparams);
139         outstructs.println("#endif");
140         outstructs.close();
141         
142         /* Generate information for task with optional parameters */
143         if (state.TASK&&state.OPTIONAL){
144             generateOptionalArrays(outoptionalarrays, optionalheaders, state.getAnalysisResult(), state.getOptionalTaskDescriptors());
145             outoptionalarrays.close();
146         } 
147
148         /* Output structure definitions for repair tool */
149         if (state.structfile!=null) {
150             buildRepairStructs(outrepairstructs);
151             outrepairstructs.close();
152         }
153     }
154
155     private void outputMainMethod(PrintWriter outmethod) {
156         outmethod.println("int main(int argc, const char *argv[]) {");
157         outmethod.println("  int i;");
158         if (GENERATEPRECISEGC) {
159             outmethod.println("  struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);");
160         } else {
161             outmethod.println("  struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);");
162         }
163         if (state.THREAD) {
164             outmethod.println("initializethreads();");
165         }
166         outmethod.println("  for(i=1;i<argc;i++) {");
167         outmethod.println("    int length=strlen(argv[i]);");
168         if (GENERATEPRECISEGC) {
169             outmethod.println("    struct ___String___ *newstring=NewString(NULL, argv[i], length);");
170         } else {
171             outmethod.println("    struct ___String___ *newstring=NewString(argv[i], length);");
172         }
173         outmethod.println("    ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i-1]=newstring;");
174         outmethod.println("  }");
175         
176         
177         MethodDescriptor md=typeutil.getMain();
178         ClassDescriptor cd=typeutil.getMainClass();
179         
180         outmethod.println("   {");
181         if (GENERATEPRECISEGC) {
182             outmethod.print("       struct "+cd.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params __parameterlist__={");
183             outmethod.println("1, NULL,"+"stringarray};");
184             outmethod.println("     "+cd.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(& __parameterlist__);");
185         } else
186             outmethod.println("     "+cd.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(stringarray);");
187         outmethod.println("   }");
188         
189         if (state.THREAD) {
190             outmethod.println("pthread_mutex_lock(&gclistlock);");
191             outmethod.println("threadcount--;");
192             outmethod.println("pthread_cond_signal(&gccond);");
193             outmethod.println("pthread_mutex_unlock(&gclistlock);");
194             outmethod.println("pthread_exit(NULL);");
195         }
196         outmethod.println("}");
197     }
198
199     private void outputTaskCode(PrintWriter outtaskdefs, PrintWriter outmethod) {
200         /* Compile task based program */
201         outtaskdefs.println("#include \"task.h\"");
202         outtaskdefs.println("#include \"methodheaders.h\"");
203         Iterator taskit=state.getTaskSymbolTable().getDescriptorsIterator();
204         while(taskit.hasNext()) {
205             TaskDescriptor td=(TaskDescriptor)taskit.next();
206             FlatMethod fm=state.getMethodFlat(td);
207             generateFlatMethod(fm, outmethod);
208             generateTaskDescriptor(outtaskdefs, fm, td);
209         }
210         
211         //Output task descriptors
212         taskit=state.getTaskSymbolTable().getDescriptorsIterator();
213         outtaskdefs.println("struct taskdescriptor * taskarray[]= {");
214         boolean first=true;
215         while(taskit.hasNext()) {
216             TaskDescriptor td=(TaskDescriptor)taskit.next();
217             if (first)
218                 first=false;
219             else
220                 outtaskdefs.println(",");
221             outtaskdefs.print("&task_"+td.getSafeSymbol());
222         }
223         outtaskdefs.println("};");
224
225         outtaskdefs.println("int numtasks="+state.getTaskSymbolTable().getValueSet().size()+";");
226     }
227
228     private void outputMethods(PrintWriter outmethod) {
229         outmethod.println("#include \"methodheaders.h\"");
230         outmethod.println("#include \"virtualtable.h\"");
231         outmethod.println("#include <runtime.h>");
232         if (state.THREAD)
233             outmethod.println("#include <thread.h>");
234         if (state.main!=null) {
235             outmethod.println("#include <string.h>");       
236         }
237         if (state.CONSCHECK) {
238             outmethod.println("#include \"checkers.h\"");
239         }
240         //Store the sizes of classes & array elements
241         generateSizeArray(outmethod);
242         
243         //Store table of supertypes
244         generateSuperTypeTable(outmethod);
245
246         //Store the layout of classes
247         generateLayoutStructs(outmethod);
248
249         /* Generate code for methods */
250         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
251         while(classit.hasNext()) {
252             ClassDescriptor cn=(ClassDescriptor)classit.next();
253             Iterator methodit=cn.getMethods();
254             while(methodit.hasNext()) {
255                 /* Classify parameters */
256                 MethodDescriptor md=(MethodDescriptor)methodit.next();
257                 FlatMethod fm=state.getMethodFlat(md);
258                 if (!md.getModifiers().isNative())
259                     generateFlatMethod(fm,outmethod);
260             }
261         }
262     }
263
264     private void outputStructs(PrintWriter outstructs) {
265         outstructs.println("#ifndef STRUCTDEFS_H");
266         outstructs.println("#define STRUCTDEFS_H");
267         outstructs.println("#include \"classdefs.h\"");
268
269         /* Output #defines that the runtime uses to determine type
270          * numbers for various objects it needs */
271
272         outstructs.println("#define STRINGARRAYTYPE "+
273                            (state.getArrayNumber(
274                                                  (new TypeDescriptor(typeutil.getClass(TypeUtil.StringClass))).makeArray(state))+state.numClasses()));
275
276         outstructs.println("#define OBJECTARRAYTYPE "+
277                            (state.getArrayNumber(
278                                                  (new TypeDescriptor(typeutil.getClass(TypeUtil.ObjectClass))).makeArray(state))+state.numClasses()));
279
280
281         outstructs.println("#define STRINGTYPE "+typeutil.getClass(TypeUtil.StringClass).getId());
282         outstructs.println("#define CHARARRAYTYPE "+
283                            (state.getArrayNumber((new TypeDescriptor(TypeDescriptor.CHAR)).makeArray(state))+state.numClasses()));
284
285         outstructs.println("#define BYTEARRAYTYPE "+
286                            (state.getArrayNumber((new TypeDescriptor(TypeDescriptor.BYTE)).makeArray(state))+state.numClasses()));
287
288         outstructs.println("#define BYTEARRAYARRAYTYPE "+
289                            (state.getArrayNumber((new TypeDescriptor(TypeDescriptor.BYTE)).makeArray(state).makeArray(state))+state.numClasses()));
290         
291         outstructs.println("#define NUMCLASSES "+state.numClasses());
292         if (state.TASK) {
293             outstructs.println("#define STARTUPTYPE "+typeutil.getClass(TypeUtil.StartupClass).getId());
294             outstructs.println("#define TAGTYPE "+typeutil.getClass(TypeUtil.TagClass).getId());
295             outstructs.println("#define TAGARRAYTYPE "+
296                                (state.getArrayNumber(new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass)).makeArray(state))+state.numClasses()));
297         }
298     }
299
300     private void outputClassDeclarations(PrintWriter outclassdefs) {
301         if (state.THREAD)
302             outclassdefs.println("#include <pthread.h>");
303         outclassdefs.println("struct "+arraytype+";");
304         /* Start by declaring all structs */
305         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
306         while(it.hasNext()) {
307             ClassDescriptor cn=(ClassDescriptor)it.next();
308             outclassdefs.println("struct "+cn.getSafeSymbol()+";");
309         }
310         outclassdefs.println("");
311         //Print out definition for array type
312         outclassdefs.println("struct "+arraytype+" {");
313         outclassdefs.println("  int type;");
314         if (state.THREAD) {
315             outclassdefs.println("  pthread_t tid;");
316             outclassdefs.println("  void * lockentry;");
317             outclassdefs.println("  int lockcount;");
318         }
319         if (state.TASK) {
320             outclassdefs.println("  int flag;");
321             outclassdefs.println("  void * flagptr;");
322             if(state.OPTIONAL) outclassdefs.println("  int failedstatus;");
323         }
324         printClassStruct(typeutil.getClass(TypeUtil.ObjectClass), outclassdefs);
325         
326         outclassdefs.println("  int ___length___;");
327         outclassdefs.println("};\n");
328         outclassdefs.println("extern int classsize[];");
329         outclassdefs.println("extern int hasflags[];");
330         outclassdefs.println("extern int * pointerarray[];");
331         outclassdefs.println("extern int supertypes[];");
332     }
333
334     private void outputTaskTypes(PrintWriter outtask) {
335         //Print out definitions for task types
336         outtask.println("#ifndef _TASK_H");
337         outtask.println("#define _TASK_H");
338         outtask.println("struct parameterdescriptor {");
339         outtask.println("int type;");
340         outtask.println("int numberterms;");
341         outtask.println("int *intarray;");
342         outtask.println("void * queue;");
343         outtask.println("int numbertags;");
344         outtask.println("int *tagarray;");
345         outtask.println("};");
346         
347         outtask.println("struct taskdescriptor {");
348         outtask.println("void * taskptr;");
349         outtask.println("int numParameters;");
350         outtask.println("int numTotal;");
351         outtask.println("struct parameterdescriptor **descriptorarray;");
352         outtask.println("char * name;");
353         outtask.println("};");
354         outtask.println("extern struct taskdescriptor * taskarray[];");
355         outtask.println("extern numtasks;");
356         outtask.println("#endif");
357     }
358
359     private void buildRepairStructs(PrintWriter outrepairstructs) {
360         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
361         while(classit.hasNext()) {
362             ClassDescriptor cn=(ClassDescriptor)classit.next();
363             outrepairstructs.println("structure "+cn.getSymbol()+" {");
364             outrepairstructs.println("  int __type__;");
365             if (state.TASK) {
366                 outrepairstructs.println("  int __flag__;");
367                 outrepairstructs.println("  int __flagptr__;");
368             }
369             printRepairStruct(cn, outrepairstructs);
370             outrepairstructs.println("}\n");
371         }
372         
373         for(int i=0;i<state.numArrays();i++) {
374             TypeDescriptor tdarray=arraytable[i];
375             TypeDescriptor tdelement=tdarray.dereference();
376             outrepairstructs.println("structure "+arraytype+"_"+state.getArrayNumber(tdarray)+" {");
377             outrepairstructs.println("  int __type__;");
378             printRepairStruct(typeutil.getClass(TypeUtil.ObjectClass), outrepairstructs);
379             outrepairstructs.println("  int length;");
380             /*
381               // Need to add support to repair tool for this
382               if (tdelement.isClass()||tdelement.isArray())
383                 outrepairstructs.println("  "+tdelement.getRepairSymbol()+" * elem[this.length];");
384             else
385                 outrepairstructs.println("  "+tdelement.getRepairSymbol()+" elem[this.length];");
386             */
387             outrepairstructs.println("}\n");
388         }
389
390     }
391
392     private void printRepairStruct(ClassDescriptor cn, PrintWriter output) {
393         ClassDescriptor sp=cn.getSuperDesc();
394         if (sp!=null)
395             printRepairStruct(sp, output);
396         
397         Vector fields=(Vector)fieldorder.get(cn);
398
399         for(int i=0;i<fields.size();i++) {
400             FieldDescriptor fd=(FieldDescriptor)fields.get(i);
401             if (fd.getType().isArray()) {
402                 output.println("  "+arraytype+"_"+ state.getArrayNumber(fd.getType()) +" * "+fd.getSymbol()+";");
403             } else if (fd.getType().isClass())
404                 output.println("  "+fd.getType().getRepairSymbol()+" * "+fd.getSymbol()+";");
405             else if (fd.getType().isFloat())
406                 output.println("  int "+fd.getSymbol()+"; /* really float */");
407             else 
408                 output.println("  "+fd.getType().getRepairSymbol()+" "+fd.getSymbol()+";");
409         }
410     }
411
412     /** This method outputs TaskDescriptor information */
413     void generateTaskDescriptor(PrintWriter output, FlatMethod fm, TaskDescriptor task) {
414         for (int i=0;i<task.numParameters();i++) {
415             VarDescriptor param_var=task.getParameter(i);
416             TypeDescriptor param_type=task.getParamType(i);
417             FlagExpressionNode param_flag=task.getFlag(param_var);
418             TagExpressionList param_tag=task.getTag(param_var);
419
420             int dnfterms;
421             if (param_flag==null) {
422                 output.println("int parameterdnf_"+i+"_"+task.getSafeSymbol()+"[]={");
423                 output.println("0x0, 0x0 };");
424                 dnfterms=1;
425             } else {
426
427                 DNFFlag dflag=param_flag.getDNF();
428                 dnfterms=dflag.size();
429                 
430                 Hashtable flags=(Hashtable)flagorder.get(param_type.getClassDesc());
431                 output.println("int parameterdnf_"+i+"_"+task.getSafeSymbol()+"[]={");
432                 for(int j=0;j<dflag.size();j++) {
433                     if (j!=0)
434                         output.println(",");
435                     Vector term=dflag.get(j);
436                     int andmask=0;
437                     int checkmask=0;
438                     for(int k=0;k<term.size();k++) {
439                         DNFFlagAtom dfa=(DNFFlagAtom)term.get(k);
440                         FlagDescriptor fd=dfa.getFlag();
441                         boolean negated=dfa.getNegated();
442                         int flagid=1<<((Integer)flags.get(fd)).intValue();
443                         andmask|=flagid;
444                         if (!negated)
445                             checkmask|=flagid;
446                     }
447                     output.print("0x"+Integer.toHexString(andmask)+", 0x"+Integer.toHexString(checkmask));
448                 }
449                 output.println("};");
450             }
451
452             output.println("int parametertag_"+i+"_"+task.getSafeSymbol()+"[]={");
453             //BUG...added next line to fix, test with any task program
454             if (param_tag!=null)
455                 for(int j=0;j<param_tag.numTags();j++) {
456                     if (j!=0)
457                         output.println(",");
458                     /* for each tag we need */
459                     /* which slot it is */
460                     /* what type it is */
461                     TagVarDescriptor tvd=(TagVarDescriptor)task.getParameterTable().get(param_tag.getName(j));
462                     TempDescriptor tmp=param_tag.getTemp(j);
463                     int slot=fm.getTagInt(tmp);
464                     output.println(slot+", "+state.getTagId(tvd.getTag()));
465                 }
466             output.println("};");
467
468             output.println("struct parameterdescriptor parameter_"+i+"_"+task.getSafeSymbol()+"={");
469             output.println("/* type */"+param_type.getClassDesc().getId()+",");
470             output.println("/* number of DNF terms */"+dnfterms+",");
471             output.println("parameterdnf_"+i+"_"+task.getSafeSymbol()+",");
472             output.println("0,");
473             //BUG, added next line to fix and else statement...test
474             //with any task program
475             if (param_tag!=null)
476                 output.println("/* number of tags */"+param_tag.numTags()+",");
477             else
478                 output.println("/* number of tags */ 0,");
479             output.println("parametertag_"+i+"_"+task.getSafeSymbol());
480             output.println("};");
481         }
482
483
484         output.println("struct parameterdescriptor * parameterdescriptors_"+task.getSafeSymbol()+"[] = {");
485         for (int i=0;i<task.numParameters();i++) {
486             if (i!=0)
487                 output.println(",");
488             output.print("&parameter_"+i+"_"+task.getSafeSymbol());
489         }
490         output.println("};");
491
492         output.println("struct taskdescriptor task_"+task.getSafeSymbol()+"={");
493         output.println("&"+task.getSafeSymbol()+",");
494         output.println("/* number of parameters */" +task.numParameters() + ",");
495         int numtotal=task.numParameters()+fm.numTags();
496         output.println("/* number total parameters */" +numtotal + ",");
497         output.println("parameterdescriptors_"+task.getSafeSymbol()+",");
498         output.println("\""+task.getSymbol()+"\"");
499         output.println("};");
500     }
501
502
503     /** The buildVirtualTables method outputs the virtual dispatch
504      * tables for methods. */
505
506     private void buildVirtualTables(PrintWriter outvirtual) {
507         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
508         while(classit.hasNext()) {
509             ClassDescriptor cd=(ClassDescriptor)classit.next();
510             if (virtualcalls.getMethodCount(cd)>maxcount)
511                 maxcount=virtualcalls.getMethodCount(cd);
512         }
513         MethodDescriptor[][] virtualtable=new MethodDescriptor[state.numClasses()+state.numArrays()][maxcount];
514
515         /* Fill in virtual table */
516         classit=state.getClassSymbolTable().getDescriptorsIterator();
517         while(classit.hasNext()) {
518             ClassDescriptor cd=(ClassDescriptor)classit.next();
519             fillinRow(cd, virtualtable, cd.getId());
520         }
521
522         ClassDescriptor objectcd=typeutil.getClass(TypeUtil.ObjectClass);
523         Iterator arrayit=state.getArrayIterator();
524         while(arrayit.hasNext()) {
525             TypeDescriptor td=(TypeDescriptor)arrayit.next();
526             int id=state.getArrayNumber(td);
527             fillinRow(objectcd, virtualtable, id+state.numClasses());
528         }
529         
530         outvirtual.print("void * virtualtable[]={");
531         boolean needcomma=false;
532         for(int i=0;i<state.numClasses()+state.numArrays();i++) {
533             for(int j=0;j<maxcount;j++) {
534                 if (needcomma)
535                     outvirtual.print(", ");
536                 if (virtualtable[i][j]!=null) {
537                     MethodDescriptor md=virtualtable[i][j];
538                     outvirtual.print("& "+md.getClassDesc().getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor());
539                 } else {
540                     outvirtual.print("0");
541                 }
542                 needcomma=true;
543             }
544             outvirtual.println("");
545         }
546         outvirtual.println("};");
547         outvirtual.close();
548     }
549
550     private void fillinRow(ClassDescriptor cd, MethodDescriptor[][] virtualtable, int rownum) {
551         /* Get inherited methods */
552         if (cd.getSuperDesc()!=null)
553             fillinRow(cd.getSuperDesc(), virtualtable, rownum);
554         /* Override them with our methods */
555         for(Iterator it=cd.getMethods();it.hasNext();) {
556             MethodDescriptor md=(MethodDescriptor)it.next();
557             if (md.isStatic()||md.getReturnType()==null)
558                 continue;
559             int methodnum=virtualcalls.getMethodNumber(md);
560             virtualtable[rownum][methodnum]=md;
561         }
562     }
563
564     /** Generate array that contains the sizes of class objects.  The
565      * object allocation functions in the runtime use this
566      * information. */
567
568     private void generateSizeArray(PrintWriter outclassdefs) {
569         outclassdefs.print("int classsize[]={");
570         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
571         cdarray=new ClassDescriptor[state.numClasses()];
572         while(it.hasNext()) {
573             ClassDescriptor cd=(ClassDescriptor)it.next();
574             cdarray[cd.getId()]=cd;
575         }
576         boolean needcomma=false;
577         for(int i=0;i<state.numClasses();i++) {
578             if (needcomma)
579                 outclassdefs.print(", ");
580             outclassdefs.print("sizeof(struct "+cdarray[i].getSafeSymbol()+")");            
581             needcomma=true;
582         }
583
584         arraytable=new TypeDescriptor[state.numArrays()];
585
586         Iterator arrayit=state.getArrayIterator();
587         while(arrayit.hasNext()) {
588             TypeDescriptor td=(TypeDescriptor)arrayit.next();
589             int id=state.getArrayNumber(td);
590             arraytable[id]=td;
591         }
592         
593         for(int i=0;i<state.numArrays();i++) {
594             if (needcomma)
595                 outclassdefs.print(", ");
596             TypeDescriptor tdelement=arraytable[i].dereference();
597             if (tdelement.isArray()||tdelement.isClass())
598                 outclassdefs.print("sizeof(void *)");
599             else
600                 outclassdefs.print("sizeof("+tdelement.getSafeSymbol()+")");
601             needcomma=true;
602         }
603
604         outclassdefs.println("};");
605     }
606
607     /** Constructs params and temp objects for each method or task.
608      * These objects tell the compiler which temps need to be
609      * allocated.  */
610
611     private void generateTempStructs(FlatMethod fm) {
612         MethodDescriptor md=fm.getMethod();
613         TaskDescriptor task=fm.getTask();
614
615         ParamsObject objectparams=md!=null?new ParamsObject(md,tag++):new ParamsObject(task, tag++);
616         if (md!=null)
617             paramstable.put(md, objectparams);
618         else
619             paramstable.put(task, objectparams);
620
621         for(int i=0;i<fm.numParameters();i++) {
622             TempDescriptor temp=fm.getParameter(i);
623             TypeDescriptor type=temp.getType();
624             if ((type.isPtr()||type.isArray())&&GENERATEPRECISEGC)
625                 objectparams.addPtr(temp);
626             else
627                 objectparams.addPrim(temp);
628         }
629
630         for(int i=0;i<fm.numTags();i++) {
631             TempDescriptor temp=fm.getTag(i);
632             if (GENERATEPRECISEGC)
633                 objectparams.addPtr(temp);
634             else
635                 objectparams.addPrim(temp);
636         }
637
638         TempObject objecttemps=md!=null?new TempObject(objectparams,md,tag++):new TempObject(objectparams, task, tag++);
639         if (md!=null)
640             tempstable.put(md, objecttemps);
641         else
642             tempstable.put(task, objecttemps);
643
644         for(Iterator nodeit=fm.getNodeSet().iterator();nodeit.hasNext();) {
645             FlatNode fn=(FlatNode)nodeit.next();
646             TempDescriptor[] writes=fn.writesTemps();
647             for(int i=0;i<writes.length;i++) {
648                 TempDescriptor temp=writes[i];
649                 TypeDescriptor type=temp.getType();
650                 if ((type.isPtr()||type.isArray())&&GENERATEPRECISEGC)
651                     objecttemps.addPtr(temp);
652                 else
653                     objecttemps.addPrim(temp);
654             }
655         }
656     }
657     
658     private void generateLayoutStructs(PrintWriter output) {
659         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
660         while(it.hasNext()) {
661             ClassDescriptor cn=(ClassDescriptor)it.next();
662             output.println("int "+cn.getSafeSymbol()+"_pointers[]={");
663             Iterator allit=cn.getFieldTable().getAllDescriptorsIterator();
664             int count=0;
665             while(allit.hasNext()) {
666                 FieldDescriptor fd=(FieldDescriptor)allit.next();
667                 TypeDescriptor type=fd.getType();
668                 if (type.isPtr()||type.isArray())
669                     count++;
670             }
671             output.print(count);
672             allit=cn.getFieldTable().getAllDescriptorsIterator();
673             while(allit.hasNext()) {
674                 FieldDescriptor fd=(FieldDescriptor)allit.next();
675                 TypeDescriptor type=fd.getType();
676                 if (type.isPtr()||type.isArray()) {
677                     output.println(",");
678                     output.print("((int)&(((struct "+cn.getSafeSymbol() +" *)0)->"+fd.getSafeSymbol()+"))");
679                 }
680             }
681             output.println("};");
682         }
683         output.println("int * pointerarray[]={");
684         boolean needcomma=false;
685         for(int i=0;i<state.numClasses();i++) {
686             ClassDescriptor cn=cdarray[i];
687             if (needcomma)
688                 output.println(",");
689             needcomma=true;
690             output.print(cn.getSafeSymbol()+"_pointers");
691         }
692
693         for(int i=0;i<state.numArrays();i++) {
694             if (needcomma)
695                 output.println(", ");
696             TypeDescriptor tdelement=arraytable[i].dereference();
697             if (tdelement.isArray()||tdelement.isClass())
698                 output.print("((int *)1)");
699             else
700                 output.print("0");
701             needcomma=true;
702         }
703         
704         output.println("};");
705         needcomma=false;
706         output.println("int hasflags[]={");
707         for(int i=0;i<state.numClasses();i++) {
708             ClassDescriptor cn=cdarray[i];
709             if (needcomma)
710                 output.println(", ");
711             needcomma=true;
712             if (cn.hasFlags())
713                 output.print("1");
714             else
715                 output.print("0");
716         }
717         output.println("};");
718     }
719
720     /** Print out table to give us supertypes */
721     private void generateSuperTypeTable(PrintWriter output) {
722         output.println("int supertypes[]={");
723         boolean needcomma=false;
724         for(int i=0;i<state.numClasses();i++) {
725             ClassDescriptor cn=cdarray[i];
726             if (needcomma)
727                 output.println(",");
728             needcomma=true;
729             if (cn.getSuperDesc()!=null) {
730                 ClassDescriptor cdsuper=cn.getSuperDesc();
731                 output.print(cdsuper.getId());
732             } else
733                 output.print("-1");
734         }
735         output.println("};");
736     }
737
738     /** Force consistent field ordering between inherited classes. */
739
740     private void printClassStruct(ClassDescriptor cn, PrintWriter classdefout) {
741         ClassDescriptor sp=cn.getSuperDesc();
742         if (sp!=null)
743             printClassStruct(sp, classdefout);
744         
745         if (!fieldorder.containsKey(cn)) {
746             Vector fields=new Vector();
747             fieldorder.put(cn,fields);
748             Iterator fieldit=cn.getFields();
749             while(fieldit.hasNext()) {
750                 FieldDescriptor fd=(FieldDescriptor)fieldit.next();
751                 if (sp==null||!sp.getFieldTable().contains(fd.getSymbol()))
752                     fields.add(fd);
753             }
754         }
755         Vector fields=(Vector)fieldorder.get(cn);
756
757         for(int i=0;i<fields.size();i++) {
758             FieldDescriptor fd=(FieldDescriptor)fields.get(i);
759             if (fd.getType().isClass()||fd.getType().isArray())
760                 classdefout.println("  struct "+fd.getType().getSafeSymbol()+" * "+fd.getSafeSymbol()+";");
761             else 
762                 classdefout.println("  "+fd.getType().getSafeSymbol()+" "+fd.getSafeSymbol()+";");
763         }
764     }
765
766
767     /* Map flags to integers consistently between inherited
768      * classes. */
769
770     private void mapFlags(ClassDescriptor cn) {
771         ClassDescriptor sp=cn.getSuperDesc();
772         if (sp!=null)
773             mapFlags(sp);
774         int max=0;
775         if (!flagorder.containsKey(cn)) {
776             Hashtable flags=new Hashtable();
777             flagorder.put(cn,flags);
778             if (sp!=null) {
779                 Hashtable superflags=(Hashtable)flagorder.get(sp);
780                 Iterator superflagit=superflags.keySet().iterator();
781                 while(superflagit.hasNext()) {
782                     FlagDescriptor fd=(FlagDescriptor)superflagit.next();
783                     Integer number=(Integer)superflags.get(fd);
784                     flags.put(fd, number);
785                     if ((number.intValue()+1)>max)
786                         max=number.intValue()+1;
787                 }
788             }
789             
790             Iterator flagit=cn.getFlags();
791             while(flagit.hasNext()) {
792                 FlagDescriptor fd=(FlagDescriptor)flagit.next();
793                 if (sp==null||!sp.getFlagTable().contains(fd.getSymbol()))
794                     flags.put(fd, new Integer(max++));
795             }
796         }
797     }
798
799
800     /** This function outputs (1) structures that parameters are
801      * passed in (when PRECISE GC is enabled) and (2) function
802      * prototypes for the methods */
803
804     private void generateCallStructs(ClassDescriptor cn, PrintWriter classdefout, PrintWriter output, PrintWriter headersout) {
805         /* Output class structure */
806         classdefout.println("struct "+cn.getSafeSymbol()+" {");
807         classdefout.println("  int type;");
808         if (state.THREAD) {
809             classdefout.println("  pthread_t tid;");
810             classdefout.println("  void * lockentry;");
811             classdefout.println("  int lockcount;");
812         }
813
814         if (state.TASK) {
815             classdefout.println("  int flag;");
816             classdefout.println("  void * flagptr;");
817             if (state.OPTIONAL) classdefout.println("  int failedstatus;");
818         }
819         printClassStruct(cn, classdefout);
820         classdefout.println("};\n");
821
822         /* Cycle through methods */
823         Iterator methodit=cn.getMethods();
824         while(methodit.hasNext()) {
825             /* Classify parameters */
826             MethodDescriptor md=(MethodDescriptor)methodit.next();
827             FlatMethod fm=state.getMethodFlat(md);
828             generateTempStructs(fm);
829
830             ParamsObject objectparams=(ParamsObject) paramstable.get(md);
831             TempObject objecttemps=(TempObject) tempstable.get(md);
832
833             /* Output parameter structure */
834             if (GENERATEPRECISEGC) {
835                 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params {");
836                 output.println("  int size;");
837                 output.println("  void * next;");
838                 for(int i=0;i<objectparams.numPointers();i++) {
839                     TempDescriptor temp=objectparams.getPointer(i);
840                     output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
841                 }
842                 output.println("};\n");
843             }
844
845             /* Output temp structure */
846             if (GENERATEPRECISEGC) {
847                 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals {");
848                 output.println("  int size;");
849                 output.println("  void * next;");
850                 for(int i=0;i<objecttemps.numPointers();i++) {
851                     TempDescriptor temp=objecttemps.getPointer(i);
852                     if (temp.getType().isNull())
853                         output.println("  void * "+temp.getSafeSymbol()+";");
854                     else
855                         output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
856                 }
857                 output.println("};\n");
858             }
859             
860             /* Output method declaration */
861             if (md.getReturnType()!=null) {
862                 if (md.getReturnType().isClass()||md.getReturnType().isArray())
863                     headersout.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
864                 else
865                     headersout.print(md.getReturnType().getSafeSymbol()+" ");
866             } else 
867                 //catch the constructor case
868                 headersout.print("void ");
869             headersout.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
870             
871             boolean printcomma=false;
872             if (GENERATEPRECISEGC) {
873                 headersout.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
874                 printcomma=true;
875             }
876
877             //output parameter list
878             for(int i=0;i<objectparams.numPrimitives();i++) {
879                 TempDescriptor temp=objectparams.getPrimitive(i);
880                 if (printcomma)
881                     headersout.print(", ");
882                 printcomma=true;
883                 if (temp.getType().isClass()||temp.getType().isArray())
884                     headersout.print("struct " + temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
885                 else
886                     headersout.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
887             }
888             headersout.println(");\n");
889         }
890     }
891
892
893     /** This function outputs (1) structures that parameters are
894      * passed in (when PRECISE GC is enabled) and (2) function
895      * prototypes for the tasks */
896
897     private void generateTaskStructs(PrintWriter output, PrintWriter headersout) {
898         /* Cycle through tasks */
899         Iterator taskit=state.getTaskSymbolTable().getDescriptorsIterator();
900
901         while(taskit.hasNext()) {
902             /* Classify parameters */
903             TaskDescriptor task=(TaskDescriptor)taskit.next();
904             FlatMethod fm=state.getMethodFlat(task);
905             generateTempStructs(fm);
906
907             ParamsObject objectparams=(ParamsObject) paramstable.get(task);
908             TempObject objecttemps=(TempObject) tempstable.get(task);
909
910             /* Output parameter structure */
911             if (GENERATEPRECISEGC) {
912                 output.println("struct "+task.getSafeSymbol()+"_params {");
913
914                 output.println("  int size;");
915                 output.println("  void * next;");
916                 for(int i=0;i<objectparams.numPointers();i++) {
917                     TempDescriptor temp=objectparams.getPointer(i);
918                     output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
919                 }
920
921                 output.println("};\n");
922                 if ((objectparams.numPointers()+fm.numTags())>maxtaskparams) {
923                     maxtaskparams=objectparams.numPointers()+fm.numTags();
924                 }
925             }
926
927             /* Output temp structure */
928             if (GENERATEPRECISEGC) {
929                 output.println("struct "+task.getSafeSymbol()+"_locals {");
930                 output.println("  int size;");
931                 output.println("  void * next;");
932                 for(int i=0;i<objecttemps.numPointers();i++) {
933                     TempDescriptor temp=objecttemps.getPointer(i);
934                     if (temp.getType().isNull())
935                         output.println("  void * "+temp.getSafeSymbol()+";");
936                     else if(temp.getType().isTag())
937                         output.println("  struct "+
938                                        (new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass))).getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
939                     else
940                         output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
941                 }
942                 output.println("};\n");
943             }
944             
945             /* Output task declaration */
946             headersout.print("void " + task.getSafeSymbol()+"(");
947             
948             boolean printcomma=false;
949             if (GENERATEPRECISEGC) {
950                 headersout.print("struct "+task.getSafeSymbol()+"_params * "+paramsprefix);
951             } else
952                 headersout.print("void * parameterarray[]");
953             headersout.println(");\n");
954         }
955     }
956
957     /** Generate code for flatmethod fm. */
958
959     private void generateFlatMethod(FlatMethod fm, PrintWriter output) {
960         MethodDescriptor md=fm.getMethod();
961         TaskDescriptor task=fm.getTask();
962
963         ClassDescriptor cn=md!=null?md.getClassDesc():null;
964
965         ParamsObject objectparams=(ParamsObject)paramstable.get(md!=null?md:task);
966
967         generateHeader(fm, md!=null?md:task,output);
968
969         TempObject objecttemp=(TempObject) tempstable.get(md!=null?md:task);
970
971         /* Print code */
972         if (GENERATEPRECISEGC) {
973             if (md!=null)
974                 output.print("   struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals "+localsprefix+"={");
975             else
976                 output.print("   struct "+task.getSafeSymbol()+"_locals "+localsprefix+"={");
977
978             output.print(objecttemp.numPointers()+",");
979             output.print(paramsprefix);
980             for(int j=0;j<objecttemp.numPointers();j++)
981                 output.print(", NULL");
982             output.println("};");
983         }
984
985         for(int i=0;i<objecttemp.numPrimitives();i++) {
986             TempDescriptor td=objecttemp.getPrimitive(i);
987             TypeDescriptor type=td.getType();
988             if (type.isNull())
989                 output.println("   void * "+td.getSafeSymbol()+";");
990             else if (type.isClass()||type.isArray())
991                 output.println("   struct "+type.getSafeSymbol()+" * "+td.getSafeSymbol()+";");
992             else
993                 output.println("   "+type.getSafeSymbol()+" "+td.getSafeSymbol()+";");
994         }
995
996         /* Generate labels first */
997         HashSet tovisit=new HashSet();
998         HashSet visited=new HashSet();
999         int labelindex=0;
1000         Hashtable nodetolabel=new Hashtable();
1001         tovisit.add(fm.getNext(0));
1002         FlatNode current_node=null;
1003
1004         //Assign labels 1st
1005         //Node needs a label if it is
1006         while(!tovisit.isEmpty()) {
1007             FlatNode fn=(FlatNode)tovisit.iterator().next();
1008             tovisit.remove(fn);
1009             visited.add(fn);
1010             for(int i=0;i<fn.numNext();i++) {
1011                 FlatNode nn=fn.getNext(i);
1012                 if(i>0) {
1013                     //1) Edge >1 of node
1014                     nodetolabel.put(nn,new Integer(labelindex++));
1015                 }
1016                 if (!visited.contains(nn)&&!tovisit.contains(nn)) {
1017                     tovisit.add(nn);
1018                 } else {
1019                     //2) Join point
1020                     nodetolabel.put(nn,new Integer(labelindex++));
1021                 }
1022             }
1023         }
1024
1025         if (state.THREAD&&GENERATEPRECISEGC) {
1026             output.println("checkcollect(&"+localsprefix+");");
1027         }
1028         
1029         //Do the actual code generation
1030         tovisit=new HashSet();
1031         visited=new HashSet();
1032         tovisit.add(fm.getNext(0));
1033         while(current_node!=null||!tovisit.isEmpty()) {
1034             if (current_node==null) {
1035                 current_node=(FlatNode)tovisit.iterator().next();
1036                 tovisit.remove(current_node);
1037             }
1038             visited.add(current_node);
1039             if (nodetolabel.containsKey(current_node))
1040                 output.println("L"+nodetolabel.get(current_node)+":");
1041             if (state.INSTRUCTIONFAILURE) {
1042                 if (state.THREAD) {
1043                     output.println("if ((++instructioncount)>failurecount) {instructioncount=0;injectinstructionfailure();}");
1044                 }
1045                 else
1046                     output.println("if ((--instructioncount)==0) injectinstructionfailure();");
1047             }
1048             if (current_node.numNext()==0) {
1049                 output.print("   ");
1050                 generateFlatNode(fm, current_node, output);
1051                 if (current_node.kind()!=FKind.FlatReturnNode) {
1052                     output.println("   return;");
1053                 }
1054                 current_node=null;
1055             } else if(current_node.numNext()==1) {
1056                 output.print("   ");
1057                 generateFlatNode(fm, current_node, output);
1058                 FlatNode nextnode=current_node.getNext(0);
1059                 if (visited.contains(nextnode)) {
1060                     output.println("goto L"+nodetolabel.get(nextnode)+";");
1061                     current_node=null;
1062                 } else
1063                     current_node=nextnode;
1064             } else if (current_node.numNext()==2) {
1065                 /* Branch */
1066                 output.print("   ");
1067                 generateFlatCondBranch(fm, (FlatCondBranch)current_node, "L"+nodetolabel.get(current_node.getNext(1)), output);
1068                 if (!visited.contains(current_node.getNext(1)))
1069                     tovisit.add(current_node.getNext(1));
1070                 if (visited.contains(current_node.getNext(0))) {
1071                     output.println("goto L"+nodetolabel.get(current_node.getNext(0))+";");
1072                     current_node=null;
1073                 } else
1074                     current_node=current_node.getNext(0);
1075             } else throw new Error();
1076         }
1077
1078
1079         output.println("}\n\n");
1080     }
1081
1082     /** Generate text string that corresponds to the Temp td. */
1083     private String generateTemp(FlatMethod fm, TempDescriptor td) {
1084         MethodDescriptor md=fm.getMethod();
1085         TaskDescriptor task=fm.getTask();
1086         TempObject objecttemps=(TempObject) tempstable.get(md!=null?md:task);
1087
1088         if (objecttemps.isLocalPrim(td)||objecttemps.isParamPrim(td)) {
1089             return td.getSafeSymbol();
1090         }
1091
1092         if (objecttemps.isLocalPtr(td)) {
1093             return localsprefix+"."+td.getSafeSymbol();
1094         }
1095
1096         if (objecttemps.isParamPtr(td)) {
1097             return paramsprefix+"->"+td.getSafeSymbol();
1098         }
1099         throw new Error();
1100     }
1101
1102     private void generateFlatNode(FlatMethod fm, FlatNode fn, PrintWriter output) {
1103         switch(fn.kind()) {
1104         case FKind.FlatAtomicEnterNode:
1105             generateFlatAtomicEnterNode(fm, (FlatAtomicEnterNode) fn, output);
1106             return;
1107         case FKind.FlatAtomicExitNode:
1108             generateFlatAtomicExitNode(fm, (FlatAtomicExitNode) fn, output);
1109             return;
1110         case FKind.FlatTagDeclaration:
1111             generateFlatTagDeclaration(fm, (FlatTagDeclaration) fn,output);
1112             return;
1113         case FKind.FlatCall:
1114             generateFlatCall(fm, (FlatCall) fn,output);
1115             return;
1116         case FKind.FlatFieldNode:
1117             generateFlatFieldNode(fm, (FlatFieldNode) fn,output);
1118             return;
1119         case FKind.FlatElementNode:
1120             generateFlatElementNode(fm, (FlatElementNode) fn,output);
1121             return;
1122         case FKind.FlatSetElementNode:
1123             generateFlatSetElementNode(fm, (FlatSetElementNode) fn,output);
1124             return;
1125         case FKind.FlatSetFieldNode:
1126             generateFlatSetFieldNode(fm, (FlatSetFieldNode) fn,output);
1127             return;
1128         case FKind.FlatNew:
1129             generateFlatNew(fm, (FlatNew) fn,output);
1130             return;
1131         case FKind.FlatOpNode:
1132             generateFlatOpNode(fm, (FlatOpNode) fn,output);
1133             return;
1134         case FKind.FlatCastNode:
1135             generateFlatCastNode(fm, (FlatCastNode) fn,output);
1136             return;
1137         case FKind.FlatLiteralNode:
1138             generateFlatLiteralNode(fm, (FlatLiteralNode) fn,output);
1139             return;
1140         case FKind.FlatReturnNode:
1141             generateFlatReturnNode(fm, (FlatReturnNode) fn,output);
1142             return;
1143         case FKind.FlatNop:
1144             output.println("/* nop */");
1145             return;
1146         case FKind.FlatBackEdge:
1147             if (state.THREAD&&GENERATEPRECISEGC) {
1148                 output.println("checkcollect(&"+localsprefix+");");
1149             } else
1150                 output.println("/* nop */");
1151             return;
1152         case FKind.FlatCheckNode:
1153             generateFlatCheckNode(fm, (FlatCheckNode) fn, output);
1154             return;
1155         case FKind.FlatFlagActionNode:
1156             generateFlatFlagActionNode(fm, (FlatFlagActionNode) fn, output);
1157             return;
1158         }
1159         throw new Error();
1160
1161     }
1162
1163     
1164     public void generateFlatAtomicEnterNode(FlatMethod fm,  FlatAtomicEnterNode faen, PrintWriter output) {
1165     }
1166
1167     public void generateFlatAtomicExitNode(FlatMethod fm,  FlatAtomicExitNode faen, PrintWriter output) {
1168     }
1169
1170     private void generateFlatCheckNode(FlatMethod fm,  FlatCheckNode fcn, PrintWriter output) {
1171
1172         if (state.CONSCHECK) {
1173             String specname=fcn.getSpec();
1174             String varname="repairstate___";
1175             output.println("{");
1176             output.println("struct "+specname+"_state * "+varname+"=allocate"+specname+"_state();");
1177
1178             TempDescriptor[] temps=fcn.getTemps();
1179             String[] vars=fcn.getVars();
1180             for(int i=0;i<temps.length;i++) {
1181                 output.println(varname+"->"+vars[i]+"=(int)"+generateTemp(fm, temps[i])+";");
1182             }
1183
1184             output.println("if (doanalysis"+specname+"("+varname+")) {");
1185             output.println("free"+specname+"_state("+varname+");");
1186             output.println("} else {");
1187             output.println("/* Bad invariant */");
1188             output.println("free"+specname+"_state("+varname+");");
1189             output.println("abort_task();");
1190             output.println("}");
1191
1192             output.println("}");
1193         }
1194     }
1195
1196     private void generateFlatCall(FlatMethod fm, FlatCall fc, PrintWriter output) {
1197         MethodDescriptor md=fc.getMethod();
1198         ParamsObject objectparams=(ParamsObject) paramstable.get(md);
1199         ClassDescriptor cn=md.getClassDesc();
1200         output.println("{");
1201         if (GENERATEPRECISEGC) {
1202             output.print("       struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params __parameterlist__={");
1203             
1204             output.print(objectparams.numPointers());
1205             //      output.print(objectparams.getUID());
1206             output.print(", & "+localsprefix);
1207             if (fc.getThis()!=null) {
1208                 output.print(", ");
1209                 output.print("(struct "+md.getThis().getType().getSafeSymbol() +" *)"+ generateTemp(fm,fc.getThis()));
1210             }
1211             for(int i=0;i<fc.numArgs();i++) {
1212                 Descriptor var=md.getParameter(i);
1213                 TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
1214                 if (objectparams.isParamPtr(paramtemp)) {
1215                     TempDescriptor targ=fc.getArg(i);
1216                     output.print(", ");
1217                     TypeDescriptor td=md.getParamType(i);
1218                     if (td.isTag())
1219                         output.print("(struct "+(new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass))).getSafeSymbol()  +" *)"+generateTemp(fm, targ));
1220                     else
1221                         output.print("(struct "+md.getParamType(i).getSafeSymbol()  +" *)"+generateTemp(fm, targ));
1222                 }
1223             }
1224             output.println("};");
1225         }
1226         output.print("       ");
1227
1228
1229         if (fc.getReturnTemp()!=null)
1230             output.print(generateTemp(fm,fc.getReturnTemp())+"=");
1231
1232         /* Do we need to do virtual dispatch? */
1233         if (md.isStatic()||md.getReturnType()==null||singleCall(fc.getThis().getType().getClassDesc(),md)) {
1234             output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor());
1235         } else {
1236             
1237             output.print("((");
1238             if (md.getReturnType().isClass()||md.getReturnType().isArray())
1239                 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
1240             else
1241                 output.print(md.getReturnType().getSafeSymbol()+" ");
1242             output.print("(*)(");
1243
1244             boolean printcomma=false;
1245             if (GENERATEPRECISEGC) {
1246                 output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * ");
1247                 printcomma=true;
1248             } 
1249
1250
1251             for(int i=0;i<objectparams.numPrimitives();i++) {
1252                 TempDescriptor temp=objectparams.getPrimitive(i);
1253                 if (printcomma)
1254                     output.print(", ");
1255                 printcomma=true;
1256                 if (temp.getType().isClass()||temp.getType().isArray())
1257                     output.print("struct " + temp.getType().getSafeSymbol()+" * ");
1258                 else
1259                     output.print(temp.getType().getSafeSymbol());
1260             }
1261
1262             output.print("))virtualtable["+generateTemp(fm,fc.getThis())+"->type*"+maxcount+"+"+virtualcalls.getMethodNumber(md)+"])");
1263         }
1264
1265         output.print("(");
1266         boolean needcomma=false;
1267         if (GENERATEPRECISEGC) {
1268             output.print("&__parameterlist__");
1269             needcomma=true;
1270         } else {
1271             if (fc.getThis()!=null) {
1272                 TypeDescriptor ptd=md.getThis().getType();
1273                 if (ptd.isClass()&&!ptd.isArray())
1274                     output.print("(struct "+ptd.getSafeSymbol()+" *) ");
1275                 output.print(generateTemp(fm,fc.getThis()));
1276                 needcomma=true;
1277             }
1278         }
1279         for(int i=0;i<fc.numArgs();i++) {
1280             Descriptor var=md.getParameter(i);
1281             TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
1282             if (objectparams.isParamPrim(paramtemp)) {
1283                 TempDescriptor targ=fc.getArg(i);
1284                 if (needcomma)
1285                     output.print(", ");
1286
1287                 TypeDescriptor ptd=md.getParamType(i);
1288                 if (ptd.isClass()&&!ptd.isArray())
1289                     output.print("(struct "+ptd.getSafeSymbol()+" *) ");
1290                 output.print(generateTemp(fm, targ));
1291                 needcomma=true;
1292             }
1293         }
1294         output.println(");");
1295         output.println("   }");
1296     }
1297
1298     private boolean singleCall(ClassDescriptor thiscd, MethodDescriptor md) {
1299         Set subclasses=typeutil.getSubClasses(thiscd);
1300         if (subclasses==null)
1301             return true;
1302         for(Iterator classit=subclasses.iterator();classit.hasNext();) {
1303             ClassDescriptor cd=(ClassDescriptor)classit.next();
1304             Set possiblematches=cd.getMethodTable().getSet(md.getSymbol());
1305             for(Iterator matchit=possiblematches.iterator();matchit.hasNext();) {
1306                 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
1307                 if (md.matches(matchmd))
1308                     return false;
1309             }
1310         }
1311         return true;
1312     }
1313
1314     private void generateFlatFieldNode(FlatMethod fm, FlatFieldNode ffn, PrintWriter output) {
1315         output.println(generateTemp(fm, ffn.getDst())+"="+ generateTemp(fm,ffn.getSrc())+"->"+ ffn.getField().getSafeSymbol()+";");
1316     }
1317
1318     private void generateFlatSetFieldNode(FlatMethod fm, FlatSetFieldNode fsfn, PrintWriter output) {
1319         if (fsfn.getField().getSymbol().equals("length")&&fsfn.getDst().getType().isArray())
1320             throw new Error("Can't set array length");
1321         output.println(generateTemp(fm, fsfn.getDst())+"->"+ fsfn.getField().getSafeSymbol()+"="+ generateTemp(fm,fsfn.getSrc())+";");
1322     }
1323
1324     private void generateFlatElementNode(FlatMethod fm, FlatElementNode fen, PrintWriter output) {
1325         TypeDescriptor elementtype=fen.getSrc().getType().dereference();
1326         String type="";
1327
1328         if (elementtype.isArray()||elementtype.isClass())
1329             type="void *";
1330         else 
1331             type=elementtype.getSafeSymbol()+" ";
1332
1333         if (fen.needsBoundsCheck()) {
1334             output.println("if ("+generateTemp(fm, fen.getIndex())+"< 0 || "+generateTemp(fm, fen.getIndex())+" >= "+generateTemp(fm,fen.getSrc()) + "->___length___)");
1335             output.println("failedboundschk();");
1336         }
1337
1338         output.println(generateTemp(fm, fen.getDst())+"=(("+ type+"*)(((char *) &("+ generateTemp(fm,fen.getSrc())+"->___length___))+sizeof(int)))["+generateTemp(fm, fen.getIndex())+"];");
1339     }
1340
1341     private void generateFlatSetElementNode(FlatMethod fm, FlatSetElementNode fsen, PrintWriter output) {
1342         //TODO: need dynamic check to make sure this assignment is actually legal
1343         //Because Object[] could actually be something more specific...ie. Integer[]
1344
1345         TypeDescriptor elementtype=fsen.getDst().getType().dereference();
1346         String type="";
1347
1348         if (elementtype.isArray()||elementtype.isClass())
1349             type="void *";
1350         else 
1351             type=elementtype.getSafeSymbol()+" ";
1352
1353         if (fsen.needsBoundsCheck()) {
1354             output.println("if ("+generateTemp(fm, fsen.getIndex())+"< 0 || "+generateTemp(fm, fsen.getIndex())+" >= "+generateTemp(fm,fsen.getDst()) + "->___length___)");
1355             output.println("failedboundschk();");
1356         }
1357
1358         output.println("(("+type +"*)(((char *) &("+ generateTemp(fm,fsen.getDst())+"->___length___))+sizeof(int)))["+generateTemp(fm, fsen.getIndex())+"]="+generateTemp(fm,fsen.getSrc())+";");
1359     }
1360
1361     private void generateFlatNew(FlatMethod fm, FlatNew fn, PrintWriter output) {
1362         if (fn.getType().isArray()) {
1363             int arrayid=state.getArrayNumber(fn.getType())+state.numClasses();
1364             if (GENERATEPRECISEGC) {
1365                 output.println(generateTemp(fm,fn.getDst())+"=allocate_newarray(&"+localsprefix+", "+arrayid+", "+generateTemp(fm, fn.getSize())+");");
1366             } else {
1367                 output.println(generateTemp(fm,fn.getDst())+"=allocate_newarray("+arrayid+", "+generateTemp(fm, fn.getSize())+");");
1368             }
1369         } else {
1370             if (GENERATEPRECISEGC) {
1371                 output.println(generateTemp(fm,fn.getDst())+"=allocate_new(&"+localsprefix+", "+fn.getType().getClassDesc().getId()+");");
1372             } else {
1373                 output.println(generateTemp(fm,fn.getDst())+"=allocate_new("+fn.getType().getClassDesc().getId()+");");
1374             }
1375         }
1376     }
1377
1378
1379     private void generateFlatTagDeclaration(FlatMethod fm, FlatTagDeclaration fn, PrintWriter output) {
1380         if (GENERATEPRECISEGC) {
1381             output.println(generateTemp(fm,fn.getDst())+"=allocate_tag(&"+localsprefix+", "+state.getTagId(fn.getType())+");");
1382         } else {
1383             output.println(generateTemp(fm,fn.getDst())+"=allocate_tag("+state.getTagId(fn.getType())+");");
1384         }
1385     }
1386
1387     private void generateFlatOpNode(FlatMethod fm, FlatOpNode fon, PrintWriter output) {
1388
1389         if (fon.getRight()!=null)
1390             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+fon.getOp().toString()+generateTemp(fm,fon.getRight())+";");
1391         else if (fon.getOp().getOp()==Operation.ASSIGN)
1392             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
1393         else if (fon.getOp().getOp()==Operation.UNARYPLUS)
1394             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
1395         else if (fon.getOp().getOp()==Operation.UNARYMINUS)
1396             output.println(generateTemp(fm, fon.getDest())+" = -"+generateTemp(fm, fon.getLeft())+";");
1397         else if (fon.getOp().getOp()==Operation.LOGIC_NOT)
1398             output.println(generateTemp(fm, fon.getDest())+" = !"+generateTemp(fm, fon.getLeft())+";");
1399         else
1400             output.println(generateTemp(fm, fon.getDest())+fon.getOp().toString()+generateTemp(fm, fon.getLeft())+";");
1401     }
1402
1403     private void generateFlatCastNode(FlatMethod fm, FlatCastNode fcn, PrintWriter output) {
1404         /* TODO: Do type check here */
1405         if (fcn.getType().isArray()) {
1406             throw new Error();
1407         } else if (fcn.getType().isClass())
1408             output.println(generateTemp(fm,fcn.getDst())+"=(struct "+fcn.getType().getSafeSymbol()+" *)"+generateTemp(fm,fcn.getSrc())+";");
1409         else
1410             output.println(generateTemp(fm,fcn.getDst())+"=("+fcn.getType().getSafeSymbol()+")"+generateTemp(fm,fcn.getSrc())+";");
1411     }
1412
1413     private void generateFlatLiteralNode(FlatMethod fm, FlatLiteralNode fln, PrintWriter output) {
1414         if (fln.getValue()==null)
1415             output.println(generateTemp(fm, fln.getDst())+"=0;");
1416         else if (fln.getType().getSymbol().equals(TypeUtil.StringClass)) {
1417             if (GENERATEPRECISEGC) {
1418                 output.println(generateTemp(fm, fln.getDst())+"=NewString(&"+localsprefix+", \""+FlatLiteralNode.escapeString((String)fln.getValue())+"\","+((String)fln.getValue()).length()+");");
1419             } else {
1420                 output.println(generateTemp(fm, fln.getDst())+"=NewString(\""+FlatLiteralNode.escapeString((String)fln.getValue())+"\","+((String)fln.getValue()).length()+");");
1421             }
1422         } else if (fln.getType().isBoolean()) {
1423             if (((Boolean)fln.getValue()).booleanValue())
1424                 output.println(generateTemp(fm, fln.getDst())+"=1;");
1425             else
1426                 output.println(generateTemp(fm, fln.getDst())+"=0;");
1427         } else if (fln.getType().isChar()) {
1428             String st=FlatLiteralNode.escapeString(fln.getValue().toString());
1429             output.println(generateTemp(fm, fln.getDst())+"='"+st+"';");
1430         } else
1431             output.println(generateTemp(fm, fln.getDst())+"="+fln.getValue()+";");
1432     }
1433
1434     private void generateFlatReturnNode(FlatMethod fm, FlatReturnNode frn, PrintWriter output) {
1435         
1436         if (frn.getReturnTemp()!=null)
1437             output.println("return "+generateTemp(fm, frn.getReturnTemp())+";");
1438         else
1439             output.println("return;");
1440     }
1441
1442     private void generateFlatCondBranch(FlatMethod fm, FlatCondBranch fcb, String label, PrintWriter output) {
1443         output.println("if (!"+generateTemp(fm, fcb.getTest())+") goto "+label+";");
1444     }
1445
1446     private void generateHeader(FlatMethod fm, Descriptor des, PrintWriter output) {
1447         /* Print header */
1448         ParamsObject objectparams=(ParamsObject)paramstable.get(des);
1449         MethodDescriptor md=null;
1450         TaskDescriptor task=null;
1451         if (des instanceof MethodDescriptor)
1452             md=(MethodDescriptor) des;
1453         else
1454             task=(TaskDescriptor) des;
1455
1456         ClassDescriptor cn=md!=null?md.getClassDesc():null;
1457         
1458         if (md!=null&&md.getReturnType()!=null) {
1459             if (md.getReturnType().isClass()||md.getReturnType().isArray())
1460                 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
1461             else
1462                 output.print(md.getReturnType().getSafeSymbol()+" ");
1463         } else 
1464             //catch the constructor case
1465             output.print("void ");
1466         if (md!=null)
1467             output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
1468         else
1469             output.print(task.getSafeSymbol()+"(");
1470         
1471         boolean printcomma=false;
1472         if (GENERATEPRECISEGC) {
1473             if (md!=null)
1474                 output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
1475             else
1476                 output.print("struct "+task.getSafeSymbol()+"_params * "+paramsprefix);
1477             printcomma=true;
1478         }
1479
1480         if (md!=null) {
1481             /* Method */
1482             for(int i=0;i<objectparams.numPrimitives();i++) {
1483                 TempDescriptor temp=objectparams.getPrimitive(i);
1484                 if (printcomma)
1485                     output.print(", ");
1486                 printcomma=true;
1487                 if (temp.getType().isClass()||temp.getType().isArray())
1488                     output.print("struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
1489                 else
1490                     output.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
1491             }
1492             output.println(") {");
1493         } else if (!GENERATEPRECISEGC) {
1494             /* Imprecise Task */
1495             output.println("void * parameterarray[]) {");
1496             /* Unpack variables */
1497             for(int i=0;i<objectparams.numPrimitives();i++) {
1498                 TempDescriptor temp=objectparams.getPrimitive(i);
1499                 output.println("struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+"=parameterarray["+i+"];");
1500             }
1501             for(int i=0;i<fm.numTags();i++) {
1502                 TempDescriptor temp=fm.getTag(i);
1503                 int offset=i+objectparams.numPrimitives();
1504                 output.println("struct ___TagDescriptor___ * "+temp.getSafeSymbol()+"=parameterarray["+offset+"];");
1505             }
1506
1507             if ((objectparams.numPrimitives()+fm.numTags())>maxtaskparams)
1508                 maxtaskparams=objectparams.numPrimitives()+fm.numTags();
1509         } else output.println(") {");
1510     }
1511     
1512     public void generateFlatFlagActionNode(FlatMethod fm, FlatFlagActionNode ffan, PrintWriter output) {
1513         output.println("/* FlatFlagActionNode */");
1514
1515
1516         /* Process tag changes */
1517         Relation tagsettable=new Relation();
1518         Relation tagcleartable=new Relation();
1519
1520         Iterator tagsit=ffan.getTempTagPairs(); 
1521         while (tagsit.hasNext()) {
1522             TempTagPair ttp=(TempTagPair) tagsit.next();
1523             TempDescriptor objtmp=ttp.getTemp();
1524             TagDescriptor tag=ttp.getTag();
1525             TempDescriptor tagtmp=ttp.getTagTemp();
1526             boolean tagstatus=ffan.getTagChange(ttp);
1527             if (tagstatus) {
1528                 tagsettable.put(objtmp, tagtmp);
1529             } else {
1530                 tagcleartable.put(objtmp, tagtmp);
1531             }
1532         }
1533
1534
1535         Hashtable flagandtable=new Hashtable();
1536         Hashtable flagortable=new Hashtable();
1537
1538         /* Process flag changes */
1539         Iterator flagsit=ffan.getTempFlagPairs();
1540         while(flagsit.hasNext()) {
1541             TempFlagPair tfp=(TempFlagPair)flagsit.next();
1542             TempDescriptor temp=tfp.getTemp();
1543             Hashtable flagtable=(Hashtable)flagorder.get(temp.getType().getClassDesc());
1544             FlagDescriptor flag=tfp.getFlag();
1545             if (flag==null) {
1546                 //Newly allocate objects that don't set any flags case
1547                 if (flagortable.containsKey(temp)) {
1548                     throw new Error();
1549                 }
1550                 int mask=0;
1551                 flagortable.put(temp,new Integer(mask));
1552             } else {
1553                 int flagid=1<<((Integer)flagtable.get(flag)).intValue();
1554                 boolean flagstatus=ffan.getFlagChange(tfp);
1555                 if (flagstatus) {
1556                     int mask=0;
1557                     if (flagortable.containsKey(temp)) {
1558                         mask=((Integer)flagortable.get(temp)).intValue();
1559                     }
1560                     mask|=flagid;
1561                     flagortable.put(temp,new Integer(mask));
1562                 } else {
1563                     int mask=0xFFFFFFFF;
1564                     if (flagandtable.containsKey(temp)) {
1565                         mask=((Integer)flagandtable.get(temp)).intValue();
1566                     }
1567                     mask&=(0xFFFFFFFF^flagid);
1568                     flagandtable.put(temp,new Integer(mask));
1569                 }
1570             }
1571         }
1572
1573
1574         HashSet flagtagset=new HashSet();
1575         flagtagset.addAll(flagortable.keySet());
1576         flagtagset.addAll(flagandtable.keySet());
1577         flagtagset.addAll(tagsettable.keySet());
1578         flagtagset.addAll(tagcleartable.keySet());
1579
1580         Iterator ftit=flagtagset.iterator();
1581         while(ftit.hasNext()) {
1582             TempDescriptor temp=(TempDescriptor)ftit.next();
1583             
1584             
1585             Set tagtmps=tagcleartable.get(temp);
1586             if (tagtmps!=null) {
1587                 Iterator tagit=tagtmps.iterator();
1588                 while(tagit.hasNext()) {
1589                     TempDescriptor tagtmp=(TempDescriptor)tagit.next();
1590                     if (GENERATEPRECISEGC) 
1591                         output.println("tagclear(&"+localsprefix+", (struct ___Object___ *)"+generateTemp(fm, temp)+", "+generateTemp(fm,tagtmp)+");");
1592                     else
1593                         output.println("tagclear((struct ___Object___ *)"+generateTemp(fm, temp)+", "+generateTemp(fm,tagtmp)+");");
1594                 }
1595             }
1596
1597             tagtmps=tagsettable.get(temp);
1598             if (tagtmps!=null) {
1599                 Iterator tagit=tagtmps.iterator();
1600                 while(tagit.hasNext()) {
1601                     TempDescriptor tagtmp=(TempDescriptor)tagit.next();
1602                     if (GENERATEPRECISEGC)
1603                         output.println("tagset(&"+localsprefix+", (struct ___Object___ *)"+generateTemp(fm, temp)+", "+generateTemp(fm,tagtmp)+");");
1604                     else
1605                         output.println("tagset((struct ___Object___ *)"+generateTemp(fm, temp)+", "+generateTemp(fm,tagtmp)+");");
1606                 }
1607             }
1608
1609             int ormask=0;
1610             int andmask=0xFFFFFFF;
1611             
1612             if (flagortable.containsKey(temp))
1613                 ormask=((Integer)flagortable.get(temp)).intValue();
1614             if (flagandtable.containsKey(temp))
1615                 andmask=((Integer)flagandtable.get(temp)).intValue();
1616             if (ffan.getTaskType()==FlatFlagActionNode.NEWOBJECT) {
1617                 output.println("flagorandinit("+generateTemp(fm, temp)+", 0x"+Integer.toHexString(ormask)+", 0x"+Integer.toHexString(andmask)+");");
1618             } else {
1619                 output.println("flagorand("+generateTemp(fm, temp)+", 0x"+Integer.toHexString(ormask)+", 0x"+Integer.toHexString(andmask)+");");
1620             }
1621         }
1622     }
1623
1624      void generateOptionalArrays(PrintWriter output, PrintWriter headers, Hashtable<ClassDescriptor, Hashtable<FlagState, HashSet>> safeexecution, Hashtable optionaltaskdescriptors) {
1625          
1626          //GENERATE HEADERS
1627          headers.println("#include \"task.h\"\n\n");
1628          
1629
1630          
1631          //STRUCT PREDICATEMEMBER
1632          headers.println("struct predicatemember{");
1633          headers.println("int type;");
1634          headers.println("int numdnfterms;");
1635          headers.println("int * flags;");
1636          headers.println("int numtags;");
1637          headers.println("int * tags;\n};\n\n");
1638
1639          //STRUCT EXITFLAGSTATE
1640          headers.println("struct exitflagstate{");
1641          headers.println("int numflags;");
1642          headers.println("int * flags;");
1643          /*
1644            headers.println("int numtags;");
1645            headers.println("int * tags;");
1646          */
1647          headers.println("\n};\n\n");
1648          
1649          //STRUCT EXITSTATES
1650          headers.println("struct exitstates{");
1651          headers.println("int numexitflagstates;");
1652          headers.println("struct exitflagstate * exitflagstatearray;\n};\n\n");
1653
1654          //STRUCT OPTIONALTASKDESCRIPTOR
1655          headers.println("struct optionaltaskdescriptor{");
1656          headers.println("struct taskdescriptor * task;");
1657          headers.println("int numpredicatemembers;");
1658          headers.println("struct predicatemember * predicatememberarray;");
1659          headers.println("int numexitstates;");
1660          headers.println("struct existates * exitstatesarray;\n};\n\n");
1661                  
1662          //STRUCT FSANALYSISWRAPPER
1663          headers.println("struct fsanalysiswrapper{");
1664          headers.println("int numflags;");
1665          headers.println("int * flags;");
1666          headers.println("int numtags;");
1667          headers.println("int * tags;");
1668          headers.println("int numoptionaltaskdescriptors;");
1669          headers.println("struct optionaltaskdescriptor * optionaltaskdescriptorarray;\n};\n\n");
1670
1671          //STRUCT CLASSANALYSISWRAPPER
1672          headers.println("struct classanalyiswrapper{");
1673          headers.println("int type;");
1674          headers.println("int numfsanalysiswrappers;");
1675          headers.println("struct fsanalysiswrapper * fsanalysiswrapperarray;\n};\n\n");
1676
1677          Iterator taskit=state.getTaskSymbolTable().getDescriptorsIterator();
1678          while(taskit.hasNext()) {
1679              TaskDescriptor td=(TaskDescriptor)taskit.next();
1680              headers.println("extern struct taskdescriptor task_"+td.getSafeSymbol()+";");
1681          }
1682          
1683                                                    
1684          
1685          //GENERATE STRUCTS
1686          output.println("#include \"optionalstruct.h\"\n\n");    
1687          HashSet processedcd = new HashSet();
1688         
1689
1690          Enumeration e = safeexecution.keys();
1691          while (e.hasMoreElements()) {
1692              
1693              //get the class
1694              ClassDescriptor cdtemp=(ClassDescriptor)e.nextElement();
1695              Hashtable flaginfo=(Hashtable)flagorder.get(cdtemp);//will be used several times
1696              
1697              //Generate the struct of optionals
1698              if((Hashtable)optionaltaskdescriptors.get(cdtemp)==null) System.out.println("Was in cd :"+cdtemp.getSymbol());
1699              Collection c_otd = ((Hashtable)optionaltaskdescriptors.get(cdtemp)).values();
1700              if( !c_otd.isEmpty() ){
1701                  for(Iterator otd_it = c_otd.iterator(); otd_it.hasNext();){
1702                      OptionalTaskDescriptor otd = (OptionalTaskDescriptor)otd_it.next();
1703                      
1704                      //generate the int arrays for the predicate
1705                      Predicate predicate = otd.predicate;
1706                      int predicateindex = 0;
1707                      //iterate through the classes concerned by the predicate
1708                      Collection c_vard = predicate.vardescriptors.values();
1709                      for(Iterator vard_it = c_vard.iterator(); vard_it.hasNext();){
1710                          VarDescriptor vard = (VarDescriptor)vard_it.next();
1711                          TypeDescriptor typed = vard.getType();
1712                          
1713                          //generate for flags
1714                          HashSet fen_hashset = predicate.flags.get(vard.getSymbol());
1715                          output.println("int predicateflags_"+predicateindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"[]={");
1716                          int numberterms=0;
1717                          if (fen_hashset!=null){
1718                              for (Iterator fen_it = fen_hashset.iterator(); fen_it.hasNext();){
1719                                  FlagExpressionNode fen = (FlagExpressionNode)fen_it.next();
1720                                  if (fen==null) {
1721                                      //output.println("0x0, 0x0 };");
1722                                      //numberterms+=1;
1723                                  }
1724                                  else {
1725                                      
1726                                      DNFFlag dflag=fen.getDNF();
1727                                      numberterms+=dflag.size();
1728                                      
1729                                      Hashtable flags=(Hashtable)flagorder.get(typed.getClassDesc());
1730                                      
1731                                      for(int j=0;j<dflag.size();j++) {
1732                                          if (j!=0)
1733                                              output.println(",");
1734                                          Vector term=dflag.get(j);
1735                                          int andmask=0;
1736                                          int checkmask=0;
1737                                          for(int k=0;k<term.size();k++) {
1738                                              DNFFlagAtom dfa=(DNFFlagAtom)term.get(k);
1739                                              FlagDescriptor fd=dfa.getFlag();
1740                                              boolean negated=dfa.getNegated();
1741                                              int flagid=1<<((Integer)flags.get(fd)).intValue();
1742                                              andmask|=flagid;
1743                                              if (!negated)
1744                                                  checkmask|=flagid;
1745                                          }
1746                                          output.print("/*andmask*/0x"+Integer.toHexString(andmask)+", /*checkmask*/0x"+Integer.toHexString(checkmask));
1747                                      }
1748                                  }
1749                              }
1750                          }
1751                          output.println("};\n");
1752                          
1753                          //generate for tags
1754                          TagExpressionList tagel = predicate.tags.get(vard.getSymbol()); 
1755                          output.println("int predicatetags_"+predicateindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"[]={");
1756                          //BUG...added next line to fix, test with any task program
1757                          int numtags = 0;
1758                          if (tagel!=null){
1759                              for(int j=0;j<tagel.numTags();j++) {
1760                                  if (j!=0)
1761                                      output.println(",");
1762                                  /* for each tag we need */
1763                                  /* which slot it is */
1764                                  /* what type it is */
1765                                  //TagVarDescriptor tvd=(TagVarDescriptor)task.getParameterTable().get(tagel.getName(j));
1766                                  TempDescriptor tmp=tagel.getTemp(j);
1767                                  //got rid of slot
1768                                  output.println("/*tagid*/"+state.getTagId(tmp.getTag()));
1769                              }
1770                              numtags = tagel.numTags();
1771                          }
1772                          output.println("};");
1773                          
1774                          //store the result into a predicatemember struct
1775                          output.println("struct predicatemember predicatemember_"+predicateindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"={");
1776                          output.println("/*type*/"+typed.getClassDesc().getId()+",");
1777                          output.println("/* number of dnf terms */"+numberterms+",");
1778                          output.println("predicateflags_"+predicateindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+",");
1779                          output.println("/* number of tag */"+numtags+",");
1780                          output.println("predicatetags_"+predicateindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+",");
1781                          output.println("};\n");
1782                          predicateindex++;
1783                      }
1784                      
1785
1786                      //generate an array that stores the entire predicate
1787                      output.println("struct predicatemember * predicatememberarray_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"[]={");
1788                      for( int j = 0; j<predicateindex; j++){
1789                          if( j != predicateindex-1)output.println("&predicatemember_"+j+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+",");
1790                          else output.println("&predicatemember_"+j+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"};\n");
1791                      }
1792
1793                      //generate the struct for possible exitfses
1794                      HashSet<HashSet> exitfses = otd.exitfses;
1795                      int exitindex = 0;
1796                      int nbexit = exitfses.size();
1797                      int fsnumber;
1798                      
1799                      //iterate through possible exits
1800                      for(Iterator exitfseshash = exitfses.iterator(); exitfseshash.hasNext();){
1801                          HashSet temp_hashset = (HashSet)exitfseshash.next();
1802                          fsnumber = 0 ;
1803                          
1804                          //iterate through possible FSes corresponding to the exit
1805                          for(Iterator exfses = temp_hashset.iterator(); exfses.hasNext();){
1806                             FlagState fs = (FlagState)exfses.next();
1807                             fsnumber++;
1808                             output.println("int flags"+fsnumber+"_EXIT"+exitindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"[]={");
1809                             int counterflag = 0;
1810                             for(Iterator flags = fs.getFlags(); flags.hasNext();){
1811                                 FlagDescriptor flagd = (FlagDescriptor)flags.next();
1812                                 int flagid=1<<((Integer)flaginfo.get(flagd)).intValue();
1813                                 if( flags.hasNext() ) output.print("0x"+Integer.toHexString(flagid)+" /*"+Integer.toBinaryString(flagid)+"*/,");
1814                                 else  output.print("0x"+Integer.toHexString(flagid)+" /*"+Integer.toBinaryString(flagid)+"*/");
1815                                 counterflag++;
1816                             } 
1817                             output.println("};\n");
1818                             //do the same for tags;
1819                             //maybe not needed because no tag changes tolerated.
1820
1821                             //store the information into a struct
1822                             output.println("struct exitflagstate exitflagstate"+fsnumber+"_EXIT"+exitindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"={");
1823                             output.println("/*number of flags*/"+counterflag+",");
1824                             output.println("flags"+fsnumber+"_EXIT"+exitindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol());
1825                             output.println("};\n");
1826                          }
1827                          
1828                          //store fses corresponding to this exit into an array
1829                          output.println("struct exitflagstate * exitflagstatearray"+"_EXIT"+exitindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+" [] = {");
1830                          for( int j = 0; j<fsnumber; j++){
1831                              if( j != fsnumber-1)output.println("&exitflagstate"+(j+1)+"_EXIT"+exitindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"'");
1832                              else output.println("&exitflagstate"+(j+1)+"_EXIT"+exitindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"};\n");
1833                          }
1834                          
1835                          //store that information in a struct
1836                          output.println("struct exitstates exitstates"+exitindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"={");
1837                          output.println("/*number of exitflagstate*/"+fsnumber+",");
1838                          output.println("exitflagstatearray"+"_EXIT"+exitindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol());
1839                          output.println("};\n");
1840
1841                          exitindex++;
1842                      }
1843                      
1844                      //store the information concerning all exits into an array
1845                      output.println("struct exitstates * exitstatesarray_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"[]={");
1846                      for( int j = 0; j<nbexit; j++){
1847                          if( j != nbexit-1)output.println("&exitstates"+j+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+",");
1848                          else output.println("&exitstates"+j+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"};\n");
1849                      }
1850                                      
1851                                      
1852                      //generate optionaltaskdescriptor that actually includes exit fses, predicate and the task concerned
1853                      output.println("struct optionaltaskdescriptor optionaltaskdescriptor_"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"={");
1854                      output.println("task_"+otd.td.getSafeSymbol()+",");
1855                      output.println("/*number of members */"+predicateindex+",");
1856                      output.println("predicatememberarray_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+",");
1857                      output.println("/*number of exit fses */"+nbexit+",");
1858                      output.println("exitstatearray_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol());
1859                      output.println("};\n");
1860                  }      
1861              }
1862              else continue; // if there is no optionals, there is no need to build the rest of the struct 
1863              
1864              //get all the possible falgstates reachable by an object
1865              Hashtable hashtbtemp = safeexecution.get(cdtemp);
1866              Enumeration fses = hashtbtemp.keys();
1867              int fscounter = 0;
1868              while(fses.hasMoreElements()){
1869                  FlagState fs = (FlagState)fses.nextElement();
1870                  fscounter++;
1871                  
1872                  //get the set of OptionalTaskDescriptors corresponding
1873                  HashSet availabletasks = (HashSet)hashtbtemp.get(fs);
1874                  //iterate through the OptionalTaskDescriptors and store the pointers to the optionals struct (see on top) into an array
1875                  
1876                  output.println("struct optionaltaskdescriptor * optionaltaskdescriptorarray_FS"+fscounter+"_"+cdtemp.getSafeSymbol()+"[] = {");
1877                  for(Iterator mos = availabletasks.iterator(); mos.hasNext();){
1878                      OptionalTaskDescriptor mm = (OptionalTaskDescriptor)mos.next();
1879                      if(!mos.hasNext()) output.println("&optionaltaskdescriptor_"+mm.getuid()+"_"+cdtemp.getSafeSymbol()+"};\n");
1880                      
1881                      else output.println("&optionaltaskdescriptor_"+mm.getuid()+"_"+cdtemp.getSafeSymbol()+",");
1882                  }
1883
1884                  //process flag information (what the flag after failure is) so we know what optionaltaskdescriptors to choose.
1885                  
1886                  output.println("int flags_FS"+fscounter+"_"+cdtemp.getSafeSymbol()+"[]={");
1887                  for(Iterator flags = fs.getFlags(); flags.hasNext();){
1888                      FlagDescriptor flagd = (FlagDescriptor)flags.next();
1889                      int flagid=1<<((Integer)flaginfo.get(flagd)).intValue();
1890                      if( flags.hasNext() ) output.print("0x"+Integer.toHexString(flagid)+" /*"+Integer.toBinaryString(flagid)+"*/,");
1891                      else  output.print("0x"+Integer.toHexString(flagid)+" /*"+Integer.toBinaryString(flagid)+"*/");
1892                      
1893                  }
1894                  //process tag information
1895                  
1896                  int tagcounter = 0;
1897                  //TagExpressionList tagel = fs.getTags(); 
1898                  //output.println("int predicatetags_"+predicateindex+"_OTD"+otd.getuid()+"_"+cdtemp.getSafeSymbol()+"[]={");
1899                  //BUG...added next line to fix, test with any task program
1900                  
1901                  //if (tagel!=null){
1902                  //    for(int j=0;j<tagel.numTags();j++) {
1903                  //      if (j!=0)
1904                  //          output.println(",");
1905                  //      TempDescriptor tmp=tagel.getTemp(j);
1906                  //      output.println("/*tagid*/"+state.getTagId(tmp.getTag()));
1907                  //   }
1908                  //  numtags = tagel.numTags();
1909                  //}
1910                  //output.println("};");
1911                  
1912                  
1913                  //Store the result in fsanalysiswrapper
1914                  output.println("};\n");
1915                  output.println("struct fsanalysiswrapper fsanalysiswrapper_FS"+fscounter+"_"+cdtemp.getSafeSymbol()+"={");
1916                  output.println("/* number of flags*/"+fs.numFlags()+",");
1917                  output.println("flags_FS"+fscounter+"_"+cdtemp.getSafeSymbol()+",");
1918                  output.println("/* number of tags*/"+tagcounter+",");
1919                  output.println("tags_FS"+fscounter+"_"+cdtemp.getSafeSymbol()+",");
1920                  output.println("/* number of optionaltaskdescriptors */"+availabletasks.size()+",");
1921                  output.println("optionaltaskdescriptorarray_FS"+fscounter+"_"+cdtemp.getSafeSymbol());
1922                  output.println("};\n");
1923                  
1924              }
1925
1926              //Build the array of fsanalysiswrappers
1927              output.println("struct fsanalysiswrapper * fsanalysiswrapperarray_"+cdtemp.getSafeSymbol()+"[] = {");
1928              for(int i = 0; i<fscounter; i++){
1929                  if(i==fscounter-1) output.println("&fsanalysiswrapper_FS"+(i+1)+"_"+cdtemp.getSafeSymbol()+"};\n");
1930                          
1931                      else output.println("&fsanalysiswrapper_FS"+(i+1)+"_"+cdtemp.getSafeSymbol()+",");
1932              }
1933
1934              //Build the classanalysiswrapper referring to the previous array
1935              output.println("struct classanalysiswrapper classanalysiswrapper_"+cdtemp.getSafeSymbol()+"={");
1936              output.println("/*type*/"+cdtemp.getId()+",");
1937              output.println("/* number of fsanalysiswrappers */"+fscounter+",");
1938              output.println("fsanalysiswrapperarray_"+cdtemp.getSafeSymbol()+"};\n");
1939              fscounter = 0;
1940              processedcd.add(cdtemp);
1941          }
1942
1943          //build an array containing every classes for which code has been build
1944          output.println("struct classanalysiswrapper * classanalysiswrapperarray[]={");
1945          for(Iterator classit = processedcd.iterator(); classit.hasNext();){
1946              ClassDescriptor cdtemp=(ClassDescriptor)classit.next();
1947              if(!classit.hasNext()) output.println("&classanalysiswrapper_"+cdtemp.getSafeSymbol()+"};\n");
1948              else output.println("&classanalysiswrapper_"+cdtemp.getSafeSymbol()+",");
1949          }
1950          output.println("int numclasses = "+processedcd.size()+";");
1951          
1952      }
1953     
1954 }
1955          
1956
1957
1958
1959
1960