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