bug fixed in taskanalysis. we missed self edges if the task just returned w/o settin...
[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         TempObject objecttemps=md!=null?new TempObject(objectparams,md,tag++):new TempObject(objectparams, task, tag++);
619         if (md!=null)
620             tempstable.put(md, objecttemps);
621         else
622             tempstable.put(task, objecttemps);
623
624         for(Iterator nodeit=fm.getNodeSet().iterator();nodeit.hasNext();) {
625             FlatNode fn=(FlatNode)nodeit.next();
626             TempDescriptor[] writes=fn.writesTemps();
627             for(int i=0;i<writes.length;i++) {
628                 TempDescriptor temp=writes[i];
629                 TypeDescriptor type=temp.getType();
630                 if ((type.isPtr()||type.isArray())&&GENERATEPRECISEGC)
631                     objecttemps.addPtr(temp);
632                 else
633                     objecttemps.addPrim(temp);
634             }
635         }
636     }
637     
638     private void generateLayoutStructs(PrintWriter output) {
639         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
640         while(it.hasNext()) {
641             ClassDescriptor cn=(ClassDescriptor)it.next();
642             output.println("int "+cn.getSafeSymbol()+"_pointers[]={");
643             Iterator allit=cn.getFieldTable().getAllDescriptorsIterator();
644             int count=0;
645             while(allit.hasNext()) {
646                 FieldDescriptor fd=(FieldDescriptor)allit.next();
647                 TypeDescriptor type=fd.getType();
648                 if (type.isPtr()||type.isArray())
649                     count++;
650             }
651             output.print(count);
652             allit=cn.getFieldTable().getAllDescriptorsIterator();
653             while(allit.hasNext()) {
654                 FieldDescriptor fd=(FieldDescriptor)allit.next();
655                 TypeDescriptor type=fd.getType();
656                 if (type.isPtr()||type.isArray()) {
657                     output.println(",");
658                     output.print("((int)&(((struct "+cn.getSafeSymbol() +" *)0)->"+fd.getSafeSymbol()+"))");
659                 }
660             }
661             output.println("};");
662         }
663         output.println("int * pointerarray[]={");
664         boolean needcomma=false;
665         for(int i=0;i<state.numClasses();i++) {
666             ClassDescriptor cn=cdarray[i];
667             if (needcomma)
668                 output.println(",");
669             needcomma=true;
670             output.print(cn.getSafeSymbol()+"_pointers");
671         }
672
673         for(int i=0;i<state.numArrays();i++) {
674             if (needcomma)
675                 output.println(", ");
676             TypeDescriptor tdelement=arraytable[i].dereference();
677             if (tdelement.isArray()||tdelement.isClass())
678                 output.print("((int *)1)");
679             else
680                 output.print("0");
681             needcomma=true;
682         }
683         
684         output.println("};");
685         needcomma=false;
686         output.println("int hasflags[]={");
687         for(int i=0;i<state.numClasses();i++) {
688             ClassDescriptor cn=cdarray[i];
689             if (needcomma)
690                 output.println(", ");
691             needcomma=true;
692             if (cn.hasFlags())
693                 output.print("1");
694             else
695                 output.print("0");
696         }
697         output.println("};");
698     }
699
700     /** Print out table to give us supertypes */
701     private void generateSuperTypeTable(PrintWriter output) {
702         output.println("int supertypes[]={");
703         boolean needcomma=false;
704         for(int i=0;i<state.numClasses();i++) {
705             ClassDescriptor cn=cdarray[i];
706             if (needcomma)
707                 output.println(",");
708             needcomma=true;
709             if (cn.getSuperDesc()!=null) {
710                 ClassDescriptor cdsuper=cn.getSuperDesc();
711                 output.print(cdsuper.getId());
712             } else
713                 output.print("-1");
714         }
715         output.println("};");
716     }
717
718     /** Force consistent field ordering between inherited classes. */
719
720     private void printClassStruct(ClassDescriptor cn, PrintWriter classdefout) {
721         ClassDescriptor sp=cn.getSuperDesc();
722         if (sp!=null)
723             printClassStruct(sp, classdefout);
724         
725         if (!fieldorder.containsKey(cn)) {
726             Vector fields=new Vector();
727             fieldorder.put(cn,fields);
728             Iterator fieldit=cn.getFields();
729             while(fieldit.hasNext()) {
730                 FieldDescriptor fd=(FieldDescriptor)fieldit.next();
731                 if (sp==null||!sp.getFieldTable().contains(fd.getSymbol()))
732                     fields.add(fd);
733             }
734         }
735         Vector fields=(Vector)fieldorder.get(cn);
736
737         for(int i=0;i<fields.size();i++) {
738             FieldDescriptor fd=(FieldDescriptor)fields.get(i);
739             if (fd.getType().isClass()||fd.getType().isArray())
740                 classdefout.println("  struct "+fd.getType().getSafeSymbol()+" * "+fd.getSafeSymbol()+";");
741             else 
742                 classdefout.println("  "+fd.getType().getSafeSymbol()+" "+fd.getSafeSymbol()+";");
743         }
744     }
745
746
747     /* Map flags to integers consistently between inherited
748      * classes. */
749
750     private void mapFlags(ClassDescriptor cn) {
751         ClassDescriptor sp=cn.getSuperDesc();
752         if (sp!=null)
753             mapFlags(sp);
754         int max=0;
755         if (!flagorder.containsKey(cn)) {
756             Hashtable flags=new Hashtable();
757             flagorder.put(cn,flags);
758             if (sp!=null) {
759                 Hashtable superflags=(Hashtable)flagorder.get(sp);
760                 Iterator superflagit=superflags.keySet().iterator();
761                 while(superflagit.hasNext()) {
762                     FlagDescriptor fd=(FlagDescriptor)superflagit.next();
763                     Integer number=(Integer)superflags.get(fd);
764                     flags.put(fd, number);
765                     if ((number.intValue()+1)>max)
766                         max=number.intValue()+1;
767                 }
768             }
769             
770             Iterator flagit=cn.getFlags();
771             while(flagit.hasNext()) {
772                 FlagDescriptor fd=(FlagDescriptor)flagit.next();
773                 if (sp==null||!sp.getFlagTable().contains(fd.getSymbol()))
774                     flags.put(fd, new Integer(max++));
775             }
776         }
777     }
778
779
780     /** This function outputs (1) structures that parameters are
781      * passed in (when PRECISE GC is enabled) and (2) function
782      * prototypes for the methods */
783
784     private void generateCallStructs(ClassDescriptor cn, PrintWriter classdefout, PrintWriter output, PrintWriter headersout) {
785         /* Output class structure */
786         classdefout.println("struct "+cn.getSafeSymbol()+" {");
787         classdefout.println("  int type;");
788         if (state.THREAD) {
789             classdefout.println("  pthread_t tid;");
790             classdefout.println("  void * lockentry;");
791             classdefout.println("  int lockcount;");
792         }
793
794         if (state.TASK) {
795             classdefout.println("  int flag;");
796             classdefout.println("  void * flagptr;");
797         }
798         printClassStruct(cn, classdefout);
799         classdefout.println("};\n");
800
801         /* Cycle through methods */
802         Iterator methodit=cn.getMethods();
803         while(methodit.hasNext()) {
804             /* Classify parameters */
805             MethodDescriptor md=(MethodDescriptor)methodit.next();
806             FlatMethod fm=state.getMethodFlat(md);
807             generateTempStructs(fm);
808
809             ParamsObject objectparams=(ParamsObject) paramstable.get(md);
810             TempObject objecttemps=(TempObject) tempstable.get(md);
811
812             /* Output parameter structure */
813             if (GENERATEPRECISEGC) {
814                 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params {");
815                 output.println("  int size;");
816                 output.println("  void * next;");
817                 for(int i=0;i<objectparams.numPointers();i++) {
818                     TempDescriptor temp=objectparams.getPointer(i);
819                     output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
820                 }
821                 output.println("};\n");
822             }
823
824             /* Output temp structure */
825             if (GENERATEPRECISEGC) {
826                 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals {");
827                 output.println("  int size;");
828                 output.println("  void * next;");
829                 for(int i=0;i<objecttemps.numPointers();i++) {
830                     TempDescriptor temp=objecttemps.getPointer(i);
831                     if (temp.getType().isNull())
832                         output.println("  void * "+temp.getSafeSymbol()+";");
833                     else
834                         output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
835                 }
836                 output.println("};\n");
837             }
838             
839             /* Output method declaration */
840             if (md.getReturnType()!=null) {
841                 if (md.getReturnType().isClass()||md.getReturnType().isArray())
842                     headersout.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
843                 else
844                     headersout.print(md.getReturnType().getSafeSymbol()+" ");
845             } else 
846                 //catch the constructor case
847                 headersout.print("void ");
848             headersout.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
849             
850             boolean printcomma=false;
851             if (GENERATEPRECISEGC) {
852                 headersout.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
853                 printcomma=true;
854             }
855
856             //output parameter list
857             for(int i=0;i<objectparams.numPrimitives();i++) {
858                 TempDescriptor temp=objectparams.getPrimitive(i);
859                 if (printcomma)
860                     headersout.print(", ");
861                 printcomma=true;
862                 if (temp.getType().isClass()||temp.getType().isArray())
863                     headersout.print("struct " + temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
864                 else
865                     headersout.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
866             }
867             headersout.println(");\n");
868         }
869     }
870
871
872     /** This function outputs (1) structures that parameters are
873      * passed in (when PRECISE GC is enabled) and (2) function
874      * prototypes for the tasks */
875
876     private void generateTaskStructs(PrintWriter output, PrintWriter headersout) {
877         /* Cycle through tasks */
878         Iterator taskit=state.getTaskSymbolTable().getDescriptorsIterator();
879
880         while(taskit.hasNext()) {
881             /* Classify parameters */
882             TaskDescriptor task=(TaskDescriptor)taskit.next();
883             FlatMethod fm=state.getMethodFlat(task);
884             generateTempStructs(fm);
885
886             ParamsObject objectparams=(ParamsObject) paramstable.get(task);
887             TempObject objecttemps=(TempObject) tempstable.get(task);
888
889             /* Output parameter structure */
890             if (GENERATEPRECISEGC) {
891                 output.println("struct "+task.getSafeSymbol()+"_params {");
892
893                 output.println("  int size;");
894                 output.println("  void * next;");
895                 for(int i=0;i<objectparams.numPointers();i++) {
896                     TempDescriptor temp=objectparams.getPointer(i);
897                     output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
898                 }
899                 for(int i=0;i<fm.numTags();i++) {
900                     TempDescriptor temp=fm.getTag(i);
901                     output.println("  struct ___TagDescriptor___ * "+temp.getSafeSymbol()+";");
902                 }
903
904                 output.println("};\n");
905                 if ((objectparams.numPointers()+fm.numTags())>maxtaskparams) {
906                     maxtaskparams=objectparams.numPointers()+fm.numTags();
907                 }
908             }
909
910             /* Output temp structure */
911             if (GENERATEPRECISEGC) {
912                 output.println("struct "+task.getSafeSymbol()+"_locals {");
913                 output.println("  int size;");
914                 output.println("  void * next;");
915                 for(int i=0;i<objecttemps.numPointers();i++) {
916                     TempDescriptor temp=objecttemps.getPointer(i);
917                     if (temp.getType().isNull())
918                         output.println("  void * "+temp.getSafeSymbol()+";");
919                     else if(temp.getType().isTag())
920                         output.println("  struct "+
921                                        (new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass))).getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
922                     else
923                         output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
924                 }
925                 output.println("};\n");
926             }
927             
928             /* Output task declaration */
929             headersout.print("void " + task.getSafeSymbol()+"(");
930             
931             boolean printcomma=false;
932             if (GENERATEPRECISEGC) {
933                 headersout.print("struct "+task.getSafeSymbol()+"_params * "+paramsprefix);
934             } else
935                 headersout.print("void * parameterarray[]");
936             headersout.println(");\n");
937         }
938     }
939
940     /** Generate code for flatmethod fm. */
941
942     private void generateFlatMethod(FlatMethod fm, PrintWriter output) {
943         MethodDescriptor md=fm.getMethod();
944         TaskDescriptor task=fm.getTask();
945
946         ClassDescriptor cn=md!=null?md.getClassDesc():null;
947
948         ParamsObject objectparams=(ParamsObject)paramstable.get(md!=null?md:task);
949
950         generateHeader(fm, md!=null?md:task,output);
951
952         TempObject objecttemp=(TempObject) tempstable.get(md!=null?md:task);
953
954         /* Print code */
955         if (GENERATEPRECISEGC) {
956             if (md!=null)
957                 output.print("   struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals "+localsprefix+"={");
958             else
959                 output.print("   struct "+task.getSafeSymbol()+"_locals "+localsprefix+"={");
960
961             output.print(objecttemp.numPointers()+",");
962             output.print(paramsprefix);
963             for(int j=0;j<objecttemp.numPointers();j++)
964                 output.print(", NULL");
965             output.println("};");
966         }
967
968         for(int i=0;i<objecttemp.numPrimitives();i++) {
969             TempDescriptor td=objecttemp.getPrimitive(i);
970             TypeDescriptor type=td.getType();
971             if (type.isNull())
972                 output.println("   void * "+td.getSafeSymbol()+";");
973             else if (type.isClass()||type.isArray())
974                 output.println("   struct "+type.getSafeSymbol()+" * "+td.getSafeSymbol()+";");
975             else
976                 output.println("   "+type.getSafeSymbol()+" "+td.getSafeSymbol()+";");
977         }
978
979         /* Generate labels first */
980         HashSet tovisit=new HashSet();
981         HashSet visited=new HashSet();
982         int labelindex=0;
983         Hashtable nodetolabel=new Hashtable();
984         tovisit.add(fm.getNext(0));
985         FlatNode current_node=null;
986
987         //Assign labels 1st
988         //Node needs a label if it is
989         while(!tovisit.isEmpty()) {
990             FlatNode fn=(FlatNode)tovisit.iterator().next();
991             tovisit.remove(fn);
992             visited.add(fn);
993             for(int i=0;i<fn.numNext();i++) {
994                 FlatNode nn=fn.getNext(i);
995                 if(i>0) {
996                     //1) Edge >1 of node
997                     nodetolabel.put(nn,new Integer(labelindex++));
998                 }
999                 if (!visited.contains(nn)&&!tovisit.contains(nn)) {
1000                     tovisit.add(nn);
1001                 } else {
1002                     //2) Join point
1003                     nodetolabel.put(nn,new Integer(labelindex++));
1004                 }
1005             }
1006         }
1007
1008         if (state.THREAD&&GENERATEPRECISEGC) {
1009             output.println("checkcollect(&"+localsprefix+");");
1010         }
1011         
1012         //Do the actual code generation
1013         tovisit=new HashSet();
1014         visited=new HashSet();
1015         tovisit.add(fm.getNext(0));
1016         while(current_node!=null||!tovisit.isEmpty()) {
1017             if (current_node==null) {
1018                 current_node=(FlatNode)tovisit.iterator().next();
1019                 tovisit.remove(current_node);
1020             }
1021             visited.add(current_node);
1022             if (nodetolabel.containsKey(current_node))
1023                 output.println("L"+nodetolabel.get(current_node)+":");
1024             if (state.INSTRUCTIONFAILURE) {
1025                 if (state.THREAD) {
1026                     output.println("if ((++instructioncount)>failurecount) {instructioncount=0;injectinstructionfailure();}");
1027                 }
1028                 else
1029                     output.println("if ((--instructioncount)==0) injectinstructionfailure();");
1030             }
1031             if (current_node.numNext()==0) {
1032                 output.print("   ");
1033                 generateFlatNode(fm, current_node, output);
1034                 if (current_node.kind()!=FKind.FlatReturnNode) {
1035                     output.println("   return;");
1036                 }
1037                 current_node=null;
1038             } else if(current_node.numNext()==1) {
1039                 output.print("   ");
1040                 generateFlatNode(fm, current_node, output);
1041                 FlatNode nextnode=current_node.getNext(0);
1042                 if (visited.contains(nextnode)) {
1043                     output.println("goto L"+nodetolabel.get(nextnode)+";");
1044                     current_node=null;
1045                 } else
1046                     current_node=nextnode;
1047             } else if (current_node.numNext()==2) {
1048                 /* Branch */
1049                 output.print("   ");
1050                 generateFlatCondBranch(fm, (FlatCondBranch)current_node, "L"+nodetolabel.get(current_node.getNext(1)), output);
1051                 if (!visited.contains(current_node.getNext(1)))
1052                     tovisit.add(current_node.getNext(1));
1053                 if (visited.contains(current_node.getNext(0))) {
1054                     output.println("goto L"+nodetolabel.get(current_node.getNext(0))+";");
1055                     current_node=null;
1056                 } else
1057                     current_node=current_node.getNext(0);
1058             } else throw new Error();
1059         }
1060
1061
1062         output.println("}\n\n");
1063     }
1064
1065     /** Generate text string that corresponds to the Temp td. */
1066     private String generateTemp(FlatMethod fm, TempDescriptor td) {
1067         MethodDescriptor md=fm.getMethod();
1068         TaskDescriptor task=fm.getTask();
1069         TempObject objecttemps=(TempObject) tempstable.get(md!=null?md:task);
1070
1071         if (objecttemps.isLocalPrim(td)||objecttemps.isParamPrim(td)) {
1072             return td.getSafeSymbol();
1073         }
1074
1075         if (objecttemps.isLocalPtr(td)) {
1076             return localsprefix+"."+td.getSafeSymbol();
1077         }
1078
1079         if (objecttemps.isParamPtr(td)) {
1080             return paramsprefix+"->"+td.getSafeSymbol();
1081         }
1082         throw new Error();
1083     }
1084
1085     private void generateFlatNode(FlatMethod fm, FlatNode fn, PrintWriter output) {
1086         switch(fn.kind()) {
1087         case FKind.FlatTagDeclaration:
1088             generateFlatTagDeclaration(fm, (FlatTagDeclaration) fn,output);
1089             return;
1090         case FKind.FlatCall:
1091             generateFlatCall(fm, (FlatCall) fn,output);
1092             return;
1093         case FKind.FlatFieldNode:
1094             generateFlatFieldNode(fm, (FlatFieldNode) fn,output);
1095             return;
1096         case FKind.FlatElementNode:
1097             generateFlatElementNode(fm, (FlatElementNode) fn,output);
1098             return;
1099         case FKind.FlatSetElementNode:
1100             generateFlatSetElementNode(fm, (FlatSetElementNode) fn,output);
1101             return;
1102         case FKind.FlatSetFieldNode:
1103             generateFlatSetFieldNode(fm, (FlatSetFieldNode) fn,output);
1104             return;
1105         case FKind.FlatNew:
1106             generateFlatNew(fm, (FlatNew) fn,output);
1107             return;
1108         case FKind.FlatOpNode:
1109             generateFlatOpNode(fm, (FlatOpNode) fn,output);
1110             return;
1111         case FKind.FlatCastNode:
1112             generateFlatCastNode(fm, (FlatCastNode) fn,output);
1113             return;
1114         case FKind.FlatLiteralNode:
1115             generateFlatLiteralNode(fm, (FlatLiteralNode) fn,output);
1116             return;
1117         case FKind.FlatReturnNode:
1118             generateFlatReturnNode(fm, (FlatReturnNode) fn,output);
1119             return;
1120         case FKind.FlatNop:
1121             output.println("/* nop */");
1122             return;
1123         case FKind.FlatBackEdge:
1124             if (state.THREAD&&GENERATEPRECISEGC) {
1125                 output.println("checkcollect(&"+localsprefix+");");
1126             } else
1127                 output.println("/* nop */");
1128             return;
1129         case FKind.FlatCheckNode:
1130             generateFlatCheckNode(fm, (FlatCheckNode) fn, output);
1131             return;
1132         case FKind.FlatFlagActionNode:
1133             generateFlatFlagActionNode(fm, (FlatFlagActionNode) fn, output);
1134             return;
1135         }
1136         throw new Error();
1137
1138     }
1139
1140     private void generateFlatCheckNode(FlatMethod fm,  FlatCheckNode fcn, PrintWriter output) {
1141
1142         if (state.CONSCHECK) {
1143             String specname=fcn.getSpec();
1144             String varname="repairstate___";
1145             output.println("{");
1146             output.println("struct "+specname+"_state * "+varname+"=allocate"+specname+"_state();");
1147
1148             TempDescriptor[] temps=fcn.getTemps();
1149             String[] vars=fcn.getVars();
1150             for(int i=0;i<temps.length;i++) {
1151                 output.println(varname+"->"+vars[i]+"=(int)"+generateTemp(fm, temps[i])+";");
1152             }
1153
1154             output.println("if (doanalysis"+specname+"("+varname+")) {");
1155             output.println("free"+specname+"_state("+varname+");");
1156             output.println("} else {");
1157             output.println("/* Bad invariant */");
1158             output.println("free"+specname+"_state("+varname+");");
1159             output.println("abort_task();");
1160             output.println("}");
1161
1162             output.println("}");
1163         }
1164     }
1165
1166     private void generateFlatCall(FlatMethod fm, FlatCall fc, PrintWriter output) {
1167         MethodDescriptor md=fc.getMethod();
1168         ParamsObject objectparams=(ParamsObject) paramstable.get(md);
1169         ClassDescriptor cn=md.getClassDesc();
1170         output.println("{");
1171         if (GENERATEPRECISEGC) {
1172             output.print("       struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params __parameterlist__={");
1173             
1174             output.print(objectparams.numPointers());
1175             //      output.print(objectparams.getUID());
1176             output.print(", & "+localsprefix);
1177             if (fc.getThis()!=null) {
1178                 output.print(", ");
1179                 output.print("(struct "+md.getThis().getType().getSafeSymbol() +" *)"+ generateTemp(fm,fc.getThis()));
1180             }
1181             for(int i=0;i<fc.numArgs();i++) {
1182                 Descriptor var=md.getParameter(i);
1183                 TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
1184                 if (objectparams.isParamPtr(paramtemp)) {
1185                     TempDescriptor targ=fc.getArg(i);
1186                     output.print(", ");
1187                     TypeDescriptor td=md.getParamType(i);
1188                     if (td.isTag())
1189                         output.print("(struct "+(new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass))).getSafeSymbol()  +" *)"+generateTemp(fm, targ));
1190                     else
1191                         output.print("(struct "+md.getParamType(i).getSafeSymbol()  +" *)"+generateTemp(fm, targ));
1192                 }
1193             }
1194             output.println("};");
1195         }
1196         output.print("       ");
1197
1198
1199         if (fc.getReturnTemp()!=null)
1200             output.print(generateTemp(fm,fc.getReturnTemp())+"=");
1201
1202         /* Do we need to do virtual dispatch? */
1203         if (md.isStatic()||md.getReturnType()==null||singleCall(fc.getThis().getType().getClassDesc(),md)) {
1204             output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor());
1205         } else {
1206             
1207             output.print("((");
1208             if (md.getReturnType().isClass()||md.getReturnType().isArray())
1209                 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
1210             else
1211                 output.print(md.getReturnType().getSafeSymbol()+" ");
1212             output.print("(*)(");
1213
1214             boolean printcomma=false;
1215             if (GENERATEPRECISEGC) {
1216                 output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * ");
1217                 printcomma=true;
1218             } 
1219
1220
1221             for(int i=0;i<objectparams.numPrimitives();i++) {
1222                 TempDescriptor temp=objectparams.getPrimitive(i);
1223                 if (printcomma)
1224                     output.print(", ");
1225                 printcomma=true;
1226                 if (temp.getType().isClass()||temp.getType().isArray())
1227                     output.print("struct " + temp.getType().getSafeSymbol()+" * ");
1228                 else
1229                     output.print(temp.getType().getSafeSymbol());
1230             }
1231
1232             output.print("))virtualtable["+generateTemp(fm,fc.getThis())+"->type*"+maxcount+"+"+virtualcalls.getMethodNumber(md)+"])");
1233         }
1234
1235         output.print("(");
1236         boolean needcomma=false;
1237         if (GENERATEPRECISEGC) {
1238             output.print("&__parameterlist__");
1239             needcomma=true;
1240         } else {
1241             if (fc.getThis()!=null) {
1242                 TypeDescriptor ptd=md.getThis().getType();
1243                 if (ptd.isClass()&&!ptd.isArray())
1244                     output.print("(struct "+ptd.getSafeSymbol()+" *) ");
1245                 output.print(generateTemp(fm,fc.getThis()));
1246                 needcomma=true;
1247             }
1248         }
1249         for(int i=0;i<fc.numArgs();i++) {
1250             Descriptor var=md.getParameter(i);
1251             TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
1252             if (objectparams.isParamPrim(paramtemp)) {
1253                 TempDescriptor targ=fc.getArg(i);
1254                 if (needcomma)
1255                     output.print(", ");
1256
1257                 TypeDescriptor ptd=md.getParamType(i);
1258                 if (ptd.isClass()&&!ptd.isArray())
1259                     output.print("(struct "+ptd.getSafeSymbol()+" *) ");
1260                 output.print(generateTemp(fm, targ));
1261                 needcomma=true;
1262             }
1263         }
1264         output.println(");");
1265         output.println("   }");
1266     }
1267
1268     private boolean singleCall(ClassDescriptor thiscd, MethodDescriptor md) {
1269         Set subclasses=typeutil.getSubClasses(thiscd);
1270         if (subclasses==null)
1271             return true;
1272         for(Iterator classit=subclasses.iterator();classit.hasNext();) {
1273             ClassDescriptor cd=(ClassDescriptor)classit.next();
1274             Set possiblematches=cd.getMethodTable().getSet(md.getSymbol());
1275             for(Iterator matchit=possiblematches.iterator();matchit.hasNext();) {
1276                 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
1277                 if (md.matches(matchmd))
1278                     return false;
1279             }
1280         }
1281         return true;
1282     }
1283
1284     private void generateFlatFieldNode(FlatMethod fm, FlatFieldNode ffn, PrintWriter output) {
1285         output.println(generateTemp(fm, ffn.getDst())+"="+ generateTemp(fm,ffn.getSrc())+"->"+ ffn.getField().getSafeSymbol()+";");
1286     }
1287
1288     private void generateFlatSetFieldNode(FlatMethod fm, FlatSetFieldNode fsfn, PrintWriter output) {
1289         if (fsfn.getField().getSymbol().equals("length")&&fsfn.getDst().getType().isArray())
1290             throw new Error("Can't set array length");
1291         output.println(generateTemp(fm, fsfn.getDst())+"->"+ fsfn.getField().getSafeSymbol()+"="+ generateTemp(fm,fsfn.getSrc())+";");
1292     }
1293
1294     private void generateFlatElementNode(FlatMethod fm, FlatElementNode fen, PrintWriter output) {
1295         TypeDescriptor elementtype=fen.getSrc().getType().dereference();
1296         String type="";
1297
1298         if (elementtype.isArray()||elementtype.isClass())
1299             type="void *";
1300         else 
1301             type=elementtype.getSafeSymbol()+" ";
1302
1303         if (fen.needsBoundsCheck()) {
1304             output.println("if ("+generateTemp(fm, fen.getIndex())+"< 0 || "+generateTemp(fm, fen.getIndex())+" >= "+generateTemp(fm,fen.getSrc()) + "->___length___)");
1305             output.println("failedboundschk();");
1306         }
1307
1308         output.println(generateTemp(fm, fen.getDst())+"=(("+ type+"*)(((char *) &("+ generateTemp(fm,fen.getSrc())+"->___length___))+sizeof(int)))["+generateTemp(fm, fen.getIndex())+"];");
1309     }
1310
1311     private void generateFlatSetElementNode(FlatMethod fm, FlatSetElementNode fsen, PrintWriter output) {
1312         //TODO: need dynamic check to make sure this assignment is actually legal
1313         //Because Object[] could actually be something more specific...ie. Integer[]
1314
1315         TypeDescriptor elementtype=fsen.getDst().getType().dereference();
1316         String type="";
1317
1318         if (elementtype.isArray()||elementtype.isClass())
1319             type="void *";
1320         else 
1321             type=elementtype.getSafeSymbol()+" ";
1322
1323         if (fsen.needsBoundsCheck()) {
1324             output.println("if ("+generateTemp(fm, fsen.getIndex())+"< 0 || "+generateTemp(fm, fsen.getIndex())+" >= "+generateTemp(fm,fsen.getDst()) + "->___length___)");
1325             output.println("failedboundschk();");
1326         }
1327
1328         output.println("(("+type +"*)(((char *) &("+ generateTemp(fm,fsen.getDst())+"->___length___))+sizeof(int)))["+generateTemp(fm, fsen.getIndex())+"]="+generateTemp(fm,fsen.getSrc())+";");
1329     }
1330
1331     private void generateFlatNew(FlatMethod fm, FlatNew fn, PrintWriter output) {
1332         if (fn.getType().isArray()) {
1333             int arrayid=state.getArrayNumber(fn.getType())+state.numClasses();
1334             if (GENERATEPRECISEGC) {
1335                 output.println(generateTemp(fm,fn.getDst())+"=allocate_newarray(&"+localsprefix+", "+arrayid+", "+generateTemp(fm, fn.getSize())+");");
1336             } else {
1337                 output.println(generateTemp(fm,fn.getDst())+"=allocate_newarray("+arrayid+", "+generateTemp(fm, fn.getSize())+");");
1338             }
1339         } else {
1340             if (GENERATEPRECISEGC) {
1341                 output.println(generateTemp(fm,fn.getDst())+"=allocate_new(&"+localsprefix+", "+fn.getType().getClassDesc().getId()+");");
1342             } else {
1343                 output.println(generateTemp(fm,fn.getDst())+"=allocate_new("+fn.getType().getClassDesc().getId()+");");
1344             }
1345         }
1346     }
1347
1348
1349     private void generateFlatTagDeclaration(FlatMethod fm, FlatTagDeclaration fn, PrintWriter output) {
1350         if (GENERATEPRECISEGC) {
1351             output.println(generateTemp(fm,fn.getDst())+"=allocate_tag(&"+localsprefix+", "+state.getTagId(fn.getType())+");");
1352         } else {
1353             output.println(generateTemp(fm,fn.getDst())+"=allocate_tag("+state.getTagId(fn.getType())+");");
1354         }
1355     }
1356
1357     private void generateFlatOpNode(FlatMethod fm, FlatOpNode fon, PrintWriter output) {
1358
1359         if (fon.getRight()!=null)
1360             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+fon.getOp().toString()+generateTemp(fm,fon.getRight())+";");
1361         else if (fon.getOp().getOp()==Operation.ASSIGN)
1362             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
1363         else if (fon.getOp().getOp()==Operation.UNARYPLUS)
1364             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
1365         else if (fon.getOp().getOp()==Operation.UNARYMINUS)
1366             output.println(generateTemp(fm, fon.getDest())+" = -"+generateTemp(fm, fon.getLeft())+";");
1367         else if (fon.getOp().getOp()==Operation.LOGIC_NOT)
1368             output.println(generateTemp(fm, fon.getDest())+" = !"+generateTemp(fm, fon.getLeft())+";");
1369         else
1370             output.println(generateTemp(fm, fon.getDest())+fon.getOp().toString()+generateTemp(fm, fon.getLeft())+";");
1371     }
1372
1373     private void generateFlatCastNode(FlatMethod fm, FlatCastNode fcn, PrintWriter output) {
1374         /* TODO: Do type check here */
1375         if (fcn.getType().isArray()) {
1376             throw new Error();
1377         } else if (fcn.getType().isClass())
1378             output.println(generateTemp(fm,fcn.getDst())+"=(struct "+fcn.getType().getSafeSymbol()+" *)"+generateTemp(fm,fcn.getSrc())+";");
1379         else
1380             output.println(generateTemp(fm,fcn.getDst())+"=("+fcn.getType().getSafeSymbol()+")"+generateTemp(fm,fcn.getSrc())+";");
1381     }
1382
1383     private void generateFlatLiteralNode(FlatMethod fm, FlatLiteralNode fln, PrintWriter output) {
1384         if (fln.getValue()==null)
1385             output.println(generateTemp(fm, fln.getDst())+"=0;");
1386         else if (fln.getType().getSymbol().equals(TypeUtil.StringClass)) {
1387             if (GENERATEPRECISEGC) {
1388                 output.println(generateTemp(fm, fln.getDst())+"=NewString(&"+localsprefix+", \""+FlatLiteralNode.escapeString((String)fln.getValue())+"\","+((String)fln.getValue()).length()+");");
1389             } else {
1390                 output.println(generateTemp(fm, fln.getDst())+"=NewString(\""+FlatLiteralNode.escapeString((String)fln.getValue())+"\","+((String)fln.getValue()).length()+");");
1391             }
1392         } else if (fln.getType().isBoolean()) {
1393             if (((Boolean)fln.getValue()).booleanValue())
1394                 output.println(generateTemp(fm, fln.getDst())+"=1;");
1395             else
1396                 output.println(generateTemp(fm, fln.getDst())+"=0;");
1397         } else if (fln.getType().isChar()) {
1398             String st=FlatLiteralNode.escapeString(fln.getValue().toString());
1399             output.println(generateTemp(fm, fln.getDst())+"='"+st+"';");
1400         } else
1401             output.println(generateTemp(fm, fln.getDst())+"="+fln.getValue()+";");
1402     }
1403
1404     private void generateFlatReturnNode(FlatMethod fm, FlatReturnNode frn, PrintWriter output) {
1405         
1406         if (frn.getReturnTemp()!=null)
1407             output.println("return "+generateTemp(fm, frn.getReturnTemp())+";");
1408         else
1409             output.println("return;");
1410     }
1411
1412     private void generateFlatCondBranch(FlatMethod fm, FlatCondBranch fcb, String label, PrintWriter output) {
1413         output.println("if (!"+generateTemp(fm, fcb.getTest())+") goto "+label+";");
1414     }
1415
1416     private void generateHeader(FlatMethod fm, Descriptor des, PrintWriter output) {
1417         /* Print header */
1418         ParamsObject objectparams=(ParamsObject)paramstable.get(des);
1419         MethodDescriptor md=null;
1420         TaskDescriptor task=null;
1421         if (des instanceof MethodDescriptor)
1422             md=(MethodDescriptor) des;
1423         else
1424             task=(TaskDescriptor) des;
1425
1426         ClassDescriptor cn=md!=null?md.getClassDesc():null;
1427         
1428         if (md!=null&&md.getReturnType()!=null) {
1429             if (md.getReturnType().isClass()||md.getReturnType().isArray())
1430                 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
1431             else
1432                 output.print(md.getReturnType().getSafeSymbol()+" ");
1433         } else 
1434             //catch the constructor case
1435             output.print("void ");
1436         if (md!=null)
1437             output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
1438         else
1439             output.print(task.getSafeSymbol()+"(");
1440         
1441         boolean printcomma=false;
1442         if (GENERATEPRECISEGC) {
1443             if (md!=null)
1444                 output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
1445             else
1446                 output.print("struct "+task.getSafeSymbol()+"_params * "+paramsprefix);
1447             printcomma=true;
1448         }
1449
1450         if (md!=null) {
1451             /* Method */
1452             for(int i=0;i<objectparams.numPrimitives();i++) {
1453                 TempDescriptor temp=objectparams.getPrimitive(i);
1454                 if (printcomma)
1455                     output.print(", ");
1456                 printcomma=true;
1457                 if (temp.getType().isClass()||temp.getType().isArray())
1458                     output.print("struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
1459                 else
1460                     output.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
1461             }
1462             output.println(") {");
1463         } else if (!GENERATEPRECISEGC) {
1464             /* Imprecise Task */
1465             output.println("void * parameterarray[]) {");
1466             /* Unpack variables */
1467             for(int i=0;i<objectparams.numPrimitives();i++) {
1468                 TempDescriptor temp=objectparams.getPrimitive(i);
1469                 output.println("struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+"=parameterarray["+i+"];");
1470             }
1471             for(int i=0;i<fm.numTags();i++) {
1472                 TempDescriptor temp=fm.getTag(i);
1473                 int offset=i+objectparams.numPrimitives();
1474                 output.println("struct ___TagDescriptor___ * "+temp.getSafeSymbol()+"=parameterarray["+offset+"];");
1475             }
1476
1477             if ((objectparams.numPrimitives()+fm.numTags())>maxtaskparams)
1478                 maxtaskparams=objectparams.numPrimitives()+fm.numTags();
1479         } else output.println(") {");
1480     }
1481     
1482     public void generateFlatFlagActionNode(FlatMethod fm, FlatFlagActionNode ffan, PrintWriter output) {
1483         output.println("/* FlatFlagActionNode */");
1484
1485
1486         /* Process tag changes */
1487         Relation tagsettable=new Relation();
1488         Relation tagcleartable=new Relation();
1489
1490         Iterator tagsit=ffan.getTempTagPairs(); 
1491         while (tagsit.hasNext()) {
1492             TempTagPair ttp=(TempTagPair) tagsit.next();
1493             TempDescriptor objtmp=ttp.getTemp();
1494             TagDescriptor tag=ttp.getTag();
1495             TempDescriptor tagtmp=ttp.getTagTemp();
1496             boolean tagstatus=ffan.getTagChange(ttp);
1497             if (tagstatus) {
1498                 tagsettable.put(objtmp, tagtmp);
1499             } else {
1500                 tagcleartable.put(objtmp, tagtmp);
1501             }
1502         }
1503
1504
1505         Hashtable flagandtable=new Hashtable();
1506         Hashtable flagortable=new Hashtable();
1507
1508         /* Process flag changes */
1509         Iterator flagsit=ffan.getTempFlagPairs();
1510         while(flagsit.hasNext()) {
1511             TempFlagPair tfp=(TempFlagPair)flagsit.next();
1512             TempDescriptor temp=tfp.getTemp();
1513             Hashtable flagtable=(Hashtable)flagorder.get(temp.getType().getClassDesc());
1514             FlagDescriptor flag=tfp.getFlag();
1515             if (flag==null) {
1516                 //Newly allocate objects that don't set any flags case
1517                 if (flagortable.containsKey(temp)) {
1518                     throw new Error();
1519                 }
1520                 int mask=0;
1521                 flagortable.put(temp,new Integer(mask));
1522             } else {
1523                 int flagid=1<<((Integer)flagtable.get(flag)).intValue();
1524                 boolean flagstatus=ffan.getFlagChange(tfp);
1525                 if (flagstatus) {
1526                     int mask=0;
1527                     if (flagortable.containsKey(temp)) {
1528                         mask=((Integer)flagortable.get(temp)).intValue();
1529                     }
1530                     mask|=flagid;
1531                     flagortable.put(temp,new Integer(mask));
1532                 } else {
1533                     int mask=0xFFFFFFFF;
1534                     if (flagandtable.containsKey(temp)) {
1535                         mask=((Integer)flagandtable.get(temp)).intValue();
1536                     }
1537                     mask&=(0xFFFFFFFF^flagid);
1538                     flagandtable.put(temp,new Integer(mask));
1539                 }
1540             }
1541         }
1542
1543
1544         HashSet flagtagset=new HashSet();
1545         flagtagset.addAll(flagortable.keySet());
1546         flagtagset.addAll(flagandtable.keySet());
1547         flagtagset.addAll(tagsettable.keySet());
1548         flagtagset.addAll(tagcleartable.keySet());
1549
1550         Iterator ftit=flagtagset.iterator();
1551         while(ftit.hasNext()) {
1552             TempDescriptor temp=(TempDescriptor)ftit.next();
1553             
1554             
1555             Set tagtmps=tagcleartable.get(temp);
1556             if (tagtmps!=null) {
1557                 Iterator tagit=tagtmps.iterator();
1558                 while(tagit.hasNext()) {
1559                     TempDescriptor tagtmp=(TempDescriptor)tagit.next();
1560                     if (GENERATEPRECISEGC) 
1561                         output.println("tagclear(&"+localsprefix+", (struct ___Object___ *)"+generateTemp(fm, temp)+", "+generateTemp(fm,tagtmp)+");");
1562                     else
1563                         output.println("tagclear((struct ___Object___ *)"+generateTemp(fm, temp)+", "+generateTemp(fm,tagtmp)+");");
1564                 }
1565             }
1566
1567             tagtmps=tagsettable.get(temp);
1568             if (tagtmps!=null) {
1569                 Iterator tagit=tagtmps.iterator();
1570                 while(tagit.hasNext()) {
1571                     TempDescriptor tagtmp=(TempDescriptor)tagit.next();
1572                     if (GENERATEPRECISEGC)
1573                         output.println("tagset(&"+localsprefix+", (struct ___Object___ *)"+generateTemp(fm, temp)+", "+generateTemp(fm,tagtmp)+");");
1574                     else
1575                         output.println("tagset((struct ___Object___ *)"+generateTemp(fm, temp)+", "+generateTemp(fm,tagtmp)+");");
1576                 }
1577             }
1578
1579             int ormask=0;
1580             int andmask=0xFFFFFFF;
1581             
1582             if (flagortable.containsKey(temp))
1583                 ormask=((Integer)flagortable.get(temp)).intValue();
1584             if (flagandtable.containsKey(temp))
1585                 andmask=((Integer)flagandtable.get(temp)).intValue();
1586             if (ffan.getTaskType()==FlatFlagActionNode.NEWOBJECT) {
1587                 output.println("flagorandinit("+generateTemp(fm, temp)+", 0x"+Integer.toHexString(ormask)+", 0x"+Integer.toHexString(andmask)+");");
1588             } else {
1589                 output.println("flagorand("+generateTemp(fm, temp)+", 0x"+Integer.toHexString(ormask)+", 0x"+Integer.toHexString(andmask)+");");
1590             }
1591         }
1592     }
1593 }