changes
[IRC.git] / Robust / src / IR / Flat / BuildFlat.java
1 package IR.Flat;
2 import IR.*;
3 import IR.Tree.*;
4
5 import java.util.*;
6
7 public class BuildFlat {
8   State state;
9   Hashtable temptovar;
10   MethodDescriptor currmd;
11   TypeUtil typeutil;
12
13   HashSet breakset;
14   HashSet continueset;
15   FlatExit fe;
16   
17   // for synchronized blocks
18   Stack<TempDescriptor> lockStack;
19
20   public BuildFlat(State st, TypeUtil typeutil) {
21     state=st;
22     temptovar=new Hashtable();
23     this.typeutil=typeutil;
24     this.breakset=new HashSet();
25     this.continueset=new HashSet();
26     this.lockStack = new Stack<TempDescriptor>();
27   }
28
29   public Hashtable getMap() {
30     return temptovar;
31   }
32
33   public void buildFlat() {
34     Iterator it=state.getClassSymbolTable().getDescriptorsIterator();
35     while(it.hasNext()) {
36       ClassDescriptor cn=(ClassDescriptor)it.next();
37       flattenClass(cn);
38     }
39
40     Iterator task_it=state.getTaskSymbolTable().getDescriptorsIterator();
41     while(task_it.hasNext()) {
42       TaskDescriptor td=(TaskDescriptor)task_it.next();
43       flattenTask(td);
44     }
45   }
46
47   private void flattenTask(TaskDescriptor td) {
48     BlockNode bn=state.getMethodBody(td);
49     NodePair np=flattenBlockNode(bn);
50     FlatNode fn=np.getBegin();
51     fe=new FlatExit();
52     FlatNode fn2=np.getEnd();
53
54     if (fn2!=null&& fn2.kind()!=FKind.FlatReturnNode) {
55       FlatReturnNode rnflat=new FlatReturnNode(null);
56       rnflat.addNext(fe);
57       fn2.addNext(rnflat);
58     }
59
60     FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.PRE);
61     ffan.setNumLine(bn.getNumLine());
62     ffan.addNext(fn);
63
64     FlatMethod fm=new FlatMethod(td, fe);
65     fm.addNext(ffan);
66
67     Hashtable visitedset=new Hashtable();
68
69     for(int i=0; i<td.numParameters(); i++) {
70       VarDescriptor paramvd=td.getParameter(i);
71       fm.addParameterTemp(getTempforVar(paramvd));
72       TagExpressionList tel=td.getTag(paramvd);
73       //BUG added next line to fix...to test feed in any task program
74       if (tel!=null)
75         for(int j=0; j<tel.numTags(); j++) {
76           TagVarDescriptor tvd=(TagVarDescriptor) td.getParameterTable().getFromSameScope(tel.getName(j));
77           TempDescriptor tagtmp=getTempforVar(tvd);
78           if (!visitedset.containsKey(tvd.getName())) {
79             visitedset.put(tvd.getName(),tvd.getTag());
80             fm.addTagTemp(tagtmp);
81           } else {
82             TagDescriptor tmptd=(TagDescriptor) visitedset.get(tvd.getName());
83             if (!tmptd.equals(tvd.getTag()))
84               throw new Error("Two different tag types with same name as parameters to:"+td);
85           }
86           tel.setTemp(j, tagtmp);
87         }
88     }
89
90     /* Flatten Vector of Flag Effects */
91     Vector flags=td.getFlagEffects();
92     updateFlagActionNode(ffan,flags);
93
94     state.addFlatCode(td,fm);
95   }
96
97
98   /* This method transforms a vector of FlagEffects into the FlatFlagActionNode */
99   private void updateFlagActionNode(FlatFlagActionNode ffan, Vector flags) {
100     if (flags==null)     // Do nothing if the flag effects vector is empty
101       return;
102
103     for(int i=0; i<flags.size(); i++) {
104       FlagEffects fes=(FlagEffects)flags.get(i);
105       TempDescriptor flagtemp=getTempforVar(fes.getVar());
106       // Process the flags
107       for(int j=0; j<fes.numEffects(); j++) {
108         FlagEffect fe=fes.getEffect(j);
109         ffan.addFlagAction(flagtemp, fe.getFlag(), fe.getStatus());
110       }
111       // Process the tags
112       for(int j=0; j<fes.numTagEffects(); j++) {
113         TagEffect te=fes.getTagEffect(j);
114         TempDescriptor tagtemp=getTempforVar(te.getTag());
115
116         ffan.addTagAction(flagtemp, te.getTag().getTag(), tagtemp, te.getStatus());
117       }
118     }
119   }
120
121   FlatAtomicEnterNode curran=null;
122
123   private FlatNode spliceReturn(FlatNode fn) {
124     FlatReturnNode rnflat=null;
125     if (currmd.getReturnType()==null||currmd.getReturnType().isVoid()) {
126       rnflat=new FlatReturnNode(null);
127       fn.addNext(rnflat);
128     } else {
129       TempDescriptor tmp=TempDescriptor.tempFactory("rettmp",currmd.getReturnType());
130       Object o=null;
131       if (currmd.getReturnType().isPtr()) {
132         o=null;
133       } else if (currmd.getReturnType().isByte()) {
134         o=new Byte((byte)0);
135       } else if (currmd.getReturnType().isShort()) {
136         o=new Short((short)0);
137       } else if (currmd.getReturnType().isChar()) {
138         o=new Character('\0');
139       } else if (currmd.getReturnType().isInt()) {
140         o=new Integer(0);
141       } else if (currmd.getReturnType().isLong()) {
142         o=new Long(0);
143       } else if (currmd.getReturnType().isBoolean()) {
144         o=new Boolean(false);
145       } else if (currmd.getReturnType().isFloat()) {
146         o=new Float(0.0);
147       } else if (currmd.getReturnType().isDouble()) {
148         o=new Double(0.0);
149     }
150
151
152       FlatLiteralNode fln=new FlatLiteralNode(currmd.getReturnType(),o,tmp);
153       rnflat=new FlatReturnNode(tmp);
154       fln.addNext(rnflat);
155       fn.addNext(fln);      
156     }
157     return rnflat;
158   }
159
160   private void flattenClass(ClassDescriptor cn) {
161     Iterator methodit=cn.getMethods();
162     while(methodit.hasNext()) {     
163       currmd=(MethodDescriptor)methodit.next();
164       
165       // if OOOJava is on, splice a special SESE in to
166       // enclose the main method
167       boolean spliceInImplicitMain = 
168         state.OOOJAVA &&
169         currmd.equals( typeutil.getMain() );
170
171       FlatSESEEnterNode spliceSESE = null;
172       FlatSESEExitNode  spliceExit = null;
173
174       if( spliceInImplicitMain ) {
175         SESENode mainTree = new SESENode( "main" );
176         spliceSESE = new FlatSESEEnterNode( mainTree );
177         spliceExit = new FlatSESEExitNode ( mainTree );
178         spliceSESE.setFlatExit ( spliceExit );
179         spliceExit.setFlatEnter( spliceSESE );
180         spliceSESE.setIsMainSESE();
181       } 
182
183
184       fe=new FlatExit();
185
186       BlockNode bn=state.getMethodBody(currmd);
187
188       if (state.DSM&&currmd.getModifiers().isAtomic()) {
189         FlatAtomicEnterNode faen=new FlatAtomicEnterNode();
190         faen.setNumLine(bn.getNumLine());
191         curran = faen;
192       } else
193         curran=null;
194       if ((state.THREAD||state.MGC)&&currmd.getModifiers().isSynchronized()) {
195         TempDescriptor thistd = null;
196         if(currmd.getModifiers().isStatic()) {
197           // need to lock the Class object
198           thistd=new TempDescriptor("classobj", cn);
199         } else {
200           // lock this object
201           thistd=getTempforVar(currmd.getThis());
202         }
203         if(!this.lockStack.isEmpty()) {
204           throw new Error("The lock stack for synchronized blocks/methods is not empty!");
205         }
206         this.lockStack.push(thistd);
207       }
208       NodePair np=flattenBlockNode(bn);
209       FlatNode fn=np.getBegin();
210       if ((state.THREAD||state.MGC)&&currmd.getModifiers().isSynchronized()) {
211         MethodDescriptor memd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorEnter");
212     FlatNode first = null;
213     FlatNode end = null;
214     for(int j = 0; j < this.lockStack.size(); j++) {
215       TempDescriptor thistd = this.lockStack.elementAt(j);
216       FlatCall fc = new FlatCall(memd, null, thistd, new TempDescriptor[0]);
217       fc.setNumLine(bn.getNumLine());
218       if(first == null)  {
219         first = end = fc;
220       } else {
221         end.addNext(fc);
222         end = fc;
223       }
224     }
225         end.addNext(fn);
226         fn=first;
227     end = np.getEnd();
228         if (np.getEnd()!=null&&np.getEnd().kind()!=FKind.FlatReturnNode) {
229           MethodDescriptor memdex=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
230           while(!this.lockStack.isEmpty()) {
231             TempDescriptor thistd = this.lockStack.pop();
232             FlatCall fcunlock = new FlatCall(memdex, null, thistd, new TempDescriptor[0]);
233             fcunlock.setNumLine(bn.getNumLine());
234             end.addNext(fcunlock);
235             end = fcunlock;
236           }
237           FlatNode rnflat=spliceReturn(end);
238           rnflat.addNext(fe);
239         } else {
240    this.lockStack.clear();   
241     }
242       } else if (state.DSM&&currmd.getModifiers().isAtomic()) {
243         curran.addNext(fn);
244         fn=curran;
245         if (np.getEnd()!=null&&np.getEnd().kind()!=FKind.FlatReturnNode) {
246           FlatAtomicExitNode aen=new FlatAtomicExitNode(curran);
247           np.getEnd().addNext(aen);
248           FlatNode rnflat=spliceReturn(aen);
249           rnflat.addNext(fe);
250         }       
251
252       } else if (np.getEnd()!=null&&np.getEnd().kind()!=FKind.FlatReturnNode) {
253         FlatNode rnflat=null;
254         if( spliceInImplicitMain ) {
255           np.getEnd().addNext(spliceExit);
256           rnflat=spliceReturn(spliceExit);
257         } else {
258           rnflat=spliceReturn(np.getEnd());
259         }
260         rnflat.addNext(fe);
261       } else if (np.getEnd()!=null) {
262         if( spliceInImplicitMain ) {
263           FlatReturnNode rnflat=(FlatReturnNode)np.getEnd();
264           np.getEnd().addNext(spliceExit);
265           spliceExit.addNext(fe);
266         }
267       }
268
269       if( spliceInImplicitMain ) {
270         spliceSESE.addNext(fn);
271         fn=spliceSESE;   
272       }
273
274       FlatMethod fm=new FlatMethod(currmd, fe);
275       fm.setNumLine(bn.getNumLine());
276       fm.addNext(fn);
277       if (!currmd.isStatic())
278         fm.addParameterTemp(getTempforParam(currmd.getThis()));
279       for(int i=0; i<currmd.numParameters(); i++) {
280         fm.addParameterTemp(getTempforParam(currmd.getParameter(i)));
281       }
282
283       state.addFlatCode(currmd,fm);
284     }
285   }
286
287   private NodePair flattenBlockNode(BlockNode bn) {
288     FlatNode begin=null;
289     FlatNode end=null;
290     for(int i=0; i<bn.size(); i++) {
291       NodePair np=flattenBlockStatementNode(bn.get(i));
292       FlatNode np_begin=np.getBegin();
293       FlatNode np_end=np.getEnd();
294       if (begin==null) {
295         begin=np_begin;
296       }
297       if (end==null) {
298         end=np_end;
299       } else {
300         end.addNext(np_begin);
301         if (np_end==null) {
302             return new NodePair(begin, null);
303         } else
304             end=np_end;
305       }
306     }
307     if (begin==null) {
308       end=begin=new FlatNop();
309     }
310     return new NodePair(begin,end);
311   }
312
313   private NodePair flattenBlockExpressionNode(BlockExpressionNode en) {
314     //System.out.println("DEBUG -> inside flattenBlockExpressionNode\n");
315     TempDescriptor tmp=TempDescriptor.tempFactory("neverused",en.getExpression().getType());
316     return flattenExpressionNode(en.getExpression(),tmp);
317   }
318
319   private NodePair flattenCastNode(CastNode cn,TempDescriptor out_temp) {
320     TempDescriptor tmp=TempDescriptor.tempFactory("tocast",cn.getExpression().getType());
321     NodePair np=flattenExpressionNode(cn.getExpression(), tmp);
322     FlatCastNode fcn=new FlatCastNode(cn.getType(), tmp, out_temp);
323     fcn.setNumLine(cn.getNumLine());
324     np.getEnd().addNext(fcn);
325     return new NodePair(np.getBegin(),fcn);
326   }
327
328   private NodePair flattenLiteralNode(LiteralNode ln,TempDescriptor out_temp) {
329     FlatLiteralNode fln=new FlatLiteralNode(ln.getType(), ln.getValue(), out_temp);
330     fln.setNumLine(ln.getNumLine());
331     return new NodePair(fln,fln);
332   }
333
334   private NodePair flattenOffsetNode(OffsetNode ofn, TempDescriptor out_temp) {
335     FlatOffsetNode fln = new FlatOffsetNode(ofn.getClassType(), ofn.getField(), out_temp);
336     fln.setNumLine(ofn.getNumLine());
337     return new NodePair(fln, fln);
338   }
339
340   private NodePair flattenCreateObjectNode(CreateObjectNode con,TempDescriptor out_temp) {
341     TypeDescriptor td=con.getType();
342     if (!td.isArray()) {
343       FlatNode fn=new FlatNew(td, out_temp, con.isGlobal(), con.getDisjointId());
344       FlatNode last=fn;
345       //handle wrapper fields
346       ClassDescriptor cd=td.getClassDesc();
347       for(Iterator fieldit=cd.getFields();fieldit.hasNext();) {
348         FieldDescriptor fd=(FieldDescriptor)fieldit.next();
349         if (fd.getType().iswrapper()) {
350           TempDescriptor wrap_tmp=TempDescriptor.tempFactory("wrapper_obj",fd.getType());
351           FlatNode fnwrapper=new FlatNew(fd.getType(), wrap_tmp, con.isGlobal());
352           fnwrapper.setNumLine(con.getNumLine());
353           FlatSetFieldNode fsfn=new FlatSetFieldNode(out_temp, fd, wrap_tmp);
354           fsfn.setNumLine(con.getNumLine());
355           last.addNext(fnwrapper);
356           fnwrapper.addNext(fsfn);
357           last=fsfn;
358         }
359       }
360
361       TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
362
363       // Build arguments
364       for(int i=0; i<con.numArgs(); i++) {
365         ExpressionNode en=con.getArg(i);
366         TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
367         temps[i]=tmp;
368         NodePair np=flattenExpressionNode(en, tmp);
369         last.addNext(np.getBegin());
370         last=np.getEnd();
371       }
372       MethodDescriptor md=con.getConstructor();
373       //Call to constructor
374       FlatCall fc=new FlatCall(md, null, out_temp, temps);
375       fc.setNumLine(con.getNumLine());
376       last.addNext(fc);
377       last=fc;
378       if (td.getClassDesc().hasFlags()) {
379         //          if (con.getFlagEffects()!=null) {
380         FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.NEWOBJECT);
381         ffan.setNumLine(con.getNumLine());
382         FlagEffects fes=con.getFlagEffects();
383         TempDescriptor flagtemp=out_temp;
384         if (fes!=null) {
385           for(int j=0; j<fes.numEffects(); j++) {
386             FlagEffect fe=fes.getEffect(j);
387             ffan.addFlagAction(flagtemp, fe.getFlag(), fe.getStatus());
388           }
389           for(int j=0; j<fes.numTagEffects(); j++) {
390             TagEffect te=fes.getTagEffect(j);
391             TempDescriptor tagtemp=getTempforVar(te.getTag());
392
393             ffan.addTagAction(flagtemp, te.getTag().getTag(), tagtemp, te.getStatus());
394           }
395         } else {
396           ffan.addFlagAction(flagtemp, null, false);
397         }
398         last.addNext(ffan);
399         last=ffan;
400       }
401       return new NodePair(fn,last);
402     } else {
403       if(con.getArrayInitializer() == null) {
404       FlatNode first=null;
405       FlatNode last=null;
406       TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
407       for (int i=0; i<con.numArgs(); i++) {
408         ExpressionNode en=con.getArg(i);
409         TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
410         temps[i]=tmp;
411         NodePair np=flattenExpressionNode(en, tmp);
412         if (first==null)
413           first=np.getBegin();
414         else
415           last.addNext(np.getBegin());
416         last=np.getEnd();
417
418         TempDescriptor tmp2=(i==0) ?
419                              out_temp :
420                              TempDescriptor.tempFactory("arg",en.getType());
421       }
422       FlatNew fn=new FlatNew(td, out_temp, temps[0], con.isGlobal(), con.getDisjointId());
423       last.addNext(fn);
424       if (temps.length>1) {
425         NodePair np=generateNewArrayLoop(temps, td.dereference(), out_temp, 0, con.isGlobal());
426         fn.addNext(np.getBegin());
427         return new NodePair(first,np.getEnd());
428       } else if (td.isArray()&&td.dereference().iswrapper()) {
429         NodePair np=generateNewArrayLoop(temps, td.dereference(), out_temp, 0, con.isGlobal());
430         fn.addNext(np.getBegin());
431         return new NodePair(first,np.getEnd());
432       } else
433         return new NodePair(first, fn);
434       } else {
435       // array creation with initializers
436         return flattenArrayInitializerNode(con.getArrayInitializer(), out_temp);
437       }
438     }
439   }
440
441   private NodePair generateNewArrayLoop(TempDescriptor[] temparray, TypeDescriptor td, TempDescriptor tmp, int i, boolean isglobal) {
442     TempDescriptor index=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
443     TempDescriptor tmpone=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
444     FlatNop fnop=new FlatNop();    //last node
445
446     //index=0
447     FlatLiteralNode fln=new FlatLiteralNode(index.getType(),new Integer(0),index);
448     //tmpone=1
449     FlatLiteralNode fln2=new FlatLiteralNode(tmpone.getType(),new Integer(1),tmpone);
450
451     TempDescriptor tmpbool=TempDescriptor.tempFactory("comp",new TypeDescriptor(TypeDescriptor.BOOLEAN));
452
453     FlatOpNode fcomp=new FlatOpNode(tmpbool,index,temparray[i],new Operation(Operation.LT));
454     FlatCondBranch fcb=new FlatCondBranch(tmpbool);
455     fcb.setTrueProb(State.TRUEPROB);
456     fcb.setLoop();
457     //is index<temp[i]
458     TempDescriptor new_tmp=TempDescriptor.tempFactory("tmp",td);
459     FlatNew fn=td.iswrapper()?new FlatNew(td, new_tmp, isglobal):new FlatNew(td, new_tmp, temparray[i+1], isglobal);
460     FlatSetElementNode fsen=new FlatSetElementNode(tmp,index,new_tmp);
461     // index=index+1
462     FlatOpNode fon=new FlatOpNode(index,index,tmpone,new Operation(Operation.ADD));
463     //jump out
464     fln.addNext(fln2);
465     fln2.addNext(fcomp);
466     fcomp.addNext(fcb);
467     fcb.addTrueNext(fn);
468     fcb.addFalseNext(fnop);
469     fn.addNext(fsen);
470     //Recursive call here
471     if ((i+2)<temparray.length) {
472       NodePair np2=generateNewArrayLoop(temparray, td.dereference(), new_tmp, i+1, isglobal);
473       fsen.addNext(np2.getBegin());
474       np2.getEnd().addNext(fon);
475     } else if (td.isArray()&&td.dereference().iswrapper()) {
476       NodePair np2=generateNewArrayLoop(temparray, td.dereference(), new_tmp, i+1, isglobal);
477       fsen.addNext(np2.getBegin());
478       np2.getEnd().addNext(fon);      
479     } else {
480       fsen.addNext(fon);
481     }
482     fon.addNext(fcomp);
483     return new NodePair(fln, fnop);
484   }
485
486   private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) {
487     TempDescriptor[] temps=new TempDescriptor[min.numArgs()];
488     FlatNode first=null;
489     FlatNode last=null;
490     TempDescriptor thisarg=null;
491
492     if (min.getExpression()!=null) {
493       TypeDescriptor mtd = min.getExpression().getType();
494       if(mtd.isClass() && mtd.getClassDesc().isEnum()) {
495         mtd = new TypeDescriptor(TypeDescriptor.INT);
496       }
497       thisarg=TempDescriptor.tempFactory("thisarg", mtd);
498       NodePair np=flattenExpressionNode(min.getExpression(),thisarg);
499       first=np.getBegin();
500       last=np.getEnd();
501     }
502
503     //Build arguments
504     for(int i=0; i<min.numArgs(); i++) {
505       ExpressionNode en=min.getArg(i);
506       TypeDescriptor etd = en.getType();
507       if(etd.isClass() && etd.getClassDesc().isEnum()) {
508         etd = new TypeDescriptor(TypeDescriptor.INT);
509       }
510       TempDescriptor td=TempDescriptor.tempFactory("arg", etd);
511       temps[i]=td;
512       NodePair np=flattenExpressionNode(en, td);
513       if (first==null)
514         first=np.getBegin();
515       else
516         last.addNext(np.getBegin());
517       last=np.getEnd();
518     }
519
520     MethodDescriptor md=min.getMethod();
521
522     //Call to constructor
523
524     FlatCall fc;
525     if(md.getReturnType()==null||md.getReturnType().isVoid())
526       fc=new FlatCall(md, null, thisarg, temps, min.getSuper());
527     else
528       fc=new FlatCall(md, out_temp, thisarg, temps, min.getSuper());
529     
530     fc.setNumLine(min.getNumLine());
531     
532     if (first==null) {
533       first=fc;
534     } else
535       last.addNext(fc);
536     return new NodePair(first,fc);
537   }
538
539   private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) {
540     TempDescriptor tmp=null;
541     if(fan.getExpression().getType().isClassNameRef()) {
542       // static field dereference with class name
543       tmp = new TempDescriptor(fan.getExpression().getType().getClassDesc().getSymbol(), fan.getExpression().getType());
544       FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
545       fn.setNumLine(fan.getNumLine());
546       return new NodePair(fn,fn);
547     } else {
548       tmp=TempDescriptor.tempFactory("temp",fan.getExpression().getType());
549       NodePair npe=flattenExpressionNode(fan.getExpression(),tmp);
550       FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
551       fn.setNumLine(fan.getNumLine());
552       npe.getEnd().addNext(fn);
553       return new NodePair(npe.getBegin(),fn);
554     }
555   }
556
557   private NodePair flattenArrayAccessNode(ArrayAccessNode aan,TempDescriptor out_temp) {
558     TempDescriptor tmp=TempDescriptor.tempFactory("temp",aan.getExpression().getType());
559     TempDescriptor tmpindex=TempDescriptor.tempFactory("temp",aan.getIndex().getType());
560     NodePair npe=flattenExpressionNode(aan.getExpression(),tmp);
561     NodePair npi=flattenExpressionNode(aan.getIndex(),tmpindex);
562     TempDescriptor arraytmp=out_temp;
563     if (aan.iswrapper()) {
564       //have wrapper
565       arraytmp=TempDescriptor.tempFactory("temp", aan.getExpression().getType().dereference());
566     }
567     FlatNode fn=new FlatElementNode(tmp,tmpindex,arraytmp);
568     fn.setNumLine(aan.getNumLine());
569     npe.getEnd().addNext(npi.getBegin());
570     npi.getEnd().addNext(fn);
571     if (aan.iswrapper()) {
572       FlatFieldNode ffn=new FlatFieldNode((FieldDescriptor)aan.getExpression().getType().dereference().getClassDesc().getFieldTable().get("value") ,arraytmp,out_temp);
573       ffn.setNumLine(aan.getNumLine());
574       fn.addNext(ffn);
575       fn=ffn;
576     }
577     return new NodePair(npe.getBegin(),fn);
578   }
579
580   private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
581     // Three cases:
582     // left side is variable
583     // left side is field
584     // left side is array
585
586     Operation base=an.getOperation().getBaseOp();
587     boolean pre=base==null||(base.getOp()!=Operation.POSTINC&&base.getOp()!=Operation.POSTDEC);
588
589     if (!pre) {
590       //rewrite the base operation
591       base=base.getOp()==Operation.POSTINC ? new Operation(Operation.ADD) : new Operation(Operation.SUB);
592     }
593     FlatNode first=null;
594     FlatNode last=null;
595     TempDescriptor src_tmp = src_tmp=an.getSrc()==null ? TempDescriptor.tempFactory("srctmp",an.getDest().getType()) : TempDescriptor.tempFactory("srctmp",an.getSrc().getType());
596
597     //Get src value
598     if (an.getSrc()!=null) {
599       if(an.getSrc().getEval() != null) {
600         FlatLiteralNode fln=new FlatLiteralNode(an.getSrc().getType(), an.getSrc().getEval().longValue(), src_tmp);
601         fln.setNumLine(an.getSrc().getNumLine());
602         first = last =fln;
603       } else {
604         NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
605         first=np_src.getBegin();
606         last=np_src.getEnd();
607       }
608     } else if (!pre) {
609       FlatLiteralNode fln=new FlatLiteralNode(new TypeDescriptor(TypeDescriptor.INT),new Integer(1),src_tmp);
610       fln.setNumLine(an.getNumLine());
611       first=fln;
612       last=fln;
613     }
614
615     if (an.getDest().kind()==Kind.FieldAccessNode) {
616       //We are assigning an object field
617
618       FieldAccessNode fan=(FieldAccessNode)an.getDest();
619       ExpressionNode en=fan.getExpression();
620       TempDescriptor dst_tmp=null;
621       NodePair np_baseexp=null;
622       if(en.getType().isClassNameRef()) {
623         // static field dereference with class name
624         dst_tmp = new TempDescriptor(en.getType().getClassDesc().getSymbol(), en.getType());
625         FlatNop nop=new FlatNop();
626         np_baseexp = new NodePair(nop,nop);
627       } else {
628         dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
629         np_baseexp=flattenExpressionNode(en, dst_tmp);
630       }
631       if (first==null)
632         first=np_baseexp.getBegin();
633       else
634         last.addNext(np_baseexp.getBegin());
635       last=np_baseexp.getEnd();
636
637       //See if we need to perform an operation
638       if (base!=null) {
639         //If it is a preinc we need to store the initial value
640         TempDescriptor src_tmp2=pre ? TempDescriptor.tempFactory("src",an.getDest().getType()) : out_temp;
641         TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
642         FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
643         ffn.setNumLine(an.getNumLine());
644         last.addNext(ffn);
645         last=ffn;
646
647         if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
648           ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
649           MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
650           FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
651           fc.setNumLine(an.getNumLine());
652           src_tmp=tmp;
653           last.addNext(fc);
654           last=fc;
655         } else {
656           FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
657           fon.setNumLine(an.getNumLine());
658           src_tmp=tmp;
659           last.addNext(fon);
660           last=fon;
661         }
662       }
663
664       FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
665       fsfn.setNumLine(en.getNumLine());
666       last.addNext(fsfn);
667       last=fsfn;
668       if (pre) {
669         FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
670         fon2.setNumLine(an.getNumLine());
671         fsfn.addNext(fon2);
672         last=fon2;
673       }
674       return new NodePair(first, last);
675     } else if (an.getDest().kind()==Kind.ArrayAccessNode) {
676       //We are assigning an array element
677
678       ArrayAccessNode aan=(ArrayAccessNode)an.getDest();
679       ExpressionNode en=aan.getExpression();
680       ExpressionNode enindex=aan.getIndex();
681       TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
682       TempDescriptor index_tmp=TempDescriptor.tempFactory("index",enindex.getType());
683       NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
684       NodePair np_indexexp=flattenExpressionNode(enindex, index_tmp);
685       if (first==null)
686         first=np_baseexp.getBegin();
687       else
688         last.addNext(np_baseexp.getBegin());
689       np_baseexp.getEnd().addNext(np_indexexp.getBegin());
690       last=np_indexexp.getEnd();
691
692       //See if we need to perform an operation
693       if (base!=null) {
694         //If it is a preinc we need to store the initial value
695         TempDescriptor src_tmp2=pre ? TempDescriptor.tempFactory("src",an.getDest().getType()) : out_temp;
696         TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
697
698         if (aan.iswrapper()) {
699           TypeDescriptor arrayeltype=aan.getExpression().getType().dereference();
700           TempDescriptor src_tmp3=TempDescriptor.tempFactory("src3",arrayeltype);
701           FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp3);
702           fen.setNumLine(aan.getNumLine());
703           FlatFieldNode ffn=new FlatFieldNode((FieldDescriptor)arrayeltype.getClassDesc().getFieldTable().get("value"),src_tmp3,src_tmp2);
704           ffn.setNumLine(aan.getNumLine());
705           last.addNext(fen);
706           fen.addNext(ffn);
707           last=ffn;
708         } else {
709           FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp2);
710           fen.setNumLine(aan.getNumLine());
711           last.addNext(fen);
712           last=fen;
713         }
714         if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
715           ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
716           MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
717           FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
718           fc.setNumLine(an.getNumLine());
719           src_tmp=tmp;
720           last.addNext(fc);
721           last=fc;
722         } else {
723           FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
724           fon.setNumLine(an.getNumLine());
725           src_tmp=tmp;
726           last.addNext(fon);
727           last=fon;
728         }
729       }
730
731       if (aan.iswrapper()) { 
732         TypeDescriptor arrayeltype=aan.getExpression().getType().dereference();
733         TempDescriptor src_tmp3=TempDescriptor.tempFactory("src3",arrayeltype);
734         FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp3);
735         fen.setNumLine(aan.getNumLine());
736         FlatSetFieldNode fsfn=new FlatSetFieldNode(src_tmp3,(FieldDescriptor)arrayeltype.getClassDesc().getFieldTable().get("value"),src_tmp);
737         fsfn.setNumLine(aan.getExpression().getNumLine());
738         last.addNext(fen);
739         fen.addNext(fsfn);
740         last=fsfn;
741       } else { 
742         FlatSetElementNode fsen=new FlatSetElementNode(dst_tmp, index_tmp, src_tmp);
743         fsen.setNumLine(aan.getNumLine());
744         last.addNext(fsen);
745         last=fsen;
746       }
747       if (pre) {
748         FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
749         fon2.setNumLine(an.getNumLine());
750         last.addNext(fon2);
751         last=fon2;
752       }
753       return new NodePair(first, last);
754     } else if (an.getDest().kind()==Kind.NameNode) {
755       //We could be assigning a field or variable
756       NameNode nn=(NameNode)an.getDest();
757
758
759       if (nn.getExpression()!=null) {
760         //It is a field
761         FieldAccessNode fan=(FieldAccessNode)nn.getExpression();
762         ExpressionNode en=fan.getExpression();
763     TempDescriptor dst_tmp=null;
764     NodePair np_baseexp=null;
765     if(en.getType().isClassNameRef()) {
766       // static field dereference with class name
767       dst_tmp = new TempDescriptor(en.getType().getClassDesc().getSymbol(), en.getType());
768       FlatNop nop=new FlatNop();
769       np_baseexp = new NodePair(nop,nop);
770     } else {
771       dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
772       np_baseexp=flattenExpressionNode(en, dst_tmp);
773     }
774         if (first==null)
775           first=np_baseexp.getBegin();
776         else
777           last.addNext(np_baseexp.getBegin());
778         last=np_baseexp.getEnd();
779
780         //See if we need to perform an operation
781         if (base!=null) {
782           //If it is a preinc we need to store the initial value
783           TempDescriptor src_tmp2=pre ? TempDescriptor.tempFactory("src",an.getDest().getType()) : out_temp;
784           TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
785
786           FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
787           ffn.setNumLine(an.getNumLine());
788           last.addNext(ffn);
789           last=ffn;
790
791
792           if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
793             ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
794             MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
795             FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
796             fc.setNumLine(an.getNumLine());
797             src_tmp=tmp;
798             last.addNext(fc);
799             last=fc;
800           } else {
801             FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
802             fon.setNumLine(an.getNumLine());
803             src_tmp=tmp;
804             last.addNext(fon);
805             last=fon;
806           }
807         }
808
809
810         FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
811         fsfn.setNumLine(en.getNumLine());
812         last.addNext(fsfn);
813         last=fsfn;
814         if (pre) {
815           FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
816           fon2.setNumLine(an.getNumLine());
817           fsfn.addNext(fon2);
818           last=fon2;
819         }
820         return new NodePair(first, last);
821       } else {
822         if (nn.getField()!=null) {
823           //It is a field
824           //Get src value
825
826           //See if we need to perform an operation
827           if (base!=null) {
828             //If it is a preinc we need to store the initial value
829             TempDescriptor src_tmp2=pre ? TempDescriptor.tempFactory("src",an.getDest().getType()) : out_temp;
830             TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
831         
832         TempDescriptor ftmp= null;
833         if((nn.getClassDesc() != null)) {
834           // this is a static field
835           ftmp = new TempDescriptor(nn.getClassDesc().getSymbol(), nn.getClassType());
836
837         } else {
838           ftmp=getTempforVar(nn.getVar());
839         }
840         FlatFieldNode ffn=new FlatFieldNode(nn.getField(), ftmp, src_tmp2);
841         ffn.setNumLine(an.getNumLine());
842
843             if (first==null)
844               first=ffn;
845             else {
846               last.addNext(ffn);
847             }
848             last=ffn;
849
850
851             if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
852               ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
853               MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
854               FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
855               fc.setNumLine(an.getNumLine());
856               src_tmp=tmp;
857               last.addNext(fc);
858               last=fc;
859             } else {
860               FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
861               fon.setNumLine(an.getNumLine());
862               src_tmp=tmp;
863               last.addNext(fon);
864               last=fon;
865             }
866           }
867
868       FlatSetFieldNode fsfn=null;
869       if(nn.getClassDesc()!=null) {
870         // this is a static field access inside of a static block
871         fsfn=new FlatSetFieldNode(new TempDescriptor("sfsb", nn.getClassType()), nn.getField(), src_tmp);
872         fsfn.setNumLine(nn.getNumLine());
873       } else {
874         fsfn=new FlatSetFieldNode(getTempforVar(nn.getVar()), nn.getField(), src_tmp);
875         fsfn.setNumLine(nn.getNumLine());
876       }
877           if (first==null) {
878             first=fsfn;
879           } else {
880             last.addNext(fsfn);
881           }
882           last=fsfn;
883           if (pre) {
884             FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
885             fon2.setNumLine(an.getNumLine());
886             fsfn.addNext(fon2);
887             last=fon2;
888           }
889           return new NodePair(first, last);
890         } else {
891           //It is a variable
892           //See if we need to perform an operation
893
894           if (base!=null) {
895             //If it is a preinc we need to store the initial value
896             TempDescriptor src_tmp2=getTempforVar(nn.getVar());
897             TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
898             if (!pre) {
899               FlatOpNode fon=new FlatOpNode(out_temp, src_tmp2, null, new Operation(Operation.ASSIGN));
900               fon.setNumLine(an.getNumLine());
901               if (first==null)
902                 first=fon;
903               else
904                 last.addNext(fon);
905               last=fon;
906             }
907
908
909             if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
910               ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
911               MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
912               FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
913               fc.setNumLine(an.getNumLine());
914               if (first==null)
915                 first=fc;
916               else
917                 last.addNext(fc);
918               src_tmp=tmp;
919               last=fc;
920             } else {
921               FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
922               fon.setNumLine(an.getNumLine());
923               if (first==null)
924                 first=fon;
925               else
926                 last.addNext(fon);
927               src_tmp=tmp;
928               last=fon;
929             }
930           }
931
932           FlatOpNode fon=new FlatOpNode(getTempforVar(nn.getVar()), src_tmp, null, new Operation(Operation.ASSIGN));
933           fon.setNumLine(an.getNumLine());
934
935           last.addNext(fon);
936           last=fon;
937           if (pre) {
938             FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
939             fon2.setNumLine(an.getNumLine());
940             fon.addNext(fon2);
941             last=fon2;
942           }
943           return new NodePair(first, last);
944         } //end of else
945       }
946     }
947
948     throw new Error();
949   }
950
951   private NodePair flattenNameNode(NameNode nn,TempDescriptor out_temp) {
952     if (nn.getExpression()!=null) {
953       /* Hack - use subtree instead */
954       return flattenExpressionNode(nn.getExpression(),out_temp);
955     } else if (nn.getField()!=null) {
956       TempDescriptor tmp= null;
957       if((nn.getClassDesc() != null)) {
958         // this is a static field
959         tmp = new TempDescriptor(nn.getClassDesc().getSymbol(), nn.getClassType());
960         
961       } else {
962       tmp=getTempforVar(nn.getVar());
963       }
964       FlatFieldNode ffn=new FlatFieldNode(nn.getField(), tmp, out_temp);
965       ffn.setNumLine(nn.getNumLine());
966       return new NodePair(ffn,ffn);
967     } else {
968       TempDescriptor tmp=getTempforVar(nn.isTag() ? nn.getTagVar() : nn.getVar());
969       if (nn.isTag()) {
970         //propagate tag
971         out_temp.setTag(tmp.getTag());
972       }
973       FlatOpNode fon=new FlatOpNode(out_temp, tmp, null, new Operation(Operation.ASSIGN));
974       fon.setNumLine(nn.getNumLine());
975       return new NodePair(fon,fon);
976     }
977   }
978
979   private NodePair flattenOpNode(OpNode on,TempDescriptor out_temp) {
980     TempDescriptor temp_left=TempDescriptor.tempFactory("leftop",on.getLeft().getType());
981     TempDescriptor temp_right=null;
982
983     Operation op=on.getOp();
984
985     NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
986     NodePair right;
987     if (on.getRight()!=null) {
988       temp_right=TempDescriptor.tempFactory("rightop",on.getRight().getType());
989       right=flattenExpressionNode(on.getRight(),temp_right);
990     } else {
991       FlatNop nop=new FlatNop();
992       right=new NodePair(nop,nop);
993     }
994
995     if (op.getOp()==Operation.LOGIC_OR) {
996       /* Need to do shortcircuiting */
997       FlatCondBranch fcb=new FlatCondBranch(temp_left);
998       fcb.setNumLine(on.getNumLine());
999       FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
1000       fon1.setNumLine(on.getNumLine());
1001       FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
1002       fon2.setNumLine(on.getNumLine());
1003       FlatNop fnop=new FlatNop();
1004       left.getEnd().addNext(fcb);
1005       fcb.addFalseNext(right.getBegin());
1006       right.getEnd().addNext(fon2);
1007       fon2.addNext(fnop);
1008       fcb.addTrueNext(fon1);
1009       fon1.addNext(fnop);
1010       return new NodePair(left.getBegin(), fnop);
1011     } else if (op.getOp()==Operation.LOGIC_AND) {
1012       /* Need to do shortcircuiting */
1013       FlatCondBranch fcb=new FlatCondBranch(temp_left);
1014       fcb.setNumLine(on.getNumLine());
1015       FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
1016       fon1.setNumLine(on.getNumLine());
1017       FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
1018       fon2.setNumLine(on.getNumLine());
1019       FlatNop fnop=new FlatNop();
1020       left.getEnd().addNext(fcb);
1021       fcb.addTrueNext(right.getBegin());
1022       right.getEnd().addNext(fon2);
1023       fon2.addNext(fnop);
1024       fcb.addFalseNext(fon1);
1025       fon1.addNext(fnop);
1026       return new NodePair(left.getBegin(), fnop);
1027     } else if (op.getOp()==Operation.ADD&&on.getLeft().getType().isString()) {
1028       //We have a string concatenate
1029       ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
1030       MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat", new TypeDescriptor[] {new TypeDescriptor(stringcd)});
1031       FlatCall fc=new FlatCall(concatmd, out_temp, temp_left, new TempDescriptor[] {temp_right});
1032       fc.setNumLine(on.getNumLine());
1033       left.getEnd().addNext(right.getBegin());
1034       right.getEnd().addNext(fc);
1035       return new NodePair(left.getBegin(), fc);
1036     }
1037
1038     FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
1039     fon.setNumLine(on.getNumLine());
1040     left.getEnd().addNext(right.getBegin());
1041     right.getEnd().addNext(fon);
1042     return new NodePair(left.getBegin(),fon);
1043   }
1044
1045   private NodePair flattenExpressionNode(ExpressionNode en, TempDescriptor out_temp) {
1046     switch(en.kind()) {
1047     case Kind.AssignmentNode:
1048       return flattenAssignmentNode((AssignmentNode)en,out_temp);
1049
1050     case Kind.CastNode:
1051       return flattenCastNode((CastNode)en,out_temp);
1052
1053     case Kind.CreateObjectNode:
1054       return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
1055
1056     case Kind.FieldAccessNode:
1057       return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
1058
1059     case Kind.ArrayAccessNode:
1060       return flattenArrayAccessNode((ArrayAccessNode)en,out_temp);
1061
1062     case Kind.LiteralNode:
1063       return flattenLiteralNode((LiteralNode)en,out_temp);
1064
1065     case Kind.MethodInvokeNode:
1066       return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
1067
1068     case Kind.NameNode:
1069       return flattenNameNode((NameNode)en,out_temp);
1070
1071     case Kind.OpNode:
1072       return flattenOpNode((OpNode)en,out_temp);      
1073
1074     case Kind.OffsetNode:
1075       return flattenOffsetNode((OffsetNode)en,out_temp);
1076
1077     case Kind.TertiaryNode:
1078       return flattenTertiaryNode((TertiaryNode)en,out_temp);
1079
1080     case Kind.InstanceOfNode:
1081       return flattenInstanceOfNode((InstanceOfNode)en,out_temp);
1082
1083     case Kind.ArrayInitializerNode:
1084       return flattenArrayInitializerNode((ArrayInitializerNode)en,out_temp);
1085     }
1086     throw new Error();
1087   }
1088
1089   private NodePair flattenDeclarationNode(DeclarationNode dn) {
1090     VarDescriptor vd=dn.getVarDescriptor();
1091     TempDescriptor td=getTempforVar(vd);
1092     if (dn.getExpression()!=null)
1093       return flattenExpressionNode(dn.getExpression(),td);
1094     else {
1095       FlatNop fn=new FlatNop();
1096       return new NodePair(fn,fn);
1097     }
1098   }
1099
1100   private NodePair flattenTagDeclarationNode(TagDeclarationNode dn) {
1101     TagVarDescriptor tvd=dn.getTagVarDescriptor();
1102     TagDescriptor tag=tvd.getTag();
1103     TempDescriptor tmp=getTempforVar(tvd);
1104     FlatTagDeclaration ftd=new FlatTagDeclaration(tag, tmp);
1105     ftd.setNumLine(dn.getNumLine());
1106     return new NodePair(ftd,ftd);
1107   }
1108
1109   private TempDescriptor getTempforParam(Descriptor d) {
1110     if (temptovar.containsKey(d))
1111       return (TempDescriptor)temptovar.get(d);
1112     else {
1113       if (d instanceof VarDescriptor) {
1114         VarDescriptor vd=(VarDescriptor)d;
1115         TempDescriptor td=TempDescriptor.paramtempFactory(vd.getName(),vd.getType());
1116         temptovar.put(vd,td);
1117         return td;
1118       } else if (d instanceof TagVarDescriptor) {
1119         TagVarDescriptor tvd=(TagVarDescriptor)d;
1120         TypeDescriptor tagtype=new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass));
1121         TempDescriptor td=TempDescriptor.paramtempFactory(tvd.getName(), tagtype, tvd.getTag());
1122         temptovar.put(tvd,td);
1123         return td;
1124       } else throw new Error("Unreconized Descriptor");
1125     }
1126   }
1127
1128   private TempDescriptor getTempforVar(Descriptor d) {
1129     if (temptovar.containsKey(d))
1130       return (TempDescriptor)temptovar.get(d);
1131     else {
1132       if (d instanceof VarDescriptor) {
1133         VarDescriptor vd=(VarDescriptor)d;
1134         TempDescriptor td=TempDescriptor.tempFactory(vd.getName(), vd.getType());
1135         temptovar.put(vd,td);
1136         return td;
1137       } else if (d instanceof TagVarDescriptor) {
1138         TagVarDescriptor tvd=(TagVarDescriptor)d;
1139         //BUGFIX TAGTYPE - add next line, modify following
1140         //line to tag this new type descriptor, modify
1141         //TempDescriptor constructor & factory to set type
1142         //using this Type To test, use any program with tags
1143         TypeDescriptor tagtype=new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass));
1144         TempDescriptor td=TempDescriptor.tempFactory(tvd.getName(),tagtype, tvd.getTag());
1145         temptovar.put(tvd,td);
1146         return td;
1147       } else throw new Error("Unrecognized Descriptor");
1148     }
1149   }
1150
1151   private NodePair flattenIfStatementNode(IfStatementNode isn) {
1152     TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
1153     NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
1154     FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1155     fcb.setNumLine(isn.getNumLine());
1156     NodePair true_np=flattenBlockNode(isn.getTrueBlock());
1157     NodePair false_np;
1158     FlatNop nopend=new FlatNop();
1159
1160     if (isn.getFalseBlock()!=null)
1161       false_np=flattenBlockNode(isn.getFalseBlock());
1162     else {
1163       FlatNop nop=new FlatNop();
1164       false_np=new NodePair(nop,nop);
1165     }
1166
1167     cond.getEnd().addNext(fcb);
1168     fcb.addTrueNext(true_np.getBegin());
1169     fcb.addFalseNext(false_np.getBegin());
1170     if (true_np.getEnd()!=null)
1171         true_np.getEnd().addNext(nopend);
1172     if (false_np.getEnd()!=null)
1173         false_np.getEnd().addNext(nopend);
1174     if (nopend.numPrev()==0)
1175       return new NodePair(cond.getBegin(), null);
1176
1177     return new NodePair(cond.getBegin(), nopend);
1178   }
1179   
1180   private NodePair flattenSwitchStatementNode(SwitchStatementNode ssn) {
1181     TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.INT));
1182     NodePair cond=flattenExpressionNode(ssn.getCondition(),cond_temp);
1183     FlatNop nopend=new FlatNop();
1184     NodePair sbody = flattenSwitchBodyNode(ssn.getSwitchBody(), cond_temp, nopend);
1185     
1186     cond.getEnd().addNext(sbody.getBegin());
1187
1188     return new NodePair(cond.getBegin(), sbody.getEnd());
1189   }
1190   
1191   private NodePair flattenSwitchBodyNode(BlockNode bn, TempDescriptor cond_temp, FlatNode endnode) {
1192     FlatNode begin=null;
1193     FlatNode end=endnode;
1194     NodePair prev_true_branch = null;
1195     NodePair prev_false_branch = null;
1196     for(int i=0; i<bn.size(); i++) {
1197       SwitchBlockNode sbn = (SwitchBlockNode)bn.get(i);
1198       HashSet oldbs=breakset;
1199       breakset=new HashSet();
1200       
1201       NodePair body=flattenBlockNode(sbn.getSwitchBlockStatement());
1202       Vector<SwitchLabelNode> slnv = sbn.getSwitchConditions();
1203       FlatNode cond_begin = null;
1204       NodePair prev_fnp = null;
1205       for(int j = 0; j < slnv.size(); j++) {
1206         SwitchLabelNode sln = slnv.elementAt(j);
1207         NodePair left = null;
1208         NodePair false_np = null;
1209         if(sln.isDefault()) {
1210           left = body;
1211         } else {
1212           TempDescriptor cond_tmp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
1213           TempDescriptor temp_left=TempDescriptor.tempFactory("leftop", sln.getCondition().getType());
1214           Operation op=new Operation(Operation.EQUAL);
1215           left=flattenExpressionNode(sln.getCondition(), temp_left);
1216           FlatOpNode fon=new FlatOpNode(cond_tmp, temp_left, cond_temp, op);
1217           fon.setNumLine(sln.getNumLine());
1218           left.getEnd().addNext(fon);
1219
1220           FlatCondBranch fcb=new FlatCondBranch(cond_tmp);
1221           fcb.setNumLine(bn.getNumLine());
1222           fcb.setTrueProb(State.TRUEPROB);
1223
1224           FlatNop nop=new FlatNop();
1225           false_np=new NodePair(nop,nop);
1226
1227           fon.addNext(fcb);
1228           fcb.addTrueNext(body.getBegin());
1229           fcb.addFalseNext(false_np.getBegin());
1230         }
1231         if((prev_fnp != null) && (prev_fnp.getEnd() != null)) {
1232           prev_fnp.getEnd().addNext(left.getBegin());
1233         }
1234         prev_fnp = false_np;
1235         
1236         if (begin==null) {
1237           begin = left.getBegin();
1238         }
1239         if(cond_begin == null) {
1240           cond_begin = left.getBegin();
1241         }
1242       }
1243       if((prev_false_branch != null) && (prev_false_branch.getEnd() != null)) {
1244         prev_false_branch.getEnd().addNext(cond_begin);
1245       }
1246       prev_false_branch = prev_fnp;
1247       if((prev_true_branch != null) && (prev_true_branch.getEnd() != null)) {
1248         prev_true_branch.getEnd().addNext(body.getBegin());
1249       }
1250       prev_true_branch = body;
1251       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
1252         FlatNode fn=(FlatNode)breakit.next();
1253         breakit.remove();
1254         fn.addNext(endnode);
1255       }
1256       breakset=oldbs;
1257     }
1258     if((prev_true_branch != null) && (prev_true_branch.getEnd() != null)) {
1259       prev_true_branch.getEnd().addNext(endnode);
1260     }
1261     if((prev_false_branch != null) && (prev_false_branch.getEnd() != null)) {
1262       prev_false_branch.getEnd().addNext(endnode);
1263     }
1264     if(begin == null) {
1265       end=begin=new FlatNop();
1266     }
1267     return new NodePair(begin,end);
1268   }
1269   
1270   private NodePair flattenLoopNode(LoopNode ln) {
1271     HashSet oldbs=breakset;
1272     HashSet oldcs=continueset;
1273     breakset=new HashSet();
1274     continueset=new HashSet();
1275     
1276     if (ln.getType()==LoopNode.FORLOOP) {
1277       NodePair initializer=flattenBlockNode(ln.getInitializer());
1278       TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
1279       NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
1280       NodePair update=flattenBlockNode(ln.getUpdate());
1281       NodePair body=flattenBlockNode(ln.getBody());
1282       FlatNode begin=initializer.getBegin();
1283       FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1284       fcb.setNumLine(ln.getNumLine());
1285       fcb.setTrueProb(State.TRUEPROB);
1286       fcb.setLoop();
1287       FlatNop nopend=new FlatNop();
1288       FlatBackEdge backedge=new FlatBackEdge();
1289
1290       FlatNop nop2=new FlatNop();
1291       initializer.getEnd().addNext(nop2);
1292       nop2.addNext(condition.getBegin());
1293       if (body.getEnd()!=null)
1294           body.getEnd().addNext(update.getBegin());
1295       update.getEnd().addNext(backedge);
1296       backedge.addNext(condition.getBegin());
1297       condition.getEnd().addNext(fcb);
1298       fcb.addFalseNext(nopend);
1299       fcb.addTrueNext(body.getBegin());
1300       for(Iterator contit=continueset.iterator();contit.hasNext();) {
1301           FlatNode fn=(FlatNode)contit.next();
1302           contit.remove();
1303           fn.addNext(update.getBegin());
1304       }
1305       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
1306           FlatNode fn=(FlatNode)breakit.next();
1307           breakit.remove();
1308           fn.addNext(nopend);
1309       }
1310       breakset=oldbs;
1311       continueset=oldcs;
1312       return new NodePair(begin,nopend);
1313     } else if (ln.getType()==LoopNode.WHILELOOP) {
1314       TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
1315       NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
1316       NodePair body=flattenBlockNode(ln.getBody());
1317       FlatNode begin=condition.getBegin();
1318       FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1319       fcb.setNumLine(ln.getNumLine());
1320       fcb.setTrueProb(State.TRUEPROB);
1321       fcb.setLoop();
1322       FlatNop nopend=new FlatNop();
1323       FlatBackEdge backedge=new FlatBackEdge();
1324
1325       if (body.getEnd()!=null)
1326         body.getEnd().addNext(backedge);
1327       backedge.addNext(condition.getBegin());
1328
1329       condition.getEnd().addNext(fcb);
1330       fcb.addFalseNext(nopend);
1331       fcb.addTrueNext(body.getBegin());
1332
1333       for(Iterator contit=continueset.iterator();contit.hasNext();) {
1334           FlatNode fn=(FlatNode)contit.next();
1335           contit.remove();
1336           fn.addNext(backedge);
1337       }
1338       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
1339           FlatNode fn=(FlatNode)breakit.next();
1340           breakit.remove();
1341           fn.addNext(nopend);
1342       }
1343       breakset=oldbs;
1344       continueset=oldcs;
1345       return new NodePair(begin,nopend);
1346     } else if (ln.getType()==LoopNode.DOWHILELOOP) {
1347       TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
1348       NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
1349       NodePair body=flattenBlockNode(ln.getBody());
1350       FlatNode begin=body.getBegin();
1351       FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1352       fcb.setNumLine(ln.getNumLine());
1353       fcb.setTrueProb(State.TRUEPROB);
1354       fcb.setLoop();
1355       FlatNop nopend=new FlatNop();
1356       FlatBackEdge backedge=new FlatBackEdge();
1357
1358       if (body.getEnd()!=null)
1359         body.getEnd().addNext(condition.getBegin());
1360       condition.getEnd().addNext(fcb);
1361       fcb.addFalseNext(nopend);
1362       fcb.addTrueNext(backedge);
1363       backedge.addNext(body.getBegin());
1364
1365       for(Iterator contit=continueset.iterator();contit.hasNext();) {
1366           FlatNode fn=(FlatNode)contit.next();
1367           contit.remove();
1368           fn.addNext(condition.getBegin());
1369       }
1370       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
1371           FlatNode fn=(FlatNode)breakit.next();
1372           breakit.remove();
1373           fn.addNext(nopend);
1374       }
1375       breakset=oldbs;
1376       continueset=oldcs;
1377       return new NodePair(begin,nopend);
1378     } else throw new Error();
1379   }
1380
1381   private NodePair flattenReturnNode(ReturnNode rntree) {
1382     TempDescriptor retval=null;
1383     NodePair cond=null;
1384     if (rntree.getReturnExpression()!=null) {
1385       retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
1386       cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
1387     }
1388
1389     FlatReturnNode rnflat=new FlatReturnNode(retval);
1390     rnflat.setNumLine(rntree.getNumLine());
1391     rnflat.addNext(fe);
1392     FlatNode ln=rnflat;
1393     if ((state.THREAD||state.MGC)&&!this.lockStack.isEmpty()) {
1394       FlatNode end = null;
1395       MethodDescriptor memdex=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
1396       for(int j = this.lockStack.size(); j > 0; j--) {
1397         TempDescriptor thistd = this.lockStack.elementAt(j-1);
1398         FlatCall fcunlock = new FlatCall(memdex, null, thistd, new TempDescriptor[0]);
1399         fcunlock.setNumLine(rntree.getNumLine());
1400         if(end != null) {
1401           end.addNext(fcunlock);
1402         }
1403         end = fcunlock;
1404       }
1405       end.addNext(ln);
1406       ln=end;
1407     }
1408     if (state.DSM&&currmd.getModifiers().isAtomic()) {
1409       FlatAtomicExitNode faen=new FlatAtomicExitNode(curran);
1410       faen.addNext(ln);
1411       ln=faen;
1412     }
1413
1414     if (cond!=null) {
1415       cond.getEnd().addNext(ln);
1416       return new NodePair(cond.getBegin(),null);
1417     } else
1418       return new NodePair(ln,null);
1419   }
1420
1421   private NodePair flattenTaskExitNode(TaskExitNode ten) {
1422     FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.TASKEXIT);
1423     ffan.setTaskExitIndex(ten.getTaskExitIndex());
1424     updateFlagActionNode(ffan, ten.getFlagEffects());
1425     NodePair fcn=flattenConstraintCheck(ten.getChecks());
1426     ffan.addNext(fcn.getBegin());
1427     FlatReturnNode rnflat=new FlatReturnNode(null);
1428     rnflat.setNumLine(ten.getNumLine());
1429     rnflat.addNext(fe);
1430     fcn.getEnd().addNext(rnflat);
1431     return new NodePair(ffan, null);
1432   }
1433
1434   private NodePair flattenConstraintCheck(Vector ccs) {
1435     FlatNode begin=new FlatNop();
1436     if (ccs==null)
1437       return new NodePair(begin,begin);
1438     FlatNode last=begin;
1439     for(int i=0; i<ccs.size(); i++) {
1440       ConstraintCheck cc=(ConstraintCheck) ccs.get(i);
1441       /* Flatten the arguments */
1442       TempDescriptor[] temps=new TempDescriptor[cc.numArgs()];
1443       String[] vars=new String[cc.numArgs()];
1444       for(int j=0; j<cc.numArgs(); j++) {
1445         ExpressionNode en=cc.getArg(j);
1446         TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
1447         temps[j]=td;
1448         vars[j]=cc.getVar(j);
1449         NodePair np=flattenExpressionNode(en, td);
1450         last.addNext(np.getBegin());
1451         last=np.getEnd();
1452       }
1453
1454       FlatCheckNode fcn=new FlatCheckNode(cc.getSpec(), vars, temps);
1455       last.addNext(fcn);
1456       last=fcn;
1457     }
1458     return new NodePair(begin,last);
1459   }
1460
1461   private NodePair flattenSubBlockNode(SubBlockNode sbn) {
1462     return flattenBlockNode(sbn.getBlockNode());
1463   }
1464
1465   private NodePair flattenSynchronizedNode(SynchronizedNode sbn) {
1466     TempDescriptor montmp=null;
1467     FlatNode first = null;
1468     FlatNode end = null;
1469     if(sbn.getExpr() instanceof ClassTypeNode) {
1470       montmp=new TempDescriptor("classobj", ((ClassTypeNode)sbn.getExpr()).getType().getClassDesc());
1471     } else {
1472       montmp = TempDescriptor.tempFactory("monitor",sbn.getExpr().getType());
1473       NodePair npexp=flattenExpressionNode(sbn.getExpr(), montmp);
1474       first = npexp.getBegin();
1475       end = npexp.getEnd();
1476     }
1477     this.lockStack.push(montmp);
1478     NodePair npblock=flattenBlockNode(sbn.getBlockNode());
1479
1480     MethodDescriptor menmd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorEnter");
1481     FlatCall fcen=new FlatCall(menmd, null, montmp, new TempDescriptor[0]);
1482     fcen.setNumLine(sbn.getNumLine());
1483
1484     MethodDescriptor mexmd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
1485     FlatCall fcex=new FlatCall(mexmd, null, montmp, new TempDescriptor[0]);
1486     fcex.setNumLine(sbn.getNumLine());
1487     
1488     this.lockStack.pop();
1489
1490     if(first != null) {
1491       end.addNext(fcen);
1492     } else {
1493       first = fcen;
1494     }
1495     fcen.addNext(npblock.getBegin());
1496     
1497     if (npblock.getEnd()!=null&&npblock.getEnd().kind()!=FKind.FlatReturnNode) {
1498       npblock.getEnd().addNext(fcex);
1499     }
1500     
1501     /*if(npblock.getEnd() != null) {
1502       npblock.getEnd().addNext(fcex);
1503     }*/
1504     return new NodePair(first, fcex);
1505   }
1506
1507   private NodePair flattenAtomicNode(AtomicNode sbn) {
1508     NodePair np=flattenBlockNode(sbn.getBlockNode());
1509     FlatAtomicEnterNode faen=new FlatAtomicEnterNode();
1510     faen.setNumLine(sbn.getNumLine());
1511     FlatAtomicExitNode faexn=new FlatAtomicExitNode(faen);
1512     faen.addNext(np.getBegin());
1513     np.getEnd().addNext(faexn);
1514     return new NodePair(faen, faexn);
1515   }
1516
1517   private NodePair flattenGenReachNode( GenReachNode grn ) {
1518     FlatGenReachNode fgrn = new FlatGenReachNode( grn.getGraphName() );
1519     return new NodePair( fgrn, fgrn );
1520   }
1521
1522   private NodePair flattenSESENode(SESENode sn) {
1523     if( sn.isStart() ) {
1524       FlatSESEEnterNode fsen=new FlatSESEEnterNode(sn);
1525       fsen.setNumLine(sn.getNumLine());
1526       sn.setFlatEnter(fsen);
1527       return new NodePair(fsen, fsen);
1528     }
1529
1530     FlatSESEExitNode fsexn=new FlatSESEExitNode(sn);
1531     sn.setFlatExit(fsexn);
1532     FlatSESEEnterNode fsen=sn.getStart().getFlatEnter();
1533     fsexn.setFlatEnter(fsen);    
1534     sn.getStart().getFlatEnter().setFlatExit( fsexn );
1535     
1536     return new NodePair(fsexn, fsexn);
1537   }
1538
1539   private NodePair flattenContinueBreakNode(ContinueBreakNode cbn) {
1540       FlatNop fn=new FlatNop();
1541       if (cbn.isBreak())
1542           breakset.add(fn);
1543       else
1544           continueset.add(fn);
1545       return new NodePair(fn,null);
1546   }
1547
1548   private NodePair flattenInstanceOfNode(InstanceOfNode tn, TempDescriptor out_temp) {
1549     TempDescriptor expr_temp=TempDescriptor.tempFactory("expr",tn.getExpr().getType());
1550     NodePair cond=flattenExpressionNode(tn.getExpr(), expr_temp);
1551     FlatInstanceOfNode fion=new FlatInstanceOfNode(tn.getExprType(), expr_temp, out_temp);
1552     fion.setNumLine(tn.getNumLine());
1553     cond.getEnd().addNext(fion);
1554     return new NodePair(cond.getBegin(),fion);
1555   }
1556
1557   private NodePair flattenArrayInitializerNode(ArrayInitializerNode ain, TempDescriptor out_temp) {
1558     boolean isGlobal = false;
1559     String disjointId = null;
1560     // get the type the array to be initialized
1561     TypeDescriptor td = ain.getType();
1562
1563     // create a new array of size equal to the array initializer
1564     FlatNode first=null;
1565     FlatNode last=null;
1566     TempDescriptor tmp=TempDescriptor.tempFactory("arg", new TypeDescriptor(TypeDescriptor.INT));
1567     FlatLiteralNode fln_tmp=new FlatLiteralNode(tmp.getType(), new Integer(ain.numVarInitializers()), tmp);
1568     fln_tmp.setNumLine(ain.getNumLine());
1569     first = last=fln_tmp;
1570     
1571     // create the new array
1572     FlatNew fn=new FlatNew(td, out_temp, tmp, isGlobal, disjointId);
1573     last.addNext(fn);
1574     last = fn;
1575     
1576     // initialize the new array
1577     for(int i = 0; i < ain.numVarInitializers(); i++) {
1578       ExpressionNode var_init_node = ain.getVarInitializer(i);
1579       TempDescriptor tmp_toinit = out_temp;
1580       TempDescriptor tmp_init=TempDescriptor.tempFactory("array_init", td.dereference());
1581       // index=i
1582       TempDescriptor index=TempDescriptor.tempFactory("index", new TypeDescriptor(TypeDescriptor.INT));
1583       FlatLiteralNode fln=new FlatLiteralNode(index.getType(), new Integer(i), index);
1584       fln.setNumLine(ain.getNumLine());
1585       // calculate the initial value
1586       NodePair np_init = flattenExpressionNode(var_init_node, tmp_init);
1587       // TODO wrapper class process is missing now
1588       /*if(td.isArray() && td.dereference().iswrapper()) {
1589       }*/
1590       FlatSetElementNode fsen=new FlatSetElementNode(tmp_toinit, index, tmp_init);
1591       fsen.setNumLine(ain.getNumLine());
1592       last.addNext(fln);
1593       fln.addNext(np_init.getBegin());
1594       np_init.getEnd().addNext(fsen);
1595       last = fsen;
1596     }
1597     
1598     return new NodePair(first, last);
1599   }
1600
1601   private NodePair flattenTertiaryNode(TertiaryNode tn, TempDescriptor out_temp) {
1602     TempDescriptor cond_temp=TempDescriptor.tempFactory("tert_cond",new TypeDescriptor(TypeDescriptor.BOOLEAN));
1603     TempDescriptor true_temp=TempDescriptor.tempFactory("tert_true",tn.getTrueExpr().getType());
1604     TempDescriptor fals_temp=TempDescriptor.tempFactory("tert_fals",tn.getFalseExpr().getType());
1605
1606     NodePair cond=flattenExpressionNode(tn.getCond(),cond_temp);
1607     FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1608     fcb.setNumLine(tn.getNumLine());
1609
1610     NodePair trueExpr=flattenExpressionNode(tn.getTrueExpr(),true_temp);
1611     FlatOpNode fonT=new FlatOpNode(out_temp, true_temp, null, new Operation(Operation.ASSIGN));
1612     fonT.setNumLine(tn.getNumLine());
1613
1614     NodePair falseExpr=flattenExpressionNode(tn.getFalseExpr(),fals_temp);
1615     FlatOpNode fonF=new FlatOpNode(out_temp, fals_temp, null, new Operation(Operation.ASSIGN));
1616     fonF.setNumLine(tn.getNumLine());
1617
1618     FlatNop nopend=new FlatNop();
1619
1620     cond.getEnd().addNext(fcb);
1621
1622     fcb.addTrueNext(trueExpr.getBegin());
1623     fcb.addFalseNext(falseExpr.getBegin());
1624
1625     trueExpr.getEnd().addNext(fonT);
1626     fonT.addNext(nopend);
1627
1628     falseExpr.getEnd().addNext(fonF);
1629     fonF.addNext(nopend);
1630     
1631     return new NodePair(cond.getBegin(), nopend);
1632   }
1633
1634   private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
1635     switch(bsn.kind()) {
1636     case Kind.BlockExpressionNode:
1637       return flattenBlockExpressionNode((BlockExpressionNode)bsn);
1638
1639     case Kind.DeclarationNode:
1640       return flattenDeclarationNode((DeclarationNode)bsn);
1641
1642     case Kind.TagDeclarationNode:
1643       return flattenTagDeclarationNode((TagDeclarationNode)bsn);
1644
1645     case Kind.IfStatementNode:
1646       return flattenIfStatementNode((IfStatementNode)bsn);
1647       
1648     case Kind.SwitchStatementNode:
1649       return flattenSwitchStatementNode((SwitchStatementNode)bsn);
1650
1651     case Kind.LoopNode:
1652       return flattenLoopNode((LoopNode)bsn);
1653
1654     case Kind.ReturnNode:
1655       return flattenReturnNode((IR.Tree.ReturnNode)bsn);
1656
1657     case Kind.TaskExitNode:
1658       return flattenTaskExitNode((IR.Tree.TaskExitNode)bsn);
1659
1660     case Kind.SubBlockNode:
1661       return flattenSubBlockNode((SubBlockNode)bsn);
1662
1663     case Kind.AtomicNode:
1664       return flattenAtomicNode((AtomicNode)bsn);
1665
1666     case Kind.SynchronizedNode:
1667       return flattenSynchronizedNode((SynchronizedNode)bsn);
1668
1669     case Kind.SESENode:
1670       return flattenSESENode((SESENode)bsn);
1671
1672     case Kind.GenReachNode:
1673       return flattenGenReachNode((GenReachNode)bsn);
1674
1675     case Kind.ContinueBreakNode:
1676       return flattenContinueBreakNode((ContinueBreakNode)bsn);
1677     }
1678     throw new Error();
1679   }
1680 }