29e5a4a6c41ceb6d6880ca46e8e85c6c9eeeb027
[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 the C declarations
61         // These could mutually reference each other
62         outclassdefs.println("struct "+arraytype+";");
63         while(it.hasNext()) {
64             ClassDescriptor cn=(ClassDescriptor)it.next();
65             outclassdefs.println("struct "+cn.getSafeSymbol()+";");
66         }
67         outclassdefs.println("");
68         {
69             //Print out definition for array type
70             outclassdefs.println("struct "+arraytype+" {");
71             outclassdefs.println("  int type;");
72             printClassStruct(typeutil.getClass(TypeUtil.ObjectClass), outclassdefs);
73             outclassdefs.println("  int length;");
74             outclassdefs.println("};\n");
75         }
76         it=state.getClassSymbolTable().getDescriptorsIterator();
77         while(it.hasNext()) {
78             ClassDescriptor cn=(ClassDescriptor)it.next();
79             generateCallStructs(cn, outclassdefs, outstructs, outmethodheader);
80         }
81
82         outstructs.close();
83         outmethodheader.close();
84
85         /* Build the actual methods */
86         outmethod.println("#include \"methodheaders.h\"");
87         outmethod.println("#include \"virtualtable.h\"");
88         outmethod.println("#include <runtime.h>");
89
90         outclassdefs.println("extern int classsize[];");
91         //Store the sizes of classes & array elements
92         generateSizeArray(outmethod);
93
94         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
95         while(classit.hasNext()) {
96             ClassDescriptor cn=(ClassDescriptor)classit.next();
97             Iterator methodit=cn.getMethods();
98             while(methodit.hasNext()) {
99                 /* Classify parameters */
100                 MethodDescriptor md=(MethodDescriptor)methodit.next();
101                 FlatMethod fm=state.getMethodFlat(md);
102                 if (!md.getModifiers().isNative())
103                     generateFlatMethod(fm,outmethod);
104             }
105         }
106         if (state.main!=null) {
107             outmethod.println("int main(int argc, const char *argv[]) {");
108             ClassDescriptor cd=typeutil.getClass(state.main);
109             Set mainset=cd.getMethodTable().getSet("main");
110             for(Iterator mainit=mainset.iterator();mainit.hasNext();) {
111                 MethodDescriptor md=(MethodDescriptor)mainit.next();
112                 if (md.numParameters()!=0)
113                     continue;
114                 if (!md.getModifiers().isStatic())
115                     throw new Error("Error: Non static main");
116                 outmethod.println("   "+cd.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"();");
117                 break;
118             }
119             outmethod.println("}");
120         }
121         outmethod.close();
122     }
123
124     private int maxcount=0;
125
126     private void buildVirtualTables(PrintWriter outvirtual) {
127         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
128         while(classit.hasNext()) {
129             ClassDescriptor cd=(ClassDescriptor)classit.next();
130             if (virtualcalls.getMethodCount(cd)>maxcount)
131                 maxcount=virtualcalls.getMethodCount(cd);
132         }
133         MethodDescriptor[][] virtualtable=new MethodDescriptor[state.numClasses()+state.numArrays()][maxcount];
134
135         /* Fill in virtual table */
136         classit=state.getClassSymbolTable().getDescriptorsIterator();
137         while(classit.hasNext()) {
138             ClassDescriptor cd=(ClassDescriptor)classit.next();
139             fillinRow(cd, virtualtable, cd.getId());
140         }
141
142         ClassDescriptor objectcd=typeutil.getClass(TypeUtil.ObjectClass);
143         Iterator arrayit=state.getArrayIterator();
144         while(arrayit.hasNext()) {
145             TypeDescriptor td=(TypeDescriptor)arrayit.next();
146             int id=state.getArrayNumber(td);
147             fillinRow(objectcd, virtualtable, id+state.numClasses());
148         }
149         
150         outvirtual.print("void * virtualtable[]={");
151         boolean needcomma=false;
152         for(int i=0;i<state.numClasses()+state.numArrays();i++) {
153             for(int j=0;j<maxcount;j++) {
154                 if (needcomma)
155                     outvirtual.print(", ");
156                 if (virtualtable[i][j]!=null) {
157                     MethodDescriptor md=virtualtable[i][j];
158                     outvirtual.print("& "+md.getClassDesc().getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor());
159                 } else {
160                     outvirtual.print("0");
161                 }
162                 needcomma=true;
163             }
164             outvirtual.println("");
165         }
166         outvirtual.println("};");
167         outvirtual.close();
168     }
169
170     private void fillinRow(ClassDescriptor cd, MethodDescriptor[][] virtualtable, int rownum) {
171         /* Get inherited methods */
172         if (cd.getSuperDesc()!=null)
173             fillinRow(cd.getSuperDesc(), virtualtable, rownum);
174         /* Override them with our methods */
175         for(Iterator it=cd.getMethods();it.hasNext();) {
176             MethodDescriptor md=(MethodDescriptor)it.next();
177             if (md.isStatic()||md.getReturnType()==null)
178                 continue;
179             int methodnum=virtualcalls.getMethodNumber(md);
180             virtualtable[rownum][methodnum]=md;
181         }
182     }
183
184     private void generateSizeArray(PrintWriter outclassdefs) {
185         outclassdefs.print("int classsize[]={");
186         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
187         ClassDescriptor[] cdarray=new ClassDescriptor[state.numClasses()];
188         while(it.hasNext()) {
189             ClassDescriptor cd=(ClassDescriptor)it.next();
190             cdarray[cd.getId()]=cd;
191         }
192         boolean needcomma=false;
193         for(int i=0;i<state.numClasses();i++) {
194             if (needcomma)
195                 outclassdefs.print(", ");
196             outclassdefs.print("sizeof(struct "+cdarray[i].getSafeSymbol()+")");            
197             needcomma=true;
198         }
199
200         TypeDescriptor[] sizetable=new TypeDescriptor[state.numArrays()];
201
202         Iterator arrayit=state.getArrayIterator();
203         while(arrayit.hasNext()) {
204             TypeDescriptor td=(TypeDescriptor)arrayit.next();
205             int id=state.getArrayNumber(td);
206             sizetable[id]=td;
207         }
208         
209         for(int i=0;i<state.numArrays();i++) {
210             if (needcomma)
211                 outclassdefs.print(", ");
212             TypeDescriptor tdelement=sizetable[i].dereference();
213             if (tdelement.isArray()||tdelement.isClass())
214                 outclassdefs.print("sizeof(void *)");
215             else
216                 outclassdefs.print("sizeof("+tdelement.getSafeSymbol()+")");
217             needcomma=true;
218         }
219
220         outclassdefs.println("};");
221     }
222
223     private void generateTempStructs(FlatMethod fm) {
224         MethodDescriptor md=fm.getMethod();
225         ParamsObject objectparams=new ParamsObject(md,tag++);
226         paramstable.put(md, objectparams);
227         for(int i=0;i<fm.numParameters();i++) {
228             TempDescriptor temp=fm.getParameter(i);
229             TypeDescriptor type=temp.getType();
230             if (type.isPtr()&&GENERATEPRECISEGC)
231                 objectparams.addPtr(temp);
232             else
233                 objectparams.addPrim(temp);
234         }
235
236         TempObject objecttemps=new TempObject(objectparams,md,tag++);
237         tempstable.put(md, objecttemps);
238         for(Iterator nodeit=fm.getNodeSet().iterator();nodeit.hasNext();) {
239             FlatNode fn=(FlatNode)nodeit.next();
240             TempDescriptor[] writes=fn.writesTemps();
241             for(int i=0;i<writes.length;i++) {
242                 TempDescriptor temp=writes[i];
243                 TypeDescriptor type=temp.getType();
244                 if (type.isPtr()&&GENERATEPRECISEGC)
245                     objecttemps.addPtr(temp);
246                 else
247                     objecttemps.addPrim(temp);
248             }
249         }
250     }
251     
252     /* Force consistent field ordering between inherited classes */
253     private void printClassStruct(ClassDescriptor cn, PrintWriter classdefout) {
254         ClassDescriptor sp=cn.getSuperDesc();
255         if (sp!=null)
256             printClassStruct(sp, classdefout);
257         
258         if (!fieldorder.containsKey(cn)) {
259             Vector fields=new Vector();
260             fieldorder.put(cn,fields);
261             Iterator fieldit=cn.getFields();
262             while(fieldit.hasNext()) {
263                 FieldDescriptor fd=(FieldDescriptor)fieldit.next();
264                 if (sp==null||!sp.getFieldTable().contains(fd.getSymbol()))
265                     fields.add(fd);
266             }
267         }
268         Vector fields=(Vector)fieldorder.get(cn);
269
270         for(int i=0;i<fields.size();i++) {
271             FieldDescriptor fd=(FieldDescriptor)fields.get(i);
272             if (fd.getType().isClass()||fd.getType().isArray())
273                 classdefout.println("  struct "+fd.getType().getSafeSymbol()+" * "+fd.getSafeSymbol()+";");
274             else 
275                 classdefout.println("  "+fd.getType().getSafeSymbol()+" "+fd.getSafeSymbol()+";");
276         }
277     }
278
279     private void generateCallStructs(ClassDescriptor cn, PrintWriter classdefout, PrintWriter output, PrintWriter headersout) {
280         /* Output class structure */
281         classdefout.println("struct "+cn.getSafeSymbol()+" {");
282         classdefout.println("  int type;");
283         printClassStruct(cn, classdefout);
284         classdefout.println("};\n");
285
286         /* Cycle through methods */
287         Iterator methodit=cn.getMethods();
288         while(methodit.hasNext()) {
289             /* Classify parameters */
290             MethodDescriptor md=(MethodDescriptor)methodit.next();
291             FlatMethod fm=state.getMethodFlat(md);
292             generateTempStructs(fm);
293
294             ParamsObject objectparams=(ParamsObject) paramstable.get(md);
295             TempObject objecttemps=(TempObject) tempstable.get(md);
296
297             /* Output parameter structure */
298             if (GENERATEPRECISEGC) {
299                 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params {");
300                 output.println("  int type;");
301                 output.println("  void * next;");
302                 for(int i=0;i<objectparams.numPointers();i++) {
303                     TempDescriptor temp=objectparams.getPointer(i);
304                     output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
305                 }
306                 output.println("};\n");
307             }
308
309             /* Output temp structure */
310             if (GENERATEPRECISEGC) {
311                 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals {");
312                 output.println("  int type;");
313                 output.println("  void * next;");
314                 for(int i=0;i<objecttemps.numPointers();i++) {
315                     TempDescriptor temp=objecttemps.getPointer(i);
316                     if (temp.getType().isNull())
317                         output.println("  void * "+temp.getSafeSymbol()+";");
318                     else
319                         output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
320                 }
321                 output.println("};\n");
322             }
323             
324             /* Output method declaration */
325             if (md.getReturnType()!=null) {
326                 if (md.getReturnType().isClass()||md.getReturnType().isArray())
327                     headersout.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
328                 else
329                     headersout.print(md.getReturnType().getSafeSymbol()+" ");
330             } else 
331                 //catch the constructor case
332                 headersout.print("void ");
333             headersout.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
334             
335             boolean printcomma=false;
336             if (GENERATEPRECISEGC) {
337                 headersout.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
338                 printcomma=true;
339             }
340
341             for(int i=0;i<objectparams.numPrimitives();i++) {
342                 TempDescriptor temp=objectparams.getPrimitive(i);
343                 if (printcomma)
344                     headersout.print(", ");
345                 printcomma=true;
346                 if (temp.getType().isClass()||temp.getType().isArray())
347                     headersout.print("struct " + temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
348                 else
349                     headersout.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
350             }
351             headersout.println(");\n");
352         }
353     }
354
355     private void generateFlatMethod(FlatMethod fm, PrintWriter output) {
356         MethodDescriptor md=fm.getMethod();
357         ClassDescriptor cn=md.getClassDesc();
358         ParamsObject objectparams=(ParamsObject)paramstable.get(md);
359
360         generateHeader(md,output);
361         /* Print code */
362         output.println(" {");
363         
364         if (GENERATEPRECISEGC) {
365             output.println("   struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals "+localsprefix+";");
366         }
367         TempObject objecttemp=(TempObject) tempstable.get(md);
368         for(int i=0;i<objecttemp.numPrimitives();i++) {
369             TempDescriptor td=objecttemp.getPrimitive(i);
370             TypeDescriptor type=td.getType();
371             if (type.isNull())
372                 output.println("   void * "+td.getSafeSymbol()+";");
373             else if (type.isClass()||type.isArray())
374                 output.println("   struct "+type.getSafeSymbol()+" * "+td.getSafeSymbol()+";");
375             else
376                 output.println("   "+type.getSafeSymbol()+" "+td.getSafeSymbol()+";");
377         }
378         
379
380         /* Generate labels first */
381         HashSet tovisit=new HashSet();
382         HashSet visited=new HashSet();
383         int labelindex=0;
384         Hashtable nodetolabel=new Hashtable();
385         tovisit.add(fm.methodEntryNode());
386         FlatNode current_node=null;
387
388         //Assign labels 1st
389         //Node needs a label if it is
390         while(!tovisit.isEmpty()) {
391             FlatNode fn=(FlatNode)tovisit.iterator().next();
392             tovisit.remove(fn);
393             visited.add(fn);
394             for(int i=0;i<fn.numNext();i++) {
395                 FlatNode nn=fn.getNext(i);
396                 if(i>0) {
397                     //1) Edge >1 of node
398                     nodetolabel.put(nn,new Integer(labelindex++));
399                 }
400                 if (!visited.contains(nn)&&!tovisit.contains(nn)) {
401                     tovisit.add(nn);
402                 } else {
403                     //2) Join point
404                     nodetolabel.put(nn,new Integer(labelindex++));
405                 }
406             }
407         }
408
409         //Do the actual code generation
410         tovisit=new HashSet();
411         visited=new HashSet();
412         tovisit.add(fm.methodEntryNode());
413         while(current_node!=null||!tovisit.isEmpty()) {
414             if (current_node==null) {
415                 current_node=(FlatNode)tovisit.iterator().next();
416                 tovisit.remove(current_node);
417             }
418             visited.add(current_node);
419             if (nodetolabel.containsKey(current_node))
420                 output.println("L"+nodetolabel.get(current_node)+":");
421             if (current_node.numNext()==0) {
422                 output.print("   ");
423                 generateFlatNode(fm, current_node, output);
424                 if (current_node.kind()!=FKind.FlatReturnNode) {
425                     output.println("   return;");
426                 }
427                 current_node=null;
428             } else if(current_node.numNext()==1) {
429                 output.print("   ");
430                 generateFlatNode(fm, current_node, output);
431                 FlatNode nextnode=current_node.getNext(0);
432                 if (visited.contains(nextnode)) {
433                     output.println("goto L"+nodetolabel.get(nextnode)+";");
434                     current_node=null;
435                 } else
436                     current_node=nextnode;
437             } else if (current_node.numNext()==2) {
438                 /* Branch */
439                 output.print("   ");
440                 generateFlatCondBranch(fm, (FlatCondBranch)current_node, "L"+nodetolabel.get(current_node.getNext(1)), output);
441                 if (!visited.contains(current_node.getNext(1)))
442                     tovisit.add(current_node.getNext(1));
443                 if (visited.contains(current_node.getNext(0))) {
444                     output.println("goto L"+nodetolabel.get(current_node.getNext(0))+";");
445                     current_node=null;
446                 } else
447                     current_node=current_node.getNext(0);
448             } else throw new Error();
449         }
450         output.println("}\n\n");
451     }
452
453     private String generateTemp(FlatMethod fm, TempDescriptor td) {
454         MethodDescriptor md=fm.getMethod();
455         TempObject objecttemps=(TempObject) tempstable.get(md);
456         if (objecttemps.isLocalPrim(td)||objecttemps.isParamPrim(td)) {
457             return td.getSafeSymbol();
458         }
459
460         if (objecttemps.isLocalPtr(td)) {
461             return localsprefix+"."+td.getSafeSymbol();
462         }
463
464         if (objecttemps.isParamPtr(td)) {
465             return paramsprefix+"->"+td.getSafeSymbol();
466         }
467         throw new Error();
468     }
469
470     private void generateFlatNode(FlatMethod fm, FlatNode fn, PrintWriter output) {
471         switch(fn.kind()) {
472         case FKind.FlatCall:
473             generateFlatCall(fm, (FlatCall) fn,output);
474             return;
475         case FKind.FlatFieldNode:
476             generateFlatFieldNode(fm, (FlatFieldNode) fn,output);
477             return;
478         case FKind.FlatElementNode:
479             generateFlatElementNode(fm, (FlatElementNode) fn,output);
480             return;
481         case FKind.FlatSetElementNode:
482             generateFlatSetElementNode(fm, (FlatSetElementNode) fn,output);
483             return;
484         case FKind.FlatSetFieldNode:
485             generateFlatSetFieldNode(fm, (FlatSetFieldNode) fn,output);
486             return;
487         case FKind.FlatNew:
488             generateFlatNew(fm, (FlatNew) fn,output);
489             return;
490         case FKind.FlatOpNode:
491             generateFlatOpNode(fm, (FlatOpNode) fn,output);
492             return;
493         case FKind.FlatCastNode:
494             generateFlatCastNode(fm, (FlatCastNode) fn,output);
495             return;
496         case FKind.FlatLiteralNode:
497             generateFlatLiteralNode(fm, (FlatLiteralNode) fn,output);
498             return;
499         case FKind.FlatReturnNode:
500             generateFlatReturnNode(fm, (FlatReturnNode) fn,output);
501             return;
502         case FKind.FlatNop:
503             output.println("/* nop */");
504             return;
505         }
506         throw new Error();
507
508     }
509
510     private void generateFlatCall(FlatMethod fm, FlatCall fc, PrintWriter output) {
511         MethodDescriptor md=fc.getMethod();
512         ParamsObject objectparams=(ParamsObject) paramstable.get(md);
513         ClassDescriptor cn=md.getClassDesc();
514         output.println("{");
515         if (GENERATEPRECISEGC) {
516             output.print("       struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params __parameterlist__={");
517             
518             output.print(objectparams.getUID());
519             output.print(", & "+localsprefix);
520             if (fc.getThis()!=null) {
521                 output.print(", ");
522                 output.print(generateTemp(fm,fc.getThis()));
523             }
524             for(int i=0;i<fc.numArgs();i++) {
525                 VarDescriptor var=md.getParameter(i);
526                 TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
527                 if (objectparams.isParamPtr(paramtemp)) {
528                     TempDescriptor targ=fc.getArg(i);
529                     output.print(", ");
530                     output.print(generateTemp(fm, targ));
531                 }
532             }
533             output.println("};");
534         }
535         output.print("       ");
536
537
538         if (fc.getReturnTemp()!=null)
539             output.print(generateTemp(fm,fc.getReturnTemp())+"=");
540         if (md.isStatic()||md.getReturnType()==null||singleCall(fc.getThis().getType().getClassDesc(),md)) {
541             output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor());
542         } else {
543             
544             output.print("((");
545             if (md.getReturnType().isClass()||md.getReturnType().isArray())
546                 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
547             else
548                 output.print(md.getReturnType().getSafeSymbol()+" ");
549             output.print("(*)(");
550
551             boolean printcomma=false;
552             if (GENERATEPRECISEGC) {
553                 output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * ");
554                 printcomma=true;
555             } 
556
557
558             for(int i=0;i<objectparams.numPrimitives();i++) {
559                 TempDescriptor temp=objectparams.getPrimitive(i);
560                 if (printcomma)
561                     output.print(", ");
562                 printcomma=true;
563                 if (temp.getType().isClass()||temp.getType().isArray())
564                     output.print("struct " + temp.getType().getSafeSymbol()+" * ");
565                 else
566                     output.print(temp.getType().getSafeSymbol());
567             }
568
569             output.print("))virtualtable["+generateTemp(fm,fc.getThis())+"->type*"+maxcount+"+"+virtualcalls.getMethodNumber(md)+"])");
570         }
571
572         output.print("(");
573         boolean needcomma=false;
574         if (GENERATEPRECISEGC) {
575             output.print("&__parameterlist__");
576             needcomma=true;
577         } else {
578             if (fc.getThis()!=null) {
579                 output.print(generateTemp(fm,fc.getThis()));
580                 needcomma=true;
581             }
582         }
583         for(int i=0;i<fc.numArgs();i++) {
584             VarDescriptor var=md.getParameter(i);
585             TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
586             if (objectparams.isParamPrim(paramtemp)) {
587                 TempDescriptor targ=fc.getArg(i);
588                 if (needcomma)
589                     output.print(", ");
590                 output.print(generateTemp(fm, targ));
591                 needcomma=true;
592             }
593         }
594         output.println(");");
595         output.println("   }");
596     }
597
598     private boolean singleCall(ClassDescriptor thiscd, MethodDescriptor md) {
599         Set subclasses=typeutil.getSubClasses(thiscd);
600         if (subclasses==null)
601             return true;
602         for(Iterator classit=subclasses.iterator();classit.hasNext();) {
603             ClassDescriptor cd=(ClassDescriptor)classit.next();
604             Set possiblematches=cd.getMethodTable().getSet(md.getSymbol());
605             for(Iterator matchit=possiblematches.iterator();matchit.hasNext();) {
606                 MethodDescriptor matchmd=(MethodDescriptor)matchit.next();
607                 if (md.matches(matchmd))
608                     return false;
609             }
610         }
611         return true;
612     }
613
614     private void generateFlatFieldNode(FlatMethod fm, FlatFieldNode ffn, PrintWriter output) {
615         output.println(generateTemp(fm, ffn.getDst())+"="+ generateTemp(fm,ffn.getSrc())+"->"+ ffn.getField().getSafeSymbol()+";");
616     }
617
618     private void generateFlatSetFieldNode(FlatMethod fm, FlatSetFieldNode fsfn, PrintWriter output) {
619         output.println(generateTemp(fm, fsfn.getDst())+"->"+ fsfn.getField().getSafeSymbol()+"="+ generateTemp(fm,fsfn.getSrc())+";");
620     }
621
622     private void generateFlatElementNode(FlatMethod fm, FlatElementNode fen, PrintWriter output) {
623         TypeDescriptor elementtype=fen.getSrc().getType().dereference();
624         String type="";
625
626         if (elementtype.isArray()||elementtype.isClass())
627             type="void *";
628         else 
629             type=elementtype.getSafeSymbol()+" ";
630         output.println(generateTemp(fm, fen.getDst())+"=(("+ type+"*)(((char *) &("+ generateTemp(fm,fen.getSrc())+"->length))+sizeof(int)))["+generateTemp(fm, fen.getIndex())+"];");
631     }
632
633     private void generateFlatSetElementNode(FlatMethod fm, FlatSetElementNode fsen, PrintWriter output) {
634         //TODO: need dynamic check to make sure this assignment is actually legal
635         //Because Object[] could actually be something more specific...ie. Integer[]
636         TypeDescriptor elementtype=fsen.getDst().getType().dereference();
637         String type="";
638
639         if (elementtype.isArray()||elementtype.isClass())
640             type="void *";
641         else 
642             type=elementtype.getSafeSymbol()+" ";
643
644         output.println("(("+type +"*)(((char *) &("+ generateTemp(fm,fsen.getDst())+"->length))+sizeof(int)))["+generateTemp(fm, fsen.getIndex())+"]="+generateTemp(fm,fsen.getSrc())+";");
645     }
646
647     private void generateFlatNew(FlatMethod fm, FlatNew fn, PrintWriter output) {
648         if (fn.getType().isArray()) {
649             int arrayid=state.getArrayNumber(fn.getType())+state.numClasses();
650             output.println(generateTemp(fm,fn.getDst())+"=allocate_newarray("+arrayid+", "+generateTemp(fm, fn.getSize())+");");
651         } else
652             output.println(generateTemp(fm,fn.getDst())+"=allocate_new("+fn.getType().getClassDesc().getId()+");");
653     }
654
655     private void generateFlatOpNode(FlatMethod fm, FlatOpNode fon, PrintWriter output) {
656
657         if (fon.getRight()!=null)
658             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+fon.getOp().toString()+generateTemp(fm,fon.getRight())+";");
659         else if (fon.getOp().getOp()==Operation.ASSIGN)
660             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
661         else if (fon.getOp().getOp()==Operation.UNARYPLUS)
662             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
663         else if (fon.getOp().getOp()==Operation.UNARYMINUS)
664             output.println(generateTemp(fm, fon.getDest())+" = -"+generateTemp(fm, fon.getLeft())+";");
665         else if (fon.getOp().getOp()==Operation.POSTINC)
666             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+"++;");
667         else if (fon.getOp().getOp()==Operation.POSTDEC)
668             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+"--;");
669         else if (fon.getOp().getOp()==Operation.PREINC)
670             output.println(generateTemp(fm, fon.getDest())+" = ++"+generateTemp(fm, fon.getLeft())+";");
671         else if (fon.getOp().getOp()==Operation.PREDEC)
672             output.println(generateTemp(fm, fon.getDest())+" = --"+generateTemp(fm, fon.getLeft())+";");
673         else
674             output.println(generateTemp(fm, fon.getDest())+fon.getOp().toString()+generateTemp(fm, fon.getLeft())+";");
675     }
676
677     private void generateFlatCastNode(FlatMethod fm, FlatCastNode fcn, PrintWriter output) {
678         /* TODO: Do type check here */
679         output.println(generateTemp(fm,fcn.getDst())+"=("+fcn.getType().getSafeSymbol()+")"+generateTemp(fm,fcn.getSrc())+";");
680     }
681
682     private void generateFlatLiteralNode(FlatMethod fm, FlatLiteralNode fln, PrintWriter output) {
683         if (fln.getValue()==null)
684             output.println(generateTemp(fm, fln.getDst())+"=0;");
685         else if (fln.getType().getSymbol().equals(TypeUtil.StringClass))
686             output.println(generateTemp(fm, fln.getDst())+"=newstring(\""+FlatLiteralNode.escapeString((String)fln.getValue())+"\");");
687         else if (fln.getType().isBoolean()) {
688             if (((Boolean)fln.getValue()).booleanValue())
689                 output.println(generateTemp(fm, fln.getDst())+"=1;");
690             else
691                 output.println(generateTemp(fm, fln.getDst())+"=0;");
692         } else
693             output.println(generateTemp(fm, fln.getDst())+"="+fln.getValue()+";");
694     }
695
696     private void generateFlatReturnNode(FlatMethod fm, FlatReturnNode frn, PrintWriter output) {
697         if (frn.getReturnTemp()!=null)
698             output.println("return "+generateTemp(fm, frn.getReturnTemp())+";");
699         else
700             output.println("return;");
701     }
702
703     private void generateFlatCondBranch(FlatMethod fm, FlatCondBranch fcb, String label, PrintWriter output) {
704         output.println("if (!"+generateTemp(fm, fcb.getTest())+") goto "+label+";");
705     }
706
707     private void generateHeader(MethodDescriptor md, PrintWriter output) {
708         /* Print header */
709         ParamsObject objectparams=(ParamsObject)paramstable.get(md);
710         ClassDescriptor cn=md.getClassDesc();
711         
712         if (md.getReturnType()!=null) {
713             if (md.getReturnType().isClass()||md.getReturnType().isArray())
714                 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
715             else
716                 output.print(md.getReturnType().getSafeSymbol()+" ");
717         } else 
718             //catch the constructor case
719             output.print("void ");
720
721         output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
722         
723         boolean printcomma=false;
724         if (GENERATEPRECISEGC) {
725             output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
726             printcomma=true;
727         } 
728
729         for(int i=0;i<objectparams.numPrimitives();i++) {
730             TempDescriptor temp=objectparams.getPrimitive(i);
731             if (printcomma)
732                 output.print(", ");
733             printcomma=true;
734             if (temp.getType().isClass()||temp.getType().isArray())
735                 output.print("struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
736             else
737                 output.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
738         }
739         output.print(")");
740     }
741 }