Checking in changes
[IRC.git] / Robust / src / IR / Flat / BuildFlat.java
1 package IR.Flat;
2 import IR.*;
3 import IR.Tree.*;
4 import java.util.*;
5
6 public class BuildFlat {
7     State state;
8     Hashtable temptovar;
9
10     public BuildFlat(State st) {
11         state=st;
12         temptovar=new Hashtable();
13     }
14
15     public Hashtable getMap() {
16         return temptovar;
17     }
18
19     public void buildFlat() {
20         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
21         while(it.hasNext()) {
22             ClassDescriptor cn=(ClassDescriptor)it.next();
23             flattenClass(cn);
24         }
25     }
26     
27     private void flattenClass(ClassDescriptor cn) {
28         Iterator methodit=cn.getMethods();
29         while(methodit.hasNext()) {
30             MethodDescriptor md=(MethodDescriptor)methodit.next();
31             BlockNode bn=state.getMethodBody(md);
32             FlatNode fn=flattenBlockNode(bn).getBegin();
33             FlatMethod fm=new FlatMethod(md, fn);
34             if (!md.isStatic())
35                 fm.addParameterTemp(getTempforVar(md.getThis()));
36             for(int i=0;i<md.numParameters();i++) {
37                 fm.addParameterTemp(getTempforVar(md.getParameter(i)));
38             }
39             System.out.println(fm.printMethod());
40             state.addFlatCode(md,fm);
41         }
42     }
43
44     private NodePair flattenBlockNode(BlockNode bn) {
45         FlatNode begin=null;
46         FlatNode end=null;
47         for(int i=0;i<bn.size();i++) {
48             NodePair np=flattenBlockStatementNode(bn.get(i));
49             FlatNode np_begin=np.getBegin();
50             FlatNode np_end=np.getEnd();
51             if (begin==null) {
52                 begin=np_begin;
53             }
54             if (end==null) {
55                 end=np_end;
56             } else {
57                 end.addNext(np_begin);
58                 end=np_end;
59             }
60         }
61         if (begin==null) {
62             end=begin=new FlatNop();
63         }
64         return new NodePair(begin,end);
65     }
66
67     private NodePair flattenBlockExpressionNode(BlockExpressionNode en) {
68         TempDescriptor tmp=TempDescriptor.tempFactory("neverused",en.getExpression().getType());
69         return flattenExpressionNode(en.getExpression(),tmp);
70     }
71
72     private NodePair flattenCastNode(CastNode cn,TempDescriptor out_temp) {
73         TempDescriptor tmp=TempDescriptor.tempFactory("tocast",cn.getExpression().getType());
74         NodePair np=flattenExpressionNode(cn.getExpression(), tmp);
75         FlatCastNode fcn=new FlatCastNode(cn.getType(), tmp, out_temp);
76         np.getEnd().addNext(fcn);
77         return new NodePair(np.getBegin(),fcn);
78     }
79
80     private NodePair flattenLiteralNode(LiteralNode ln,TempDescriptor out_temp) {
81         FlatLiteralNode fln=new FlatLiteralNode(ln.getType(), ln.getValue(), out_temp);
82         return new NodePair(fln,fln);
83     }
84
85     private NodePair flattenCreateObjectNode(CreateObjectNode con,TempDescriptor out_temp) {
86         TypeDescriptor td=con.getType();
87         if (!td.isArray()) {
88             FlatNew fn=new FlatNew(td, out_temp);
89             TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
90             FlatNode last=fn;
91             //Build arguments
92             for(int i=0;i<con.numArgs();i++) {
93                 ExpressionNode en=con.getArg(i);
94                 TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
95                 temps[i]=tmp;
96                 NodePair np=flattenExpressionNode(en, tmp);
97                 last.addNext(np.getBegin());
98                 last=np.getEnd();
99             }
100             MethodDescriptor md=con.getConstructor();
101             //Call to constructor
102             FlatCall fc=new FlatCall(md, null, out_temp, temps);
103             last.addNext(fc);
104             return new NodePair(fn,fc); 
105         } else {
106             FlatNode first=null;
107             FlatNode last=null;
108             TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
109             for (int i=0;i<con.numArgs();i++) {
110                 ExpressionNode en=con.getArg(i);
111                 TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
112                 temps[i]=tmp;           
113                 NodePair np=flattenExpressionNode(en, tmp);
114                 if (first==null)
115                     first=np.getBegin();
116                 else
117                     last.addNext(np.getBegin());
118                 last=np.getEnd();
119                 
120                 TempDescriptor tmp2=(i==0)?
121                     out_temp:
122                 TempDescriptor.tempFactory("arg",en.getType());
123             }
124             FlatNew fn=new FlatNew(td, out_temp, temps[0]);
125             last.addNext(fn);
126             NodePair np=generateNewArrayLoop(temps, td.dereference(), out_temp, 0);
127             fn.addNext(np.getBegin());
128             return new NodePair(first,np.getEnd()); 
129         }
130     }
131
132     private NodePair generateNewArrayLoop(TempDescriptor[] temparray, TypeDescriptor td, TempDescriptor tmp, int i) {
133         TempDescriptor index=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
134         TempDescriptor tmpone=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
135         FlatNop fnop=new FlatNop();//last node
136
137         //index=0
138         FlatLiteralNode fln=new FlatLiteralNode(index.getType(),new Integer(0),index);
139         //tmpone=1
140         FlatLiteralNode fln2=new FlatLiteralNode(tmpone.getType(),new Integer(1),tmpone);
141
142         TempDescriptor tmpbool=TempDescriptor.tempFactory("comp",new TypeDescriptor(TypeDescriptor.BOOLEAN));
143
144         FlatOpNode fcomp=new FlatOpNode(tmpbool,index,temparray[i],new Operation(Operation.LT));
145         FlatCondBranch fcb=new FlatCondBranch(tmpbool);
146         //is index<temp[i]
147         TempDescriptor new_tmp=TempDescriptor.tempFactory("tmp",td);
148         FlatNew fn=new FlatNew(td, new_tmp, temparray[i+1]);
149         FlatSetElementNode fsen=new FlatSetElementNode(tmp,index,new_tmp);
150         // index=index+1
151         FlatOpNode fon=new FlatOpNode(index,index,tmpone,new Operation(Operation.ADD));
152         //jump out
153         fln.addNext(fln2);
154         fln2.addNext(fcomp);
155         fcomp.addNext(fcb);
156         fcb.addTrueNext(fn);
157         fcb.addFalseNext(fnop);
158         fn.addNext(fsen);
159         //Recursive call here
160         if ((i+1)<temparray.length) {
161             NodePair np2=generateNewArrayLoop(temparray, td.dereference(), new_tmp, i+1);
162             fsen.addNext(np2.getBegin());
163             np2.getEnd().addNext(fon);
164         } else {
165             fsen.addNext(fon);
166         }
167         fon.addNext(fcomp);
168         return new NodePair(fln, fnop);
169     }
170
171     private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) {
172         TempDescriptor[] temps=new TempDescriptor[min.numArgs()];
173         FlatNode first=null;
174         FlatNode last=null;
175         TempDescriptor thisarg=null;
176
177         if (min.getExpression()!=null) {
178             thisarg=TempDescriptor.tempFactory("thisarg",min.getExpression().getType());
179             NodePair np=flattenExpressionNode(min.getExpression(),thisarg);
180             first=np.getBegin();
181             last=np.getEnd();
182         }
183         
184         //Build arguments
185         for(int i=0;i<min.numArgs();i++) {
186             ExpressionNode en=min.getArg(i);
187             TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
188             temps[i]=td;
189             NodePair np=flattenExpressionNode(en, td);
190             if (first==null)
191                 first=np.getBegin();
192             else 
193                 last.addNext(np.getBegin());
194             last=np.getEnd();
195         }
196
197         MethodDescriptor md=min.getMethod();
198         
199         //Call to constructor
200         
201         FlatCall fc;
202         if(md.getReturnType()==null||md.getReturnType().isVoid())
203             fc=new FlatCall(md, null, thisarg, temps);
204         else 
205             fc=new FlatCall(md, out_temp, thisarg, temps);
206         if (first==null) {
207             first=fc;
208         } else
209             last.addNext(fc);
210         return new NodePair(first,fc);
211     }
212
213     private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) {
214         TempDescriptor tmp=TempDescriptor.tempFactory("temp",fan.getExpression().getType());
215         NodePair npe=flattenExpressionNode(fan.getExpression(),tmp);
216         FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
217         npe.getEnd().addNext(fn);
218         return new NodePair(npe.getBegin(),fn);
219     }
220
221     private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
222         // Two cases:
223         // left side is variable
224         // left side is field
225         
226         Operation base=an.getOperation().getBaseOp();
227         TempDescriptor src_tmp=TempDescriptor.tempFactory("src",an.getSrc().getType());
228         NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
229         FlatNode last=np_src.getEnd();
230         if (base!=null) {
231             TempDescriptor src_tmp2=TempDescriptor.tempFactory("tmp", an.getDest().getType());
232             NodePair np_dst_init=flattenExpressionNode(an.getDest(),src_tmp2);
233             last.addNext(np_dst_init.getBegin());
234             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst_tmp",an.getDest().getType());
235             FlatOpNode fon=new FlatOpNode(dst_tmp, src_tmp,src_tmp2, base);
236             np_dst_init.getEnd().addNext(fon);
237             last=fon;
238             src_tmp=dst_tmp;
239         }
240         
241         if (an.getDest().kind()==Kind.FieldAccessNode) {
242             FieldAccessNode fan=(FieldAccessNode)an.getDest();
243             ExpressionNode en=fan.getExpression();
244             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
245             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
246             last.addNext(np_baseexp.getBegin());
247             FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
248             np_baseexp.getEnd().addNext(fsfn);
249             return new NodePair(np_src.getBegin(), fsfn);
250         } else if (an.getDest().kind()==Kind.NameNode) {
251             NameNode nn=(NameNode)an.getDest();
252             if (nn.getExpression()!=null) {
253                 FieldAccessNode fan=(FieldAccessNode)nn.getExpression();
254                 ExpressionNode en=fan.getExpression();
255                 TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
256                 NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
257                 last.addNext(np_baseexp.getBegin());
258                 FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
259                 np_baseexp.getEnd().addNext(fsfn);
260                 return new NodePair(np_src.getBegin(), fsfn);
261             } else {
262                 if (nn.getField()!=null) {
263                     FlatSetFieldNode fsfn=new FlatSetFieldNode(getTempforVar(nn.getVar()), nn.getField(), src_tmp);
264                     last.addNext(fsfn);
265                     return new NodePair(np_src.getBegin(), fsfn);
266                 } else {
267                     FlatOpNode fon=new FlatOpNode(getTempforVar(nn.getVar()), src_tmp, null, new Operation(Operation.ASSIGN));
268                     last.addNext(fon);
269                     return new NodePair(np_src.getBegin(),fon);
270                 }
271             }
272         } 
273         throw new Error();
274     }
275
276     private NodePair flattenNameNode(NameNode nn,TempDescriptor out_temp) {
277         if (nn.getExpression()!=null) {
278             /* Hack - use subtree instead */
279             return flattenExpressionNode(nn.getExpression(),out_temp);
280         } else if (nn.getField()!=null) {
281             TempDescriptor tmp=getTempforVar(nn.getVar());
282             FlatFieldNode ffn=new FlatFieldNode(nn.getField(), tmp, out_temp); 
283             return new NodePair(ffn,ffn);
284         } else {
285             TempDescriptor tmp=getTempforVar(nn.getVar());
286             FlatOpNode fon=new FlatOpNode(out_temp, tmp, null, new Operation(Operation.ASSIGN));
287             return new NodePair(fon,fon);
288         }
289     }
290
291     private NodePair flattenOpNode(OpNode on,TempDescriptor out_temp) {
292         TempDescriptor temp_left=TempDescriptor.tempFactory("leftop",on.getLeft().getType());
293         TempDescriptor temp_right=null;
294
295         Operation op=on.getOp();
296         if (op.getOp()==Operation.POSTINC||
297             op.getOp()==Operation.POSTDEC||
298             op.getOp()==Operation.PREINC||
299             op.getOp()==Operation.PREDEC) {
300             LiteralNode ln=new LiteralNode("int",new Integer(1));
301             ln.setType(new TypeDescriptor(TypeDescriptor.INT));
302             AssignmentNode an=new AssignmentNode(on.getLeft(),ln,
303                                new AssignOperation((op.getOp()==Operation.POSTINC||op.getOp()==Operation.PREINC)?AssignOperation.PLUSEQ:AssignOperation.MINUSEQ));
304             if (op.getOp()==Operation.POSTINC||
305                 op.getOp()==Operation.POSTDEC) {
306                 NodePair left=flattenExpressionNode(on.getLeft(),out_temp);
307                 NodePair assign=flattenAssignmentNode(an,temp_left);
308                 left.getEnd().addNext(assign.getBegin());
309                 return new NodePair(left.getBegin(),assign.getEnd());
310             } else {
311                 NodePair assign=flattenAssignmentNode(an,out_temp);
312                 return assign;
313             }
314         } 
315         
316         NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
317         NodePair right;
318         if (on.getRight()!=null) {
319             temp_right=TempDescriptor.tempFactory("rightop",on.getRight().getType());
320             right=flattenExpressionNode(on.getRight(),temp_right);
321         } else {
322             FlatNop nop=new FlatNop();
323             right=new NodePair(nop,nop);
324         }
325
326         if (op.getOp()==Operation.LOGIC_OR) {
327             /* Need to do shortcircuiting */
328             FlatCondBranch fcb=new FlatCondBranch(temp_left);
329             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
330             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
331             FlatNop fnop=new FlatNop();
332             left.getEnd().addNext(fcb);
333             fcb.addFalseNext(right.getBegin());
334             right.getEnd().addNext(fon2);
335             fon2.addNext(fnop);
336             fcb.addTrueNext(fon1);
337             fon1.addNext(fnop);
338             return new NodePair(left.getBegin(), fnop);
339         } else if (op.getOp()==Operation.LOGIC_AND) {
340             /* Need to do shortcircuiting */
341             FlatCondBranch fcb=new FlatCondBranch(temp_left);
342             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
343             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
344             FlatNop fnop=new FlatNop();
345             left.getEnd().addNext(fcb);
346             fcb.addTrueNext(right.getBegin());
347             right.getEnd().addNext(fon2);
348             fon2.addNext(fnop);
349             fcb.addFalseNext(fon1);
350             fon1.addNext(fnop);
351             return new NodePair(left.getBegin(), fnop);
352         }
353
354         FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
355         left.getEnd().addNext(right.getBegin());
356         right.getEnd().addNext(fon);
357         return new NodePair(left.getBegin(),fon);
358     }
359
360     private NodePair flattenExpressionNode(ExpressionNode en, TempDescriptor out_temp) {
361         switch(en.kind()) {
362         case Kind.AssignmentNode:
363             return flattenAssignmentNode((AssignmentNode)en,out_temp);
364         case Kind.CastNode:
365             return flattenCastNode((CastNode)en,out_temp);
366         case Kind.CreateObjectNode:
367             return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
368         case Kind.FieldAccessNode:
369             return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
370         case Kind.LiteralNode:
371             return flattenLiteralNode((LiteralNode)en,out_temp);
372         case Kind.MethodInvokeNode:
373             return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
374         case Kind.NameNode:
375             return flattenNameNode((NameNode)en,out_temp);
376         case Kind.OpNode:
377             return flattenOpNode((OpNode)en,out_temp);
378         }
379         throw new Error();
380     }
381
382     private NodePair flattenDeclarationNode(DeclarationNode dn) {
383         VarDescriptor vd=dn.getVarDescriptor();
384         TempDescriptor td=getTempforVar(vd);
385         if (dn.getExpression()!=null)
386             return flattenExpressionNode(dn.getExpression(),td);
387         else {
388             FlatNop fn=new FlatNop();
389             return new NodePair(fn,fn);
390         }
391     }
392         
393     private TempDescriptor getTempforVar(VarDescriptor vd) {
394         if (temptovar.containsKey(vd))
395             return (TempDescriptor)temptovar.get(vd);
396         else {
397             TempDescriptor td=TempDescriptor.tempFactory(vd.getName(),vd.getType());
398             temptovar.put(vd,td);
399             return td;
400         }
401     }
402
403     private NodePair flattenIfStatementNode(IfStatementNode isn) {
404         TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
405         NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
406         FlatCondBranch fcb=new FlatCondBranch(cond_temp);
407         NodePair true_np=flattenBlockNode(isn.getTrueBlock());
408         NodePair false_np;
409         FlatNop nopend=new FlatNop();
410
411         if (isn.getFalseBlock()!=null)
412             false_np=flattenBlockNode(isn.getFalseBlock());
413         else {
414             FlatNop nop=new FlatNop();
415             false_np=new NodePair(nop,nop);
416         }
417
418         cond.getEnd().addNext(fcb);
419         fcb.addTrueNext(true_np.getBegin());
420         fcb.addFalseNext(false_np.getBegin());
421         true_np.getEnd().addNext(nopend);
422         false_np.getEnd().addNext(nopend);
423         return new NodePair(cond.getBegin(), nopend);
424     }
425             
426     private NodePair flattenLoopNode(LoopNode ln) {
427         if (ln.getType()==LoopNode.FORLOOP) {
428             NodePair initializer=flattenBlockNode(ln.getInitializer());
429             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
430             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
431             NodePair update=flattenBlockNode(ln.getUpdate());
432             NodePair body=flattenBlockNode(ln.getBody());
433             FlatNode begin=initializer.getBegin();
434             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
435             FlatNop nopend=new FlatNop();
436
437             initializer.getEnd().addNext(condition.getBegin());
438             body.getEnd().addNext(update.getBegin());
439             update.getEnd().addNext(condition.getBegin());
440             condition.getEnd().addNext(fcb);
441             fcb.addFalseNext(nopend);
442             fcb.addTrueNext(body.getBegin());
443             return new NodePair(begin,nopend);
444         } else if (ln.getType()==LoopNode.WHILELOOP) {
445             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
446             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
447             NodePair body=flattenBlockNode(ln.getBody());
448             FlatNode begin=condition.getBegin();
449             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
450             FlatNop nopend=new FlatNop();
451
452             body.getEnd().addNext(condition.getBegin());
453             condition.getEnd().addNext(fcb);
454             fcb.addFalseNext(nopend);
455             fcb.addTrueNext(body.getBegin());
456             return new NodePair(begin,nopend);
457         } else if (ln.getType()==LoopNode.DOWHILELOOP) {
458             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
459             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
460             NodePair body=flattenBlockNode(ln.getBody());
461             FlatNode begin=body.getBegin();
462             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
463             FlatNop nopend=new FlatNop();
464
465             body.getEnd().addNext(condition.getBegin());
466             condition.getEnd().addNext(fcb);
467             fcb.addFalseNext(nopend);
468             fcb.addTrueNext(body.getBegin());
469             return new NodePair(begin,nopend);
470         } else throw new Error();
471     }
472             
473     private NodePair flattenReturnNode(ReturnNode rntree) {
474         TempDescriptor retval=null;
475         NodePair cond=null;
476         if (rntree.getReturnExpression()!=null) {
477             retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
478             cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
479         }
480
481         FlatReturnNode rnflat=new FlatReturnNode(retval);
482
483         if (cond!=null) {
484             cond.getEnd().addNext(rnflat);
485             return new NodePair(cond.getBegin(),rnflat);
486         } else
487             return new NodePair(rnflat,rnflat);
488         
489     }
490             
491     private NodePair flattenSubBlockNode(SubBlockNode sbn) {
492         return flattenBlockNode(sbn.getBlockNode());
493     }
494
495     private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
496         switch(bsn.kind()) {
497         case Kind.BlockExpressionNode:
498             return flattenBlockExpressionNode((BlockExpressionNode)bsn);
499             
500         case Kind.DeclarationNode:
501             return flattenDeclarationNode((DeclarationNode)bsn);
502             
503         case Kind.IfStatementNode:
504             return flattenIfStatementNode((IfStatementNode)bsn);
505             
506         case Kind.LoopNode:
507             return flattenLoopNode((LoopNode)bsn);
508             
509         case Kind.ReturnNode:
510             return flattenReturnNode((IR.Tree.ReturnNode)bsn);
511             
512         case Kind.SubBlockNode:
513             return flattenSubBlockNode((SubBlockNode)bsn);
514             
515         }
516         throw new Error();
517     }
518 }