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