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