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