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