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