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