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