Outgoing socket I/O
[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     MethodDescriptor currmd;
10     TypeUtil typeutil;
11
12     public BuildFlat(State st, TypeUtil typeutil) {
13         state=st;
14         temptovar=new Hashtable();
15         this.typeutil=typeutil;
16     }
17
18     public Hashtable getMap() {
19         return temptovar;
20     }
21
22     public void buildFlat() {
23         Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
24         while(it.hasNext()) {
25             ClassDescriptor cn=(ClassDescriptor)it.next();
26             flattenClass(cn);
27         }
28         
29         Iterator task_it=state.getTaskSymbolTable().getDescriptorsIterator();
30         while(task_it.hasNext()) {
31             TaskDescriptor td=(TaskDescriptor)task_it.next();
32             flattenTask(td);
33         }
34     }
35     
36     private void flattenTask(TaskDescriptor td) {
37         BlockNode bn=state.getMethodBody(td);
38         FlatNode fn=flattenBlockNode(bn).getBegin();
39         FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.PRE);
40         ffan.addNext(fn);
41         FlatMethod fm=new FlatMethod(td, ffan);
42
43         for(int i=0;i<td.numParameters();i++) {
44             fm.addParameterTemp(getTempforVar(td.getParameter(i)));
45         }
46
47         /* Flatten Vector of Flag Effects */
48         Vector flags=td.getFlagEffects();
49         updateFlagActionNode(ffan,flags);
50
51         state.addFlatCode(td,fm);
52     }
53
54
55     /* This method transforms a vector of FlagEffects into the FlatFlagActionNode */
56     private void updateFlagActionNode(FlatFlagActionNode ffan, Vector flags) {
57         if (flags==null) // Do nothing if the flag effects vector is empty
58             return;
59
60         for(int i=0;i<flags.size();i++) {
61             FlagEffects fes=(FlagEffects)flags.get(i);
62             TempDescriptor flagtemp=getTempforVar(fes.getVar());
63             for(int j=0;j<fes.numEffects();j++) {
64                 FlagEffect fe=fes.getEffect(j);
65                 ffan.addFlagAction(flagtemp, fe.getFlag(), fe.getStatus());
66             }
67         }
68     }
69
70     private void flattenClass(ClassDescriptor cn) {
71         Iterator methodit=cn.getMethods();
72         while(methodit.hasNext()) {
73             currmd=(MethodDescriptor)methodit.next();
74             BlockNode bn=state.getMethodBody(currmd);
75             NodePair np=flattenBlockNode(bn);
76             FlatNode fn=np.getBegin();
77             if (state.THREAD&&currmd.getModifiers().isSynchronized()) {
78                 MethodDescriptor memd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorEnter");
79                 TempDescriptor thistd=getTempforVar(currmd.getThis());
80                 FlatCall fc=new FlatCall(memd, null, thistd, new TempDescriptor[0]);
81                 fc.addNext(fn);
82                 fn=fc;
83                 if (np.getEnd().kind()!=FKind.FlatReturnNode) {
84                     MethodDescriptor memdex=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
85                     FlatCall fcunlock=new FlatCall(memdex, null, thistd, new TempDescriptor[0]);
86                     np.getEnd().addNext(fcunlock);
87                 }
88             }
89
90             FlatMethod fm=new FlatMethod(currmd, fn);
91             if (!currmd.isStatic())
92                 fm.addParameterTemp(getTempforParam(currmd.getThis()));
93             for(int i=0;i<currmd.numParameters();i++) {
94                 fm.addParameterTemp(getTempforParam(currmd.getParameter(i)));
95             }
96             state.addFlatCode(currmd,fm);
97         }
98     }
99
100     private NodePair flattenBlockNode(BlockNode bn) {
101         FlatNode begin=null;
102         FlatNode end=null;
103         for(int i=0;i<bn.size();i++) {
104             NodePair np=flattenBlockStatementNode(bn.get(i));
105             FlatNode np_begin=np.getBegin();
106             FlatNode np_end=np.getEnd();
107             if (begin==null) {
108                 begin=np_begin;
109             }
110             if (end==null) {
111                 end=np_end;
112             } else {
113                 end.addNext(np_begin);
114                 end=np_end;
115             }
116         }
117         if (begin==null) {
118             end=begin=new FlatNop();
119         }
120         return new NodePair(begin,end);
121     }
122
123     private NodePair flattenBlockExpressionNode(BlockExpressionNode en) {
124         TempDescriptor tmp=TempDescriptor.tempFactory("neverused",en.getExpression().getType());
125         return flattenExpressionNode(en.getExpression(),tmp);
126     }
127
128     private NodePair flattenCastNode(CastNode cn,TempDescriptor out_temp) {
129         TempDescriptor tmp=TempDescriptor.tempFactory("tocast",cn.getExpression().getType());
130         NodePair np=flattenExpressionNode(cn.getExpression(), tmp);
131         FlatCastNode fcn=new FlatCastNode(cn.getType(), tmp, out_temp);
132         np.getEnd().addNext(fcn);
133         return new NodePair(np.getBegin(),fcn);
134     }
135
136     private NodePair flattenLiteralNode(LiteralNode ln,TempDescriptor out_temp) {
137         FlatLiteralNode fln=new FlatLiteralNode(ln.getType(), ln.getValue(), out_temp);
138         return new NodePair(fln,fln);
139     }
140
141     private NodePair flattenCreateObjectNode(CreateObjectNode con,TempDescriptor out_temp) {
142         TypeDescriptor td=con.getType();
143         if (!td.isArray()) {
144             FlatNew fn=new FlatNew(td, out_temp);
145             TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
146             FlatNode last=fn;
147             if (td.getClassDesc().hasFlags()) {
148                 //          if (con.getFlagEffects()!=null) {
149                 FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.NEWOBJECT);
150                 FlagEffects fes=con.getFlagEffects();
151                 TempDescriptor flagtemp=out_temp;
152                 if (fes!=null)
153                     for(int j=0;j<fes.numEffects();j++) {
154                         FlagEffect fe=fes.getEffect(j);
155                         ffan.addFlagAction(flagtemp, fe.getFlag(), fe.getStatus());
156                     } else {
157                         ffan.addFlagAction(flagtemp, null, false);
158                     }
159                 
160                 last.addNext(ffan);
161                 last=ffan;
162             }
163             //Build arguments
164             for(int i=0;i<con.numArgs();i++) {
165                 ExpressionNode en=con.getArg(i);
166                 TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
167                 temps[i]=tmp;
168                 NodePair np=flattenExpressionNode(en, tmp);
169                 last.addNext(np.getBegin());
170                 last=np.getEnd();
171             }
172             MethodDescriptor md=con.getConstructor();
173             //Call to constructor
174             FlatCall fc=new FlatCall(md, null, out_temp, temps);
175             last.addNext(fc);
176             last=fc;
177             return new NodePair(fn,last); 
178         } else {
179             FlatNode first=null;
180             FlatNode last=null;
181             TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
182             for (int i=0;i<con.numArgs();i++) {
183                 ExpressionNode en=con.getArg(i);
184                 TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
185                 temps[i]=tmp;           
186                 NodePair np=flattenExpressionNode(en, tmp);
187                 if (first==null)
188                     first=np.getBegin();
189                 else
190                     last.addNext(np.getBegin());
191                 last=np.getEnd();
192                 
193                 TempDescriptor tmp2=(i==0)?
194                     out_temp:
195                 TempDescriptor.tempFactory("arg",en.getType());
196             }
197             FlatNew fn=new FlatNew(td, out_temp, temps[0]);
198             last.addNext(fn);
199             if (temps.length>1) {
200                 NodePair np=generateNewArrayLoop(temps, td.dereference(), out_temp, 0);
201                 fn.addNext(np.getBegin());
202                 return new NodePair(first,np.getEnd()); 
203             } else
204                 return new NodePair(first, fn);
205         }
206     }
207
208     private NodePair generateNewArrayLoop(TempDescriptor[] temparray, TypeDescriptor td, TempDescriptor tmp, int i) {
209         TempDescriptor index=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
210         TempDescriptor tmpone=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
211         FlatNop fnop=new FlatNop();//last node
212
213         //index=0
214         FlatLiteralNode fln=new FlatLiteralNode(index.getType(),new Integer(0),index);
215         //tmpone=1
216         FlatLiteralNode fln2=new FlatLiteralNode(tmpone.getType(),new Integer(1),tmpone);
217
218         TempDescriptor tmpbool=TempDescriptor.tempFactory("comp",new TypeDescriptor(TypeDescriptor.BOOLEAN));
219
220         FlatOpNode fcomp=new FlatOpNode(tmpbool,index,temparray[i],new Operation(Operation.LT));
221         FlatCondBranch fcb=new FlatCondBranch(tmpbool);
222         //is index<temp[i]
223         TempDescriptor new_tmp=TempDescriptor.tempFactory("tmp",td);
224         FlatNew fn=new FlatNew(td, new_tmp, temparray[i+1]);
225         FlatSetElementNode fsen=new FlatSetElementNode(tmp,index,new_tmp);
226         // index=index+1
227         FlatOpNode fon=new FlatOpNode(index,index,tmpone,new Operation(Operation.ADD));
228         //jump out
229         fln.addNext(fln2);
230         fln2.addNext(fcomp);
231         fcomp.addNext(fcb);
232         fcb.addTrueNext(fn);
233         fcb.addFalseNext(fnop);
234         fn.addNext(fsen);
235         //Recursive call here
236         if ((i+2)<temparray.length) {
237             NodePair np2=generateNewArrayLoop(temparray, td.dereference(), new_tmp, i+1);
238             fsen.addNext(np2.getBegin());
239             np2.getEnd().addNext(fon);
240         } else {
241             fsen.addNext(fon);
242         }
243         fon.addNext(fcomp);
244         return new NodePair(fln, fnop);
245     }
246
247     private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) {
248         TempDescriptor[] temps=new TempDescriptor[min.numArgs()];
249         FlatNode first=null;
250         FlatNode last=null;
251         TempDescriptor thisarg=null;
252
253         if (min.getExpression()!=null) {
254             thisarg=TempDescriptor.tempFactory("thisarg",min.getExpression().getType());
255             NodePair np=flattenExpressionNode(min.getExpression(),thisarg);
256             first=np.getBegin();
257             last=np.getEnd();
258         }
259         
260         //Build arguments
261         for(int i=0;i<min.numArgs();i++) {
262             ExpressionNode en=min.getArg(i);
263             TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
264             temps[i]=td;
265             NodePair np=flattenExpressionNode(en, td);
266             if (first==null)
267                 first=np.getBegin();
268             else 
269                 last.addNext(np.getBegin());
270             last=np.getEnd();
271         }
272
273         MethodDescriptor md=min.getMethod();
274         
275         //Call to constructor
276         
277         FlatCall fc;
278         if(md.getReturnType()==null||md.getReturnType().isVoid())
279             fc=new FlatCall(md, null, thisarg, temps);
280         else 
281             fc=new FlatCall(md, out_temp, thisarg, temps);
282         if (first==null) {
283             first=fc;
284         } else
285             last.addNext(fc);
286         return new NodePair(first,fc);
287     }
288
289     private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) {
290         TempDescriptor tmp=TempDescriptor.tempFactory("temp",fan.getExpression().getType());
291         NodePair npe=flattenExpressionNode(fan.getExpression(),tmp);
292         FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
293         npe.getEnd().addNext(fn);
294         return new NodePair(npe.getBegin(),fn);
295     }
296
297     private NodePair flattenArrayAccessNode(ArrayAccessNode aan,TempDescriptor out_temp) {
298         TempDescriptor tmp=TempDescriptor.tempFactory("temp",aan.getExpression().getType());
299         TempDescriptor tmpindex=TempDescriptor.tempFactory("temp",aan.getIndex().getType());
300         NodePair npe=flattenExpressionNode(aan.getExpression(),tmp);
301         NodePair npi=flattenExpressionNode(aan.getIndex(),tmpindex);
302         FlatElementNode fn=new FlatElementNode(tmp,tmpindex,out_temp);
303         npe.getEnd().addNext(npi.getBegin());
304         npi.getEnd().addNext(fn);
305         return new NodePair(npe.getBegin(),fn);
306     }
307
308     private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
309         // Three cases:
310         // left side is variable
311         // left side is field
312         // left side is array
313         
314         Operation base=an.getOperation().getBaseOp();
315         boolean pre=base==null||(base.getOp()!=Operation.POSTINC&&base.getOp()!=Operation.POSTDEC);
316         
317         if (!pre) {
318             //rewrite the base operation
319             base=base.getOp()==Operation.POSTINC?new Operation(Operation.ADD):new Operation(Operation.SUB);
320         }
321         FlatNode first=null;
322         FlatNode last=null;
323         TempDescriptor src_tmp=an.getSrc()==null?TempDescriptor.tempFactory("srctmp",an.getDest().getType()):TempDescriptor.tempFactory("srctmp",an.getSrc().getType());
324
325         //Get src value
326         if (an.getSrc()!=null) {
327             NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
328             first=np_src.getBegin();
329             last=np_src.getEnd();
330         } else if (!pre) {
331             FlatLiteralNode fln=new FlatLiteralNode(new TypeDescriptor(TypeDescriptor.INT) ,new Integer(1),src_tmp);
332             first=fln;
333             last=fln;
334         }
335         
336         if (an.getDest().kind()==Kind.FieldAccessNode) {
337             //We are assigning an object field
338
339             FieldAccessNode fan=(FieldAccessNode)an.getDest();
340             ExpressionNode en=fan.getExpression();
341             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
342             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
343             if (first==null)
344                 first=np_baseexp.getBegin();
345             else
346                 last.addNext(np_baseexp.getBegin());
347             last=np_baseexp.getEnd();
348
349             //See if we need to perform an operation
350             if (base!=null) {
351                 //If it is a preinc we need to store the initial value
352                 TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
353                 TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
354
355                 FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
356                 last.addNext(ffn);
357                 last=ffn;
358                 FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
359                 src_tmp=tmp;
360                 last.addNext(fon);
361                 last=fon;
362             }
363
364             FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
365             last.addNext(fsfn);
366             last=fsfn;
367             if (pre) {
368                 FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
369                 fsfn.addNext(fon2);
370                 last=fon2;
371             }
372             return new NodePair(first, last);
373         } else if (an.getDest().kind()==Kind.ArrayAccessNode) {
374             //We are assigning an array element
375
376
377             ArrayAccessNode aan=(ArrayAccessNode)an.getDest();
378             ExpressionNode en=aan.getExpression();
379             ExpressionNode enindex=aan.getIndex();
380             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
381             TempDescriptor index_tmp=TempDescriptor.tempFactory("index",enindex.getType());
382             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
383             NodePair np_indexexp=flattenExpressionNode(enindex, index_tmp);
384             if (first==null)
385                 first=np_baseexp.getBegin();
386             else
387                 last.addNext(np_baseexp.getBegin());
388             np_baseexp.getEnd().addNext(np_indexexp.getBegin());
389             last=np_indexexp.getEnd();
390
391             //See if we need to perform an operation
392             if (base!=null) {
393                 //If it is a preinc we need to store the initial value
394                 TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
395                 TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
396
397                 FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp2);
398                 last.addNext(fen);
399                 last=fen;
400                 FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
401                 src_tmp=tmp;
402                 last.addNext(fon);
403                 last=fon;
404             }
405
406
407             FlatSetElementNode fsen=new FlatSetElementNode(dst_tmp, index_tmp, src_tmp);
408             last.addNext(fsen);
409             last=fsen;
410             if (pre) {
411                 FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
412                 fsen.addNext(fon2);
413                 last=fon2;
414             }
415             return new NodePair(first, last);
416         } else if (an.getDest().kind()==Kind.NameNode) {
417             //We could be assigning a field or variable
418             NameNode nn=(NameNode)an.getDest();
419             if (nn.getExpression()!=null) {
420                 //It is a field
421                 FieldAccessNode fan=(FieldAccessNode)nn.getExpression();
422                 ExpressionNode en=fan.getExpression();
423                 TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
424                 NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
425                 if (first==null)
426                     first=np_baseexp.getBegin();
427                 else
428                     last.addNext(np_baseexp.getBegin());
429                 last=np_baseexp.getEnd();
430
431                 //See if we need to perform an operation
432                 if (base!=null) {
433                     //If it is a preinc we need to store the initial value
434                     TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
435                     TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
436                     
437                     FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
438                     last.addNext(ffn);
439                     last=ffn;
440                     FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
441                     src_tmp=tmp;
442                     last.addNext(fon);
443                     last=fon;
444                 }
445
446
447                 FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
448                 last.addNext(fsfn);
449                 last=fsfn;
450                 if (pre) {
451                     FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
452                     fsfn.addNext(fon2);
453                     last=fon2;
454                 }
455                 return new NodePair(first, last);
456             } else {
457                 if (nn.getField()!=null) {
458                     //It is a field
459                     //Get src value
460
461                     //See if we need to perform an operation
462                     if (base!=null) {
463                         //If it is a preinc we need to store the initial value
464                         TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
465                         TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
466                         
467                         FlatFieldNode ffn=new FlatFieldNode(nn.getField(), getTempforVar(nn.getVar()), src_tmp2);
468                         if (first==null)
469                             first=ffn;
470                         else {
471                             last.addNext(ffn);
472                         }
473                         last=ffn;
474                         FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
475                         src_tmp=tmp;
476                         last.addNext(fon);
477                         last=fon;
478                     }               
479
480                     FlatSetFieldNode fsfn=new FlatSetFieldNode(getTempforVar(nn.getVar()), nn.getField(), src_tmp);
481                     if (first==null) {
482                         first=fsfn;
483                     } else {
484                         last.addNext(fsfn);
485                     }
486                     last=fsfn;
487                     if (pre) {
488                         FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
489                         fsfn.addNext(fon2);
490                         last=fon2;
491                     }
492                     return new NodePair(first, last);
493                 } else {
494                     //It is a variable
495                     //See if we need to perform an operation
496
497                     if (base!=null) {
498                         //If it is a preinc we need to store the initial value
499                         TempDescriptor src_tmp2=getTempforVar(nn.getVar());
500                         TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
501                         if (!pre) {
502                             FlatOpNode fon=new FlatOpNode(out_temp, src_tmp2, null, new Operation(Operation.ASSIGN));
503                             if (first==null)
504                                 first=fon;
505                             else
506                                 last.addNext(fon);
507                             last=fon;
508                         }
509
510                         FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
511                         if (first==null) 
512                             first=fon;
513                         else 
514                             last.addNext(fon);
515                         src_tmp=tmp;
516                         last=fon;
517                     }
518
519                     FlatOpNode fon=new FlatOpNode(getTempforVar(nn.getVar()), src_tmp, null, new Operation(Operation.ASSIGN));
520                     last.addNext(fon);
521                     last=fon;
522                     if (pre) {
523                         FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
524                         fon.addNext(fon2);
525                         last=fon2;
526                     }
527                     return new NodePair(first, last);
528                 }
529             }
530         } 
531         throw new Error();
532     }
533
534     private NodePair flattenNameNode(NameNode nn,TempDescriptor out_temp) {
535         if (nn.getExpression()!=null) {
536             /* Hack - use subtree instead */
537             return flattenExpressionNode(nn.getExpression(),out_temp);
538         } else if (nn.getField()!=null) {
539             TempDescriptor tmp=getTempforVar(nn.getVar());
540             FlatFieldNode ffn=new FlatFieldNode(nn.getField(), tmp, out_temp); 
541             return new NodePair(ffn,ffn);
542         } else {
543             TempDescriptor tmp=getTempforVar(nn.getVar());
544             FlatOpNode fon=new FlatOpNode(out_temp, tmp, null, new Operation(Operation.ASSIGN));
545             return new NodePair(fon,fon);
546         }
547     }
548
549     private NodePair flattenOpNode(OpNode on,TempDescriptor out_temp) {
550         TempDescriptor temp_left=TempDescriptor.tempFactory("leftop",on.getLeft().getType());
551         TempDescriptor temp_right=null;
552
553         Operation op=on.getOp();
554         /* We've moved this to assignment nodes
555
556         if (op.getOp()==Operation.POSTINC||
557             op.getOp()==Operation.POSTDEC||
558             op.getOp()==Operation.PREINC||
559             op.getOp()==Operation.PREDEC) {
560             LiteralNode ln=new LiteralNode("int",new Integer(1));
561             ln.setType(new TypeDescriptor(TypeDescriptor.INT));
562             
563             AssignmentNode an=new AssignmentNode(on.getLeft(),
564                                                  new OpNode(on.getLeft(),ln, 
565                                                             new Operation((op.getOp()==Operation.POSTINC||op.getOp()==Operation.PREINC)?Operation.PLUS:Operation.MINUS))
566                                                  );
567             if (op.getOp()==Operation.POSTINC||
568                 op.getOp()==Operation.POSTDEC) {
569                 //Can't do, this could have side effects
570                 NodePair left=flattenExpressionNode(on.getLeft(),out_temp);
571                 NodePair assign=flattenAssignmentNode(an,temp_left);
572                 left.getEnd().addNext(assign.getBegin());
573                 return new NodePair(left.getBegin(),assign.getEnd());
574             } else {
575                 NodePair assign=flattenAssignmentNode(an,out_temp);
576                 return assign;
577             }
578             } */
579         
580         NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
581         NodePair right;
582         if (on.getRight()!=null) {
583             temp_right=TempDescriptor.tempFactory("rightop",on.getRight().getType());
584             right=flattenExpressionNode(on.getRight(),temp_right);
585         } else {
586             FlatNop nop=new FlatNop();
587             right=new NodePair(nop,nop);
588         }
589
590         if (op.getOp()==Operation.LOGIC_OR) {
591             /* Need to do shortcircuiting */
592             FlatCondBranch fcb=new FlatCondBranch(temp_left);
593             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
594             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
595             FlatNop fnop=new FlatNop();
596             left.getEnd().addNext(fcb);
597             fcb.addFalseNext(right.getBegin());
598             right.getEnd().addNext(fon2);
599             fon2.addNext(fnop);
600             fcb.addTrueNext(fon1);
601             fon1.addNext(fnop);
602             return new NodePair(left.getBegin(), fnop);
603         } else if (op.getOp()==Operation.LOGIC_AND) {
604             /* Need to do shortcircuiting */
605             FlatCondBranch fcb=new FlatCondBranch(temp_left);
606             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
607             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
608             FlatNop fnop=new FlatNop();
609             left.getEnd().addNext(fcb);
610             fcb.addTrueNext(right.getBegin());
611             right.getEnd().addNext(fon2);
612             fon2.addNext(fnop);
613             fcb.addFalseNext(fon1);
614             fon1.addNext(fnop);
615             return new NodePair(left.getBegin(), fnop);
616         }
617
618         FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
619         left.getEnd().addNext(right.getBegin());
620         right.getEnd().addNext(fon);
621         return new NodePair(left.getBegin(),fon);
622     }
623
624     private NodePair flattenExpressionNode(ExpressionNode en, TempDescriptor out_temp) {
625         switch(en.kind()) {
626         case Kind.AssignmentNode:
627             return flattenAssignmentNode((AssignmentNode)en,out_temp);
628         case Kind.CastNode:
629             return flattenCastNode((CastNode)en,out_temp);
630         case Kind.CreateObjectNode:
631             return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
632         case Kind.FieldAccessNode:
633             return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
634         case Kind.ArrayAccessNode:
635             return flattenArrayAccessNode((ArrayAccessNode)en,out_temp);
636         case Kind.LiteralNode:
637             return flattenLiteralNode((LiteralNode)en,out_temp);
638         case Kind.MethodInvokeNode:
639             return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
640         case Kind.NameNode:
641             return flattenNameNode((NameNode)en,out_temp);
642         case Kind.OpNode:
643             return flattenOpNode((OpNode)en,out_temp);
644         }
645         throw new Error();
646     }
647
648     private NodePair flattenDeclarationNode(DeclarationNode dn) {
649         VarDescriptor vd=dn.getVarDescriptor();
650         TempDescriptor td=getTempforVar(vd);
651         if (dn.getExpression()!=null)
652             return flattenExpressionNode(dn.getExpression(),td);
653         else {
654             FlatNop fn=new FlatNop();
655             return new NodePair(fn,fn);
656         }
657     }
658
659     private TempDescriptor getTempforParam(VarDescriptor vd) {
660         if (temptovar.containsKey(vd))
661             return (TempDescriptor)temptovar.get(vd);
662         else {
663             TempDescriptor td=TempDescriptor.paramtempFactory(vd.getName(),vd.getType());
664             temptovar.put(vd,td);
665             return td;
666         }
667     }
668
669     private TempDescriptor getTempforVar(VarDescriptor vd) {
670         if (temptovar.containsKey(vd))
671             return (TempDescriptor)temptovar.get(vd);
672         else {
673             TempDescriptor td=TempDescriptor.tempFactory(vd.getName(),vd.getType());
674             temptovar.put(vd,td);
675             return td;
676         }
677     }
678
679     private NodePair flattenIfStatementNode(IfStatementNode isn) {
680         TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
681         NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
682         FlatCondBranch fcb=new FlatCondBranch(cond_temp);
683         NodePair true_np=flattenBlockNode(isn.getTrueBlock());
684         NodePair false_np;
685         FlatNop nopend=new FlatNop();
686
687         if (isn.getFalseBlock()!=null)
688             false_np=flattenBlockNode(isn.getFalseBlock());
689         else {
690             FlatNop nop=new FlatNop();
691             false_np=new NodePair(nop,nop);
692         }
693
694         cond.getEnd().addNext(fcb);
695         fcb.addTrueNext(true_np.getBegin());
696         fcb.addFalseNext(false_np.getBegin());
697         true_np.getEnd().addNext(nopend);
698         false_np.getEnd().addNext(nopend);
699         return new NodePair(cond.getBegin(), nopend);
700     }
701             
702     private NodePair flattenLoopNode(LoopNode ln) {
703         if (ln.getType()==LoopNode.FORLOOP) {
704             NodePair initializer=flattenBlockNode(ln.getInitializer());
705             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
706             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
707             NodePair update=flattenBlockNode(ln.getUpdate());
708             NodePair body=flattenBlockNode(ln.getBody());
709             FlatNode begin=initializer.getBegin();
710             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
711             FlatNop nopend=new FlatNop();
712             FlatBackEdge backedge=new FlatBackEdge();
713
714             initializer.getEnd().addNext(condition.getBegin());
715             body.getEnd().addNext(update.getBegin());
716             update.getEnd().addNext(backedge);
717             backedge.addNext(condition.getBegin());
718             condition.getEnd().addNext(fcb);
719             fcb.addFalseNext(nopend);
720             fcb.addTrueNext(body.getBegin());
721             return new NodePair(begin,nopend);
722         } else if (ln.getType()==LoopNode.WHILELOOP) {
723             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
724             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
725             NodePair body=flattenBlockNode(ln.getBody());
726             FlatNode begin=condition.getBegin();
727             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
728             FlatNop nopend=new FlatNop();
729             FlatBackEdge backedge=new FlatBackEdge();
730
731             body.getEnd().addNext(backedge);
732             backedge.addNext(condition.getBegin());
733
734             condition.getEnd().addNext(fcb);
735             fcb.addFalseNext(nopend);
736             fcb.addTrueNext(body.getBegin());
737             return new NodePair(begin,nopend);
738         } else if (ln.getType()==LoopNode.DOWHILELOOP) {
739             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
740             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
741             NodePair body=flattenBlockNode(ln.getBody());
742             FlatNode begin=body.getBegin();
743             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
744             FlatNop nopend=new FlatNop();
745             FlatBackEdge backedge=new FlatBackEdge();
746
747             body.getEnd().addNext(condition.getBegin());
748             condition.getEnd().addNext(fcb);
749             fcb.addFalseNext(nopend);
750             fcb.addTrueNext(backedge);
751             backedge.addNext(body.getBegin());
752             return new NodePair(begin,nopend);
753         } else throw new Error();
754     }
755             
756     private NodePair flattenReturnNode(ReturnNode rntree) {
757         TempDescriptor retval=null;
758         NodePair cond=null;
759         if (rntree.getReturnExpression()!=null) {
760             retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
761             cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
762         }
763
764         FlatReturnNode rnflat=new FlatReturnNode(retval);
765         FlatNode ln=rnflat;
766         if (state.THREAD&&currmd.getModifiers().isSynchronized()) {
767             MethodDescriptor memd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
768             TempDescriptor thistd=getTempforVar(currmd.getThis());
769             FlatCall fc=new FlatCall(memd, null, thistd, new TempDescriptor[0]);
770             fc.addNext(rnflat);
771             ln=fc;
772         }
773
774         if (cond!=null) {
775             cond.getEnd().addNext(ln);
776             return new NodePair(cond.getBegin(),rnflat);
777         } else
778             return new NodePair(ln,rnflat);
779     }
780
781     private NodePair flattenTaskExitNode(TaskExitNode ten) {
782         FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.TASKEXIT);
783         updateFlagActionNode(ffan, ten.getFlagEffects());
784         NodePair fcn=flattenConstraintCheck(ten.getChecks());
785         ffan.addNext(fcn.getBegin());
786         FlatReturnNode rnflat=new FlatReturnNode(null);
787         fcn.getEnd().addNext(rnflat);
788         return new NodePair(ffan, rnflat);
789     }
790
791     private NodePair flattenConstraintCheck(Vector ccs) {
792         FlatNode begin=new FlatNop();
793         if (ccs==null)
794             return new NodePair(begin,begin);
795         FlatNode last=begin;
796         for(int i=0;i<ccs.size();i++) {
797             ConstraintCheck cc=(ConstraintCheck) ccs.get(i);
798             /* Flatten the arguments */
799             TempDescriptor[] temps=new TempDescriptor[cc.numArgs()];
800             String[] vars=new String[cc.numArgs()];
801             for(int j=0;j<cc.numArgs();j++) {
802                 ExpressionNode en=cc.getArg(j);
803                 TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
804                 temps[j]=td;
805                 vars[j]=cc.getVar(j);
806                 NodePair np=flattenExpressionNode(en, td);
807                 last.addNext(np.getBegin());
808                 last=np.getEnd();
809             }
810             
811             FlatCheckNode fcn=new FlatCheckNode(cc.getSpec(), vars, temps);
812             last.addNext(fcn);
813             last=fcn;
814         }
815         return new NodePair(begin,last);
816     }
817
818     private NodePair flattenSubBlockNode(SubBlockNode sbn) {
819         return flattenBlockNode(sbn.getBlockNode());
820     }
821
822     private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
823         switch(bsn.kind()) {
824         case Kind.BlockExpressionNode:
825             return flattenBlockExpressionNode((BlockExpressionNode)bsn);
826             
827         case Kind.DeclarationNode:
828             return flattenDeclarationNode((DeclarationNode)bsn);
829             
830         case Kind.IfStatementNode:
831             return flattenIfStatementNode((IfStatementNode)bsn);
832             
833         case Kind.LoopNode:
834             return flattenLoopNode((LoopNode)bsn);
835             
836         case Kind.ReturnNode:
837             return flattenReturnNode((IR.Tree.ReturnNode)bsn);
838
839         case Kind.TaskExitNode:
840             return flattenTaskExitNode((IR.Tree.TaskExitNode)bsn);
841             
842         case Kind.SubBlockNode:
843             return flattenSubBlockNode((SubBlockNode)bsn);
844             
845         }
846         throw new Error();
847     }
848 }