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