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