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