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