aee789840c1fb451e8ec0655da59de782fcaaff5
[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     Virtual virtualcalls;
18
19     public BuildCode(State st, Hashtable temptovar) {
20         state=st;
21         this.temptovar=temptovar;
22         paramstable=new Hashtable();    
23         tempstable=new Hashtable();
24         fieldorder=new Hashtable();
25         virtualcalls=new Virtual(state);
26     }
27
28     public void buildCode() {
29         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
30         PrintWriter outclassdefs=null;
31         PrintWriter outstructs=null;
32         PrintWriter outmethodheader=null;
33         PrintWriter outmethod=null;
34         PrintWriter outvirtual=null;
35
36         try {
37             OutputStream str=new FileOutputStream(PREFIX+"structdefs.h");
38             outstructs=new java.io.PrintWriter(str, true);
39             str=new FileOutputStream(PREFIX+"methodheaders.h");
40             outmethodheader=new java.io.PrintWriter(str, true);
41             str=new FileOutputStream(PREFIX+"classdefs.h");
42             outclassdefs=new java.io.PrintWriter(str, true);
43             str=new FileOutputStream(PREFIX+"methods.c");
44             outmethod=new java.io.PrintWriter(str, true);
45             str=new FileOutputStream(PREFIX+"virtualtable.h");
46             outvirtual=new java.io.PrintWriter(str, true);
47         } catch (Exception e) {
48             e.printStackTrace();
49             System.exit(-1);
50         }
51
52         buildVirtualTables(outvirtual);
53         outstructs.println("#include \"classdefs.h\"");
54         outmethodheader.println("#include \"structdefs.h\"");
55
56         // Output the C declarations
57         // These could mutually reference each other
58         while(it.hasNext()) {
59             ClassDescriptor cn=(ClassDescriptor)it.next();
60             outclassdefs.println("struct "+cn.getSafeSymbol()+";");
61         }
62         outclassdefs.println("");
63
64         it=state.getClassSymbolTable().getDescriptorsIterator();
65         while(it.hasNext()) {
66             ClassDescriptor cn=(ClassDescriptor)it.next();
67             generateCallStructs(cn, outclassdefs, outstructs, outmethodheader);
68         }
69         outstructs.close();
70         outmethodheader.close();
71
72         /* Build the actual methods */
73         outmethod.println("#include \"methodheaders.h\"");
74         outmethod.println("#include \"virtualtable.h\"");
75         outmethod.println("#include <runtime.h>");
76         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
77         while(classit.hasNext()) {
78             ClassDescriptor cn=(ClassDescriptor)classit.next();
79             Iterator methodit=cn.getMethods();
80             while(methodit.hasNext()) {
81                 /* Classify parameters */
82                 MethodDescriptor md=(MethodDescriptor)methodit.next();
83                 FlatMethod fm=state.getMethodFlat(md);
84                 generateFlatMethod(fm,outmethod);
85             }
86         }
87         outmethod.close();
88     }
89
90     private void buildVirtualTables(PrintWriter outvirtual) {
91         int numclasses=0;
92         int maxcount=0;
93         Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
94         while(classit.hasNext()) {
95             ClassDescriptor cd=(ClassDescriptor)classit.next();
96             if (virtualcalls.getMethodCount(cd)>maxcount)
97                 maxcount=virtualcalls.getMethodCount(cd);
98             numclasses++;
99         }
100         MethodDescriptor[][] virtualtable=new MethodDescriptor[numclasses][maxcount];
101
102         /* Fill in virtual table */
103         classit=state.getClassSymbolTable().getDescriptorsIterator();
104         while(classit.hasNext()) {
105             ClassDescriptor cd=(ClassDescriptor)classit.next();
106             fillinRow(cd, virtualtable, cd.getId());
107         }
108         outvirtual.print("void * virtualtable[]={");
109         boolean needcomma=false;
110         for(int i=0;i<numclasses;i++) {
111             for(int j=0;j<maxcount;j++) {
112                 if (needcomma)
113                     outvirtual.print(", ");
114                 if (virtualtable[i][j]!=null) {
115                     MethodDescriptor md=virtualtable[i][j];
116                     outvirtual.print("& "+md.getClassDesc().getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor());
117                 } else {
118                     outvirtual.print("0");
119                 }
120                 needcomma=true;
121             }
122             outvirtual.println("");
123         }
124         outvirtual.println("};");
125         outvirtual.close();
126     }
127
128     private void fillinRow(ClassDescriptor cd, MethodDescriptor[][] virtualtable, int rownum) {
129         /* Get inherited methods */
130         if (cd.getSuperDesc()!=null)
131             fillinRow(cd.getSuperDesc(), virtualtable, rownum);
132         /* Override them with our methods */
133         for(Iterator it=cd.getMethods();it.hasNext();) {
134             MethodDescriptor md=(MethodDescriptor)it.next();
135             if (md.isStatic()||md.getReturnType()==null)
136                 continue;
137             int methodnum=virtualcalls.getMethodNumber(md);
138             virtualtable[rownum][methodnum]=md;
139         }
140     }
141
142     private void generateTempStructs(FlatMethod fm) {
143         MethodDescriptor md=fm.getMethod();
144         ParamsObject objectparams=new ParamsObject(md,tag++);
145         paramstable.put(md, objectparams);
146         for(int i=0;i<fm.numParameters();i++) {
147             TempDescriptor temp=fm.getParameter(i);
148             TypeDescriptor type=temp.getType();
149             if (type.isPtr()&&GENERATEPRECISEGC)
150                 objectparams.addPtr(temp);
151             else
152                 objectparams.addPrim(temp);
153         }
154
155         TempObject objecttemps=new TempObject(objectparams,md,tag++);
156         tempstable.put(md, objecttemps);
157         for(Iterator nodeit=fm.getNodeSet().iterator();nodeit.hasNext();) {
158             FlatNode fn=(FlatNode)nodeit.next();
159             TempDescriptor[] writes=fn.writesTemps();
160             for(int i=0;i<writes.length;i++) {
161                 TempDescriptor temp=writes[i];
162                 TypeDescriptor type=temp.getType();
163                 if (type.isPtr()&&GENERATEPRECISEGC)
164                     objecttemps.addPtr(temp);
165                 else
166                     objecttemps.addPrim(temp);
167             }
168         }
169     }
170     
171     /* Force consistent field ordering between inherited classes */
172     private void printClassStruct(ClassDescriptor cn, PrintWriter classdefout) {
173         ClassDescriptor sp=cn.getSuperDesc();
174         if (sp!=null)
175             printClassStruct(sp, classdefout);
176         
177         if (!fieldorder.containsKey(cn)) {
178             Vector fields=new Vector();
179             fieldorder.put(cn,fields);
180             Iterator fieldit=cn.getFields();
181             while(fieldit.hasNext()) {
182                 FieldDescriptor fd=(FieldDescriptor)fieldit.next();
183                 if (sp==null||!sp.getFieldTable().contains(fd.getSymbol()))
184                     fields.add(fd);
185             }
186         }
187         Vector fields=(Vector)fieldorder.get(cn);
188
189         for(int i=0;i<fields.size();i++) {
190             FieldDescriptor fd=(FieldDescriptor)fields.get(i);
191             if (fd.getType().isClass())
192                 classdefout.println("  struct "+fd.getType().getSafeSymbol()+" * "+fd.getSafeSymbol()+";");
193             else 
194                 classdefout.println("  "+fd.getType().getSafeSymbol()+" "+fd.getSafeSymbol()+";");
195         }
196     }
197
198     private void generateCallStructs(ClassDescriptor cn, PrintWriter classdefout, PrintWriter output, PrintWriter headersout) {
199         /* Output class structure */
200         classdefout.println("struct "+cn.getSafeSymbol()+" {");
201         classdefout.println("  int type;");
202         printClassStruct(cn, classdefout);
203         classdefout.println("};\n");
204
205         /* Cycle through methods */
206         Iterator methodit=cn.getMethods();
207         while(methodit.hasNext()) {
208             /* Classify parameters */
209             MethodDescriptor md=(MethodDescriptor)methodit.next();
210             FlatMethod fm=state.getMethodFlat(md);
211             generateTempStructs(fm);
212
213             ParamsObject objectparams=(ParamsObject) paramstable.get(md);
214             TempObject objecttemps=(TempObject) tempstable.get(md);
215
216             /* Output parameter structure */
217             if (GENERATEPRECISEGC) {
218                 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params {");
219                 output.println("  int type;");
220                 output.println("  void * next;");
221                 for(int i=0;i<objectparams.numPointers();i++) {
222                     TempDescriptor temp=objectparams.getPointer(i);
223                     output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
224                 }
225                 output.println("};\n");
226             }
227
228             /* Output temp structure */
229             if (GENERATEPRECISEGC) {
230                 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals {");
231                 output.println("  int type;");
232                 output.println("  void * next;");
233                 for(int i=0;i<objecttemps.numPointers();i++) {
234                     TempDescriptor temp=objecttemps.getPointer(i);
235                     if (temp.getType().isNull())
236                         output.println("  void * "+temp.getSafeSymbol()+";");
237                     else
238                         output.println("  struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
239                 }
240                 output.println("};\n");
241             }
242             
243             /* Output method declaration */
244             if (md.getReturnType()!=null) {
245                 if (md.getReturnType().isClass())
246                     headersout.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
247                 else
248                     headersout.print(md.getReturnType().getSafeSymbol()+" ");
249             } else 
250                 //catch the constructor case
251                 headersout.print("void ");
252             headersout.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
253             
254             boolean printcomma=false;
255             if (GENERATEPRECISEGC) {
256                 headersout.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
257                 printcomma=true;
258             }
259             for(int i=0;i<objectparams.numPrimitives();i++) {
260                 TempDescriptor temp=objectparams.getPrimitive(i);
261                 if (printcomma)
262                     headersout.print(", ");
263                 printcomma=true;
264                 if (temp.getType().isClass())
265                     headersout.print("struct " + temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
266                 else
267                     headersout.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
268             }
269             headersout.println(");\n");
270         }
271     }
272
273     private void generateFlatMethod(FlatMethod fm, PrintWriter output) {
274         MethodDescriptor md=fm.getMethod();
275         ClassDescriptor cn=md.getClassDesc();
276         ParamsObject objectparams=(ParamsObject)paramstable.get(md);
277
278         generateHeader(md,output);
279         /* Print code */
280         output.println(" {");
281         
282         if (GENERATEPRECISEGC) {
283             output.println("   struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals "+localsprefix+";");
284         }
285         TempObject objecttemp=(TempObject) tempstable.get(md);
286         for(int i=0;i<objecttemp.numPrimitives();i++) {
287             TempDescriptor td=objecttemp.getPrimitive(i);
288             TypeDescriptor type=td.getType();
289             if (type.isNull())
290                 output.println("   void * "+td.getSafeSymbol()+";");
291             else if (type.isClass())
292                 output.println("   struct "+type.getSafeSymbol()+" * "+td.getSafeSymbol()+";");
293             else
294                 output.println("   "+type.getSafeSymbol()+" "+td.getSafeSymbol()+";");
295         }
296         
297
298         /* Generate labels first */
299         HashSet tovisit=new HashSet();
300         HashSet visited=new HashSet();
301         int labelindex=0;
302         Hashtable nodetolabel=new Hashtable();
303         tovisit.add(fm.methodEntryNode());
304         FlatNode current_node=null;
305
306         //Assign labels 1st
307         //Node needs a label if it is
308         while(!tovisit.isEmpty()) {
309             FlatNode fn=(FlatNode)tovisit.iterator().next();
310             tovisit.remove(fn);
311             visited.add(fn);
312             for(int i=0;i<fn.numNext();i++) {
313                 FlatNode nn=fn.getNext(i);
314                 if(i>0) {
315                     //1) Edge >1 of node
316                     nodetolabel.put(nn,new Integer(labelindex++));
317                 }
318                 if (!visited.contains(nn)&&!tovisit.contains(nn)) {
319                     tovisit.add(nn);
320                 } else {
321                     //2) Join point
322                     nodetolabel.put(nn,new Integer(labelindex++));
323                 }
324             }
325         }
326
327         //Do the actual code generation
328         tovisit=new HashSet();
329         visited=new HashSet();
330         tovisit.add(fm.methodEntryNode());
331         while(current_node!=null||!tovisit.isEmpty()) {
332             if (current_node==null) {
333                 current_node=(FlatNode)tovisit.iterator().next();
334                 tovisit.remove(current_node);
335             }
336             visited.add(current_node);
337             if (nodetolabel.containsKey(current_node))
338                 output.println("L"+nodetolabel.get(current_node)+":");
339             if (current_node.numNext()==0) {
340                 output.print("   ");
341                 generateFlatNode(fm, current_node, output);
342                 current_node=null;
343             } else if(current_node.numNext()==1) {
344                 output.print("   ");
345                 generateFlatNode(fm, current_node, output);
346                 FlatNode nextnode=current_node.getNext(0);
347                 if (visited.contains(nextnode)) {
348                     output.println("goto L"+nodetolabel.get(nextnode)+";");
349                     current_node=null;
350                 } else
351                     current_node=nextnode;
352             } else if (current_node.numNext()==2) {
353                 /* Branch */
354                 output.print("   ");
355                 generateFlatCondBranch(fm, (FlatCondBranch)current_node, "L"+nodetolabel.get(current_node.getNext(1)), output);
356                 if (!visited.contains(current_node.getNext(1)))
357                     tovisit.add(current_node.getNext(1));
358                 if (visited.contains(current_node.getNext(0))) {
359                     output.println("goto L"+nodetolabel.get(current_node.getNext(0))+";");
360                     current_node=null;
361                 } else
362                     current_node=current_node.getNext(0);
363             } else throw new Error();
364         }
365         output.println("}\n\n");
366     }
367
368     private String generateTemp(FlatMethod fm, TempDescriptor td) {
369         MethodDescriptor md=fm.getMethod();
370         TempObject objecttemps=(TempObject) tempstable.get(md);
371         if (objecttemps.isLocalPrim(td)||objecttemps.isParamPrim(td)) {
372             return td.getSafeSymbol();
373         }
374
375         if (objecttemps.isLocalPtr(td)) {
376             return localsprefix+"."+td.getSafeSymbol();
377         }
378
379         if (objecttemps.isParamPtr(td)) {
380             return paramsprefix+"->"+td.getSafeSymbol();
381         }
382         throw new Error();
383     }
384
385     private void generateFlatNode(FlatMethod fm, FlatNode fn, PrintWriter output) {
386         switch(fn.kind()) {
387         case FKind.FlatCall:
388             generateFlatCall(fm, (FlatCall) fn,output);
389             return;
390         case FKind.FlatFieldNode:
391             generateFlatFieldNode(fm, (FlatFieldNode) fn,output);
392             return;
393         case FKind.FlatSetFieldNode:
394             generateFlatSetFieldNode(fm, (FlatSetFieldNode) fn,output);
395             return;
396         case FKind.FlatNew:
397             generateFlatNew(fm, (FlatNew) fn,output);
398             return;
399         case FKind.FlatOpNode:
400             generateFlatOpNode(fm, (FlatOpNode) fn,output);
401             return;
402         case FKind.FlatCastNode:
403             generateFlatCastNode(fm, (FlatCastNode) fn,output);
404             return;
405         case FKind.FlatLiteralNode:
406             generateFlatLiteralNode(fm, (FlatLiteralNode) fn,output);
407             return;
408         case FKind.FlatReturnNode:
409             generateFlatReturnNode(fm, (FlatReturnNode) fn,output);
410             return;
411         case FKind.FlatNop:
412             output.println("/* nop */");
413             return;
414         }
415         throw new Error();
416
417     }
418
419     private void generateFlatCall(FlatMethod fm, FlatCall fc, PrintWriter output) {
420         MethodDescriptor md=fc.getMethod();
421         ParamsObject objectparams=(ParamsObject) paramstable.get(md);
422         ClassDescriptor cn=md.getClassDesc();
423         output.println("{");
424         if (GENERATEPRECISEGC) {
425             output.print("       struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params __parameterlist__={");
426             
427             output.print(objectparams.getUID());
428             output.print(", & "+localsprefix);
429             if (fc.getThis()!=null) {
430                 output.print(", ");
431                 output.print(generateTemp(fm,fc.getThis()));
432             }
433             for(int i=0;i<fc.numArgs();i++) {
434                 VarDescriptor var=md.getParameter(i);
435                 TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
436                 if (objectparams.isParamPtr(paramtemp)) {
437                     TempDescriptor targ=fc.getArg(i);
438                     output.print(", ");
439                     output.print(generateTemp(fm, targ));
440                 }
441             }
442             output.println("};");
443         }
444         output.print("       ");
445
446         /* TODO: Virtual dispatch */
447         if (fc.getReturnTemp()!=null)
448             output.print(generateTemp(fm,fc.getReturnTemp())+"=");
449         output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
450         boolean needcomma=false;
451         if (GENERATEPRECISEGC) {
452             output.print("&__parameterlist__");
453             needcomma=true;
454         } else {
455             if (fc.getThis()!=null) {
456                 output.print(generateTemp(fm,fc.getThis()));
457                 needcomma=true;
458             }
459         }
460         for(int i=0;i<fc.numArgs();i++) {
461             VarDescriptor var=md.getParameter(i);
462             TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
463             if (objectparams.isParamPrim(paramtemp)) {
464                 TempDescriptor targ=fc.getArg(i);
465                 if (needcomma)
466                     output.print(", ");
467                 output.print(generateTemp(fm, targ));
468                 needcomma=true;
469             }
470         }
471         output.println(");");
472         output.println("   }");
473     }
474
475     private void generateFlatFieldNode(FlatMethod fm, FlatFieldNode ffn, PrintWriter output) {
476         output.println(generateTemp(fm, ffn.getDst())+"="+ generateTemp(fm,ffn.getSrc())+"->"+ ffn.getField().getSafeSymbol()+";");
477     }
478
479     private void generateFlatSetFieldNode(FlatMethod fm, FlatSetFieldNode fsfn, PrintWriter output) {
480         output.println(generateTemp(fm, fsfn.getDst())+"->"+ fsfn.getField().getSafeSymbol()+"="+ generateTemp(fm,fsfn.getSrc())+";");
481     }
482
483     private void generateFlatNew(FlatMethod fm, FlatNew fn, PrintWriter output) {
484         output.println(generateTemp(fm,fn.getDst())+"=allocate_new("+fn.getType().getClassDesc().getId()+");");
485     }
486
487     private void generateFlatOpNode(FlatMethod fm, FlatOpNode fon, PrintWriter output) {
488
489         if (fon.getRight()!=null)
490             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+fon.getOp().toString()+generateTemp(fm,fon.getRight())+";");
491         else if (fon.getOp().getOp()==Operation.ASSIGN)
492             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
493         else if (fon.getOp().getOp()==Operation.UNARYPLUS)
494             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
495         else if (fon.getOp().getOp()==Operation.UNARYMINUS)
496             output.println(generateTemp(fm, fon.getDest())+" = -"+generateTemp(fm, fon.getLeft())+";");
497         else if (fon.getOp().getOp()==Operation.POSTINC)
498             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+"++;");
499         else if (fon.getOp().getOp()==Operation.POSTDEC)
500             output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+"--;");
501         else if (fon.getOp().getOp()==Operation.PREINC)
502             output.println(generateTemp(fm, fon.getDest())+" = ++"+generateTemp(fm, fon.getLeft())+";");
503         else if (fon.getOp().getOp()==Operation.PREDEC)
504             output.println(generateTemp(fm, fon.getDest())+" = --"+generateTemp(fm, fon.getLeft())+";");
505         else
506             output.println(generateTemp(fm, fon.getDest())+fon.getOp().toString()+generateTemp(fm, fon.getLeft())+";");
507     }
508
509     private void generateFlatCastNode(FlatMethod fm, FlatCastNode fcn, PrintWriter output) {
510         /* TODO: Make call into runtime */
511         output.println(generateTemp(fm,fcn.getDst())+"=("+fcn.getType().getSafeSymbol()+")"+generateTemp(fm,fcn.getSrc())+";");
512     }
513
514     private void generateFlatLiteralNode(FlatMethod fm, FlatLiteralNode fln, PrintWriter output) {
515         if (fln.getValue()==null)
516             output.println(generateTemp(fm, fln.getDst())+"=0;");
517         else if (fln.getType().getSymbol().equals(TypeUtil.StringClass))
518             output.println(generateTemp(fm, fln.getDst())+"=newstring(\""+FlatLiteralNode.escapeString((String)fln.getValue())+"\");");
519         else
520             output.println(generateTemp(fm, fln.getDst())+"="+fln.getValue()+";");
521     }
522
523     private void generateFlatReturnNode(FlatMethod fm, FlatReturnNode frn, PrintWriter output) {
524         output.println("return "+generateTemp(fm, frn.getReturnTemp())+";");
525     }
526
527     private void generateFlatCondBranch(FlatMethod fm, FlatCondBranch fcb, String label, PrintWriter output) {
528         output.println("if (!"+generateTemp(fm, fcb.getTest())+") goto "+label+";");
529     }
530
531     private void generateHeader(MethodDescriptor md, PrintWriter output) {
532         /* Print header */
533         ParamsObject objectparams=(ParamsObject)paramstable.get(md);
534         ClassDescriptor cn=md.getClassDesc();
535         
536         if (md.getReturnType()!=null) {
537             if (md.getReturnType().isClass())
538                 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
539             else
540                 output.print(md.getReturnType().getSafeSymbol()+" ");
541         } else 
542             //catch the constructor case
543             output.print("void ");
544
545         output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
546         
547         boolean printcomma=false;
548         if (GENERATEPRECISEGC) {
549             output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
550             printcomma=true;
551         }
552         for(int i=0;i<objectparams.numPrimitives();i++) {
553             TempDescriptor temp=objectparams.getPrimitive(i);
554             if (printcomma)
555                 output.print(", ");
556             printcomma=true;
557             if (temp.getType().isClass())
558                 output.print("struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol());
559             else
560                 output.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
561         }
562         output.print(")");
563     }
564 }