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