6 public class BuildCode {
12 String localsprefix="___locals___";
13 String paramsprefix="___params___";
14 private static final boolean GENERATEPRECISEGC=true;
16 public BuildCode(State st, Hashtable temptovar) {
18 this.temptovar=temptovar;
19 paramstable=new Hashtable();
20 tempstable=new Hashtable();
23 public void buildCode() {
24 Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
25 PrintWriter outclassdefs=null;
26 PrintWriter outstructs=null;
27 PrintWriter outmethodheader=null;
28 PrintWriter outmethod=null;
30 OutputStream str=new FileOutputStream("structdefs.h");
31 outstructs=new java.io.PrintWriter(str, true);
32 str=new FileOutputStream("methodheaders.h");
33 outmethodheader=new java.io.PrintWriter(str, true);
34 str=new FileOutputStream("classdefs.h");
35 outclassdefs=new java.io.PrintWriter(str, true);
36 str=new FileOutputStream("methods.c");
37 outmethod=new java.io.PrintWriter(str, true);
38 } catch (Exception e) {
42 outstructs.println("#include \"classdefs.h\"");
43 outmethodheader.println("#include \"structdefs.h\"");
45 // Output the C declarations
46 // These could mutually reference each other
48 ClassDescriptor cn=(ClassDescriptor)it.next();
49 outclassdefs.println("struct "+cn.getSafeSymbol()+";");
51 outclassdefs.println("");
53 it=state.getClassSymbolTable().getDescriptorsIterator();
55 ClassDescriptor cn=(ClassDescriptor)it.next();
56 generateCallStructs(cn, outclassdefs, outstructs, outmethodheader);
59 outmethodheader.close();
61 /* Build the actual methods */
62 outmethod.println("#include \"methodheaders.h\"");
63 Iterator classit=state.getClassSymbolTable().getDescriptorsIterator();
64 while(classit.hasNext()) {
65 ClassDescriptor cn=(ClassDescriptor)classit.next();
66 Iterator methodit=cn.getMethods();
67 while(methodit.hasNext()) {
68 /* Classify parameters */
69 MethodDescriptor md=(MethodDescriptor)methodit.next();
70 FlatMethod fm=state.getMethodFlat(md);
71 generateFlatMethod(fm,outmethod);
77 private void generateTempStructs(FlatMethod fm) {
78 MethodDescriptor md=fm.getMethod();
79 ParamsObject objectparams=new ParamsObject(md,tag++);
80 paramstable.put(md, objectparams);
81 for(int i=0;i<fm.numParameters();i++) {
82 TempDescriptor temp=fm.getParameter(i);
83 TypeDescriptor type=temp.getType();
84 if (type.isPtr()&&GENERATEPRECISEGC)
85 objectparams.addPtr(temp);
87 objectparams.addPrim(temp);
90 TempObject objecttemps=new TempObject(objectparams,md,tag++);
91 tempstable.put(md, objecttemps);
92 for(Iterator nodeit=fm.getNodeSet().iterator();nodeit.hasNext();) {
93 FlatNode fn=(FlatNode)nodeit.next();
94 TempDescriptor[] writes=fn.writesTemps();
95 for(int i=0;i<writes.length;i++) {
96 TempDescriptor temp=writes[i];
97 TypeDescriptor type=temp.getType();
98 if (type.isPtr()&&GENERATEPRECISEGC)
99 objecttemps.addPtr(temp);
101 objecttemps.addPrim(temp);
106 private void generateCallStructs(ClassDescriptor cn, PrintWriter classdefout, PrintWriter output, PrintWriter headersout) {
107 /* Output class structure */
108 Iterator fieldit=cn.getFields();
109 classdefout.println("struct "+cn.getSafeSymbol()+" {");
110 classdefout.println(" int type;");
111 while(fieldit.hasNext()) {
112 FieldDescriptor fd=(FieldDescriptor)fieldit.next();
113 if (fd.getType().isClass())
114 classdefout.println(" struct "+fd.getType().getSafeSymbol()+" * "+fd.getSafeSymbol()+";");
116 classdefout.println(" "+fd.getType().getSafeSymbol()+" "+fd.getSafeSymbol()+";");
118 classdefout.println("};\n");
120 /* Cycle through methods */
121 Iterator methodit=cn.getMethods();
122 while(methodit.hasNext()) {
123 /* Classify parameters */
124 MethodDescriptor md=(MethodDescriptor)methodit.next();
125 FlatMethod fm=state.getMethodFlat(md);
126 generateTempStructs(fm);
128 ParamsObject objectparams=(ParamsObject) paramstable.get(md);
129 TempObject objecttemps=(TempObject) tempstable.get(md);
131 /* Output parameter structure */
132 if (GENERATEPRECISEGC) {
133 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params {");
134 output.println(" int type;");
135 output.println(" void * next;");
136 for(int i=0;i<objectparams.numPointers();i++) {
137 TempDescriptor temp=objectparams.getPointer(i);
138 output.println(" struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
140 output.println("};\n");
143 /* Output temp structure */
144 if (GENERATEPRECISEGC) {
145 output.println("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals {");
146 output.println(" int type;");
147 output.println(" void * next;");
148 for(int i=0;i<objecttemps.numPointers();i++) {
149 TempDescriptor temp=objecttemps.getPointer(i);
150 if (temp.getType().isNull())
151 output.println(" void * "+temp.getSafeSymbol()+";");
153 output.println(" struct "+temp.getType().getSafeSymbol()+" * "+temp.getSafeSymbol()+";");
155 output.println("};\n");
158 /* Output method declaration */
159 if (md.getReturnType()!=null) {
160 if (md.getReturnType().isClass())
161 headersout.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
163 headersout.print(md.getReturnType().getSafeSymbol()+" ");
165 //catch the constructor case
166 headersout.print("void ");
167 headersout.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
169 boolean printcomma=false;
170 if (GENERATEPRECISEGC) {
171 headersout.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
174 for(int i=0;i<objectparams.numPrimitives();i++) {
175 TempDescriptor temp=objectparams.getPrimitive(i);
177 headersout.print(", ");
179 headersout.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());
181 headersout.println(");\n");
185 private void generateFlatMethod(FlatMethod fm, PrintWriter output) {
186 MethodDescriptor md=fm.getMethod();
187 ClassDescriptor cn=md.getClassDesc();
188 ParamsObject objectparams=(ParamsObject)paramstable.get(md);
190 generateHeader(md,output);
192 output.println(" {");
194 if (GENERATEPRECISEGC) {
195 output.println(" struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_locals "+localsprefix+";");
197 TempObject objecttemp=(TempObject) tempstable.get(md);
198 for(int i=0;i<objecttemp.numPrimitives();i++) {
199 TempDescriptor td=objecttemp.getPrimitive(i);
200 TypeDescriptor type=td.getType();
202 output.println(" struct "+type.getSafeSymbol()+" * "+td.getSafeSymbol()+";");
204 output.println(" "+type.getSafeSymbol()+" "+td.getSafeSymbol()+";");
208 /* Generate labels first */
209 HashSet tovisit=new HashSet();
210 HashSet visited=new HashSet();
212 Hashtable nodetolabel=new Hashtable();
213 tovisit.add(fm.methodEntryNode());
214 FlatNode current_node=null;
217 //Node needs a label if it is
218 while(!tovisit.isEmpty()) {
219 FlatNode fn=(FlatNode)tovisit.iterator().next();
222 for(int i=0;i<fn.numNext();i++) {
223 FlatNode nn=fn.getNext(i);
226 nodetolabel.put(nn,new Integer(labelindex++));
228 if (!visited.contains(nn)) {
232 nodetolabel.put(nn,new Integer(labelindex++));
237 //Do the actual code generation
238 tovisit=new HashSet();
239 visited=new HashSet();
240 tovisit.add(fm.methodEntryNode());
241 while(current_node!=null||!tovisit.isEmpty()) {
242 if (current_node==null) {
243 current_node=(FlatNode)tovisit.iterator().next();
244 tovisit.remove(current_node);
246 visited.add(current_node);
247 if (nodetolabel.containsKey(current_node))
248 output.println("L"+nodetolabel.get(current_node)+":");
249 if (current_node.numNext()==0) {
251 generateFlatNode(fm, current_node, output);
253 } else if(current_node.numNext()==1) {
255 generateFlatNode(fm, current_node, output);
256 FlatNode nextnode=current_node.getNext(0);
257 if (visited.contains(nextnode)) {
258 output.println("goto L"+nodetolabel.get(nextnode)+";");
261 current_node=nextnode;
262 } else if (current_node.numNext()==2) {
265 generateFlatCondBranch(fm, (FlatCondBranch)current_node, "L"+nodetolabel.get(current_node.getNext(1)), output);
266 if (!visited.contains(current_node.getNext(1)))
267 tovisit.add(current_node.getNext(1));
268 if (visited.contains(current_node.getNext(0))) {
269 output.println("goto L"+nodetolabel.get(current_node.getNext(0))+";");
272 current_node=current_node.getNext(0);
273 } else throw new Error();
275 output.println("}\n\n");
278 private String generateTemp(FlatMethod fm, TempDescriptor td) {
279 MethodDescriptor md=fm.getMethod();
280 TempObject objecttemps=(TempObject) tempstable.get(md);
281 if (objecttemps.isLocalPrim(td)||objecttemps.isParamPrim(td)) {
282 return td.getSafeSymbol();
285 if (objecttemps.isLocalPtr(td)) {
286 return localsprefix+"."+td.getSafeSymbol();
289 if (objecttemps.isParamPtr(td)) {
290 return paramsprefix+"->"+td.getSafeSymbol();
295 private void generateFlatNode(FlatMethod fm, FlatNode fn, PrintWriter output) {
298 generateFlatCall(fm, (FlatCall) fn,output);
300 case FKind.FlatFieldNode:
301 generateFlatFieldNode(fm, (FlatFieldNode) fn,output);
303 case FKind.FlatSetFieldNode:
304 generateFlatSetFieldNode(fm, (FlatSetFieldNode) fn,output);
307 generateFlatNew(fm, (FlatNew) fn,output);
309 case FKind.FlatOpNode:
310 generateFlatOpNode(fm, (FlatOpNode) fn,output);
312 case FKind.FlatCastNode:
313 generateFlatCastNode(fm, (FlatCastNode) fn,output);
315 case FKind.FlatLiteralNode:
316 generateFlatLiteralNode(fm, (FlatLiteralNode) fn,output);
318 case FKind.FlatReturnNode:
319 generateFlatReturnNode(fm, (FlatReturnNode) fn,output);
322 output.println("/* nop */");
329 private void generateFlatCall(FlatMethod fm, FlatCall fc, PrintWriter output) {
330 MethodDescriptor md=fc.getMethod();
331 ParamsObject objectparams=(ParamsObject) paramstable.get(md);
332 ClassDescriptor cn=md.getClassDesc();
334 if (GENERATEPRECISEGC) {
335 output.print(" struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params __parameterlist__={");
337 output.print(objectparams.getUID());
338 output.print(", & "+localsprefix);
339 if (fc.getThis()!=null) {
341 output.print(generateTemp(fm,fc.getThis()));
343 for(int i=0;i<fc.numArgs();i++) {
344 VarDescriptor var=md.getParameter(i);
345 TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
346 if (objectparams.isParamPtr(paramtemp)) {
347 TempDescriptor targ=fc.getArg(i);
349 output.print(generateTemp(fm, targ));
352 output.println("};");
356 /* TODO: Virtual dispatch */
357 if (fc.getReturnTemp()!=null)
358 output.print(generateTemp(fm,fc.getReturnTemp())+"=");
359 output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
360 boolean needcomma=false;
361 if (GENERATEPRECISEGC) {
362 output.print("&__parameterlist__");
365 for(int i=0;i<fc.numArgs();i++) {
366 VarDescriptor var=md.getParameter(i);
367 TempDescriptor paramtemp=(TempDescriptor)temptovar.get(var);
368 if (objectparams.isParamPrim(paramtemp)) {
369 TempDescriptor targ=fc.getArg(i);
372 output.print(generateTemp(fm, targ));
376 output.println(");");
377 output.println(" }");
380 private void generateFlatFieldNode(FlatMethod fm, FlatFieldNode ffn, PrintWriter output) {
381 output.println(generateTemp(fm, ffn.getDst())+"="+ generateTemp(fm,ffn.getSrc())+"->"+ ffn.getField().getSafeSymbol()+";");
384 private void generateFlatSetFieldNode(FlatMethod fm, FlatSetFieldNode fsfn, PrintWriter output) {
385 output.println(generateTemp(fm, fsfn.getDst())+"->"+ fsfn.getField().getSafeSymbol()+"="+ generateTemp(fm,fsfn.getSrc())+";");
388 private void generateFlatNew(FlatMethod fm, FlatNew fn, PrintWriter output) {
389 output.println(generateTemp(fm,fn.getDst())+"=allocate_new("+fn.getType().getClassDesc().getId()+");");
392 private void generateFlatOpNode(FlatMethod fm, FlatOpNode fon, PrintWriter output) {
394 if (fon.getRight()!=null)
395 output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+fon.getOp().toString()+generateTemp(fm,fon.getRight())+";");
396 else if (fon.getOp().getOp()==Operation.ASSIGN)
397 output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
398 else if (fon.getOp().getOp()==Operation.UNARYPLUS)
399 output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+";");
400 else if (fon.getOp().getOp()==Operation.UNARYMINUS)
401 output.println(generateTemp(fm, fon.getDest())+" = -"+generateTemp(fm, fon.getLeft())+";");
402 else if (fon.getOp().getOp()==Operation.POSTINC)
403 output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+"++;");
404 else if (fon.getOp().getOp()==Operation.POSTDEC)
405 output.println(generateTemp(fm, fon.getDest())+" = "+generateTemp(fm, fon.getLeft())+"--;");
406 else if (fon.getOp().getOp()==Operation.PREINC)
407 output.println(generateTemp(fm, fon.getDest())+" = ++"+generateTemp(fm, fon.getLeft())+";");
408 else if (fon.getOp().getOp()==Operation.PREDEC)
409 output.println(generateTemp(fm, fon.getDest())+" = --"+generateTemp(fm, fon.getLeft())+";");
411 output.println(generateTemp(fm, fon.getDest())+fon.getOp().toString()+generateTemp(fm, fon.getLeft())+";");
414 private void generateFlatCastNode(FlatMethod fm, FlatCastNode fcn, PrintWriter output) {
415 /* TODO: Make call into runtime */
416 output.println(generateTemp(fm,fcn.getDst())+"=("+fcn.getType().getSafeSymbol()+")"+generateTemp(fm,fcn.getSrc())+";");
419 private void generateFlatLiteralNode(FlatMethod fm, FlatLiteralNode fln, PrintWriter output) {
420 if (fln.getValue()==null)
421 output.println(generateTemp(fm, fln.getDst())+"=0;");
422 else if (fln.getType().getSymbol().equals(TypeUtil.StringClass))
423 output.println(generateTemp(fm, fln.getDst())+"=newstring(\""+FlatLiteralNode.escapeString((String)fln.getValue())+"\");");
425 output.println(generateTemp(fm, fln.getDst())+"="+fln.getValue()+";");
428 private void generateFlatReturnNode(FlatMethod fm, FlatReturnNode frn, PrintWriter output) {
429 output.println("return "+generateTemp(fm, frn.getReturnTemp())+";");
432 private void generateFlatCondBranch(FlatMethod fm, FlatCondBranch fcb, String label, PrintWriter output) {
433 output.println("if (!"+generateTemp(fm, fcb.getTest())+") goto "+label+";");
436 private void generateHeader(MethodDescriptor md, PrintWriter output) {
438 ParamsObject objectparams=(ParamsObject)paramstable.get(md);
439 ClassDescriptor cn=md.getClassDesc();
441 if (md.getReturnType()!=null) {
442 if (md.getReturnType().isClass())
443 output.print("struct " + md.getReturnType().getSafeSymbol()+" * ");
445 output.print(md.getReturnType().getSafeSymbol()+" ");
447 //catch the constructor case
448 output.print("void ");
450 output.print(cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"(");
452 boolean printcomma=false;
453 if (GENERATEPRECISEGC) {
454 output.print("struct "+cn.getSafeSymbol()+md.getSafeSymbol()+"_"+md.getSafeMethodDescriptor()+"_params * "+paramsprefix);
457 for(int i=0;i<objectparams.numPrimitives();i++) {
458 TempDescriptor temp=objectparams.getPrimitive(i);
462 output.print(temp.getType().getSafeSymbol()+" "+temp.getSafeSymbol());