Changes:
[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
11 public class BuildCode {
12     State state;
13     Hashtable temptovar;
14     Hashtable paramstable;
15     Hashtable tempstable;
16     Hashtable fieldorder;
17     Hashtable flagorder;
18     int tag=0;
19     String localsprefix="___locals___";
20     String paramsprefix="___params___";
21     public static boolean GENERATEPRECISEGC=false;
22     public static String PREFIX="";
23     public static String arraytype="ArrayObject";
24     Virtual virtualcalls;
25     TypeUtil typeutil;
26     private int maxtaskparams=0;
27     ClassDescriptor[] cdarray;
28     TypeDescriptor[] arraytable;
29
30     public BuildCode(State st, Hashtable temptovar, TypeUtil typeutil) {
31         state=st;
32         this.temptovar=temptovar;
33         paramstable=new Hashtable();    
34         tempstable=new Hashtable();
35         fieldorder=new Hashtable();
36         flagorder=new Hashtable();
37         this.typeutil=typeutil;
38         virtualcalls=new Virtual(state);
39     }
40
41     /** The buildCode method outputs C code for all the methods.  The Flat
42      * versions of the methods must already be generated and stored in
43      * the State object. */
44
45     public void buildCode() {
46         /* Create output streams to write to */
47         PrintWriter outclassdefs=null;
48         PrintWriter outstructs=null;
49         PrintWriter outrepairstructs=null;
50         PrintWriter outmethodheader=null;
51         PrintWriter outmethod=null;
52         PrintWriter outvirtual=null;
53         PrintWriter outtask=null;
54         PrintWriter outtaskdefs=null;
55
56         try {
57             OutputStream str=new FileOutputStream(PREFIX+"structdefs.h");
58             outstructs=new java.io.PrintWriter(str, true);
59             str=new FileOutputStream(PREFIX+"methodheaders.h");
60             outmethodheader=new java.io.PrintWriter(str, true);
61             str=new FileOutputStream(PREFIX+"classdefs.h");
62             outclassdefs=new java.io.PrintWriter(str, true);
63             str=new FileOutputStream(PREFIX+"methods.c");
64             outmethod=new java.io.PrintWriter(str, true);
65             str=new FileOutputStream(PREFIX+"virtualtable.h");
66             outvirtual=new java.io.PrintWriter(str, true);
67             if (state.TASK) {
68                 str=new FileOutputStream(PREFIX+"task.h");
69                 outtask=new java.io.PrintWriter(str, true);
70                 str=new FileOutputStream(PREFIX+"taskdefs.c");
71                 outtaskdefs=new java.io.PrintWriter(str, true);
72             }
73             if (state.structfile!=null) {
74                 str=new FileOutputStream(PREFIX+state.structfile+".struct");
75                 outrepairstructs=new java.io.PrintWriter(str, true);
76             }
77         } catch (Exception e) {
78             e.printStackTrace();
79             System.exit(-1);
80         }
81
82         /* Build the virtual dispatch tables */
83         buildVirtualTables(outvirtual);
84
85
86         /* Output includes */
87
88         outmethodheader.println("#ifndef METHODHEADERS_H");
89         outmethodheader.println("#define METHODHEADERS_H");
90         outmethodheader.println("#include \"structdefs.h\"");
91
92         outstructs.println("#ifndef STRUCTDEFS_H");
93         outstructs.println("#define STRUCTDEFS_H");
94         outstructs.println("#include \"classdefs.h\"");
95
96
97
98         /* Output types for short array and string */
99         outstructs.println("#define STRINGARRAYTYPE "+
100                            (state.getArrayNumber(
101                                                  (new TypeDescriptor(typeutil.getClass(TypeUtil.StringClass))).makeArray(state))+state.numClasses()));
102
103         outstructs.println("#define OBJECTARRAYTYPE "+
104                            (state.getArrayNumber(
105                                                  (new TypeDescriptor(typeutil.getClass(TypeUtil.ObjectClass))).makeArray(state))+state.numClasses()));
106
107
108         outstructs.println("#define STRINGTYPE "+typeutil.getClass(TypeUtil.StringClass).getId());
109         outstructs.println("#define CHARARRAYTYPE "+
110                            (state.getArrayNumber((new TypeDescriptor(TypeDescriptor.CHAR)).makeArray(state))+state.numClasses()));
111
112         outstructs.println("#define BYTEARRAYTYPE "+
113                            (state.getArrayNumber((new TypeDescriptor(TypeDescriptor.BYTE)).makeArray(state))+state.numClasses()));
114
115         outstructs.println("#define BYTEARRAYARRAYTYPE "+
116                            (state.getArrayNumber((new TypeDescriptor(TypeDescriptor.BYTE)).makeArray(state).makeArray(state))+state.numClasses()));
117         
118         outstructs.println("#define NUMCLASSES "+state.numClasses());
119         if (state.TASK) {
120             outstructs.println("#define STARTUPTYPE "+typeutil.getClass(TypeUtil.StartupClass).getId());
121             outstructs.println("#define TAGTYPE "+typeutil.getClass(TypeUtil.TagClass).getId());
122             outstructs.println("#define TAGARRAYTYPE "+
123                                (state.getArrayNumber(new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass)).makeArray(state))+state.numClasses()));
124         }
125         
126         // Output the C class declarations
127         // These could mutually reference each other
128         if (state.THREAD)
129             outclassdefs.println("#include <pthread.h>");
130
131         outclassdefs.println("struct "+arraytype+";");
132
133         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
134         while(it.hasNext()) {
135             ClassDescriptor cn=(ClassDescriptor)it.next();
136             outclassdefs.println("struct "+cn.getSafeSymbol()+";");
137         }
138         outclassdefs.println("");
139         {
140             //Print out definition for array type
141             outclassdefs.println("struct "+arraytype+" {");
142             outclassdefs.println("  int type;");
143             if (state.THREAD) {
144                 outclassdefs.println("  pthread_t tid;");
145                 outclassdefs.println("  void * lockentry;");
146                 outclassdefs.println("  int lockcount;");
147             }
148                 
149             if (state.TASK) {
150                 outclassdefs.println("  int flag;");
151                 outclassdefs.println("  void * flagptr;");
152             }
153             printClassStruct(typeutil.getClass(TypeUtil.ObjectClass), outclassdefs);
154             outclassdefs.println("  int ___length___;");
155             outclassdefs.println("};\n");
156
157             if (state.TASK) {
158             //Print out definitions for task types
159                 outtask.println("struct parameterdescriptor {");
160                 outtask.println("int type;");
161                 outtask.println("int numberterms;");
162                 outtask.println("int *intarray;");
163                 outtask.println("void * queue;");
164                 outtask.println("int numbertags;");
165                 outtask.println("int *tagarray;");
166                 outtask.println("};");
167
168                 outtask.println("struct taskdescriptor {");
169                 outtask.println("void * taskptr;");
170                 outtask.println("int numParameters;");
171                 outtask.println("int numTotal;");
172                 outtask.println("struct parameterdescriptor **descriptorarray;");
173                 outtask.println("char * name;");
174                 outtask.println("};");
175                 outtask.println("extern struct taskdescriptor * taskarray[];");
176                 outtask.println("extern numtasks;");
177             }
178         }
179
180         // Output function prototypes and structures for parameters
181         it=state.getClassSymbolTable().getDescriptorsIterator();
182         while(it.hasNext()) {
183             ClassDescriptor cn=(ClassDescriptor)it.next();
184             generateCallStructs(cn, outclassdefs, outstructs, outmethodheader);
185         }
186
187         if (state.TASK) {
188             /* Map flags to integers */
189             it=state.getClassSymbolTable().getDescriptorsIterator();
190             while(it.hasNext()) {
191                 ClassDescriptor cn=(ClassDescriptor)it.next();
192                 mapFlags(cn);
193             }
194             /* Generate Tasks */
195             generateTaskStructs(outstructs, outmethodheader);
196         }
197
198         outmethodheader.println("#endif");
199
200         outmethodheader.close();
201
202         /* Build the actual methods */
203         outmethod.println("#include \"methodheaders.h\"");
204         outmethod.println("#include \"virtualtable.h\"");
205         outmethod.println("#include <runtime.h>");
206         if (state.THREAD)
207             outmethod.println("#include <thread.h>");
208         if (state.main!=null) {
209             outmethod.println("#include <string.h>");       
210         }
211
212         if (state.CONSCHECK) {
213             outmethod.println("#include \"checkers.h\"");
214         }
215         outclassdefs.println("extern int classsize[];");
216         outclassdefs.println("extern int hasflags[];");
217         outclassdefs.println("extern int * pointerarray[];");
218         outclassdefs.println("extern int supertypes[];");
219
220         //Store the sizes of classes & array elements
221         generateSizeArray(outmethod);
222         
223         //Store table of supertypes
224         generateSuperTypeTable(outmethod);
225
226         //Store the layout of classes
227         generateLayoutStructs(outmethod);
228
229         /* Generate code for methods */
230         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
231         while(classit.hasNext()) {
232             ClassDescriptor cn=(ClassDescriptor)classit.next();
233             Iterator methodit=cn.getMethods();
234             while(methodit.hasNext()) {
235                 /* Classify parameters */
236                 MethodDescriptor md=(MethodDescriptor)methodit.next();
237                 FlatMethod fm=state.getMethodFlat(md);
238                 if (!md.getModifiers().isNative())
239                     generateFlatMethod(fm,outmethod);
240             }
241         }
242
243         if (state.TASK) {
244             /* Compile task based program */
245             outtaskdefs.println("#include \"task.h\"");
246             outtaskdefs.println("#include \"methodheaders.h\"");
247             Iterator taskit=state.getTaskSymbolTable().getDescriptorsIterator();
248             while(taskit.hasNext()) {
249                 TaskDescriptor td=(TaskDescriptor)taskit.next();
250                 FlatMethod fm=state.getMethodFlat(td);
251                 generateFlatMethod(fm, outmethod);
252                 generateTaskDescriptor(outtaskdefs, fm, td);
253             }
254
255             {
256                 //Output task descriptors
257                 taskit=state.getTaskSymbolTable().getDescriptorsIterator();
258                 outtaskdefs.println("struct taskdescriptor * taskarray[]= {");
259                 boolean first=true;
260                 while(taskit.hasNext()) {
261                     TaskDescriptor td=(TaskDescriptor)taskit.next();
262                     if (first)
263                         first=false;
264                     else
265                         outtaskdefs.println(",");
266                     outtaskdefs.print("&task_"+td.getSafeSymbol());
267                 }
268                 outtaskdefs.println("};");
269             }
270
271             outtaskdefs.println("int numtasks="+state.getTaskSymbolTable().getValueSet().size()+";");
272
273         } else if (state.main!=null) {
274             /* Generate main method */
275             outmethod.println("int main(int argc, const char *argv[]) {");
276             outmethod.println("  int i;");
277             if (GENERATEPRECISEGC) {
278                 outmethod.println("  struct ArrayObject * stringarray=allocate_newarray(NULL, STRINGARRAYTYPE, argc-1);");
279             } else {
280                 outmethod.println("  struct ArrayObject * stringarray=allocate_newarray(STRINGARRAYTYPE, argc-1);");
281             }
282             if (state.THREAD) {
283                 outmethod.println("initializethreads();");
284             }
285             outmethod.println("  for(i=1;i<argc;i++) {");
286             outmethod.println("    int length=strlen(argv[i]);");
287             if (GENERATEPRECISEGC) {
288                 outmethod.println("    struct ___String___ *newstring=NewString(NULL, argv[i], length);");
289             } else {
290                 outmethod.println("    struct ___String___ *newstring=NewString(argv[i], length);");
291             }
292             outmethod.println("    ((void **)(((char *)& stringarray->___length___)+sizeof(int)))[i-1]=newstring;");
293             outmethod.println("  }");
294
295
296             ClassDescriptor cd=typeutil.getClass(state.main);
297             Set mainset=cd.getMethodTable().getSet("main");
298             for(Iterator mainit=mainset.iterator();mainit.hasNext();) {
299                 MethodDescriptor md=(MethodDescriptor)mainit.next();
300                 if (md.numParameters()!=1)
301                     continue;
302                 Descriptor pd=md.getParameter(0);
303                 TypeDescriptor tpd=(pd instanceof TagVarDescriptor)?((TagVarDescriptor)pd).getType():((VarDescriptor)pd).getType();
304                 if (tpd.getArrayCount()!=1)
305                     continue;
306                 if (!tpd.getSymbol().equals("String"))
307                     continue;
308
309                 if (!md.getModifiers().isStatic())
310                     throw new Error("Error: Non static main");
311                 outmethod.println("   {");
312                 if (GENERATEPRECISEGC) {
313                     outmethod.print("       struct "+cd.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params __parameterlist__={");
314                     outmethod.println("1, NULL,"+"stringarray};");
315                     outmethod.println("     "+cd.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(& __parameterlist__);");
316                 } else
317                     outmethod.println("     "+cd.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(stringarray);");
318                 outmethod.println("   }");
319                 break;
320             }
321             if (state.THREAD) {
322                 outmethod.println("pthread_mutex_lock(&gclistlock);");
323                 outmethod.println("threadcount--;");
324                 outmethod.println("pthread_cond_signal(&gccond);");
325                 outmethod.println("pthread_mutex_unlock(&gclistlock);");
326                 outmethod.println("pthread_exit(NULL);");
327             }
328             outmethod.println("}");
329         }
330         if (state.TASK)
331             outstructs.println("#define MAXTASKPARAMS "+maxtaskparams);
332
333
334         /* Output structure definitions for repair tool */
335         if (state.structfile!=null) {
336             buildRepairStructs(outrepairstructs);
337             outrepairstructs.close();
338         }
339         outstructs.println("#endif");
340
341         outstructs.close();
342         outmethod.close();
343     }
344
345     private int maxcount=0;
346
347     private void buildRepairStructs(PrintWriter outrepairstructs) {
348         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
349         while(classit.hasNext()) {
350             ClassDescriptor cn=(ClassDescriptor)classit.next();
351             outrepairstructs.println("structure "+cn.getSymbol()+" {");
352             outrepairstructs.println("  int __type__;");
353             if (state.TASK) {
354                 outrepairstructs.println("  int __flag__;");
355                 outrepairstructs.println("  int __flagptr__;");
356             }
357             printRepairStruct(cn, outrepairstructs);
358             outrepairstructs.println("}\n");
359         }
360         
361         for(int i=0;i<state.numArrays();i++) {
362             TypeDescriptor tdarray=arraytable[i];
363             TypeDescriptor tdelement=tdarray.dereference();
364             outrepairstructs.println("structure "+arraytype+"_"+state.getArrayNumber(tdarray)+" {");
365             outrepairstructs.println("  int __type__;");
366             printRepairStruct(typeutil.getClass(TypeUtil.ObjectClass), outrepairstructs);
367             outrepairstructs.println("  int length;");
368             /*
369               // Need to add support to repair tool for this
370               if (tdelement.isClass()||tdelement.isArray())
371                 outrepairstructs.println("  "+tdelement.getRepairSymbol()+" * elem[this.length];");
372             else
373                 outrepairstructs.println("  "+tdelement.getRepairSymbol()+" elem[this.length];");
374             */
375             outrepairstructs.println("}\n");
376         }
377
378     }
379
380     private void printRepairStruct(ClassDescriptor cn, PrintWriter output) {
381         ClassDescriptor sp=cn.getSuperDesc();
382         if (sp!=null)
383             printRepairStruct(sp, output);
384         
385         Vector fields=(Vector)fieldorder.get(cn);
386
387         for(int i=0;i<fields.size();i++) {
388             FieldDescriptor fd=(FieldDescriptor)fields.get(i);
389             if (fd.getType().isArray()) {
390                 output.println("  "+arraytype+"_"+ state.getArrayNumber(fd.getType()) +" * "+fd.getSymbol()+";");
391             } else if (fd.getType().isClass())
392                 output.println("  "+fd.getType().getRepairSymbol()+" * "+fd.getSymbol()+";");
393             else if (fd.getType().isFloat())
394                 output.println("  int "+fd.getSymbol()+"; /* really float */");
395             else 
396                 output.println("  "+fd.getType().getRepairSymbol()+" "+fd.getSymbol()+";");
397         }
398     }
399
400     /** This method outputs TaskDescriptor information */
401     void generateTaskDescriptor(PrintWriter output, FlatMethod fm, TaskDescriptor task) {
402         for (int i=0;i<task.numParameters();i++) {
403             VarDescriptor param_var=task.getParameter(i);
404             TypeDescriptor param_type=task.getParamType(i);
405             FlagExpressionNode param_flag=task.getFlag(param_var);
406             TagExpressionList param_tag=task.getTag(param_var);
407
408             DNFFlag dflag=param_flag.getDNF();
409             
410             Hashtable flags=(Hashtable)flagorder.get(param_type.getClassDesc());
411             output.println("int parameterdnf_"+i+"_"+task.getSafeSymbol()+"[]={");
412             for(int j=0;j<dflag.size();j++) {
413                 if (j!=0)
414                     output.println(",");
415                 Vector term=dflag.get(j);
416                 int andmask=0;
417                 int checkmask=0;
418                 for(int k=0;k<term.size();k++) {
419                     DNFFlagAtom dfa=(DNFFlagAtom)term.get(k);
420                     FlagDescriptor fd=dfa.getFlag();
421                     boolean negated=dfa.getNegated();
422                     int flagid=1<<((Integer)flags.get(fd)).intValue();
423                     andmask|=flagid;
424                     if (!negated)
425                         checkmask|=flagid;
426                 }
427                 output.print("0x"+Integer.toHexString(andmask)+", 0x"+Integer.toHexString(checkmask));
428             }
429             output.println("};");
430
431             output.println("int parametertag_"+i+"_"+task.getSafeSymbol()+"[]={");
432             //BUG...added next line to fix, test with any task program
433             if (param_tag!=null)
434                 for(int j=0;j<param_tag.numTags();j++) {
435                     if (j!=0)
436                         output.println(",");
437                     /* for each tag we need */
438                     /* which slot it is */
439                     /* what type it is */
440                     TagVarDescriptor tvd=(TagVarDescriptor)task.getParameterTable().get(param_tag.getName(j));
441                     TempDescriptor tmp=param_tag.getTemp(j);
442                     int slot=fm.getTagInt(tmp);
443                     output.println(slot+", "+state.getTagId(tvd.getTag()));
444                 }
445             output.println("};");
446
447             output.println("struct parameterdescriptor parameter_"+i+"_"+task.getSafeSymbol()+"={");
448             output.println("/* type */"+param_type.getClassDesc().getId()+",");
449             output.println("/* number of DNF terms */"+dflag.size()+",");
450             output.println("parameterdnf_"+i+"_"+task.getSafeSymbol()+",");
451             output.println("0,");
452             //BUG, added next line to fix and else statement...test
453             //with any task program
454             if (param_tag!=null)
455                 output.println("/* number of tags */"+param_tag.numTags()+",");
456             else
457                 output.println("/* number of tags */ 0,");
458             output.println("parametertag_"+i+"_"+task.getSafeSymbol());
459             output.println("};");
460         }
461
462
463         output.println("struct parameterdescriptor * parameterdescriptors_"+task.getSafeSymbol()+"[] = {");
464         for (int i=0;i<task.numParameters();i++) {
465             if (i!=0)
466                 output.println(",");
467             output.print("&parameter_"+i+"_"+task.getSafeSymbol());
468         }
469         output.println("};");
470
471         output.println("struct taskdescriptor task_"+task.getSafeSymbol()+"={");
472         output.println("&"+task.getSafeSymbol()+",");
473         output.println("/* number of parameters */" +task.numParameters() + ",");
474         int numtotal=task.numParameters()+fm.numTags();
475         output.println("/* number total parameters */" +numtotal + ",");
476         output.println("parameterdescriptors_"+task.getSafeSymbol()+",");
477         output.println("\""+task.getSymbol()+"\"");
478         output.println("};");
479     }
480
481
482     /** The buildVirtualTables method outputs the virtual dispatch
483      * tables for methods. */
484
485     private void buildVirtualTables(PrintWriter outvirtual) {
486         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
487         while(classit.hasNext()) {
488             ClassDescriptor cd=(ClassDescriptor)classit.next();
489             if (virtualcalls.getMethodCount(cd)>maxcount)
490                 maxcount=virtualcalls.getMethodCount(cd);
491         }
492         MethodDescriptor[][] virtualtable=new MethodDescriptor[state.numClasses()+state.numArrays()][maxcount];
493
494         /* Fill in virtual table */
495         classit=state.getClassSymbolTable().getDescriptorsIterator();
496         while(classit.hasNext()) {
497             ClassDescriptor cd=(ClassDescriptor)classit.next();
498             fillinRow(cd, virtualtable, cd.getId());
499         }
500
501         ClassDescriptor objectcd=typeutil.getClass(TypeUtil.ObjectClass);
502         Iterator arrayit=state.getArrayIterator();
503         while(arrayit.hasNext()) {
504             TypeDescriptor td=(TypeDescriptor)arrayit.next();
505             int id=state.getArrayNumber(td);
506             fillinRow(objectcd, virtualtable, id+state.numClasses());
507         }
508         
509         outvirtual.print("void * virtualtable[]={");
510         boolean needcomma=false;
511         for(int i=0;i<state.numClasses()+state.numArrays();i++) {
512             for(int j=0;j<maxcount;j++) {
513                 if (needcomma)
514                     outvirtual.print(", ");
515                 if (virtualtable[i][j]!=null) {
516                     MethodDescriptor md=virtualtable[i][j];
517                     outvirtual.print("& "+md.getClassDesc().getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor());
518                 } else {
519                     outvirtual.print("0");
520                 }
521                 needcomma=true;
522             }
523             outvirtual.println("");
524         }
525         outvirtual.println("};");
526         outvirtual.close();
527     }
528
529     private void fillinRow(ClassDescriptor cd, MethodDescriptor[][] virtualtable, int rownum) {
530         /* Get inherited methods */
531         if (cd.getSuperDesc()!=null)
532             fillinRow(cd.getSuperDesc(), virtualtable, rownum);
533         /* Override them with our methods */
534         for(Iterator it=cd.getMethods();it.hasNext();) {
535             MethodDescriptor md=(MethodDescriptor)it.next();
536             if (md.isStatic()||md.getReturnType()==null)
537                 continue;
538             int methodnum=virtualcalls.getMethodNumber(md);
539             virtualtable[rownum][methodnum]=md;
540         }
541     }
542
543     /** Generate array that contains the sizes of class objects.  The
544      * object allocation functions in the runtime use this
545      * information. */
546
547     private void generateSizeArray(PrintWriter outclassdefs) {
548         outclassdefs.print("int classsize[]={");
549         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
550         cdarray=new ClassDescriptor[state.numClasses()];
551         while(it.hasNext()) {
552             ClassDescriptor cd=(ClassDescriptor)it.next();
553             cdarray[cd.getId()]=cd;
554         }
555         boolean needcomma=false;
556         for(int i=0;i<state.numClasses();i++) {
557             if (needcomma)
558                 outclassdefs.print(", ");
559             outclassdefs.print("sizeof(struct "+cdarray[i].getSafeSymbol()+")");            
560             needcomma=true;
561         }
562
563         arraytable=new TypeDescriptor[state.numArrays()];
564
565         Iterator arrayit=state.getArrayIterator();
566         while(arrayit.hasNext()) {
567             TypeDescriptor td=(TypeDescriptor)arrayit.next();
568             int id=state.getArrayNumber(td);
569             arraytable[id]=td;
570         }
571         
572         for(int i=0;i<state.numArrays();i++) {
573             if (needcomma)
574                 outclassdefs.print(", ");
575             TypeDescriptor tdelement=arraytable[i].dereference();
576             if (tdelement.isArray()||tdelement.isClass())
577                 outclassdefs.print("sizeof(void *)");
578             else
579                 outclassdefs.print("sizeof("+tdelement.getSafeSymbol()+")");
580             needcomma=true;
581         }
582
583         outclassdefs.println("};");
584     }
585
586     /** Constructs params and temp objects for each method or task.
587      * These objects tell the compiler which temps need to be
588      * allocated.  */
589
590     private void generateTempStructs(FlatMethod fm) {
591         MethodDescriptor md=fm.getMethod();
592         TaskDescriptor task=fm.getTask();
593
594         ParamsObject objectparams=md!=null?new ParamsObject(md,tag++):new ParamsObject(task, tag++);
595         if (md!=null)
596             paramstable.put(md, objectparams);
597         else
598             paramstable.put(task, objectparams);
599
600         for(int i=0;i<fm.numParameters();i++) {
601             TempDescriptor temp=fm.getParameter(i);
602             TypeDescriptor type=temp.getType();
603             if ((type.isPtr()||type.isArray())&&GENERATEPRECISEGC)
604                 objectparams.addPtr(temp);
605             else
606                 objectparams.addPrim(temp);
607         }
608
609         TempObject objecttemps=md!=null?new TempObject(objectparams,md,tag++):new TempObject(objectparams, task, tag++);
610         if (md!=null)
611             tempstable.put(md, objecttemps);
612         else
613             tempstable.put(task, objecttemps);
614
615         for(Iterator nodeit=fm.getNodeSet().iterator();nodeit.hasNext();) {
616             FlatNode fn=(FlatNode)nodeit.next();
617             TempDescriptor[] writes=fn.writesTemps();
618             for(int i=0;i<writes.length;i++) {
619                 TempDescriptor temp=writes[i];
620                 TypeDescriptor type=temp.getType();
621                 if ((type.isPtr()||type.isArray())&&GENERATEPRECISEGC)
622                     objecttemps.addPtr(temp);
623                 else
624                     objecttemps.addPrim(temp);
625             }
626         }
627     }
628     
629     private void generateLayoutStructs(PrintWriter output) {
630         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
631         while(it.hasNext()) {
632             ClassDescriptor cn=(ClassDescriptor)it.next();
633             output.println("int "+cn.getSafeSymbol()+"_pointers[]={");
634             Iterator allit=cn.getFieldTable().getAllDescriptorsIterator();
635             int count=0;
636             while(allit.hasNext()) {
637                 FieldDescriptor fd=(FieldDescriptor)allit.next();
638                 TypeDescriptor type=fd.getType();
639                 if (type.isPtr()||type.isArray())
640                     count++;
641             }
642             output.print(count);
643             allit=cn.getFieldTable().getAllDescriptorsIterator();
644             while(allit.hasNext()) {
645                 FieldDescriptor fd=(FieldDescriptor)allit.next();
646                 TypeDescriptor type=fd.getType();
647                 if (type.isPtr()||type.isArray()) {
648                     output.println(",");
649                     output.print("((int)&(((struct "+cn.getSafeSymbol() +" *)0)->"+fd.getSafeSymbol()+"))");
650                 }
651             }
652             output.println("};");
653         }
654         output.println("int * pointerarray[]={");
655         boolean needcomma=false;
656         for(int i=0;i<state.numClasses();i++) {
657             ClassDescriptor cn=cdarray[i];
658             if (needcomma)
659                 output.println(",");
660             needcomma=true;
661             output.print(cn.getSafeSymbol()+"_pointers");
662         }
663
664         for(int i=0;i<state.numArrays();i++) {
665             if (needcomma)
666                 output.println(", ");
667             TypeDescriptor tdelement=arraytable[i].dereference();
668             if (tdelement.isArray()||tdelement.isClass())
669                 output.print("((int *)1)");
670             else
671                 output.print("0");
672             needcomma=true;
673         }
674         
675         output.println("};");
676         needcomma=false;
677         output.println("int hasflags[]={");
678         for(int i=0;i<state.numClasses();i++) {
679             ClassDescriptor cn=cdarray[i];
680             if (needcomma)
681                 output.println(", ");
682             needcomma=true;
683             if (cn.hasFlags())
684                 output.print("1");
685             else
686                 output.print("0");
687         }
688         output.println("};");
689     }
690
691     /** Print out table to give us supertypes */
692     private void generateSuperTypeTable(PrintWriter output) {
693         output.println("int supertypes[]={");
694         boolean needcomma=false;
695         for(int i=0;i<state.numClasses();i++) {
696             ClassDescriptor cn=cdarray[i];
697             if (needcomma)
698                 output.println(",");
699             needcomma=true;
700             if (cn.getSuperDesc()!=null) {
701                 ClassDescriptor cdsuper=cn.getSuperDesc();
702                 output.print(cdsuper.getId());
703             } else
704                 output.print("-1");
705         }
706         output.println("};");
707     }
708
709     /** Force consistent field ordering between inherited classes. */
710
711     private void printClassStruct(ClassDescriptor cn, PrintWriter classdefout) {
712         ClassDescriptor sp=cn.getSuperDesc();
713         if (sp!=null)
714             printClassStruct(sp, classdefout);
715         
716         if (!fieldorder.containsKey(cn)) {
717             Vector fields=new Vector();
718             fieldorder.put(cn,fields);
719             Iterator fieldit=cn.getFields();
720             while(fieldit.hasNext()) {
721                 FieldDescriptor fd=(FieldDescriptor)fieldit.next();
722                 if (sp==null||!sp.getFieldTable().contains(fd.getSymbol()))
723                     fields.add(fd);
724             }
725         }
726         Vector fields=(Vector)fieldorder.get(cn);
727
728         for(int i=0;i<fields.size();i++) {
729             FieldDescriptor fd=(FieldDescriptor)fields.get(i);
730             if (fd.getType().isClass()||fd.getType().isArray())
731                 classdefout.println("  struct "+fd.getType().getSafeSymbol()+" * "+fd.getSafeSymbol()+";");
732             else 
733                 classdefout.println("  "+fd.getType().getSafeSymbol()+" "+fd.getSafeSymbol()+";");
734         }
735     }
736
737
738     /* Map flags to integers consistently between inherited
739      * classes. */
740
741     private void mapFlags(ClassDescriptor cn) {
742         ClassDescriptor sp=cn.getSuperDesc();
743         if (sp!=null)
744             mapFlags(sp);
745         int max=0;
746         if (!flagorder.containsKey(cn)) {
747             Hashtable flags=new Hashtable();
748             flagorder.put(cn,flags);
749             if (sp!=null) {
750                 Hashtable superflags=(Hashtable)flagorder.get(sp);
751                 Iterator superflagit=superflags.keySet().iterator();
752                 while(superflagit.hasNext()) {
753                     FlagDescriptor fd=(FlagDescriptor)superflagit.next();
754                     Integer number=(Integer)superflags.get(fd);
755                     flags.put(fd, number);
756                     if ((number.intValue()+1)>max)
757                         max=number.intValue()+1;
758                 }
759             }
760             
761             Iterator flagit=cn.getFlags();
762             while(flagit.hasNext()) {
763                 FlagDescriptor fd=(FlagDescriptor)flagit.next();
764                 if (sp==null||!sp.getFlagTable().contains(fd.getSymbol()))
765                     flags.put(fd, new Integer(max++));
766             }
767         }
768     }
769
770
771     /** This function outputs (1) structures that parameters are
772      * passed in (when PRECISE GC is enabled) and (2) function
773      * prototypes for the methods */
774
775     private void generateCallStructs(ClassDescriptor cn, PrintWriter classdefout, PrintWriter output, PrintWriter headersout) {
776         /* Output class structure */
777         classdefout.println("struct "+cn.getSafeSymbol()+" {");
778         classdefout.println("  int type;");
779         if (state.THREAD) {
780             classdefout.println("  pthread_t tid;");
781             classdefout.println("  void * lockentry;");
782             classdefout.println("  int lockcount;");
783         }
784
785         if (state.TASK) {
786             classdefout.println("  int flag;");
787             classdefout.println("  void * flagptr;");
788         }
789         printClassStruct(cn, classdefout);
790         classdefout.println("};\n");
791
792         /* Cycle through methods */
793         Iterator methodit=cn.getMethods();
794         while(methodit.hasNext()) {
795             /* Classify parameters */
796             MethodDescriptor md=(MethodDescriptor)methodit.next();
797             FlatMethod fm=state.getMethodFlat(md);
798             generateTempStructs(fm);
799
800             ParamsObject objectparams=(ParamsObject) paramstable.get(md);
801             TempObject objecttemps=(TempObject) tempstable.get(md);
802
803             /* Output parameter structure */
804             if (GENERATEPRECISEGC) {
805                 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params {");
806                 output.println("  int size;");
807                 output.println("  void * next;");
808                 for(int i=0;i<objectparams.numPointers();i++) {
809                     TempDescriptor temp=objectparams.getPointer(i);
810                     output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
811                 }
812                 output.println("};\n");
813             }
814
815             /* Output temp structure */
816             if (GENERATEPRECISEGC) {
817                 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals {");
818                 output.println("  int size;");
819                 output.println("  void * next;");
820                 for(int i=0;i<objecttemps.numPointers();i++) {
821                     TempDescriptor temp=objecttemps.getPointer(i);
822                     if (temp.getType().isNull())
823                         output.println("  void * "+temp.getSafeSymbol()+";");
824                     else
825                         output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
826                 }
827                 output.println("};\n");
828             }
829             
830             /* Output method declaration */
831             if (md.getReturnType()!=null) {
832                 if (md.getReturnType().isClass()||md.getReturnType().isArray())
833                     headersout.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
834                 else
835                     headersout.print(md.getReturnType().getSafeSymbol()+" ");
836             } else 
837                 //catch the constructor case
838                 headersout.print("void ");
839             headersout.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
840             
841             boolean printcomma=false;
842             if (GENERATEPRECISEGC) {
843                 headersout.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
844                 printcomma=true;
845             }
846
847             //output parameter list
848             for(int i=0;i<objectparams.numPrimitives();i++) {
849                 TempDescriptor temp=objectparams.getPrimitive(i);
850                 if (printcomma)
851                     headersout.print(", ");
852                 printcomma=true;
853                 if (temp.getType().isClass()||temp.getType().isArray())
854                     headersout.print("struct " + temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
855                 else
856                     headersout.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
857             }
858             headersout.println(");\n");
859         }
860     }
861
862
863     /** This function outputs (1) structures that parameters are
864      * passed in (when PRECISE GC is enabled) and (2) function
865      * prototypes for the tasks */
866
867     private void generateTaskStructs(PrintWriter output, PrintWriter headersout) {
868         /* Cycle through tasks */
869         Iterator taskit=state.getTaskSymbolTable().getDescriptorsIterator();
870
871         while(taskit.hasNext()) {
872             /* Classify parameters */
873             TaskDescriptor task=(TaskDescriptor)taskit.next();
874             FlatMethod fm=state.getMethodFlat(task);
875             generateTempStructs(fm);
876
877             ParamsObject objectparams=(ParamsObject) paramstable.get(task);
878             TempObject objecttemps=(TempObject) tempstable.get(task);
879
880             /* Output parameter structure */
881             if (GENERATEPRECISEGC) {
882                 output.println("struct "+task.getSafeSymbol()+"_params {");
883
884                 output.println("  int size;");
885                 output.println("  void * next;");
886                 for(int i=0;i<objectparams.numPointers();i++) {
887                     TempDescriptor temp=objectparams.getPointer(i);
888                     output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
889                 }
890                 for(int i=0;i<fm.numTags();i++) {
891                     TempDescriptor temp=fm.getTag(i);
892                     output.println("  struct ___TagDescriptor___ * "+temp.getSafeSymbol()+";");
893                 }
894
895                 output.println("};\n");
896                 if ((objectparams.numPointers()+fm.numTags())>maxtaskparams) {
897                     maxtaskparams=objectparams.numPointers()+fm.numTags();
898                 }
899             }
900
901             /* Output temp structure */
902             if (GENERATEPRECISEGC) {
903                 output.println("struct "+task.getSafeSymbol()+"_locals {");
904                 output.println("  int size;");
905                 output.println("  void * next;");
906                 for(int i=0;i<objecttemps.numPointers();i++) {
907                     TempDescriptor temp=objecttemps.getPointer(i);
908                     if (temp.getType().isNull())
909                         output.println("  void * "+temp.getSafeSymbol()+";");
910                     else if(temp.getType().isTag())
911                         output.println("  struct "+
912                                        (new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass))).getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
913                     else
914                         output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
915                 }
916                 output.println("};\n");
917             }
918             
919             /* Output task declaration */
920             headersout.print("void " + task.getSafeSymbol()+"(");
921             
922             boolean printcomma=false;
923             if (GENERATEPRECISEGC) {
924                 headersout.print("struct "+task.getSafeSymbol()+"_params * "+paramsprefix);
925             } else
926                 headersout.print("void * parameterarray[]");
927             headersout.println(");\n");
928         }
929     }
930
931     /** Generate code for flatmethod fm. */
932
933     private void generateFlatMethod(FlatMethod fm, PrintWriter output) {
934         MethodDescriptor md=fm.getMethod();
935         TaskDescriptor task=fm.getTask();
936
937         ClassDescriptor cn=md!=null?md.getClassDesc():null;
938
939         ParamsObject objectparams=(ParamsObject)paramstable.get(md!=null?md:task);
940
941         generateHeader(fm, md!=null?md:task,output);
942
943         TempObject objecttemp=(TempObject) tempstable.get(md!=null?md:task);
944
945         /* Print code */
946         if (GENERATEPRECISEGC) {
947             if (md!=null)
948                 output.print("   struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals "+localsprefix+"={");
949             else
950                 output.print("   struct "+task.getSafeSymbol()+"_locals "+localsprefix+"={");
951
952             output.print(objecttemp.numPointers()+",");
953             output.print(paramsprefix);
954             for(int j=0;j<objecttemp.numPointers();j++)
955                 output.print(", NULL");
956             output.println("};");
957         }
958
959         for(int i=0;i<objecttemp.numPrimitives();i++) {
960             TempDescriptor td=objecttemp.getPrimitive(i);
961             TypeDescriptor type=td.getType();
962             if (type.isNull())
963                 output.println("   void * "+td.getSafeSymbol()+";");
964             else if (type.isClass()||type.isArray())
965                 output.println("   struct "+type.getSafeSymbol()+" * "+td.getSafeSymbol()+";");
966             else
967                 output.println("   "+type.getSafeSymbol()+" "+td.getSafeSymbol()+";");
968         }
969
970         /* Generate labels first */
971         HashSet tovisit=new HashSet();
972         HashSet visited=new HashSet();
973         int labelindex=0;
974         Hashtable nodetolabel=new Hashtable();
975         tovisit.add(fm.methodEntryNode());
976         FlatNode current_node=null;
977
978         //Assign labels 1st
979         //Node needs a label if it is
980         while(!tovisit.isEmpty()) {
981             FlatNode fn=(FlatNode)tovisit.iterator().next();
982             tovisit.remove(fn);
983             visited.add(fn);
984             for(int i=0;i<fn.numNext();i++) {
985                 FlatNode nn=fn.getNext(i);
986                 if(i>0) {
987                     //1) Edge >1 of node
988                     nodetolabel.put(nn,new Integer(labelindex++));
989                 }
990                 if (!visited.contains(nn)&&!tovisit.contains(nn)) {
991                     tovisit.add(nn);
992                 } else {
993                     //2) Join point
994                     nodetolabel.put(nn,new Integer(labelindex++));
995                 }
996             }
997         }
998
999         if (state.THREAD&&GENERATEPRECISEGC) {
1000             output.println("checkcollect(&"+localsprefix+");");
1001         }
1002         
1003         //Do the actual code generation
1004         tovisit=new HashSet();
1005         visited=new HashSet();
1006         tovisit.add(fm.methodEntryNode());
1007         while(current_node!=null||!tovisit.isEmpty()) {
1008             if (current_node==null) {
1009                 current_node=(FlatNode)tovisit.iterator().next();
1010                 tovisit.remove(current_node);
1011             }
1012             visited.add(current_node);
1013             if (nodetolabel.containsKey(current_node))
1014                 output.println("L"+nodetolabel.get(current_node)+":");
1015             if (state.INSTRUCTIONFAILURE) {
1016                 if (state.THREAD) {
1017                     output.println("if ((++instructioncount)>failurecount) {instructioncount=0;injectinstructionfailure();}");
1018                 }
1019                 else
1020                     output.println("if ((--instructioncount)==0) injectinstructionfailure();");
1021             }
1022             if (current_node.numNext()==0) {
1023                 output.print("   ");
1024                 generateFlatNode(fm, current_node, output);
1025                 if (current_node.kind()!=FKind.FlatReturnNode) {
1026                     output.println("   return;");
1027                 }
1028                 current_node=null;
1029             } else if(current_node.numNext()==1) {
1030                 output.print("   ");
1031                 generateFlatNode(fm, current_node, output);
1032                 FlatNode nextnode=current_node.getNext(0);
1033                 if (visited.contains(nextnode)) {
1034                     output.println("goto L"+nodetolabel.get(nextnode)+";");
1035                     current_node=null;
1036                 } else
1037                     current_node=nextnode;
1038             } else if (current_node.numNext()==2) {
1039                 /* Branch */
1040                 output.print("   ");
1041                 generateFlatCondBranch(fm, (FlatCondBranch)current_node, "L"+nodetolabel.get(current_node.getNext(1)), output);
1042                 if (!visited.contains(current_node.getNext(1)))
1043                     tovisit.add(current_node.getNext(1));
1044                 if (visited.contains(current_node.getNext(0))) {
1045                     output.println("goto L"+nodetolabel.get(current_node.getNext(0))+";");
1046                     current_node=null;
1047                 } else
1048                     current_node=current_node.getNext(0);
1049             } else throw new Error();
1050         }
1051
1052
1053         output.println("}\n\n");
1054     }
1055
1056     /** Generate text string that corresponds to the Temp td. */
1057     private String generateTemp(FlatMethod fm, TempDescriptor td) {
1058         MethodDescriptor md=fm.getMethod();
1059         TaskDescriptor task=fm.getTask();
1060         TempObject objecttemps=(TempObject) tempstable.get(md!=null?md:task);
1061
1062         if (objecttemps.isLocalPrim(td)||objecttemps.isParamPrim(td)) {
1063             return td.getSafeSymbol();
1064         }
1065
1066         if (objecttemps.isLocalPtr(td)) {
1067             return localsprefix+"."+td.getSafeSymbol();
1068         }
1069
1070         if (objecttemps.isParamPtr(td)) {
1071             return paramsprefix+"->"+td.getSafeSymbol();
1072         }
1073         throw new Error();
1074     }
1075
1076     private void generateFlatNode(FlatMethod fm, FlatNode fn, PrintWriter output) {
1077         switch(fn.kind()) {
1078         case FKind.FlatTagDeclaration:
1079             generateFlatTagDeclaration(fm, (FlatTagDeclaration) fn,output);
1080             return;
1081         case FKind.FlatCall:
1082             generateFlatCall(fm, (FlatCall) fn,output);
1083             return;
1084         case FKind.FlatFieldNode:
1085             generateFlatFieldNode(fm, (FlatFieldNode) fn,output);
1086             return;
1087         case FKind.FlatElementNode:
1088             generateFlatElementNode(fm, (FlatElementNode) fn,output);
1089             return;
1090         case FKind.FlatSetElementNode:
1091             generateFlatSetElementNode(fm, (FlatSetElementNode) fn,output);
1092             return;
1093         case FKind.FlatSetFieldNode:
1094             generateFlatSetFieldNode(fm, (FlatSetFieldNode) fn,output);
1095             return;
1096         case FKind.FlatNew:
1097             generateFlatNew(fm, (FlatNew) fn,output);
1098             return;
1099         case FKind.FlatOpNode:
1100             generateFlatOpNode(fm, (FlatOpNode) fn,output);
1101             return;
1102         case FKind.FlatCastNode:
1103             generateFlatCastNode(fm, (FlatCastNode) fn,output);
1104             return;
1105         case FKind.FlatLiteralNode:
1106             generateFlatLiteralNode(fm, (FlatLiteralNode) fn,output);
1107             return;
1108         case FKind.FlatReturnNode:
1109             generateFlatReturnNode(fm, (FlatReturnNode) fn,output);
1110             return;
1111         case FKind.FlatNop:
1112             output.println("/* nop */");
1113             return;
1114         case FKind.FlatBackEdge:
1115             if (state.THREAD&&GENERATEPRECISEGC) {
1116                 output.println("checkcollect(&"+localsprefix+");");
1117             } else
1118                 output.println("/* nop */");
1119             return;
1120         case FKind.FlatCheckNode:
1121             generateFlatCheckNode(fm, (FlatCheckNode) fn, output);
1122             return;
1123         case FKind.FlatFlagActionNode:
1124             generateFlatFlagActionNode(fm, (FlatFlagActionNode) fn, output);
1125             return;
1126         }
1127         throw new Error();
1128
1129     }
1130
1131     private void generateFlatCheckNode(FlatMethod fm,  FlatCheckNode fcn, PrintWriter output) {
1132
1133         if (state.CONSCHECK) {
1134             String specname=fcn.getSpec();
1135             String varname="repairstate___";
1136             output.println("{");
1137             output.println("struct "+specname+"_state * "+varname+"=allocate"+specname+"_state();");
1138
1139             TempDescriptor[] temps=fcn.getTemps();
1140             String[] vars=fcn.getVars();
1141             for(int i=0;i<temps.length;i++) {
1142                 output.println(varname+"->"+vars[i]+"=(int)"+generateTemp(fm, temps[i])+";");
1143             }
1144
1145             output.println("if (doanalysis"+specname+"("+varname+")) {");
1146             output.println("free"+specname+"_state("+varname+");");
1147             output.println("} else {");
1148             output.println("/* Bad invariant */");
1149             output.println("free"+specname+"_state("+varname+");");
1150             output.println("abort_task();");
1151             output.println("}");
1152
1153             output.println("}");
1154         }
1155     }
1156
1157     private void generateFlatCall(FlatMethod fm, FlatCall fc, PrintWriter output) {
1158         MethodDescriptor md=fc.getMethod();
1159         ParamsObject objectparams=(ParamsObject) paramstable.get(md);
1160         ClassDescriptor cn=md.getClassDesc();
1161         output.println("{");
1162         if (GENERATEPRECISEGC) {
1163             output.print("       struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params __parameterlist__={");
1164             
1165             output.print(objectparams.numPointers());
1166             //      output.print(objectparams.getUID());
1167             output.print(", & "+localsprefix);
1168             if (fc.getThis()!=null) {
1169                 output.print(", ");
1170                 output.print("(struct "+md.getThis().getType().getSafeSymbol() +" *)"+ generateTemp(fm,fc.getThis()));
1171             }
1172             for(int i=0;i<fc.numArgs();i++) {
1173                 Descriptor var=md.getParameter(i);
1174                 TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
1175                 if (objectparams.isParamPtr(paramtemp)) {
1176                     TempDescriptor targ=fc.getArg(i);
1177                     output.print(", ");
1178                     TypeDescriptor td=md.getParamType(i);
1179                     if (td.isTag())
1180                         output.print("(struct "+(new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass))).getSafeSymbol()  +" *)"+generateTemp(fm, targ));
1181                     else
1182                         output.print("(struct "+md.getParamType(i).getSafeSymbol()  +" *)"+generateTemp(fm, targ));
1183                 }
1184             }
1185             output.println("};");
1186         }
1187         output.print("       ");
1188
1189
1190         if (fc.getReturnTemp()!=null)
1191             output.print(generateTemp(fm,fc.getReturnTemp())+"=");
1192
1193         /* Do we need to do virtual dispatch? */
1194         if (md.isStatic()||md.getReturnType()==null||singleCall(fc.getThis().getType().getClassDesc(),md)) {
1195             output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor());
1196         } else {
1197             
1198             output.print("((");
1199             if (md.getReturnType().isClass()||md.getReturnType().isArray())
1200                 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
1201             else
1202                 output.print(md.getReturnType().getSafeSymbol()+" ");
1203             output.print("(*)(");
1204
1205             boolean printcomma=false;
1206             if (GENERATEPRECISEGC) {
1207                 output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * ");
1208                 printcomma=true;
1209             } 
1210
1211
1212             for(int i=0;i<objectparams.numPrimitives();i++) {
1213                 TempDescriptor temp=objectparams.getPrimitive(i);
1214                 if (printcomma)
1215                     output.print(", ");
1216                 printcomma=true;
1217                 if (temp.getType().isClass()||temp.getType().isArray())
1218                     output.print("struct " + temp.getType().getSafeSymbol()+" * ");
1219                 else
1220                     output.print(temp.getType().getSafeSymbol());
1221             }
1222
1223             output.print("))virtualtable["+generateTemp(fm,fc.getThis())+"->type*"+maxcount+"+"+virtualcalls.getMethodNumber(md)+"])");
1224         }
1225
1226         output.print("(");
1227         boolean needcomma=false;
1228         if (GENERATEPRECISEGC) {
1229             output.print("&__parameterlist__");
1230             needcomma=true;
1231         } else {
1232             if (fc.getThis()!=null) {
1233                 TypeDescriptor ptd=md.getThis().getType();
1234                 if (ptd.isClass()&&!ptd.isArray())
1235                     output.print("(struct "+ptd.getSafeSymbol()+" *) ");
1236                 output.print(generateTemp(fm,fc.getThis()));
1237                 needcomma=true;
1238             }
1239         }
1240         for(int i=0;i<fc.numArgs();i++) {
1241             Descriptor var=md.getParameter(i);
1242             TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
1243             if (objectparams.isParamPrim(paramtemp)) {
1244                 TempDescriptor targ=fc.getArg(i);
1245                 if (needcomma)
1246                     output.print(", ");
1247
1248                 TypeDescriptor ptd=md.getParamType(i);
1249                 if (ptd.isClass()&&!ptd.isArray())
1250                     output.print("(struct "+ptd.getSafeSymbol()+" *) ");
1251                 output.print(generateTemp(fm, targ));
1252                 needcomma=true;
1253             }
1254         }
1255         output.println(");");
1256         output.println("   }");
1257     }
1258
1259     private boolean singleCall(ClassDescriptor thiscd, MethodDescriptor md) {
1260         Set subclasses=typeutil.getSubClasses(thiscd);
1261         if (subclasses==null)
1262             return true;
1263         for(Iterator classit=subclasses.iterator();classit.hasNext();) {
1264             ClassDescriptor cd=(ClassDescriptor)classit.next();
1265             Set possiblematches=cd.getMethodTable().getSet(md.getSymbol());
1266             for(Iterator matchit=possiblematches.iterator();matchit.hasNext();) {
1267                 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
1268                 if (md.matches(matchmd))
1269                     return false;
1270             }
1271         }
1272         return true;
1273     }
1274
1275     private void generateFlatFieldNode(FlatMethod fm, FlatFieldNode ffn, PrintWriter output) {
1276         output.println(generateTemp(fm, ffn.getDst())+"="+ generateTemp(fm,ffn.getSrc())+"->"+ ffn.getField().getSafeSymbol()+";");
1277     }
1278
1279     private void generateFlatSetFieldNode(FlatMethod fm, FlatSetFieldNode fsfn, PrintWriter output) {
1280         if (fsfn.getField().getSymbol().equals("length")&&fsfn.getDst().getType().isArray())
1281             throw new Error("Can't set array length");
1282         output.println(generateTemp(fm, fsfn.getDst())+"->"+ fsfn.getField().getSafeSymbol()+"="+ generateTemp(fm,fsfn.getSrc())+";");
1283     }
1284
1285     private void generateFlatElementNode(FlatMethod fm, FlatElementNode fen, PrintWriter output) {
1286         TypeDescriptor elementtype=fen.getSrc().getType().dereference();
1287         String type="";
1288
1289         if (elementtype.isArray()||elementtype.isClass())
1290             type="void *";
1291         else 
1292             type=elementtype.getSafeSymbol()+" ";
1293
1294         if (fen.needsBoundsCheck()) {
1295             output.println("if ("+generateTemp(fm, fen.getIndex())+"< 0 || "+generateTemp(fm, fen.getIndex())+" >= "+generateTemp(fm,fen.getSrc()) + "->___length___)");
1296             output.println("failedboundschk();");
1297         }
1298
1299         output.println(generateTemp(fm, fen.getDst())+"=(("+ type+"*)(((char *) &("+ generateTemp(fm,fen.getSrc())+"->___length___))+sizeof(int)))["+generateTemp(fm, fen.getIndex())+"];");
1300     }
1301
1302     private void generateFlatSetElementNode(FlatMethod fm, FlatSetElementNode fsen, PrintWriter output) {
1303         //TODO: need dynamic check to make sure this assignment is actually legal
1304         //Because Object[] could actually be something more specific...ie. Integer[]
1305
1306         TypeDescriptor elementtype=fsen.getDst().getType().dereference();
1307         String type="";
1308
1309         if (elementtype.isArray()||elementtype.isClass())
1310             type="void *";
1311         else 
1312             type=elementtype.getSafeSymbol()+" ";
1313
1314         if (fsen.needsBoundsCheck()) {
1315             output.println("if ("+generateTemp(fm, fsen.getIndex())+"< 0 || "+generateTemp(fm, fsen.getIndex())+" >= "+generateTemp(fm,fsen.getDst()) + "->___length___)");
1316             output.println("failedboundschk();");
1317         }
1318
1319         output.println("(("+type +"*)(((char *) &("+ generateTemp(fm,fsen.getDst())+"->___length___))+sizeof(int)))["+generateTemp(fm, fsen.getIndex())+"]="+generateTemp(fm,fsen.getSrc())+";");
1320     }
1321
1322     private void generateFlatNew(FlatMethod fm, FlatNew fn, PrintWriter output) {
1323         if (fn.getType().isArray()) {
1324             int arrayid=state.getArrayNumber(fn.getType())+state.numClasses();
1325             if (GENERATEPRECISEGC) {
1326                 output.println(generateTemp(fm,fn.getDst())+"=allocate_newarray(&"+localsprefix+", "+arrayid+", "+generateTemp(fm, fn.getSize())+");");
1327             } else {
1328                 output.println(generateTemp(fm,fn.getDst())+"=allocate_newarray("+arrayid+", "+generateTemp(fm, fn.getSize())+");");
1329             }
1330         } else {
1331             if (GENERATEPRECISEGC) {
1332                 output.println(generateTemp(fm,fn.getDst())+"=allocate_new(&"+localsprefix+", "+fn.getType().getClassDesc().getId()+");");
1333             } else {
1334                 output.println(generateTemp(fm,fn.getDst())+"=allocate_new("+fn.getType().getClassDesc().getId()+");");
1335             }
1336         }
1337     }
1338
1339
1340     private void generateFlatTagDeclaration(FlatMethod fm, FlatTagDeclaration fn, PrintWriter output) {
1341         if (GENERATEPRECISEGC) {
1342             output.println(generateTemp(fm,fn.getDst())+"=allocate_tag(&"+localsprefix+", "+state.getTagId(fn.getType())+");");
1343         } else {
1344             output.println(generateTemp(fm,fn.getDst())+"=allocate_tag("+state.getTagId(fn.getType())+");");
1345         }
1346     }
1347
1348     private void generateFlatOpNode(FlatMethod fm, FlatOpNode fon, PrintWriter output) {
1349
1350         if (fon.getRight()!=null)
1351             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+fon.getOp().toString()+generateTemp(fm,fon.getRight())+";");
1352         else if (fon.getOp().getOp()==Operation.ASSIGN)
1353             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
1354         else if (fon.getOp().getOp()==Operation.UNARYPLUS)
1355             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
1356         else if (fon.getOp().getOp()==Operation.UNARYMINUS)
1357             output.println(generateTemp(fm, fon.getDest())+" = -"+generateTemp(fm, fon.getLeft())+";");
1358         else if (fon.getOp().getOp()==Operation.LOGIC_NOT)
1359             output.println(generateTemp(fm, fon.getDest())+" = !"+generateTemp(fm, fon.getLeft())+";");
1360         else
1361             output.println(generateTemp(fm, fon.getDest())+fon.getOp().toString()+generateTemp(fm, fon.getLeft())+";");
1362     }
1363
1364     private void generateFlatCastNode(FlatMethod fm, FlatCastNode fcn, PrintWriter output) {
1365         /* TODO: Do type check here */
1366         if (fcn.getType().isArray()) {
1367             throw new Error();
1368         } else if (fcn.getType().isClass())
1369             output.println(generateTemp(fm,fcn.getDst())+"=(struct "+fcn.getType().getSafeSymbol()+" *)"+generateTemp(fm,fcn.getSrc())+";");
1370         else
1371             output.println(generateTemp(fm,fcn.getDst())+"=("+fcn.getType().getSafeSymbol()+")"+generateTemp(fm,fcn.getSrc())+";");
1372     }
1373
1374     private void generateFlatLiteralNode(FlatMethod fm, FlatLiteralNode fln, PrintWriter output) {
1375         if (fln.getValue()==null)
1376             output.println(generateTemp(fm, fln.getDst())+"=0;");
1377         else if (fln.getType().getSymbol().equals(TypeUtil.StringClass)) {
1378             if (GENERATEPRECISEGC) {
1379                 output.println(generateTemp(fm, fln.getDst())+"=NewString(&"+localsprefix+", \""+FlatLiteralNode.escapeString((String)fln.getValue())+"\","+((String)fln.getValue()).length()+");");
1380             } else {
1381                 output.println(generateTemp(fm, fln.getDst())+"=NewString(\""+FlatLiteralNode.escapeString((String)fln.getValue())+"\","+((String)fln.getValue()).length()+");");
1382             }
1383         } else if (fln.getType().isBoolean()) {
1384             if (((Boolean)fln.getValue()).booleanValue())
1385                 output.println(generateTemp(fm, fln.getDst())+"=1;");
1386             else
1387                 output.println(generateTemp(fm, fln.getDst())+"=0;");
1388         } else if (fln.getType().isChar()) {
1389             String st=FlatLiteralNode.escapeString(fln.getValue().toString());
1390             output.println(generateTemp(fm, fln.getDst())+"='"+st+"';");
1391         } else
1392             output.println(generateTemp(fm, fln.getDst())+"="+fln.getValue()+";");
1393     }
1394
1395     private void generateFlatReturnNode(FlatMethod fm, FlatReturnNode frn, PrintWriter output) {
1396         
1397         if (frn.getReturnTemp()!=null)
1398             output.println("return "+generateTemp(fm, frn.getReturnTemp())+";");
1399         else
1400             output.println("return;");
1401     }
1402
1403     private void generateFlatCondBranch(FlatMethod fm, FlatCondBranch fcb, String label, PrintWriter output) {
1404         output.println("if (!"+generateTemp(fm, fcb.getTest())+") goto "+label+";");
1405     }
1406
1407     private void generateHeader(FlatMethod fm, Descriptor des, PrintWriter output) {
1408         /* Print header */
1409         ParamsObject objectparams=(ParamsObject)paramstable.get(des);
1410         MethodDescriptor md=null;
1411         TaskDescriptor task=null;
1412         if (des instanceof MethodDescriptor)
1413             md=(MethodDescriptor) des;
1414         else
1415             task=(TaskDescriptor) des;
1416
1417         ClassDescriptor cn=md!=null?md.getClassDesc():null;
1418         
1419         if (md!=null&&md.getReturnType()!=null) {
1420             if (md.getReturnType().isClass()||md.getReturnType().isArray())
1421                 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
1422             else
1423                 output.print(md.getReturnType().getSafeSymbol()+" ");
1424         } else 
1425             //catch the constructor case
1426             output.print("void ");
1427         if (md!=null)
1428             output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
1429         else
1430             output.print(task.getSafeSymbol()+"(");
1431         
1432         boolean printcomma=false;
1433         if (GENERATEPRECISEGC) {
1434             if (md!=null)
1435                 output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
1436             else
1437                 output.print("struct "+task.getSafeSymbol()+"_params * "+paramsprefix);
1438             printcomma=true;
1439         }
1440
1441         if (md!=null) {
1442             /* Method */
1443             for(int i=0;i<objectparams.numPrimitives();i++) {
1444                 TempDescriptor temp=objectparams.getPrimitive(i);
1445                 if (printcomma)
1446                     output.print(", ");
1447                 printcomma=true;
1448                 if (temp.getType().isClass()||temp.getType().isArray())
1449                     output.print("struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
1450                 else
1451                     output.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
1452             }
1453             output.println(") {");
1454         } else if (!GENERATEPRECISEGC) {
1455             /* Imprecise Task */
1456             output.println("void * parameterarray[]) {");
1457             /* Unpack variables */
1458             for(int i=0;i<objectparams.numPrimitives();i++) {
1459                 TempDescriptor temp=objectparams.getPrimitive(i);
1460                 output.println("struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+"=parameterarray["+i+"];");
1461             }
1462             for(int i=0;i<fm.numTags();i++) {
1463                 TempDescriptor temp=fm.getTag(i);
1464                 int offset=i+objectparams.numPrimitives();
1465                 output.println("struct ___TagDescriptor___ * "+temp.getSafeSymbol()+"=parameterarray["+offset+"];");
1466             }
1467
1468             if ((objectparams.numPrimitives()+fm.numTags())>maxtaskparams)
1469                 maxtaskparams=objectparams.numPrimitives()+fm.numTags();
1470         } else output.println(") {");
1471     }
1472     
1473     public void generateFlatFlagActionNode(FlatMethod fm, FlatFlagActionNode ffan, PrintWriter output) {
1474         output.println("/* FlatFlagActionNode */");
1475
1476
1477         /* Process tag changes */
1478         Relation tagsettable=new Relation();
1479         Relation tagcleartable=new Relation();
1480
1481         Iterator tagsit=ffan.getTempTagPairs(); 
1482         while (tagsit.hasNext()) {
1483             TempTagPair ttp=(TempTagPair) tagsit.next();
1484             TempDescriptor objtmp=ttp.getTemp();
1485             TagDescriptor tag=ttp.getTag();
1486             TempDescriptor tagtmp=ttp.getTagTemp();
1487             boolean tagstatus=ffan.getTagChange(ttp);
1488             if (tagstatus) {
1489                 tagsettable.put(objtmp, tagtmp);
1490             } else {
1491                 tagcleartable.put(objtmp, tagtmp);
1492             }
1493         }
1494
1495
1496         Hashtable flagandtable=new Hashtable();
1497         Hashtable flagortable=new Hashtable();
1498
1499         /* Process flag changes */
1500         Iterator flagsit=ffan.getTempFlagPairs();
1501         while(flagsit.hasNext()) {
1502             TempFlagPair tfp=(TempFlagPair)flagsit.next();
1503             TempDescriptor temp=tfp.getTemp();
1504             Hashtable flagtable=(Hashtable)flagorder.get(temp.getType().getClassDesc());
1505             FlagDescriptor flag=tfp.getFlag();
1506             if (flag==null) {
1507                 //Newly allocate objects that don't set any flags case
1508                 if (flagortable.containsKey(temp)) {
1509                     throw new Error();
1510                 }
1511                 int mask=0;
1512                 flagortable.put(temp,new Integer(mask));
1513             } else {
1514                 int flagid=1<<((Integer)flagtable.get(flag)).intValue();
1515                 boolean flagstatus=ffan.getFlagChange(tfp);
1516                 if (flagstatus) {
1517                     int mask=0;
1518                     if (flagortable.containsKey(temp)) {
1519                         mask=((Integer)flagortable.get(temp)).intValue();
1520                     }
1521                     mask|=flagid;
1522                     flagortable.put(temp,new Integer(mask));
1523                 } else {
1524                     int mask=0xFFFFFFFF;
1525                     if (flagandtable.containsKey(temp)) {
1526                         mask=((Integer)flagandtable.get(temp)).intValue();
1527                     }
1528                     mask&=(0xFFFFFFFF^flagid);
1529                     flagandtable.put(temp,new Integer(mask));
1530                 }
1531             }
1532         }
1533
1534
1535         HashSet flagtagset=new HashSet();
1536         flagtagset.addAll(flagortable.keySet());
1537         flagtagset.addAll(flagandtable.keySet());
1538         flagtagset.addAll(tagsettable.keySet());
1539         flagtagset.addAll(tagcleartable.keySet());
1540
1541         Iterator ftit=flagtagset.iterator();
1542         while(ftit.hasNext()) {
1543             TempDescriptor temp=(TempDescriptor)ftit.next();
1544             
1545             
1546             Set tagtmps=tagcleartable.get(temp);
1547             if (tagtmps!=null) {
1548                 Iterator tagit=tagtmps.iterator();
1549                 while(tagit.hasNext()) {
1550                     TempDescriptor tagtmp=(TempDescriptor)tagit.next();
1551                     if (GENERATEPRECISEGC) 
1552                         output.println("tagclear(&"+localsprefix+", (struct ___Object___ *)"+generateTemp(fm, temp)+", "+generateTemp(fm,tagtmp)+");");
1553                     else
1554                         output.println("tagclear((struct ___Object___ *)"+generateTemp(fm, temp)+", "+generateTemp(fm,tagtmp)+");");
1555                 }
1556             }
1557
1558             tagtmps=tagsettable.get(temp);
1559             if (tagtmps!=null) {
1560                 Iterator tagit=tagtmps.iterator();
1561                 while(tagit.hasNext()) {
1562                     TempDescriptor tagtmp=(TempDescriptor)tagit.next();
1563                     if (GENERATEPRECISEGC)
1564                         output.println("tagset(&"+localsprefix+", (struct ___Object___ *)"+generateTemp(fm, temp)+", "+generateTemp(fm,tagtmp)+");");
1565                     else
1566                         output.println("tagset((struct ___Object___ *)"+generateTemp(fm, temp)+", "+generateTemp(fm,tagtmp)+");");
1567                 }
1568             }
1569
1570             int ormask=0;
1571             int andmask=0xFFFFFFF;
1572             
1573             if (flagortable.containsKey(temp))
1574                 ormask=((Integer)flagortable.get(temp)).intValue();
1575             if (flagandtable.containsKey(temp))
1576                 andmask=((Integer)flagandtable.get(temp)).intValue();
1577             if (ffan.getTaskType()==FlatFlagActionNode.NEWOBJECT) {
1578                 output.println("flagorandinit("+generateTemp(fm, temp)+", 0x"+Integer.toHexString(ormask)+", 0x"+Integer.toHexString(andmask)+");");
1579             } else {
1580                 output.println("flagorand("+generateTemp(fm, temp)+", 0x"+Integer.toHexString(ormask)+", 0x"+Integer.toHexString(andmask)+");");
1581             }
1582         }
1583     }
1584 }