Instanceof checks for jim
[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     case Kind.TertiaryNode:
791       return flattenTertiaryNode((TertiaryNode)en,out_temp);
792
793     case Kind.InstanceOfNode:
794       return flattenInstanceOfNode((InstanceOfNode)en,out_temp);
795     }
796     throw new Error();
797   }
798
799   private NodePair flattenDeclarationNode(DeclarationNode dn) {
800     VarDescriptor vd=dn.getVarDescriptor();
801     TempDescriptor td=getTempforVar(vd);
802     if (dn.getExpression()!=null)
803       return flattenExpressionNode(dn.getExpression(),td);
804     else {
805       FlatNop fn=new FlatNop();
806       return new NodePair(fn,fn);
807     }
808   }
809
810   private NodePair flattenTagDeclarationNode(TagDeclarationNode dn) {
811     TagVarDescriptor tvd=dn.getTagVarDescriptor();
812     TagDescriptor tag=tvd.getTag();
813     TempDescriptor tmp=getTempforVar(tvd);
814     FlatTagDeclaration ftd=new FlatTagDeclaration(tag, tmp);
815     return new NodePair(ftd,ftd);
816   }
817
818   private TempDescriptor getTempforParam(Descriptor d) {
819     if (temptovar.containsKey(d))
820       return (TempDescriptor)temptovar.get(d);
821     else {
822       if (d instanceof VarDescriptor) {
823         VarDescriptor vd=(VarDescriptor)d;
824         TempDescriptor td=TempDescriptor.paramtempFactory(vd.getName(),vd.getType());
825         temptovar.put(vd,td);
826         return td;
827       } else if (d instanceof TagVarDescriptor) {
828         TagVarDescriptor tvd=(TagVarDescriptor)d;
829         TypeDescriptor tagtype=new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass));
830         TempDescriptor td=TempDescriptor.paramtempFactory(tvd.getName(), tagtype, tvd.getTag());
831         temptovar.put(tvd,td);
832         return td;
833       } else throw new Error("Unreconized Descriptor");
834     }
835   }
836
837   private TempDescriptor getTempforVar(Descriptor d) {
838     if (temptovar.containsKey(d))
839       return (TempDescriptor)temptovar.get(d);
840     else {
841       if (d instanceof VarDescriptor) {
842         VarDescriptor vd=(VarDescriptor)d;
843         TempDescriptor td=TempDescriptor.tempFactory(vd.getName(), vd.getType());
844         temptovar.put(vd,td);
845         return td;
846       } else if (d instanceof TagVarDescriptor) {
847         TagVarDescriptor tvd=(TagVarDescriptor)d;
848         //BUGFIX TAGTYPE - add next line, modify following
849         //line to tag this new type descriptor, modify
850         //TempDescriptor constructor & factory to set type
851         //using this Type To test, use any program with tags
852         TypeDescriptor tagtype=new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass));
853         TempDescriptor td=TempDescriptor.tempFactory(tvd.getName(),tagtype, tvd.getTag());
854         temptovar.put(tvd,td);
855         return td;
856       } else throw new Error("Unrecognized Descriptor");
857     }
858   }
859
860   private NodePair flattenIfStatementNode(IfStatementNode isn) {
861     TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
862     NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
863     FlatCondBranch fcb=new FlatCondBranch(cond_temp);
864     NodePair true_np=flattenBlockNode(isn.getTrueBlock());
865     NodePair false_np;
866     FlatNop nopend=new FlatNop();
867
868     if (isn.getFalseBlock()!=null)
869       false_np=flattenBlockNode(isn.getFalseBlock());
870     else {
871       FlatNop nop=new FlatNop();
872       false_np=new NodePair(nop,nop);
873     }
874
875     cond.getEnd().addNext(fcb);
876     fcb.addTrueNext(true_np.getBegin());
877     fcb.addFalseNext(false_np.getBegin());
878     if (true_np.getEnd()!=null)
879         true_np.getEnd().addNext(nopend);
880     if (false_np.getEnd()!=null)
881         false_np.getEnd().addNext(nopend);
882     return new NodePair(cond.getBegin(), nopend);
883   }
884
885   private NodePair flattenLoopNode(LoopNode ln) {
886     if (ln.getType()==LoopNode.FORLOOP) {
887       NodePair initializer=flattenBlockNode(ln.getInitializer());
888       TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
889       NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
890       NodePair update=flattenBlockNode(ln.getUpdate());
891       NodePair body=flattenBlockNode(ln.getBody());
892       FlatNode begin=initializer.getBegin();
893       FlatCondBranch fcb=new FlatCondBranch(cond_temp);
894       fcb.setTrueProb(State.TRUEPROB);
895       fcb.setLoop();
896       FlatNop nopend=new FlatNop();
897       FlatBackEdge backedge=new FlatBackEdge();
898
899       FlatNop nop2=new FlatNop();
900       initializer.getEnd().addNext(nop2);
901       nop2.addNext(condition.getBegin());
902       if (body.getEnd()!=null)
903           body.getEnd().addNext(update.getBegin());
904       update.getEnd().addNext(backedge);
905       backedge.addNext(condition.getBegin());
906       condition.getEnd().addNext(fcb);
907       fcb.addFalseNext(nopend);
908       fcb.addTrueNext(body.getBegin());
909       for(Iterator contit=continueset.iterator();contit.hasNext();) {
910           FlatNode fn=(FlatNode)contit.next();
911           contit.remove();
912           fn.addNext(update.getBegin());
913       }
914       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
915           FlatNode fn=(FlatNode)breakit.next();
916           breakit.remove();
917           fn.addNext(nopend);
918       }
919
920       return new NodePair(begin,nopend);
921     } else if (ln.getType()==LoopNode.WHILELOOP) {
922       TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
923       NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
924       NodePair body=flattenBlockNode(ln.getBody());
925       FlatNode begin=condition.getBegin();
926       FlatCondBranch fcb=new FlatCondBranch(cond_temp);
927       fcb.setTrueProb(State.TRUEPROB);
928       fcb.setLoop();
929       FlatNop nopend=new FlatNop();
930       FlatBackEdge backedge=new FlatBackEdge();
931
932       body.getEnd().addNext(backedge);
933       backedge.addNext(condition.getBegin());
934
935       condition.getEnd().addNext(fcb);
936       fcb.addFalseNext(nopend);
937       fcb.addTrueNext(body.getBegin());
938
939       for(Iterator contit=continueset.iterator();contit.hasNext();) {
940           FlatNode fn=(FlatNode)contit.next();
941           contit.remove();
942           fn.addNext(backedge);
943       }
944       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
945           FlatNode fn=(FlatNode)breakit.next();
946           breakit.remove();
947           fn.addNext(nopend);
948       }
949       return new NodePair(begin,nopend);
950     } else if (ln.getType()==LoopNode.DOWHILELOOP) {
951       TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
952       NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
953       NodePair body=flattenBlockNode(ln.getBody());
954       FlatNode begin=body.getBegin();
955       FlatCondBranch fcb=new FlatCondBranch(cond_temp);
956       fcb.setTrueProb(State.TRUEPROB);
957       fcb.setLoop();
958       FlatNop nopend=new FlatNop();
959       FlatBackEdge backedge=new FlatBackEdge();
960
961       body.getEnd().addNext(condition.getBegin());
962       condition.getEnd().addNext(fcb);
963       fcb.addFalseNext(nopend);
964       fcb.addTrueNext(backedge);
965       backedge.addNext(body.getBegin());
966
967       for(Iterator contit=continueset.iterator();contit.hasNext();) {
968           FlatNode fn=(FlatNode)contit.next();
969           contit.remove();
970           fn.addNext(condition.getBegin());
971       }
972       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
973           FlatNode fn=(FlatNode)breakit.next();
974           breakit.remove();
975           fn.addNext(nopend);
976       }
977       return new NodePair(begin,nopend);
978     } else throw new Error();
979   }
980
981   private NodePair flattenReturnNode(ReturnNode rntree) {
982     TempDescriptor retval=null;
983     NodePair cond=null;
984     if (rntree.getReturnExpression()!=null) {
985       retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
986       cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
987     }
988
989     FlatReturnNode rnflat=new FlatReturnNode(retval);
990     FlatNode ln=rnflat;
991     if (state.THREAD&&currmd.getModifiers().isSynchronized()) {
992       MethodDescriptor memd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
993       TempDescriptor thistd=getTempforVar(currmd.getThis());
994       FlatCall fc=new FlatCall(memd, null, thistd, new TempDescriptor[0]);
995       fc.addNext(ln);
996       ln=fc;
997     }
998     if (state.DSM&&currmd.getModifiers().isAtomic()) {
999       FlatAtomicExitNode faen=new FlatAtomicExitNode(curran);
1000       faen.addNext(ln);
1001       ln=faen;
1002     }
1003
1004     if (cond!=null) {
1005       cond.getEnd().addNext(ln);
1006       return new NodePair(cond.getBegin(),rnflat);
1007     } else
1008       return new NodePair(ln,rnflat);
1009   }
1010
1011   private NodePair flattenTaskExitNode(TaskExitNode ten) {
1012     FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.TASKEXIT);
1013     ffan.setTaskExitIndex(ten.getTaskExitIndex());
1014     updateFlagActionNode(ffan, ten.getFlagEffects());
1015     NodePair fcn=flattenConstraintCheck(ten.getChecks());
1016     ffan.addNext(fcn.getBegin());
1017     FlatReturnNode rnflat=new FlatReturnNode(null);
1018     fcn.getEnd().addNext(rnflat);
1019     return new NodePair(ffan, rnflat);
1020   }
1021
1022   private NodePair flattenConstraintCheck(Vector ccs) {
1023     FlatNode begin=new FlatNop();
1024     if (ccs==null)
1025       return new NodePair(begin,begin);
1026     FlatNode last=begin;
1027     for(int i=0; i<ccs.size(); i++) {
1028       ConstraintCheck cc=(ConstraintCheck) ccs.get(i);
1029       /* Flatten the arguments */
1030       TempDescriptor[] temps=new TempDescriptor[cc.numArgs()];
1031       String[] vars=new String[cc.numArgs()];
1032       for(int j=0; j<cc.numArgs(); j++) {
1033         ExpressionNode en=cc.getArg(j);
1034         TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
1035         temps[j]=td;
1036         vars[j]=cc.getVar(j);
1037         NodePair np=flattenExpressionNode(en, td);
1038         last.addNext(np.getBegin());
1039         last=np.getEnd();
1040       }
1041
1042       FlatCheckNode fcn=new FlatCheckNode(cc.getSpec(), vars, temps);
1043       last.addNext(fcn);
1044       last=fcn;
1045     }
1046     return new NodePair(begin,last);
1047   }
1048
1049   private NodePair flattenSubBlockNode(SubBlockNode sbn) {
1050     return flattenBlockNode(sbn.getBlockNode());
1051   }
1052
1053   private NodePair flattenAtomicNode(AtomicNode sbn) {
1054     NodePair np=flattenBlockNode(sbn.getBlockNode());
1055     FlatAtomicEnterNode faen=new FlatAtomicEnterNode();
1056     FlatAtomicExitNode faexn=new FlatAtomicExitNode(faen);
1057     faen.addNext(np.getBegin());
1058     np.getEnd().addNext(faexn);
1059     return new NodePair(faen, faexn);
1060   }
1061
1062   private NodePair flattenSESENode(SESENode sn) {
1063     if( sn.isStart() ) {
1064       FlatSESEEnterNode fsen=new FlatSESEEnterNode(sn);
1065       sn.setFlatEnter(fsen);
1066       return new NodePair(fsen, fsen);
1067     }
1068
1069     FlatSESEExitNode fsexn=new FlatSESEExitNode(sn);
1070     sn.setFlatExit(fsexn);
1071     fsexn.setFlatEnter( sn.getStart().getFlatEnter() );
1072     sn.getStart().getFlatEnter().setFlatExit( fsexn );
1073     return new NodePair(fsexn, fsexn);
1074   }
1075
1076   private NodePair flattenContinueBreakNode(ContinueBreakNode cbn) {
1077       FlatNop fn=new FlatNop();
1078       if (cbn.isBreak())
1079           breakset.add(fn);
1080       else
1081           continueset.add(fn);
1082       return new NodePair(fn,null);
1083   }
1084
1085   private NodePair flattenInstanceOfNode(InstanceOfNode tn, TempDescriptor out_temp) {
1086     TempDescriptor expr_temp=TempDescriptor.tempFactory("expr",tn.getExpr().getType());
1087     NodePair cond=flattenExpressionNode(tn.getExpr(), expr_temp);
1088     FlatInstanceOfNode fion=new FlatInstanceOfNode(tn.getExprType(), expr_temp, out_temp);
1089     cond.getEnd().addNext(fion);
1090     return new NodePair(cond.getBegin(),fion);
1091   }
1092
1093   private NodePair flattenTertiaryNode(TertiaryNode tn, TempDescriptor out_temp) {
1094     TempDescriptor cond_temp=TempDescriptor.tempFactory("tert_cond",new TypeDescriptor(TypeDescriptor.BOOLEAN));
1095     TempDescriptor true_temp=TempDescriptor.tempFactory("tert_true",tn.getTrueExpr().getType());
1096     TempDescriptor fals_temp=TempDescriptor.tempFactory("tert_fals",tn.getFalseExpr().getType());
1097
1098     NodePair cond=flattenExpressionNode(tn.getCond(),cond_temp);
1099     FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1100
1101     NodePair trueExpr=flattenExpressionNode(tn.getTrueExpr(),true_temp);
1102     FlatOpNode fonT=new FlatOpNode(out_temp, true_temp, null, new Operation(Operation.ASSIGN));
1103
1104     NodePair falseExpr=flattenExpressionNode(tn.getFalseExpr(),fals_temp);
1105     FlatOpNode fonF=new FlatOpNode(out_temp, fals_temp, null, new Operation(Operation.ASSIGN));
1106
1107     FlatNop nopend=new FlatNop();
1108
1109     cond.getEnd().addNext(fcb);
1110
1111     fcb.addTrueNext(trueExpr.getBegin());
1112     fcb.addFalseNext(falseExpr.getBegin());
1113
1114     trueExpr.getEnd().addNext(fonT);
1115     fonT.addNext(nopend);
1116
1117     falseExpr.getEnd().addNext(fonF);
1118     fonF.addNext(nopend);
1119     
1120     return new NodePair(cond.getBegin(), nopend);
1121   }
1122
1123   private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
1124     switch(bsn.kind()) {
1125     case Kind.BlockExpressionNode:
1126       return flattenBlockExpressionNode((BlockExpressionNode)bsn);
1127
1128     case Kind.DeclarationNode:
1129       return flattenDeclarationNode((DeclarationNode)bsn);
1130
1131     case Kind.TagDeclarationNode:
1132       return flattenTagDeclarationNode((TagDeclarationNode)bsn);
1133
1134     case Kind.IfStatementNode:
1135       return flattenIfStatementNode((IfStatementNode)bsn);
1136
1137     case Kind.LoopNode:
1138       return flattenLoopNode((LoopNode)bsn);
1139
1140     case Kind.ReturnNode:
1141       return flattenReturnNode((IR.Tree.ReturnNode)bsn);
1142
1143     case Kind.TaskExitNode:
1144       return flattenTaskExitNode((IR.Tree.TaskExitNode)bsn);
1145
1146     case Kind.SubBlockNode:
1147       return flattenSubBlockNode((SubBlockNode)bsn);
1148
1149     case Kind.AtomicNode:
1150       return flattenAtomicNode((AtomicNode)bsn);
1151
1152     case Kind.SESENode:
1153       return flattenSESENode((SESENode)bsn);
1154
1155     case Kind.ContinueBreakNode:
1156       return flattenContinueBreakNode((ContinueBreakNode)bsn);
1157     }
1158     throw new Error();
1159   }
1160 }