Flatten fields in namenodes
[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 void buildFlat() {
16         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
17         while(it.hasNext()) {
18             ClassDescriptor cn=(ClassDescriptor)it.next();
19             flattenClass(cn);
20         }
21     }
22     
23     private void flattenClass(ClassDescriptor cn) {
24         Iterator methodit=cn.getMethods();
25         while(methodit.hasNext()) {
26             MethodDescriptor md=(MethodDescriptor)methodit.next();
27             BlockNode bn=state.getMethodBody(md);
28             FlatNode fn=flattenBlockNode(bn).getBegin();
29             FlatMethod fm=new FlatMethod(md, fn);
30             System.out.println(fm.printMethod());
31             state.addFlatCode(md,fm);
32         }
33     }
34
35     private NodePair flattenBlockNode(BlockNode bn) {
36         FlatNode begin=null;
37         FlatNode end=null;
38         for(int i=0;i<bn.size();i++) {
39             NodePair np=flattenBlockStatementNode(bn.get(i));
40             FlatNode np_begin=np.getBegin();
41             FlatNode np_end=np.getEnd();
42             if (begin==null) {
43                 begin=np_begin;
44             }
45             if (end==null) {
46                 end=np_end;
47             } else {
48                 end.addNext(np_begin);
49                 end=np_end;
50             }
51         }
52         if (begin==null) {
53             end=begin=new FlatNop();
54         }
55         return new NodePair(begin,end);
56     }
57
58     private NodePair flattenBlockExpressionNode(BlockExpressionNode en) {
59         TempDescriptor tmp=TempDescriptor.tempFactory("neverused");
60         return flattenExpressionNode(en.getExpression(),tmp);
61     }
62
63     private NodePair flattenCastNode(CastNode cn,TempDescriptor out_temp) {
64         TempDescriptor tmp=TempDescriptor.tempFactory("tocast");
65         NodePair np=flattenExpressionNode(cn.getExpression(), tmp);
66         FlatCastNode fcn=new FlatCastNode(cn.getType(), tmp, out_temp);
67         np.getEnd().addNext(fcn);
68         return new NodePair(np.getBegin(),fcn);
69     }
70
71     private NodePair flattenLiteralNode(LiteralNode ln,TempDescriptor out_temp) {
72         FlatLiteralNode fln=new FlatLiteralNode(ln.getType(), ln.getValue(), out_temp);
73         return new NodePair(fln,fln);
74     }
75
76     private NodePair flattenCreateObjectNode(CreateObjectNode con,TempDescriptor out_temp) {
77         TypeDescriptor td=con.getType();
78         FlatNew fn=new FlatNew(td, out_temp);
79         TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
80         FlatNode last=fn;
81         //Build arguments
82         for(int i=0;i<con.numArgs();i++) {
83             ExpressionNode en=con.getArg(i);
84             TempDescriptor tmp=TempDescriptor.tempFactory("arg");
85             temps[i]=tmp;
86             NodePair np=flattenExpressionNode(en, tmp);
87             last.addNext(np.getBegin());
88             last=np.getEnd();
89         }
90         MethodDescriptor md=con.getConstructor();
91         //Call to constructor
92         FlatCall fc=new FlatCall(md, null, out_temp, temps);
93         last.addNext(fc);
94         return new NodePair(fn,fc);
95     }
96
97     private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) {
98         TempDescriptor[] temps=new TempDescriptor[min.numArgs()];
99         FlatNode first=null;
100         FlatNode last=null;
101         TempDescriptor thisarg=null;
102
103         if (min.getExpression()!=null) {
104             thisarg=TempDescriptor.tempFactory("thisarg");
105             NodePair np=flattenExpressionNode(min.getExpression(),thisarg);
106             first=np.getBegin();
107             last=np.getEnd();
108         }
109         
110         //Build arguments
111         for(int i=0;i<min.numArgs();i++) {
112             ExpressionNode en=min.getArg(i);
113             TempDescriptor td=TempDescriptor.tempFactory("arg");
114             temps[i]=td;
115             NodePair np=flattenExpressionNode(en, td);
116             if (first==null)
117                 first=np.getBegin();
118             else 
119                 last.addNext(np.getBegin());
120             last=np.getEnd();
121         }
122
123         MethodDescriptor md=min.getMethod();
124         
125         //Call to constructor
126         FlatCall fc=new FlatCall(md, out_temp, thisarg, temps);
127         if (first==null) {
128             first=fc;
129         } else
130             last.addNext(fc);
131         return new NodePair(first,fc);
132     }
133
134     private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) {
135         TempDescriptor tmp=TempDescriptor.tempFactory("temp");
136         NodePair npe=flattenExpressionNode(fan.getExpression(),tmp);
137         FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
138         npe.getEnd().addNext(fn);
139         return new NodePair(npe.getBegin(),fn);
140     }
141
142     private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
143         // Two cases:
144         // left side is variable
145         // left side is field
146         
147         Operation base=an.getOperation().getBaseOp();
148         TempDescriptor src_tmp=TempDescriptor.tempFactory("src");
149         NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
150         FlatNode last=np_src.getEnd();
151         if (base!=null) {
152             TempDescriptor src_tmp2=TempDescriptor.tempFactory("tmp");
153             NodePair np_dst_init=flattenExpressionNode(an.getDest(),src_tmp2);
154             last.addNext(np_dst_init.getBegin());
155             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst_tmp");
156             FlatOpNode fon=new FlatOpNode(dst_tmp, src_tmp,src_tmp2, base);
157             np_dst_init.getEnd().addNext(fon);
158             last=fon;
159             src_tmp=dst_tmp;
160         }
161         
162         if (an.getDest().kind()==Kind.FieldAccessNode) {
163             FieldAccessNode fan=(FieldAccessNode)an.getDest();
164             ExpressionNode en=fan.getExpression();
165             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst");
166             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
167             last.addNext(np_baseexp.getBegin());
168             FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
169             np_baseexp.getEnd().addNext(fsfn);
170             return new NodePair(np_src.getBegin(), fsfn);
171         } else if (an.getDest().kind()==Kind.NameNode) {
172             NameNode nn=(NameNode)an.getDest();
173             if (nn.getExpression()!=null) {
174                 FieldAccessNode fan=(FieldAccessNode)nn.getExpression();
175                 ExpressionNode en=fan.getExpression();
176                 TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst");
177                 NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
178                 last.addNext(np_baseexp.getBegin());
179                 FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
180                 np_baseexp.getEnd().addNext(fsfn);
181                 return new NodePair(np_src.getBegin(), fsfn);
182             } else {
183                 if (nn.getField()!=null) {
184                     FlatSetFieldNode fsfn=new FlatSetFieldNode(getTempforVar(nn.getVar()), nn.getField(), src_tmp);
185                     last.addNext(fsfn);
186                     return new NodePair(np_src.getBegin(), fsfn);
187                 } else {
188                     FlatOpNode fon=new FlatOpNode(getTempforVar(nn.getVar()), src_tmp, null, new Operation(Operation.ASSIGN));
189                     last.addNext(fon);
190                     return new NodePair(np_src.getBegin(),fon);
191                 }
192             }
193         } 
194         throw new Error();
195     }
196
197     private NodePair flattenNameNode(NameNode nn,TempDescriptor out_temp) {
198         if (nn.getExpression()!=null) {
199             /* Hack - use subtree instead */
200             return flattenExpressionNode(nn.getExpression(),out_temp);
201         } else if (nn.getField()!=null) {
202             TempDescriptor tmp=getTempforVar(nn.getVar());
203             FlatFieldNode ffn=new FlatFieldNode(nn.getField(), tmp, out_temp); 
204             return new NodePair(ffn,ffn);
205         } else {
206             TempDescriptor tmp=getTempforVar(nn.getVar());
207             FlatOpNode fon=new FlatOpNode(out_temp, tmp, null, new Operation(Operation.ASSIGN));
208             return new NodePair(fon,fon);
209         }
210     }
211
212     private NodePair flattenOpNode(OpNode on,TempDescriptor out_temp) {
213         TempDescriptor temp_left=TempDescriptor.tempFactory("leftop");
214         TempDescriptor temp_right=TempDescriptor.tempFactory("rightop");
215         NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
216         NodePair right;
217         if (on.getRight()!=null)
218             right=flattenExpressionNode(on.getRight(),temp_right);
219         else {
220             FlatNop nop=new FlatNop();
221             right=new NodePair(nop,nop);
222         }
223         Operation op=on.getOp();
224         FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
225         left.getEnd().addNext(right.getBegin());
226         right.getEnd().addNext(fon);
227         return new NodePair(left.getBegin(),fon);
228     }
229
230     private NodePair flattenExpressionNode(ExpressionNode en, TempDescriptor out_temp) {
231         switch(en.kind()) {
232         case Kind.AssignmentNode:
233             return flattenAssignmentNode((AssignmentNode)en,out_temp);
234         case Kind.CastNode:
235             return flattenCastNode((CastNode)en,out_temp);
236         case Kind.CreateObjectNode:
237             return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
238         case Kind.FieldAccessNode:
239             return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
240         case Kind.LiteralNode:
241             return flattenLiteralNode((LiteralNode)en,out_temp);
242         case Kind.MethodInvokeNode:
243             return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
244         case Kind.NameNode:
245             return flattenNameNode((NameNode)en,out_temp);
246         case Kind.OpNode:
247             return flattenOpNode((OpNode)en,out_temp);
248         }
249         throw new Error();
250     }
251
252     private NodePair flattenDeclarationNode(DeclarationNode dn) {
253         VarDescriptor vd=dn.getVarDescriptor();
254         TempDescriptor td=getTempforVar(vd);
255         if (dn.getExpression()!=null)
256             return flattenExpressionNode(dn.getExpression(),td);
257         else {
258             FlatNop fn=new FlatNop();
259             return new NodePair(fn,fn);
260         }
261     }
262         
263     private TempDescriptor getTempforVar(VarDescriptor vd) {
264         if (temptovar.containsKey(vd))
265             return (TempDescriptor)temptovar.get(vd);
266         else {
267             TempDescriptor td=TempDescriptor.tempFactory(vd.getName());
268             temptovar.put(vd,td);
269             return td;
270         }
271     }
272
273     private NodePair flattenIfStatementNode(IfStatementNode isn) {
274         TempDescriptor cond_temp=TempDescriptor.tempFactory("condition");
275         NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
276         FlatCondBranch fcb=new FlatCondBranch(cond_temp);
277         NodePair true_np=flattenBlockNode(isn.getTrueBlock());
278         NodePair false_np;
279         FlatNop nopend=new FlatNop();
280
281         if (isn.getFalseBlock()!=null)
282             false_np=flattenBlockNode(isn.getFalseBlock());
283         else {
284             FlatNop nop=new FlatNop();
285             false_np=new NodePair(nop,nop);
286         }
287
288         cond.getEnd().addNext(fcb);
289         fcb.addTrueNext(true_np.getBegin());
290         fcb.addFalseNext(false_np.getBegin());
291         true_np.getEnd().addNext(nopend);
292         false_np.getEnd().addNext(nopend);
293         return new NodePair(cond.getBegin(), nopend);
294     }
295             
296     private NodePair flattenLoopNode(LoopNode ln) {
297         if (ln.getType()==LoopNode.FORLOOP) {
298             NodePair initializer=flattenBlockNode(ln.getInitializer());
299             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition");
300             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
301             NodePair update=flattenBlockNode(ln.getUpdate());
302             NodePair body=flattenBlockNode(ln.getBody());
303             FlatNode begin=initializer.getBegin();
304             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
305             FlatNop nopend=new FlatNop();
306
307             initializer.getEnd().addNext(condition.getBegin());
308             body.getEnd().addNext(update.getBegin());
309             update.getEnd().addNext(condition.getBegin());
310             condition.getEnd().addNext(fcb);
311             fcb.addFalseNext(nopend);
312             fcb.addTrueNext(body.getBegin());
313             return new NodePair(begin,nopend);
314         } else if (ln.getType()==LoopNode.WHILELOOP) {
315             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition");
316             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
317             NodePair body=flattenBlockNode(ln.getBody());
318             FlatNode begin=condition.getBegin();
319             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
320             FlatNop nopend=new FlatNop();
321
322             body.getEnd().addNext(condition.getBegin());
323             condition.getEnd().addNext(fcb);
324             fcb.addFalseNext(nopend);
325             fcb.addTrueNext(body.getBegin());
326             return new NodePair(begin,nopend);
327         } else if (ln.getType()==LoopNode.DOWHILELOOP) {
328             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition");
329             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
330             NodePair body=flattenBlockNode(ln.getBody());
331             FlatNode begin=body.getBegin();
332             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
333             FlatNop nopend=new FlatNop();
334
335             body.getEnd().addNext(condition.getBegin());
336             condition.getEnd().addNext(fcb);
337             fcb.addFalseNext(nopend);
338             fcb.addTrueNext(body.getBegin());
339             return new NodePair(begin,nopend);
340         } else throw new Error();
341     }
342             
343     private NodePair flattenReturnNode(ReturnNode rntree) {
344         TempDescriptor retval=TempDescriptor.tempFactory("ret_value");
345         NodePair cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
346         FlatReturnNode rnflat=new FlatReturnNode(retval);
347         cond.getEnd().addNext(rnflat);
348         return new NodePair(cond.getBegin(),rnflat);
349     }
350             
351     private NodePair flattenSubBlockNode(SubBlockNode sbn) {
352         return flattenBlockNode(sbn.getBlockNode());
353     }
354
355     private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
356         switch(bsn.kind()) {
357         case Kind.BlockExpressionNode:
358             return flattenBlockExpressionNode((BlockExpressionNode)bsn);
359             
360         case Kind.DeclarationNode:
361             return flattenDeclarationNode((DeclarationNode)bsn);
362             
363         case Kind.IfStatementNode:
364             return flattenIfStatementNode((IfStatementNode)bsn);
365             
366         case Kind.LoopNode:
367             return flattenLoopNode((LoopNode)bsn);
368             
369         case Kind.ReturnNode:
370             return flattenReturnNode((IR.Tree.ReturnNode)bsn);
371             
372         case Kind.SubBlockNode:
373             return flattenSubBlockNode((SubBlockNode)bsn);
374             
375         }
376         throw new Error();
377     }
378 }