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