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