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         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         NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
231         NodePair right;
232         if (on.getRight()!=null) {
233             temp_right=TempDescriptor.tempFactory("rightop",on.getRight().getType());
234             right=flattenExpressionNode(on.getRight(),temp_right);
235         } else {
236             FlatNop nop=new FlatNop();
237             right=new NodePair(nop,nop);
238         }
239         Operation op=on.getOp();
240         FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
241         left.getEnd().addNext(right.getBegin());
242         right.getEnd().addNext(fon);
243         return new NodePair(left.getBegin(),fon);
244     }
245
246     private NodePair flattenExpressionNode(ExpressionNode en, TempDescriptor out_temp) {
247         switch(en.kind()) {
248         case Kind.AssignmentNode:
249             return flattenAssignmentNode((AssignmentNode)en,out_temp);
250         case Kind.CastNode:
251             return flattenCastNode((CastNode)en,out_temp);
252         case Kind.CreateObjectNode:
253             return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
254         case Kind.FieldAccessNode:
255             return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
256         case Kind.LiteralNode:
257             return flattenLiteralNode((LiteralNode)en,out_temp);
258         case Kind.MethodInvokeNode:
259             return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
260         case Kind.NameNode:
261             return flattenNameNode((NameNode)en,out_temp);
262         case Kind.OpNode:
263             return flattenOpNode((OpNode)en,out_temp);
264         }
265         throw new Error();
266     }
267
268     private NodePair flattenDeclarationNode(DeclarationNode dn) {
269         VarDescriptor vd=dn.getVarDescriptor();
270         TempDescriptor td=getTempforVar(vd);
271         if (dn.getExpression()!=null)
272             return flattenExpressionNode(dn.getExpression(),td);
273         else {
274             FlatNop fn=new FlatNop();
275             return new NodePair(fn,fn);
276         }
277     }
278         
279     private TempDescriptor getTempforVar(VarDescriptor vd) {
280         if (temptovar.containsKey(vd))
281             return (TempDescriptor)temptovar.get(vd);
282         else {
283             TempDescriptor td=TempDescriptor.tempFactory(vd.getName(),vd.getType());
284             temptovar.put(vd,td);
285             return td;
286         }
287     }
288
289     private NodePair flattenIfStatementNode(IfStatementNode isn) {
290         TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
291         NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
292         FlatCondBranch fcb=new FlatCondBranch(cond_temp);
293         NodePair true_np=flattenBlockNode(isn.getTrueBlock());
294         NodePair false_np;
295         FlatNop nopend=new FlatNop();
296
297         if (isn.getFalseBlock()!=null)
298             false_np=flattenBlockNode(isn.getFalseBlock());
299         else {
300             FlatNop nop=new FlatNop();
301             false_np=new NodePair(nop,nop);
302         }
303
304         cond.getEnd().addNext(fcb);
305         fcb.addTrueNext(true_np.getBegin());
306         fcb.addFalseNext(false_np.getBegin());
307         true_np.getEnd().addNext(nopend);
308         false_np.getEnd().addNext(nopend);
309         return new NodePair(cond.getBegin(), nopend);
310     }
311             
312     private NodePair flattenLoopNode(LoopNode ln) {
313         if (ln.getType()==LoopNode.FORLOOP) {
314             NodePair initializer=flattenBlockNode(ln.getInitializer());
315             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
316             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
317             NodePair update=flattenBlockNode(ln.getUpdate());
318             NodePair body=flattenBlockNode(ln.getBody());
319             FlatNode begin=initializer.getBegin();
320             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
321             FlatNop nopend=new FlatNop();
322
323             initializer.getEnd().addNext(condition.getBegin());
324             body.getEnd().addNext(update.getBegin());
325             update.getEnd().addNext(condition.getBegin());
326             condition.getEnd().addNext(fcb);
327             fcb.addFalseNext(nopend);
328             fcb.addTrueNext(body.getBegin());
329             return new NodePair(begin,nopend);
330         } else if (ln.getType()==LoopNode.WHILELOOP) {
331             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
332             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
333             NodePair body=flattenBlockNode(ln.getBody());
334             FlatNode begin=condition.getBegin();
335             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
336             FlatNop nopend=new FlatNop();
337
338             body.getEnd().addNext(condition.getBegin());
339             condition.getEnd().addNext(fcb);
340             fcb.addFalseNext(nopend);
341             fcb.addTrueNext(body.getBegin());
342             return new NodePair(begin,nopend);
343         } else if (ln.getType()==LoopNode.DOWHILELOOP) {
344             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
345             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
346             NodePair body=flattenBlockNode(ln.getBody());
347             FlatNode begin=body.getBegin();
348             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
349             FlatNop nopend=new FlatNop();
350
351             body.getEnd().addNext(condition.getBegin());
352             condition.getEnd().addNext(fcb);
353             fcb.addFalseNext(nopend);
354             fcb.addTrueNext(body.getBegin());
355             return new NodePair(begin,nopend);
356         } else throw new Error();
357     }
358             
359     private NodePair flattenReturnNode(ReturnNode rntree) {
360         TempDescriptor retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
361         NodePair cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
362         FlatReturnNode rnflat=new FlatReturnNode(retval);
363         cond.getEnd().addNext(rnflat);
364         return new NodePair(cond.getBegin(),rnflat);
365     }
366             
367     private NodePair flattenSubBlockNode(SubBlockNode sbn) {
368         return flattenBlockNode(sbn.getBlockNode());
369     }
370
371     private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
372         switch(bsn.kind()) {
373         case Kind.BlockExpressionNode:
374             return flattenBlockExpressionNode((BlockExpressionNode)bsn);
375             
376         case Kind.DeclarationNode:
377             return flattenDeclarationNode((DeclarationNode)bsn);
378             
379         case Kind.IfStatementNode:
380             return flattenIfStatementNode((IfStatementNode)bsn);
381             
382         case Kind.LoopNode:
383             return flattenLoopNode((LoopNode)bsn);
384             
385         case Kind.ReturnNode:
386             return flattenReturnNode((IR.Tree.ReturnNode)bsn);
387             
388         case Kind.SubBlockNode:
389             return flattenSubBlockNode((SubBlockNode)bsn);
390             
391         }
392         throw new Error();
393     }
394 }