2 import IR.Tree.FlagExpressionNode;
3 import IR.Tree.DNFFlag;
4 import IR.Tree.DNFFlagAtom;
9 public class BuildCode {
12 Hashtable paramstable;
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";
26 public BuildCode(State st, Hashtable temptovar, TypeUtil typeutil) {
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);
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. */
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;
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) {
65 /* Build the virtual dispatch tables */
67 buildVirtualTables(outvirtual);
70 outstructs.println("#include \"classdefs.h\"");
71 outmethodheader.println("#include \"structdefs.h\"");
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()));
78 // Output the C class declarations
79 // These could mutually reference each other
80 outclassdefs.println("struct "+arraytype+";");
82 Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
84 ClassDescriptor cn=(ClassDescriptor)it.next();
85 outclassdefs.println("struct "+cn.getSafeSymbol()+";");
87 outclassdefs.println("");
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");
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("};");
104 outclassdefs.println("struct taskdescriptor {");
105 outclassdefs.println("void * taskptr;");
106 outclassdefs.println("int numParameters;");
107 outclassdefs.println("struct parameterdescriptor **descriptorarray;");
108 outclassdefs.println("};");
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);
119 outmethodheader.close();
122 /* Map flags to integers */
123 it=state.getClassSymbolTable().getDescriptorsIterator();
124 while(it.hasNext()) {
125 ClassDescriptor cn=(ClassDescriptor)it.next();
129 generateTaskStructs(outstructs, outmethodheader);
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[];");
138 //Store the sizes of classes & array elements
139 generateSizeArray(outmethod);
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);
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);
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)
172 if (!md.getModifiers().isStatic())
173 throw new Error("Error: Non static main");
174 outmethod.println(" "+cd.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"();");
177 outmethod.println("}");
182 private int maxcount=0;
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();
192 Hashtable flags=(Hashtable)flagorder.get(param_type.getClassDesc());
194 output.println("int [] parameterdnf_"+i+"_"+task.getSafeSymbol()+"={");
195 for(int j=0;j<dflag.size();j++) {
198 Vector term=dflag.get(j);
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();
210 output.print(andmask+", "+checkmask);
212 output.println("};");
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("¶meterdnf_"+i+"_"+task.getSafeSymbol());
218 output.println("};");
222 output.println("struct * parameterdescriptor parameterdescriptors_"+task.getSafeSymbol()+" [] = {");
223 for (int i=0;i<task.numParameters();i++) {
226 output.print("¶meter_"+i+"_"+task.getSafeSymbol());
228 output.println("};");
230 output.println("struct taskdescriptor task_"+task.getSafeSymbol()+"={");
231 output.println("&"+task.getSafeSymbol()+",");
232 output.println("/* number of parameters */" +task.numParameters() + ",");
233 output.println("¶meterdescriptors_"+task.getSafeSymbol());
234 output.println("};");
238 /** The buildVirtualTables method outputs the virtual dispatch
239 * tables for methods. */
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);
248 MethodDescriptor[][] virtualtable=new MethodDescriptor[state.numClasses()+state.numArrays()][maxcount];
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());
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());
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++) {
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());
275 outvirtual.print("0");
279 outvirtual.println("");
281 outvirtual.println("};");
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)
294 int methodnum=virtualcalls.getMethodNumber(md);
295 virtualtable[rownum][methodnum]=md;
299 /** Generate array that contains the sizes of class objects. The
300 * object allocation functions in the runtime use this
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;
311 boolean needcomma=false;
312 for(int i=0;i<state.numClasses();i++) {
314 outclassdefs.print(", ");
315 outclassdefs.print("sizeof(struct "+cdarray[i].getSafeSymbol()+")");
319 TypeDescriptor[] sizetable=new TypeDescriptor[state.numArrays()];
321 Iterator arrayit=state.getArrayIterator();
322 while(arrayit.hasNext()) {
323 TypeDescriptor td=(TypeDescriptor)arrayit.next();
324 int id=state.getArrayNumber(td);
328 for(int i=0;i<state.numArrays();i++) {
330 outclassdefs.print(", ");
331 TypeDescriptor tdelement=sizetable[i].dereference();
332 if (tdelement.isArray()||tdelement.isClass())
333 outclassdefs.print("sizeof(void *)");
335 outclassdefs.print("sizeof("+tdelement.getSafeSymbol()+")");
339 outclassdefs.println("};");
342 /** Constructs params and temp objects for each method or task.
343 * These objects tell the compiler which temps need to be
346 private void generateTempStructs(FlatMethod fm) {
347 MethodDescriptor md=fm.getMethod();
348 TaskDescriptor task=fm.getTask();
350 ParamsObject objectparams=md!=null?new ParamsObject(md,tag++):new ParamsObject(task, tag++);
352 paramstable.put(md, objectparams);
354 paramstable.put(task, objectparams);
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);
362 objectparams.addPrim(temp);
365 TempObject objecttemps=md!=null?new TempObject(objectparams,md,tag++):new TempObject(objectparams, task, tag++);
367 tempstable.put(md, objecttemps);
369 tempstable.put(task, objecttemps);
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);
380 objecttemps.addPrim(temp);
385 /* Force consistent field ordering between inherited classes. */
387 private void printClassStruct(ClassDescriptor cn, PrintWriter classdefout) {
388 ClassDescriptor sp=cn.getSuperDesc();
390 printClassStruct(sp, classdefout);
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()))
402 Vector fields=(Vector)fieldorder.get(cn);
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()+";");
409 classdefout.println(" "+fd.getType().getSafeSymbol()+" "+fd.getSafeSymbol()+";");
414 /* Map flags to integers consistently between inherited
417 private void mapFlags(ClassDescriptor cn) {
418 ClassDescriptor sp=cn.getSuperDesc();
422 if (!flagorder.containsKey(cn)) {
423 Hashtable flags=new Hashtable();
424 flagorder.put(cn,flags);
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();
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));
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 */
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");
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);
465 ParamsObject objectparams=(ParamsObject) paramstable.get(md);
466 TempObject objecttemps=(TempObject) tempstable.get(md);
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()+";");
477 output.println("};\n");
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()+";");
490 output.println(" struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
492 output.println("};\n");
495 /* Output method declaration */
496 if (md.getReturnType()!=null) {
497 if (md.getReturnType().isClass()||md.getReturnType().isArray())
498 headersout.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
500 headersout.print(md.getReturnType().getSafeSymbol()+" ");
502 //catch the constructor case
503 headersout.print("void ");
504 headersout.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
506 boolean printcomma=false;
507 if (GENERATEPRECISEGC) {
508 headersout.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
512 //output parameter list
513 for(int i=0;i<objectparams.numPrimitives();i++) {
514 TempDescriptor temp=objectparams.getPrimitive(i);
516 headersout.print(", ");
518 if (temp.getType().isClass()||temp.getType().isArray())
519 headersout.print("struct " + temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
521 headersout.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
523 headersout.println(");\n");
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 */
532 private void generateTaskStructs(PrintWriter output, PrintWriter headersout) {
533 /* Cycle through tasks */
534 Iterator taskit=state.getTaskSymbolTable().getDescriptorsIterator();
536 while(taskit.hasNext()) {
537 /* Classify parameters */
538 TaskDescriptor task=(TaskDescriptor)taskit.next();
539 FlatMethod fm=state.getMethodFlat(task);
540 generateTempStructs(fm);
542 ParamsObject objectparams=(ParamsObject) paramstable.get(task);
543 TempObject objecttemps=(TempObject) tempstable.get(task);
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()+";");
554 output.println("};\n");
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()+";");
567 output.println(" struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
569 output.println("};\n");
572 /* Output task declaration */
573 headersout.print("void " + task.getSafeSymbol()+"_"+"(");
575 boolean printcomma=false;
576 if (GENERATEPRECISEGC) {
577 headersout.print("struct "+task.getSafeSymbol()+"_params * "+paramsprefix);
581 //output parameter list
582 for(int i=0;i<objectparams.numPrimitives();i++) {
583 TempDescriptor temp=objectparams.getPrimitive(i);
585 headersout.print(", ");
587 if (temp.getType().isClass()||temp.getType().isArray())
588 headersout.print("struct " + temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
590 headersout.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
592 headersout.println(");\n");
596 /** Generate code for flatmethod fm. */
598 private void generateFlatMethod(FlatMethod fm, PrintWriter output) {
599 MethodDescriptor md=fm.getMethod();
600 TaskDescriptor task=fm.getTask();
602 ClassDescriptor cn=md!=null?md.getClassDesc():null;
604 ParamsObject objectparams=(ParamsObject)paramstable.get(md!=null?md:task);
606 generateHeader(md!=null?md:task,output);
609 output.println(" {");
611 if (GENERATEPRECISEGC) {
613 output.println(" struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals "+localsprefix+";");
615 output.println(" struct "+task.getSafeSymbol()+"_locals "+localsprefix+";");
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();
622 output.println(" void * "+td.getSafeSymbol()+";");
623 else if (type.isClass()||type.isArray())
624 output.println(" struct "+type.getSafeSymbol()+" * "+td.getSafeSymbol()+";");
626 output.println(" "+type.getSafeSymbol()+" "+td.getSafeSymbol()+";");
630 /* Generate labels first */
631 HashSet tovisit=new HashSet();
632 HashSet visited=new HashSet();
634 Hashtable nodetolabel=new Hashtable();
635 tovisit.add(fm.methodEntryNode());
636 FlatNode current_node=null;
639 //Node needs a label if it is
640 while(!tovisit.isEmpty()) {
641 FlatNode fn=(FlatNode)tovisit.iterator().next();
644 for(int i=0;i<fn.numNext();i++) {
645 FlatNode nn=fn.getNext(i);
648 nodetolabel.put(nn,new Integer(labelindex++));
650 if (!visited.contains(nn)&&!tovisit.contains(nn)) {
654 nodetolabel.put(nn,new Integer(labelindex++));
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);
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) {
673 generateFlatNode(fm, current_node, output);
674 if (current_node.kind()!=FKind.FlatReturnNode) {
675 output.println(" return;");
678 } else if(current_node.numNext()==1) {
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)+";");
686 current_node=nextnode;
687 } else if (current_node.numNext()==2) {
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))+";");
697 current_node=current_node.getNext(0);
698 } else throw new Error();
700 output.println("}\n\n");
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();
712 if (objecttemps.isLocalPtr(td)) {
713 return localsprefix+"."+td.getSafeSymbol();
716 if (objecttemps.isParamPtr(td)) {
717 return paramsprefix+"->"+td.getSafeSymbol();
722 private void generateFlatNode(FlatMethod fm, FlatNode fn, PrintWriter output) {
725 generateFlatCall(fm, (FlatCall) fn,output);
727 case FKind.FlatFieldNode:
728 generateFlatFieldNode(fm, (FlatFieldNode) fn,output);
730 case FKind.FlatElementNode:
731 generateFlatElementNode(fm, (FlatElementNode) fn,output);
733 case FKind.FlatSetElementNode:
734 generateFlatSetElementNode(fm, (FlatSetElementNode) fn,output);
736 case FKind.FlatSetFieldNode:
737 generateFlatSetFieldNode(fm, (FlatSetFieldNode) fn,output);
740 generateFlatNew(fm, (FlatNew) fn,output);
742 case FKind.FlatOpNode:
743 generateFlatOpNode(fm, (FlatOpNode) fn,output);
745 case FKind.FlatCastNode:
746 generateFlatCastNode(fm, (FlatCastNode) fn,output);
748 case FKind.FlatLiteralNode:
749 generateFlatLiteralNode(fm, (FlatLiteralNode) fn,output);
751 case FKind.FlatReturnNode:
752 generateFlatReturnNode(fm, (FlatReturnNode) fn,output);
755 output.println("/* nop */");
757 case FKind.FlatFlagActionNode:
758 generateFlatFlagActionNode(fm, (FlatFlagActionNode) fn, output);
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();
770 if (GENERATEPRECISEGC) {
771 output.print(" struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params __parameterlist__={");
773 output.print(objectparams.getUID());
774 output.print(", & "+localsprefix);
775 if (fc.getThis()!=null) {
777 output.print(generateTemp(fm,fc.getThis()));
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);
785 output.print(generateTemp(fm, targ));
788 output.println("};");
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());
800 if (md.getReturnType().isClass()||md.getReturnType().isArray())
801 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
803 output.print(md.getReturnType().getSafeSymbol()+" ");
804 output.print("(*)(");
806 boolean printcomma=false;
807 if (GENERATEPRECISEGC) {
808 output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * ");
813 for(int i=0;i<objectparams.numPrimitives();i++) {
814 TempDescriptor temp=objectparams.getPrimitive(i);
818 if (temp.getType().isClass()||temp.getType().isArray())
819 output.print("struct " + temp.getType().getSafeSymbol()+" * ");
821 output.print(temp.getType().getSafeSymbol());
824 output.print("))virtualtable["+generateTemp(fm,fc.getThis())+"->type*"+maxcount+"+"+virtualcalls.getMethodNumber(md)+"])");
828 boolean needcomma=false;
829 if (GENERATEPRECISEGC) {
830 output.print("&__parameterlist__");
833 if (fc.getThis()!=null) {
834 output.print(generateTemp(fm,fc.getThis()));
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);
845 output.print(generateTemp(fm, targ));
849 output.println(");");
850 output.println(" }");
853 private boolean singleCall(ClassDescriptor thiscd, MethodDescriptor md) {
854 Set subclasses=typeutil.getSubClasses(thiscd);
855 if (subclasses==null)
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))
869 private void generateFlatFieldNode(FlatMethod fm, FlatFieldNode ffn, PrintWriter output) {
870 output.println(generateTemp(fm, ffn.getDst())+"="+ generateTemp(fm,ffn.getSrc())+"->"+ ffn.getField().getSafeSymbol()+";");
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())+";");
879 private void generateFlatElementNode(FlatMethod fm, FlatElementNode fen, PrintWriter output) {
880 TypeDescriptor elementtype=fen.getSrc().getType().dereference();
883 if (elementtype.isArray()||elementtype.isClass())
886 type=elementtype.getSafeSymbol()+" ";
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();");
893 output.println(generateTemp(fm, fen.getDst())+"=(("+ type+"*)(((char *) &("+ generateTemp(fm,fen.getSrc())+"->___length___))+sizeof(int)))["+generateTemp(fm, fen.getIndex())+"];");
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[]
900 TypeDescriptor elementtype=fsen.getDst().getType().dereference();
903 if (elementtype.isArray()||elementtype.isClass())
906 type=elementtype.getSafeSymbol()+" ";
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();");
913 output.println("(("+type +"*)(((char *) &("+ generateTemp(fm,fsen.getDst())+"->___length___))+sizeof(int)))["+generateTemp(fm, fsen.getIndex())+"]="+generateTemp(fm,fsen.getSrc())+";");
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())+");");
921 output.println(generateTemp(fm,fn.getDst())+"=allocate_new("+fn.getType().getClassDesc().getId()+");");
924 private void generateFlatOpNode(FlatMethod fm, FlatOpNode fon, PrintWriter output) {
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())+";");
937 output.println(generateTemp(fm, fon.getDest())+fon.getOp().toString()+generateTemp(fm, fon.getLeft())+";");
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())+";");
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;");
954 output.println(generateTemp(fm, fln.getDst())+"=0;");
955 } else if (fln.getType().isChar()) {
956 output.println(generateTemp(fm, fln.getDst())+"='"+fln.getValue()+"';");
958 output.println(generateTemp(fm, fln.getDst())+"="+fln.getValue()+";");
961 private void generateFlatReturnNode(FlatMethod fm, FlatReturnNode frn, PrintWriter output) {
962 if (frn.getReturnTemp()!=null)
963 output.println("return "+generateTemp(fm, frn.getReturnTemp())+";");
965 output.println("return;");
968 private void generateFlatCondBranch(FlatMethod fm, FlatCondBranch fcb, String label, PrintWriter output) {
969 output.println("if (!"+generateTemp(fm, fcb.getTest())+") goto "+label+";");
972 private void generateHeader(Descriptor des, PrintWriter output) {
974 ParamsObject objectparams=(ParamsObject)paramstable.get(des);
975 MethodDescriptor md=null;
976 TaskDescriptor task=null;
977 if (des instanceof MethodDescriptor)
978 md=(MethodDescriptor) des;
980 task=(TaskDescriptor) des;
982 ClassDescriptor cn=md!=null?md.getClassDesc():null;
984 if (md!=null&&md.getReturnType()!=null) {
985 if (md.getReturnType().isClass()||md.getReturnType().isArray())
986 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
988 output.print(md.getReturnType().getSafeSymbol()+" ");
990 //catch the constructor case
991 output.print("void ");
993 output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
995 output.print(task.getSafeSymbol()+"(");
997 boolean printcomma=false;
998 if (GENERATEPRECISEGC) {
1000 output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
1002 output.print("struct "+task.getSafeSymbol()+"_params * "+paramsprefix);
1006 for(int i=0;i<objectparams.numPrimitives();i++) {
1007 TempDescriptor temp=objectparams.getPrimitive(i);
1011 if (temp.getType().isClass()||temp.getType().isArray())
1012 output.print("struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
1014 output.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
1019 public void generateFlatFlagActionNode(FlatMethod fm, FlatFlagActionNode ffann, PrintWriter output) {
1020 output.print("/* FlatFlagActionNode will go here */");