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