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