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