This update generates partial code for tasks...
[IRC.git] / Robust / src / IR / Flat / BuildCode.java
1 package IR.Flat;
2 import IR.*;
3 import java.util.*;
4 import java.io.*;
5
6 public class BuildCode {
7     State state;
8     Hashtable temptovar;
9     Hashtable paramstable;
10     Hashtable tempstable;
11     Hashtable fieldorder;
12     int tag=0;
13     String localsprefix="___locals___";
14     String paramsprefix="___params___";
15     public static boolean GENERATEPRECISEGC=false;
16     public static String PREFIX="";
17     public static String arraytype="ArrayObject";
18     Virtual virtualcalls;
19     TypeUtil typeutil;
20
21
22     public BuildCode(State st, Hashtable temptovar, TypeUtil typeutil) {
23         state=st;
24         this.temptovar=temptovar;
25         paramstable=new Hashtable();    
26         tempstable=new Hashtable();
27         fieldorder=new Hashtable();
28         this.typeutil=typeutil;
29         virtualcalls=new Virtual(state);
30     }
31
32     public void buildCode() {
33         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
34         PrintWriter outclassdefs=null;
35         PrintWriter outstructs=null;
36         PrintWriter outmethodheader=null;
37         PrintWriter outmethod=null;
38         PrintWriter outvirtual=null;
39
40         try {
41             OutputStream str=new FileOutputStream(PREFIX+"structdefs.h");
42             outstructs=new java.io.PrintWriter(str, true);
43             str=new FileOutputStream(PREFIX+"methodheaders.h");
44             outmethodheader=new java.io.PrintWriter(str, true);
45             str=new FileOutputStream(PREFIX+"classdefs.h");
46             outclassdefs=new java.io.PrintWriter(str, true);
47             str=new FileOutputStream(PREFIX+"methods.c");
48             outmethod=new java.io.PrintWriter(str, true);
49             str=new FileOutputStream(PREFIX+"virtualtable.h");
50             outvirtual=new java.io.PrintWriter(str, true);
51         } catch (Exception e) {
52             e.printStackTrace();
53             System.exit(-1);
54         }
55
56         buildVirtualTables(outvirtual);
57         outstructs.println("#include \"classdefs.h\"");
58         outmethodheader.println("#include \"structdefs.h\"");
59
60         /* Output types for short array and string */
61         outstructs.println("#define STRINGTYPE "+typeutil.getClass(TypeUtil.StringClass).getId());
62         outstructs.println("#define CHARARRAYTYPE "+
63                            (state.getArrayNumber((new TypeDescriptor(TypeDescriptor.CHAR)).makeArray(state))+state.numClasses()));
64
65         // Output the C class declarations
66         // These could mutually reference each other
67         outclassdefs.println("struct "+arraytype+";");
68         while(it.hasNext()) {
69             ClassDescriptor cn=(ClassDescriptor)it.next();
70             outclassdefs.println("struct "+cn.getSafeSymbol()+";");
71         }
72         outclassdefs.println("");
73         {
74             //Print out definition for array type
75             outclassdefs.println("struct "+arraytype+" {");
76             outclassdefs.println("  int type;");
77             printClassStruct(typeutil.getClass(TypeUtil.ObjectClass), outclassdefs);
78             outclassdefs.println("  int ___length___;");
79             outclassdefs.println("};\n");
80         }
81
82         // Output function prototypes and structures for parameters
83         it=state.getClassSymbolTable().getDescriptorsIterator();
84         while(it.hasNext()) {
85             ClassDescriptor cn=(ClassDescriptor)it.next();
86             generateCallStructs(cn, outclassdefs, outstructs, outmethodheader);
87         }
88         outstructs.close();
89         outmethodheader.close();
90
91         if (state.TASK)
92             generateTaskStructs(outstructs, outmethodheader);
93
94         /* Build the actual methods */
95         outmethod.println("#include \"methodheaders.h\"");
96         outmethod.println("#include \"virtualtable.h\"");
97         outmethod.println("#include <runtime.h>");
98
99         outclassdefs.println("extern int classsize[];");
100         //Store the sizes of classes & array elements
101         generateSizeArray(outmethod);
102
103         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
104         while(classit.hasNext()) {
105             ClassDescriptor cn=(ClassDescriptor)classit.next();
106             Iterator methodit=cn.getMethods();
107             while(methodit.hasNext()) {
108                 /* Classify parameters */
109                 MethodDescriptor md=(MethodDescriptor)methodit.next();
110                 FlatMethod fm=state.getMethodFlat(md);
111                 if (!md.getModifiers().isNative())
112                     generateFlatMethod(fm,outmethod);
113             }
114         }
115
116         if (state.TASK) {
117             /* Compile task based program */
118             Iterator taskit=state.getTaskSymbolTable().getDescriptorsIterator();
119             while(taskit.hasNext()) {
120                 TaskDescriptor td=(TaskDescriptor)taskit.next();
121                 FlatMethod fm=state.getMethodFlat(td);
122                 generateFlatMethod(fm, outmethod);
123             }
124         } else if (state.main!=null) {
125             /* Compile method based program */
126             outmethod.println("int main(int argc, const char *argv[]) {");
127             ClassDescriptor cd=typeutil.getClass(state.main);
128             Set mainset=cd.getMethodTable().getSet("main");
129             for(Iterator mainit=mainset.iterator();mainit.hasNext();) {
130                 MethodDescriptor md=(MethodDescriptor)mainit.next();
131                 if (md.numParameters()!=0)
132                     continue;
133                 if (!md.getModifiers().isStatic())
134                     throw new Error("Error: Non static main");
135                 outmethod.println("   "+cd.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"();");
136                 break;
137             }
138             outmethod.println("}");
139         }
140         outmethod.close();
141     }
142
143     private int maxcount=0;
144
145     private void buildVirtualTables(PrintWriter outvirtual) {
146         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
147         while(classit.hasNext()) {
148             ClassDescriptor cd=(ClassDescriptor)classit.next();
149             if (virtualcalls.getMethodCount(cd)>maxcount)
150                 maxcount=virtualcalls.getMethodCount(cd);
151         }
152         MethodDescriptor[][] virtualtable=new MethodDescriptor[state.numClasses()+state.numArrays()][maxcount];
153
154         /* Fill in virtual table */
155         classit=state.getClassSymbolTable().getDescriptorsIterator();
156         while(classit.hasNext()) {
157             ClassDescriptor cd=(ClassDescriptor)classit.next();
158             fillinRow(cd, virtualtable, cd.getId());
159         }
160
161         ClassDescriptor objectcd=typeutil.getClass(TypeUtil.ObjectClass);
162         Iterator arrayit=state.getArrayIterator();
163         while(arrayit.hasNext()) {
164             TypeDescriptor td=(TypeDescriptor)arrayit.next();
165             int id=state.getArrayNumber(td);
166             fillinRow(objectcd, virtualtable, id+state.numClasses());
167         }
168         
169         outvirtual.print("void * virtualtable[]={");
170         boolean needcomma=false;
171         for(int i=0;i<state.numClasses()+state.numArrays();i++) {
172             for(int j=0;j<maxcount;j++) {
173                 if (needcomma)
174                     outvirtual.print(", ");
175                 if (virtualtable[i][j]!=null) {
176                     MethodDescriptor md=virtualtable[i][j];
177                     outvirtual.print("& "+md.getClassDesc().getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor());
178                 } else {
179                     outvirtual.print("0");
180                 }
181                 needcomma=true;
182             }
183             outvirtual.println("");
184         }
185         outvirtual.println("};");
186         outvirtual.close();
187     }
188
189     private void fillinRow(ClassDescriptor cd, MethodDescriptor[][] virtualtable, int rownum) {
190         /* Get inherited methods */
191         if (cd.getSuperDesc()!=null)
192             fillinRow(cd.getSuperDesc(), virtualtable, rownum);
193         /* Override them with our methods */
194         for(Iterator it=cd.getMethods();it.hasNext();) {
195             MethodDescriptor md=(MethodDescriptor)it.next();
196             if (md.isStatic()||md.getReturnType()==null)
197                 continue;
198             int methodnum=virtualcalls.getMethodNumber(md);
199             virtualtable[rownum][methodnum]=md;
200         }
201     }
202
203     /** Generate array that contains the sizes of class objects.  The
204      * object allocation functions in the runtime use this
205      * information. */
206
207     private void generateSizeArray(PrintWriter outclassdefs) {
208         outclassdefs.print("int classsize[]={");
209         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
210         ClassDescriptor[] cdarray=new ClassDescriptor[state.numClasses()];
211         while(it.hasNext()) {
212             ClassDescriptor cd=(ClassDescriptor)it.next();
213             cdarray[cd.getId()]=cd;
214         }
215         boolean needcomma=false;
216         for(int i=0;i<state.numClasses();i++) {
217             if (needcomma)
218                 outclassdefs.print(", ");
219             outclassdefs.print("sizeof(struct "+cdarray[i].getSafeSymbol()+")");            
220             needcomma=true;
221         }
222
223         TypeDescriptor[] sizetable=new TypeDescriptor[state.numArrays()];
224
225         Iterator arrayit=state.getArrayIterator();
226         while(arrayit.hasNext()) {
227             TypeDescriptor td=(TypeDescriptor)arrayit.next();
228             int id=state.getArrayNumber(td);
229             sizetable[id]=td;
230         }
231         
232         for(int i=0;i<state.numArrays();i++) {
233             if (needcomma)
234                 outclassdefs.print(", ");
235             TypeDescriptor tdelement=sizetable[i].dereference();
236             if (tdelement.isArray()||tdelement.isClass())
237                 outclassdefs.print("sizeof(void *)");
238             else
239                 outclassdefs.print("sizeof("+tdelement.getSafeSymbol()+")");
240             needcomma=true;
241         }
242
243         outclassdefs.println("};");
244     }
245
246     /** Constructs params and temp objects for each method or task.
247      * These objects tell the compiler which temps need to be
248      * allocated.  */
249
250     private void generateTempStructs(FlatMethod fm) {
251         MethodDescriptor md=fm.getMethod();
252         TaskDescriptor task=fm.getTask();
253
254         ParamsObject objectparams=md!=null?new ParamsObject(md,tag++):new ParamsObject(task, tag++);
255         if (md!=null)
256             paramstable.put(md, objectparams);
257         else
258             paramstable.put(task, objectparams);
259
260         for(int i=0;i<fm.numParameters();i++) {
261             TempDescriptor temp=fm.getParameter(i);
262             TypeDescriptor type=temp.getType();
263             if (type.isPtr()&&GENERATEPRECISEGC)
264                 objectparams.addPtr(temp);
265             else
266                 objectparams.addPrim(temp);
267         }
268
269         TempObject objecttemps=md!=null?new TempObject(objectparams,md,tag++):new TempObject(objectparams, task, tag++);
270         if (md!=null)
271             tempstable.put(md, objecttemps);
272         else
273             tempstable.put(task, objecttemps);
274
275         for(Iterator nodeit=fm.getNodeSet().iterator();nodeit.hasNext();) {
276             FlatNode fn=(FlatNode)nodeit.next();
277             TempDescriptor[] writes=fn.writesTemps();
278             for(int i=0;i<writes.length;i++) {
279                 TempDescriptor temp=writes[i];
280                 TypeDescriptor type=temp.getType();
281                 if (type.isPtr()&&GENERATEPRECISEGC)
282                     objecttemps.addPtr(temp);
283                 else
284                     objecttemps.addPrim(temp);
285             }
286         }
287     }
288     
289     /* Force consistent field ordering between inherited classes. */
290
291     private void printClassStruct(ClassDescriptor cn, PrintWriter classdefout) {
292         ClassDescriptor sp=cn.getSuperDesc();
293         if (sp!=null)
294             printClassStruct(sp, classdefout);
295         
296         if (!fieldorder.containsKey(cn)) {
297             Vector fields=new Vector();
298             fieldorder.put(cn,fields);
299             Iterator fieldit=cn.getFields();
300             while(fieldit.hasNext()) {
301                 FieldDescriptor fd=(FieldDescriptor)fieldit.next();
302                 if (sp==null||!sp.getFieldTable().contains(fd.getSymbol()))
303                     fields.add(fd);
304             }
305         }
306         Vector fields=(Vector)fieldorder.get(cn);
307
308         for(int i=0;i<fields.size();i++) {
309             FieldDescriptor fd=(FieldDescriptor)fields.get(i);
310             if (fd.getType().isClass()||fd.getType().isArray())
311                 classdefout.println("  struct "+fd.getType().getSafeSymbol()+" * "+fd.getSafeSymbol()+";");
312             else 
313                 classdefout.println("  "+fd.getType().getSafeSymbol()+" "+fd.getSafeSymbol()+";");
314         }
315     }
316
317     /** This function outputs (1) structures that parameters are
318      * passed in (when PRECISE GC is enabled) and (2) function
319      * prototypes for the methods */
320
321     private void generateCallStructs(ClassDescriptor cn, PrintWriter classdefout, PrintWriter output, PrintWriter headersout) {
322         /* Output class structure */
323         classdefout.println("struct "+cn.getSafeSymbol()+" {");
324         classdefout.println("  int type;");
325         printClassStruct(cn, classdefout);
326         classdefout.println("};\n");
327
328         /* Cycle through methods */
329         Iterator methodit=cn.getMethods();
330         while(methodit.hasNext()) {
331             /* Classify parameters */
332             MethodDescriptor md=(MethodDescriptor)methodit.next();
333             FlatMethod fm=state.getMethodFlat(md);
334             generateTempStructs(fm);
335
336             ParamsObject objectparams=(ParamsObject) paramstable.get(md);
337             TempObject objecttemps=(TempObject) tempstable.get(md);
338
339             /* Output parameter structure */
340             if (GENERATEPRECISEGC) {
341                 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params {");
342                 output.println("  int type;");
343                 output.println("  void * next;");
344                 for(int i=0;i<objectparams.numPointers();i++) {
345                     TempDescriptor temp=objectparams.getPointer(i);
346                     output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
347                 }
348                 output.println("};\n");
349             }
350
351             /* Output temp structure */
352             if (GENERATEPRECISEGC) {
353                 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals {");
354                 output.println("  int type;");
355                 output.println("  void * next;");
356                 for(int i=0;i<objecttemps.numPointers();i++) {
357                     TempDescriptor temp=objecttemps.getPointer(i);
358                     if (temp.getType().isNull())
359                         output.println("  void * "+temp.getSafeSymbol()+";");
360                     else
361                         output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
362                 }
363                 output.println("};\n");
364             }
365             
366             /* Output method declaration */
367             if (md.getReturnType()!=null) {
368                 if (md.getReturnType().isClass()||md.getReturnType().isArray())
369                     headersout.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
370                 else
371                     headersout.print(md.getReturnType().getSafeSymbol()+" ");
372             } else 
373                 //catch the constructor case
374                 headersout.print("void ");
375             headersout.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
376             
377             boolean printcomma=false;
378             if (GENERATEPRECISEGC) {
379                 headersout.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
380                 printcomma=true;
381             }
382
383             //output parameter list
384             for(int i=0;i<objectparams.numPrimitives();i++) {
385                 TempDescriptor temp=objectparams.getPrimitive(i);
386                 if (printcomma)
387                     headersout.print(", ");
388                 printcomma=true;
389                 if (temp.getType().isClass()||temp.getType().isArray())
390                     headersout.print("struct " + temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
391                 else
392                     headersout.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
393             }
394             headersout.println(");\n");
395         }
396     }
397
398
399     /** This function outputs (1) structures that parameters are
400      * passed in (when PRECISE GC is enabled) and (2) function
401      * prototypes for the tasks */
402
403     private void generateTaskStructs(PrintWriter output, PrintWriter headersout) {
404         /* Cycle through tasks */
405         Iterator taskit=state.getTaskSymbolTable().getDescriptorsIterator();
406
407         while(taskit.hasNext()) {
408             /* Classify parameters */
409             TaskDescriptor task=(TaskDescriptor)taskit.next();
410             FlatMethod fm=state.getMethodFlat(task);
411             generateTempStructs(fm);
412
413             ParamsObject objectparams=(ParamsObject) paramstable.get(task);
414             TempObject objecttemps=(TempObject) tempstable.get(task);
415
416             /* Output parameter structure */
417             if (GENERATEPRECISEGC) {
418                 output.println("struct "+task.getSafeSymbol()+"_params {");
419                 output.println("  int type;");
420                 output.println("  void * next;");
421                 for(int i=0;i<objectparams.numPointers();i++) {
422                     TempDescriptor temp=objectparams.getPointer(i);
423                     output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
424                 }
425                 output.println("};\n");
426             }
427
428             /* Output temp structure */
429             if (GENERATEPRECISEGC) {
430                 output.println("struct "+task.getSafeSymbol()+"_locals {");
431                 output.println("  int type;");
432                 output.println("  void * next;");
433                 for(int i=0;i<objecttemps.numPointers();i++) {
434                     TempDescriptor temp=objecttemps.getPointer(i);
435                     if (temp.getType().isNull())
436                         output.println("  void * "+temp.getSafeSymbol()+";");
437                     else
438                         output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
439                 }
440                 output.println("};\n");
441             }
442             
443             /* Output task declaration */
444             headersout.print("void " + task.getSafeSymbol()+"_"+"(");
445             
446             boolean printcomma=false;
447             if (GENERATEPRECISEGC) {
448                 headersout.print("struct "+task.getSafeSymbol()+"_params * "+paramsprefix);
449                 printcomma=true;
450             }
451
452             //output parameter list
453             for(int i=0;i<objectparams.numPrimitives();i++) {
454                 TempDescriptor temp=objectparams.getPrimitive(i);
455                 if (printcomma)
456                     headersout.print(", ");
457                 printcomma=true;
458                 if (temp.getType().isClass()||temp.getType().isArray())
459                     headersout.print("struct " + temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
460                 else
461                     headersout.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
462             }
463             headersout.println(");\n");
464         }
465     }
466
467     private void generateFlatMethod(FlatMethod fm, PrintWriter output) {
468         MethodDescriptor md=fm.getMethod();
469         TaskDescriptor task=fm.getTask();
470
471         ClassDescriptor cn=md!=null?md.getClassDesc():null;
472
473         ParamsObject objectparams=(ParamsObject)paramstable.get(md!=null?md:task);
474
475         generateHeader(md!=null?md:task,output);
476
477         /* Print code */
478         output.println(" {");
479         
480         if (GENERATEPRECISEGC) {
481             if (md!=null)
482                 output.println("   struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals "+localsprefix+";");
483             else
484                 output.println("   struct "+task.getSafeSymbol()+"_locals "+localsprefix+";");
485         }
486         TempObject objecttemp=(TempObject) tempstable.get(md!=null?md:task);
487         for(int i=0;i<objecttemp.numPrimitives();i++) {
488             TempDescriptor td=objecttemp.getPrimitive(i);
489             TypeDescriptor type=td.getType();
490             if (type.isNull())
491                 output.println("   void * "+td.getSafeSymbol()+";");
492             else if (type.isClass()||type.isArray())
493                 output.println("   struct "+type.getSafeSymbol()+" * "+td.getSafeSymbol()+";");
494             else
495                 output.println("   "+type.getSafeSymbol()+" "+td.getSafeSymbol()+";");
496         }
497         
498
499         /* Generate labels first */
500         HashSet tovisit=new HashSet();
501         HashSet visited=new HashSet();
502         int labelindex=0;
503         Hashtable nodetolabel=new Hashtable();
504         tovisit.add(fm.methodEntryNode());
505         FlatNode current_node=null;
506
507         //Assign labels 1st
508         //Node needs a label if it is
509         while(!tovisit.isEmpty()) {
510             FlatNode fn=(FlatNode)tovisit.iterator().next();
511             tovisit.remove(fn);
512             visited.add(fn);
513             for(int i=0;i<fn.numNext();i++) {
514                 FlatNode nn=fn.getNext(i);
515                 if(i>0) {
516                     //1) Edge >1 of node
517                     nodetolabel.put(nn,new Integer(labelindex++));
518                 }
519                 if (!visited.contains(nn)&&!tovisit.contains(nn)) {
520                     tovisit.add(nn);
521                 } else {
522                     //2) Join point
523                     nodetolabel.put(nn,new Integer(labelindex++));
524                 }
525             }
526         }
527
528         //Do the actual code generation
529         tovisit=new HashSet();
530         visited=new HashSet();
531         tovisit.add(fm.methodEntryNode());
532         while(current_node!=null||!tovisit.isEmpty()) {
533             if (current_node==null) {
534                 current_node=(FlatNode)tovisit.iterator().next();
535                 tovisit.remove(current_node);
536             }
537             visited.add(current_node);
538             if (nodetolabel.containsKey(current_node))
539                 output.println("L"+nodetolabel.get(current_node)+":");
540             if (current_node.numNext()==0) {
541                 output.print("   ");
542                 generateFlatNode(fm, current_node, output);
543                 if (current_node.kind()!=FKind.FlatReturnNode) {
544                     output.println("   return;");
545                 }
546                 current_node=null;
547             } else if(current_node.numNext()==1) {
548                 output.print("   ");
549                 generateFlatNode(fm, current_node, output);
550                 FlatNode nextnode=current_node.getNext(0);
551                 if (visited.contains(nextnode)) {
552                     output.println("goto L"+nodetolabel.get(nextnode)+";");
553                     current_node=null;
554                 } else
555                     current_node=nextnode;
556             } else if (current_node.numNext()==2) {
557                 /* Branch */
558                 output.print("   ");
559                 generateFlatCondBranch(fm, (FlatCondBranch)current_node, "L"+nodetolabel.get(current_node.getNext(1)), output);
560                 if (!visited.contains(current_node.getNext(1)))
561                     tovisit.add(current_node.getNext(1));
562                 if (visited.contains(current_node.getNext(0))) {
563                     output.println("goto L"+nodetolabel.get(current_node.getNext(0))+";");
564                     current_node=null;
565                 } else
566                     current_node=current_node.getNext(0);
567             } else throw new Error();
568         }
569         output.println("}\n\n");
570     }
571
572     private String generateTemp(FlatMethod fm, TempDescriptor td) {
573         MethodDescriptor md=fm.getMethod();
574         TaskDescriptor task=fm.getTask();
575         TempObject objecttemps=(TempObject) tempstable.get(md!=null?md:task);
576         if (objecttemps.isLocalPrim(td)||objecttemps.isParamPrim(td)) {
577             return td.getSafeSymbol();
578         }
579
580         if (objecttemps.isLocalPtr(td)) {
581             return localsprefix+"."+td.getSafeSymbol();
582         }
583
584         if (objecttemps.isParamPtr(td)) {
585             return paramsprefix+"->"+td.getSafeSymbol();
586         }
587         throw new Error();
588     }
589
590     private void generateFlatNode(FlatMethod fm, FlatNode fn, PrintWriter output) {
591         switch(fn.kind()) {
592         case FKind.FlatCall:
593             generateFlatCall(fm, (FlatCall) fn,output);
594             return;
595         case FKind.FlatFieldNode:
596             generateFlatFieldNode(fm, (FlatFieldNode) fn,output);
597             return;
598         case FKind.FlatElementNode:
599             generateFlatElementNode(fm, (FlatElementNode) fn,output);
600             return;
601         case FKind.FlatSetElementNode:
602             generateFlatSetElementNode(fm, (FlatSetElementNode) fn,output);
603             return;
604         case FKind.FlatSetFieldNode:
605             generateFlatSetFieldNode(fm, (FlatSetFieldNode) fn,output);
606             return;
607         case FKind.FlatNew:
608             generateFlatNew(fm, (FlatNew) fn,output);
609             return;
610         case FKind.FlatOpNode:
611             generateFlatOpNode(fm, (FlatOpNode) fn,output);
612             return;
613         case FKind.FlatCastNode:
614             generateFlatCastNode(fm, (FlatCastNode) fn,output);
615             return;
616         case FKind.FlatLiteralNode:
617             generateFlatLiteralNode(fm, (FlatLiteralNode) fn,output);
618             return;
619         case FKind.FlatReturnNode:
620             generateFlatReturnNode(fm, (FlatReturnNode) fn,output);
621             return;
622         case FKind.FlatNop:
623             output.println("/* nop */");
624             return;
625         case FKind.FlatFlagActionNode:
626             generateFlatFlagActionNode(fm, (FlatFlagActionNode) fn, output);
627             return;
628         }
629         throw new Error();
630
631     }
632
633     private void generateFlatCall(FlatMethod fm, FlatCall fc, PrintWriter output) {
634         MethodDescriptor md=fc.getMethod();
635         ParamsObject objectparams=(ParamsObject) paramstable.get(md);
636         ClassDescriptor cn=md.getClassDesc();
637         output.println("{");
638         if (GENERATEPRECISEGC) {
639             output.print("       struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params __parameterlist__={");
640             
641             output.print(objectparams.getUID());
642             output.print(", & "+localsprefix);
643             if (fc.getThis()!=null) {
644                 output.print(", ");
645                 output.print(generateTemp(fm,fc.getThis()));
646             }
647             for(int i=0;i<fc.numArgs();i++) {
648                 VarDescriptor var=md.getParameter(i);
649                 TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
650                 if (objectparams.isParamPtr(paramtemp)) {
651                     TempDescriptor targ=fc.getArg(i);
652                     output.print(", ");
653                     output.print(generateTemp(fm, targ));
654                 }
655             }
656             output.println("};");
657         }
658         output.print("       ");
659
660
661         if (fc.getReturnTemp()!=null)
662             output.print(generateTemp(fm,fc.getReturnTemp())+"=");
663         if (md.isStatic()||md.getReturnType()==null||singleCall(fc.getThis().getType().getClassDesc(),md)) {
664             output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor());
665         } else {
666             
667             output.print("((");
668             if (md.getReturnType().isClass()||md.getReturnType().isArray())
669                 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
670             else
671                 output.print(md.getReturnType().getSafeSymbol()+" ");
672             output.print("(*)(");
673
674             boolean printcomma=false;
675             if (GENERATEPRECISEGC) {
676                 output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * ");
677                 printcomma=true;
678             } 
679
680
681             for(int i=0;i<objectparams.numPrimitives();i++) {
682                 TempDescriptor temp=objectparams.getPrimitive(i);
683                 if (printcomma)
684                     output.print(", ");
685                 printcomma=true;
686                 if (temp.getType().isClass()||temp.getType().isArray())
687                     output.print("struct " + temp.getType().getSafeSymbol()+" * ");
688                 else
689                     output.print(temp.getType().getSafeSymbol());
690             }
691
692             output.print("))virtualtable["+generateTemp(fm,fc.getThis())+"->type*"+maxcount+"+"+virtualcalls.getMethodNumber(md)+"])");
693         }
694
695         output.print("(");
696         boolean needcomma=false;
697         if (GENERATEPRECISEGC) {
698             output.print("&__parameterlist__");
699             needcomma=true;
700         } else {
701             if (fc.getThis()!=null) {
702                 output.print(generateTemp(fm,fc.getThis()));
703                 needcomma=true;
704             }
705         }
706         for(int i=0;i<fc.numArgs();i++) {
707             VarDescriptor var=md.getParameter(i);
708             TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
709             if (objectparams.isParamPrim(paramtemp)) {
710                 TempDescriptor targ=fc.getArg(i);
711                 if (needcomma)
712                     output.print(", ");
713                 output.print(generateTemp(fm, targ));
714                 needcomma=true;
715             }
716         }
717         output.println(");");
718         output.println("   }");
719     }
720
721     private boolean singleCall(ClassDescriptor thiscd, MethodDescriptor md) {
722         Set subclasses=typeutil.getSubClasses(thiscd);
723         if (subclasses==null)
724             return true;
725         for(Iterator classit=subclasses.iterator();classit.hasNext();) {
726             ClassDescriptor cd=(ClassDescriptor)classit.next();
727             Set possiblematches=cd.getMethodTable().getSet(md.getSymbol());
728             for(Iterator matchit=possiblematches.iterator();matchit.hasNext();) {
729                 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
730                 if (md.matches(matchmd))
731                     return false;
732             }
733         }
734         return true;
735     }
736
737     private void generateFlatFieldNode(FlatMethod fm, FlatFieldNode ffn, PrintWriter output) {
738         output.println(generateTemp(fm, ffn.getDst())+"="+ generateTemp(fm,ffn.getSrc())+"->"+ ffn.getField().getSafeSymbol()+";");
739     }
740
741     private void generateFlatSetFieldNode(FlatMethod fm, FlatSetFieldNode fsfn, PrintWriter output) {
742         if (fsfn.getField().getSymbol().equals("length")&&fsfn.getDst().getType().isArray())
743             throw new Error("Can't set array length");
744         output.println(generateTemp(fm, fsfn.getDst())+"->"+ fsfn.getField().getSafeSymbol()+"="+ generateTemp(fm,fsfn.getSrc())+";");
745     }
746
747     private void generateFlatElementNode(FlatMethod fm, FlatElementNode fen, PrintWriter output) {
748         TypeDescriptor elementtype=fen.getSrc().getType().dereference();
749         String type="";
750
751         if (elementtype.isArray()||elementtype.isClass())
752             type="void *";
753         else 
754             type=elementtype.getSafeSymbol()+" ";
755
756         if (fen.needsBoundsCheck()) {
757             output.println("if ("+generateTemp(fm, fen.getIndex())+"< 0 || "+generateTemp(fm, fen.getIndex())+" >= "+generateTemp(fm,fen.getSrc()) + "->___length___)");
758             output.println("failedboundschk();");
759         }
760
761         output.println(generateTemp(fm, fen.getDst())+"=(("+ type+"*)(((char *) &("+ generateTemp(fm,fen.getSrc())+"->___length___))+sizeof(int)))["+generateTemp(fm, fen.getIndex())+"];");
762     }
763
764     private void generateFlatSetElementNode(FlatMethod fm, FlatSetElementNode fsen, PrintWriter output) {
765         //TODO: need dynamic check to make sure this assignment is actually legal
766         //Because Object[] could actually be something more specific...ie. Integer[]
767
768         TypeDescriptor elementtype=fsen.getDst().getType().dereference();
769         String type="";
770
771         if (elementtype.isArray()||elementtype.isClass())
772             type="void *";
773         else 
774             type=elementtype.getSafeSymbol()+" ";
775
776         if (fsen.needsBoundsCheck()) {
777             output.println("if ("+generateTemp(fm, fsen.getIndex())+"< 0 || "+generateTemp(fm, fsen.getIndex())+" >= "+generateTemp(fm,fsen.getDst()) + "->___length___)");
778             output.println("failedboundschk();");
779         }
780
781         output.println("(("+type +"*)(((char *) &("+ generateTemp(fm,fsen.getDst())+"->___length___))+sizeof(int)))["+generateTemp(fm, fsen.getIndex())+"]="+generateTemp(fm,fsen.getSrc())+";");
782     }
783
784     private void generateFlatNew(FlatMethod fm, FlatNew fn, PrintWriter output) {
785         if (fn.getType().isArray()) {
786             int arrayid=state.getArrayNumber(fn.getType())+state.numClasses();
787             output.println(generateTemp(fm,fn.getDst())+"=allocate_newarray("+arrayid+", "+generateTemp(fm, fn.getSize())+");");
788         } else
789             output.println(generateTemp(fm,fn.getDst())+"=allocate_new("+fn.getType().getClassDesc().getId()+");");
790     }
791
792     private void generateFlatOpNode(FlatMethod fm, FlatOpNode fon, PrintWriter output) {
793
794         if (fon.getRight()!=null)
795             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+fon.getOp().toString()+generateTemp(fm,fon.getRight())+";");
796         else if (fon.getOp().getOp()==Operation.ASSIGN)
797             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
798         else if (fon.getOp().getOp()==Operation.UNARYPLUS)
799             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
800         else if (fon.getOp().getOp()==Operation.UNARYMINUS)
801             output.println(generateTemp(fm, fon.getDest())+" = -"+generateTemp(fm, fon.getLeft())+";");
802         else if (fon.getOp().getOp()==Operation.LOGIC_NOT)
803             output.println(generateTemp(fm, fon.getDest())+" = !"+generateTemp(fm, fon.getLeft())+";");
804         else
805             output.println(generateTemp(fm, fon.getDest())+fon.getOp().toString()+generateTemp(fm, fon.getLeft())+";");
806     }
807
808     private void generateFlatCastNode(FlatMethod fm, FlatCastNode fcn, PrintWriter output) {
809         /* TODO: Do type check here */
810         output.println(generateTemp(fm,fcn.getDst())+"=("+fcn.getType().getSafeSymbol()+")"+generateTemp(fm,fcn.getSrc())+";");
811     }
812
813     private void generateFlatLiteralNode(FlatMethod fm, FlatLiteralNode fln, PrintWriter output) {
814         if (fln.getValue()==null)
815             output.println(generateTemp(fm, fln.getDst())+"=0;");
816         else if (fln.getType().getSymbol().equals(TypeUtil.StringClass))
817             output.println(generateTemp(fm, fln.getDst())+"=NewString(\""+FlatLiteralNode.escapeString((String)fln.getValue())+"\","+((String)fln.getValue()).length()+");");
818         else if (fln.getType().isBoolean()) {
819             if (((Boolean)fln.getValue()).booleanValue())
820                 output.println(generateTemp(fm, fln.getDst())+"=1;");
821             else
822                 output.println(generateTemp(fm, fln.getDst())+"=0;");
823         } else if (fln.getType().isChar()) {
824             output.println(generateTemp(fm, fln.getDst())+"='"+fln.getValue()+"';");
825         } else
826             output.println(generateTemp(fm, fln.getDst())+"="+fln.getValue()+";");
827     }
828
829     private void generateFlatReturnNode(FlatMethod fm, FlatReturnNode frn, PrintWriter output) {
830         if (frn.getReturnTemp()!=null)
831             output.println("return "+generateTemp(fm, frn.getReturnTemp())+";");
832         else
833             output.println("return;");
834     }
835
836     private void generateFlatCondBranch(FlatMethod fm, FlatCondBranch fcb, String label, PrintWriter output) {
837         output.println("if (!"+generateTemp(fm, fcb.getTest())+") goto "+label+";");
838     }
839
840     private void generateHeader(Descriptor des, PrintWriter output) {
841         /* Print header */
842         ParamsObject objectparams=(ParamsObject)paramstable.get(des);
843         MethodDescriptor md=null;
844         TaskDescriptor task=null;
845         if (des instanceof MethodDescriptor)
846             md=(MethodDescriptor) des;
847         else
848             task=(TaskDescriptor) des;
849
850         ClassDescriptor cn=md!=null?md.getClassDesc():null;
851         
852         if (md!=null&&md.getReturnType()!=null) {
853             if (md.getReturnType().isClass()||md.getReturnType().isArray())
854                 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
855             else
856                 output.print(md.getReturnType().getSafeSymbol()+" ");
857         } else 
858             //catch the constructor case
859             output.print("void ");
860         if (md!=null)
861             output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
862         else
863             output.print(task.getSafeSymbol()+"(");
864         
865         boolean printcomma=false;
866         if (GENERATEPRECISEGC) {
867             if (md!=null)
868                 output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
869             else
870                 output.print("struct "+task.getSafeSymbol()+"_params * "+paramsprefix);
871             printcomma=true;
872         } 
873
874         for(int i=0;i<objectparams.numPrimitives();i++) {
875             TempDescriptor temp=objectparams.getPrimitive(i);
876             if (printcomma)
877                 output.print(", ");
878             printcomma=true;
879             if (temp.getType().isClass()||temp.getType().isArray())
880                 output.print("struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
881             else
882                 output.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
883         }
884         output.print(")");
885     }
886
887     public void generateFlatFlagActionNode(FlatMethod fm, FlatFlagActionNode ffann, PrintWriter output) {
888         output.print("/* FlatFlagActionNode will go here */");
889     }
890 }