Bug fixes and switches
[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         FlatNew fn=new FlatNew(td, out_temp);
88         TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
89         FlatNode last=fn;
90         //Build arguments
91         for(int i=0;i<con.numArgs();i++) {
92             ExpressionNode en=con.getArg(i);
93             TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
94             temps[i]=tmp;
95             NodePair np=flattenExpressionNode(en, tmp);
96             last.addNext(np.getBegin());
97             last=np.getEnd();
98         }
99         MethodDescriptor md=con.getConstructor();
100         //Call to constructor
101         FlatCall fc=new FlatCall(md, null, out_temp, temps);
102         last.addNext(fc);
103         return new NodePair(fn,fc);
104     }
105
106     private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) {
107         TempDescriptor[] temps=new TempDescriptor[min.numArgs()];
108         FlatNode first=null;
109         FlatNode last=null;
110         TempDescriptor thisarg=null;
111
112         if (min.getExpression()!=null) {
113             thisarg=TempDescriptor.tempFactory("thisarg",min.getExpression().getType());
114             NodePair np=flattenExpressionNode(min.getExpression(),thisarg);
115             first=np.getBegin();
116             last=np.getEnd();
117         }
118         
119         //Build arguments
120         for(int i=0;i<min.numArgs();i++) {
121             ExpressionNode en=min.getArg(i);
122             TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
123             temps[i]=td;
124             NodePair np=flattenExpressionNode(en, td);
125             if (first==null)
126                 first=np.getBegin();
127             else 
128                 last.addNext(np.getBegin());
129             last=np.getEnd();
130         }
131
132         MethodDescriptor md=min.getMethod();
133         
134         //Call to constructor
135         
136         FlatCall fc;
137         if(md.getReturnType()==null||md.getReturnType().isVoid())
138             fc=new FlatCall(md, null, thisarg, temps);
139         else 
140             fc=new FlatCall(md, out_temp, thisarg, temps);
141         if (first==null) {
142             first=fc;
143         } else
144             last.addNext(fc);
145         return new NodePair(first,fc);
146     }
147
148     private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) {
149         TempDescriptor tmp=TempDescriptor.tempFactory("temp",fan.getExpression().getType());
150         NodePair npe=flattenExpressionNode(fan.getExpression(),tmp);
151         FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
152         npe.getEnd().addNext(fn);
153         return new NodePair(npe.getBegin(),fn);
154     }
155
156     private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
157         // Two cases:
158         // left side is variable
159         // left side is field
160         
161         Operation base=an.getOperation().getBaseOp();
162         TempDescriptor src_tmp=TempDescriptor.tempFactory("src",an.getSrc().getType());
163         NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
164         FlatNode last=np_src.getEnd();
165         if (base!=null) {
166             TempDescriptor src_tmp2=TempDescriptor.tempFactory("tmp", an.getDest().getType());
167             NodePair np_dst_init=flattenExpressionNode(an.getDest(),src_tmp2);
168             last.addNext(np_dst_init.getBegin());
169             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst_tmp",an.getDest().getType());
170             FlatOpNode fon=new FlatOpNode(dst_tmp, src_tmp,src_tmp2, base);
171             np_dst_init.getEnd().addNext(fon);
172             last=fon;
173             src_tmp=dst_tmp;
174         }
175         
176         if (an.getDest().kind()==Kind.FieldAccessNode) {
177             FieldAccessNode fan=(FieldAccessNode)an.getDest();
178             ExpressionNode en=fan.getExpression();
179             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
180             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
181             last.addNext(np_baseexp.getBegin());
182             FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
183             np_baseexp.getEnd().addNext(fsfn);
184             return new NodePair(np_src.getBegin(), fsfn);
185         } else if (an.getDest().kind()==Kind.NameNode) {
186             NameNode nn=(NameNode)an.getDest();
187             if (nn.getExpression()!=null) {
188                 FieldAccessNode fan=(FieldAccessNode)nn.getExpression();
189                 ExpressionNode en=fan.getExpression();
190                 TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
191                 NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
192                 last.addNext(np_baseexp.getBegin());
193                 FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
194                 np_baseexp.getEnd().addNext(fsfn);
195                 return new NodePair(np_src.getBegin(), fsfn);
196             } else {
197                 if (nn.getField()!=null) {
198                     FlatSetFieldNode fsfn=new FlatSetFieldNode(getTempforVar(nn.getVar()), nn.getField(), src_tmp);
199                     last.addNext(fsfn);
200                     return new NodePair(np_src.getBegin(), fsfn);
201                 } else {
202                     FlatOpNode fon=new FlatOpNode(getTempforVar(nn.getVar()), src_tmp, null, new Operation(Operation.ASSIGN));
203                     last.addNext(fon);
204                     return new NodePair(np_src.getBegin(),fon);
205                 }
206             }
207         } 
208         throw new Error();
209     }
210
211     private NodePair flattenNameNode(NameNode nn,TempDescriptor out_temp) {
212         if (nn.getExpression()!=null) {
213             /* Hack - use subtree instead */
214             return flattenExpressionNode(nn.getExpression(),out_temp);
215         } else if (nn.getField()!=null) {
216             TempDescriptor tmp=getTempforVar(nn.getVar());
217             FlatFieldNode ffn=new FlatFieldNode(nn.getField(), tmp, out_temp); 
218             return new NodePair(ffn,ffn);
219         } else {
220             TempDescriptor tmp=getTempforVar(nn.getVar());
221             FlatOpNode fon=new FlatOpNode(out_temp, tmp, null, new Operation(Operation.ASSIGN));
222             return new NodePair(fon,fon);
223         }
224     }
225
226     private NodePair flattenOpNode(OpNode on,TempDescriptor out_temp) {
227         TempDescriptor temp_left=TempDescriptor.tempFactory("leftop",on.getLeft().getType());
228         TempDescriptor temp_right=null;
229
230         Operation op=on.getOp();
231         if (op.getOp()==Operation.POSTINC||
232             op.getOp()==Operation.POSTDEC||
233             op.getOp()==Operation.PREINC||
234             op.getOp()==Operation.PREDEC) {
235             LiteralNode ln=new LiteralNode("int",new Integer(1));
236             ln.setType(new TypeDescriptor(TypeDescriptor.INT));
237             AssignmentNode an=new AssignmentNode(on.getLeft(),ln,
238                                new AssignOperation((op.getOp()==Operation.POSTINC||op.getOp()==Operation.PREINC)?AssignOperation.PLUSEQ:AssignOperation.MINUSEQ));
239             if (op.getOp()==Operation.POSTINC||
240                 op.getOp()==Operation.POSTDEC) {
241                 NodePair left=flattenExpressionNode(on.getLeft(),out_temp);
242                 NodePair assign=flattenAssignmentNode(an,temp_left);
243                 left.getEnd().addNext(assign.getBegin());
244                 return new NodePair(left.getBegin(),assign.getEnd());
245             } else {
246                 NodePair assign=flattenAssignmentNode(an,out_temp);
247                 return assign;
248             }
249         } 
250         
251         NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
252         NodePair right;
253         if (on.getRight()!=null) {
254             temp_right=TempDescriptor.tempFactory("rightop",on.getRight().getType());
255             right=flattenExpressionNode(on.getRight(),temp_right);
256         } else {
257             FlatNop nop=new FlatNop();
258             right=new NodePair(nop,nop);
259         }
260
261         if (op.getOp()==Operation.LOGIC_OR) {
262             /* Need to do shortcircuiting */
263             FlatCondBranch fcb=new FlatCondBranch(temp_left);
264             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
265             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
266             FlatNop fnop=new FlatNop();
267             left.getEnd().addNext(fcb);
268             fcb.addFalseNext(right.getBegin());
269             right.getEnd().addNext(fon2);
270             fon2.addNext(fnop);
271             fcb.addTrueNext(fon1);
272             fon1.addNext(fnop);
273             return new NodePair(left.getBegin(), fnop);
274         } else if (op.getOp()==Operation.LOGIC_AND) {
275             /* Need to do shortcircuiting */
276             FlatCondBranch fcb=new FlatCondBranch(temp_left);
277             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
278             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
279             FlatNop fnop=new FlatNop();
280             left.getEnd().addNext(fcb);
281             fcb.addTrueNext(right.getBegin());
282             right.getEnd().addNext(fon2);
283             fon2.addNext(fnop);
284             fcb.addFalseNext(fon1);
285             fon1.addNext(fnop);
286             return new NodePair(left.getBegin(), fnop);
287         }
288
289         FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
290         left.getEnd().addNext(right.getBegin());
291         right.getEnd().addNext(fon);
292         return new NodePair(left.getBegin(),fon);
293     }
294
295     private NodePair flattenExpressionNode(ExpressionNode en, TempDescriptor out_temp) {
296         switch(en.kind()) {
297         case Kind.AssignmentNode:
298             return flattenAssignmentNode((AssignmentNode)en,out_temp);
299         case Kind.CastNode:
300             return flattenCastNode((CastNode)en,out_temp);
301         case Kind.CreateObjectNode:
302             return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
303         case Kind.FieldAccessNode:
304             return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
305         case Kind.LiteralNode:
306             return flattenLiteralNode((LiteralNode)en,out_temp);
307         case Kind.MethodInvokeNode:
308             return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
309         case Kind.NameNode:
310             return flattenNameNode((NameNode)en,out_temp);
311         case Kind.OpNode:
312             return flattenOpNode((OpNode)en,out_temp);
313         }
314         throw new Error();
315     }
316
317     private NodePair flattenDeclarationNode(DeclarationNode dn) {
318         VarDescriptor vd=dn.getVarDescriptor();
319         TempDescriptor td=getTempforVar(vd);
320         if (dn.getExpression()!=null)
321             return flattenExpressionNode(dn.getExpression(),td);
322         else {
323             FlatNop fn=new FlatNop();
324             return new NodePair(fn,fn);
325         }
326     }
327         
328     private TempDescriptor getTempforVar(VarDescriptor vd) {
329         if (temptovar.containsKey(vd))
330             return (TempDescriptor)temptovar.get(vd);
331         else {
332             TempDescriptor td=TempDescriptor.tempFactory(vd.getName(),vd.getType());
333             temptovar.put(vd,td);
334             return td;
335         }
336     }
337
338     private NodePair flattenIfStatementNode(IfStatementNode isn) {
339         TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
340         NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
341         FlatCondBranch fcb=new FlatCondBranch(cond_temp);
342         NodePair true_np=flattenBlockNode(isn.getTrueBlock());
343         NodePair false_np;
344         FlatNop nopend=new FlatNop();
345
346         if (isn.getFalseBlock()!=null)
347             false_np=flattenBlockNode(isn.getFalseBlock());
348         else {
349             FlatNop nop=new FlatNop();
350             false_np=new NodePair(nop,nop);
351         }
352
353         cond.getEnd().addNext(fcb);
354         fcb.addTrueNext(true_np.getBegin());
355         fcb.addFalseNext(false_np.getBegin());
356         true_np.getEnd().addNext(nopend);
357         false_np.getEnd().addNext(nopend);
358         return new NodePair(cond.getBegin(), nopend);
359     }
360             
361     private NodePair flattenLoopNode(LoopNode ln) {
362         if (ln.getType()==LoopNode.FORLOOP) {
363             NodePair initializer=flattenBlockNode(ln.getInitializer());
364             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
365             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
366             NodePair update=flattenBlockNode(ln.getUpdate());
367             NodePair body=flattenBlockNode(ln.getBody());
368             FlatNode begin=initializer.getBegin();
369             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
370             FlatNop nopend=new FlatNop();
371
372             initializer.getEnd().addNext(condition.getBegin());
373             body.getEnd().addNext(update.getBegin());
374             update.getEnd().addNext(condition.getBegin());
375             condition.getEnd().addNext(fcb);
376             fcb.addFalseNext(nopend);
377             fcb.addTrueNext(body.getBegin());
378             return new NodePair(begin,nopend);
379         } else if (ln.getType()==LoopNode.WHILELOOP) {
380             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
381             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
382             NodePair body=flattenBlockNode(ln.getBody());
383             FlatNode begin=condition.getBegin();
384             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
385             FlatNop nopend=new FlatNop();
386
387             body.getEnd().addNext(condition.getBegin());
388             condition.getEnd().addNext(fcb);
389             fcb.addFalseNext(nopend);
390             fcb.addTrueNext(body.getBegin());
391             return new NodePair(begin,nopend);
392         } else if (ln.getType()==LoopNode.DOWHILELOOP) {
393             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
394             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
395             NodePair body=flattenBlockNode(ln.getBody());
396             FlatNode begin=body.getBegin();
397             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
398             FlatNop nopend=new FlatNop();
399
400             body.getEnd().addNext(condition.getBegin());
401             condition.getEnd().addNext(fcb);
402             fcb.addFalseNext(nopend);
403             fcb.addTrueNext(body.getBegin());
404             return new NodePair(begin,nopend);
405         } else throw new Error();
406     }
407             
408     private NodePair flattenReturnNode(ReturnNode rntree) {
409         TempDescriptor retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
410         NodePair cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
411         FlatReturnNode rnflat=new FlatReturnNode(retval);
412         cond.getEnd().addNext(rnflat);
413         return new NodePair(cond.getBegin(),rnflat);
414     }
415             
416     private NodePair flattenSubBlockNode(SubBlockNode sbn) {
417         return flattenBlockNode(sbn.getBlockNode());
418     }
419
420     private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
421         switch(bsn.kind()) {
422         case Kind.BlockExpressionNode:
423             return flattenBlockExpressionNode((BlockExpressionNode)bsn);
424             
425         case Kind.DeclarationNode:
426             return flattenDeclarationNode((DeclarationNode)bsn);
427             
428         case Kind.IfStatementNode:
429             return flattenIfStatementNode((IfStatementNode)bsn);
430             
431         case Kind.LoopNode:
432             return flattenLoopNode((LoopNode)bsn);
433             
434         case Kind.ReturnNode:
435             return flattenReturnNode((IR.Tree.ReturnNode)bsn);
436             
437         case Kind.SubBlockNode:
438             return flattenSubBlockNode((SubBlockNode)bsn);
439             
440         }
441         throw new Error();
442     }
443 }