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