148f089a0b678b9fe10b54b34717e6b0c4be07ed
[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 if(state.MGC) {
435       // array creation with initializers
436         return flattenArrayInitializerNode(con.getArrayInitializer(), out_temp);
437       }
438       return null;
439     }
440   }
441
442   private NodePair generateNewArrayLoop(TempDescriptor[] temparray, TypeDescriptor td, TempDescriptor tmp, int i, boolean isglobal) {
443     TempDescriptor index=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
444     TempDescriptor tmpone=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
445     FlatNop fnop=new FlatNop();    //last node
446
447     //index=0
448     FlatLiteralNode fln=new FlatLiteralNode(index.getType(),new Integer(0),index);
449     //tmpone=1
450     FlatLiteralNode fln2=new FlatLiteralNode(tmpone.getType(),new Integer(1),tmpone);
451
452     TempDescriptor tmpbool=TempDescriptor.tempFactory("comp",new TypeDescriptor(TypeDescriptor.BOOLEAN));
453
454     FlatOpNode fcomp=new FlatOpNode(tmpbool,index,temparray[i],new Operation(Operation.LT));
455     FlatCondBranch fcb=new FlatCondBranch(tmpbool);
456     fcb.setTrueProb(State.TRUEPROB);
457     fcb.setLoop();
458     //is index<temp[i]
459     TempDescriptor new_tmp=TempDescriptor.tempFactory("tmp",td);
460     FlatNew fn=td.iswrapper()?new FlatNew(td, new_tmp, isglobal):new FlatNew(td, new_tmp, temparray[i+1], isglobal);
461     FlatSetElementNode fsen=new FlatSetElementNode(tmp,index,new_tmp);
462     // index=index+1
463     FlatOpNode fon=new FlatOpNode(index,index,tmpone,new Operation(Operation.ADD));
464     //jump out
465     fln.addNext(fln2);
466     fln2.addNext(fcomp);
467     fcomp.addNext(fcb);
468     fcb.addTrueNext(fn);
469     fcb.addFalseNext(fnop);
470     fn.addNext(fsen);
471     //Recursive call here
472     if ((i+2)<temparray.length) {
473       NodePair np2=generateNewArrayLoop(temparray, td.dereference(), new_tmp, i+1, isglobal);
474       fsen.addNext(np2.getBegin());
475       np2.getEnd().addNext(fon);
476     } else if (td.isArray()&&td.dereference().iswrapper()) {
477       NodePair np2=generateNewArrayLoop(temparray, td.dereference(), new_tmp, i+1, isglobal);
478       fsen.addNext(np2.getBegin());
479       np2.getEnd().addNext(fon);      
480     } else {
481       fsen.addNext(fon);
482     }
483     fon.addNext(fcomp);
484     return new NodePair(fln, fnop);
485   }
486
487   private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) {
488     TempDescriptor[] temps=new TempDescriptor[min.numArgs()];
489     FlatNode first=null;
490     FlatNode last=null;
491     TempDescriptor thisarg=null;
492
493     if (min.getExpression()!=null) {
494       TypeDescriptor mtd = min.getExpression().getType();
495       if(state.MGC && mtd.isClass() && mtd.getClassDesc().isEnum()) {
496         mtd = new TypeDescriptor(TypeDescriptor.INT);
497       }
498       thisarg=TempDescriptor.tempFactory("thisarg", mtd);
499       NodePair np=flattenExpressionNode(min.getExpression(),thisarg);
500       first=np.getBegin();
501       last=np.getEnd();
502     }
503
504     //Build arguments
505     for(int i=0; i<min.numArgs(); i++) {
506       ExpressionNode en=min.getArg(i);
507       TypeDescriptor etd = en.getType();
508       if(state.MGC && etd.isClass() && etd.getClassDesc().isEnum()) {
509         etd = new TypeDescriptor(TypeDescriptor.INT);
510       }
511       TempDescriptor td=TempDescriptor.tempFactory("arg", etd);
512       temps[i]=td;
513       NodePair np=flattenExpressionNode(en, td);
514       if (first==null)
515         first=np.getBegin();
516       else
517         last.addNext(np.getBegin());
518       last=np.getEnd();
519     }
520
521     MethodDescriptor md=min.getMethod();
522
523     //Call to constructor
524
525     FlatCall fc;
526     if(md.getReturnType()==null||md.getReturnType().isVoid())
527       fc=new FlatCall(md, null, thisarg, temps);      
528     else
529       fc=new FlatCall(md, out_temp, thisarg, temps);
530     
531     fc.setNumLine(min.getNumLine());
532     
533     if (first==null) {
534       first=fc;
535     } else
536       last.addNext(fc);
537     return new NodePair(first,fc);
538   }
539
540   private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) {
541     TempDescriptor tmp=null;
542     if(fan.getExpression().getType().isClassNameRef()) {
543       // static field dereference with class name
544       tmp = new TempDescriptor(fan.getExpression().getType().getClassDesc().getSymbol(), fan.getExpression().getType());
545       FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
546       fn.setNumLine(fan.getNumLine());
547       return new NodePair(fn,fn);
548     } else {
549       tmp=TempDescriptor.tempFactory("temp",fan.getExpression().getType());
550       NodePair npe=flattenExpressionNode(fan.getExpression(),tmp);
551       FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
552       fn.setNumLine(fan.getNumLine());
553       npe.getEnd().addNext(fn);
554       return new NodePair(npe.getBegin(),fn);
555     }
556   }
557
558   private NodePair flattenArrayAccessNode(ArrayAccessNode aan,TempDescriptor out_temp) {
559     TempDescriptor tmp=TempDescriptor.tempFactory("temp",aan.getExpression().getType());
560     TempDescriptor tmpindex=TempDescriptor.tempFactory("temp",aan.getIndex().getType());
561     NodePair npe=flattenExpressionNode(aan.getExpression(),tmp);
562     NodePair npi=flattenExpressionNode(aan.getIndex(),tmpindex);
563     TempDescriptor arraytmp=out_temp;
564     if (aan.iswrapper()) {
565       //have wrapper
566       arraytmp=TempDescriptor.tempFactory("temp", aan.getExpression().getType().dereference());
567     }
568     FlatNode fn=new FlatElementNode(tmp,tmpindex,arraytmp);
569     fn.setNumLine(aan.getNumLine());
570     npe.getEnd().addNext(npi.getBegin());
571     npi.getEnd().addNext(fn);
572     if (aan.iswrapper()) {
573       FlatFieldNode ffn=new FlatFieldNode((FieldDescriptor)aan.getExpression().getType().dereference().getClassDesc().getFieldTable().get("value") ,arraytmp,out_temp);
574       ffn.setNumLine(aan.getNumLine());
575       fn.addNext(ffn);
576       fn=ffn;
577     }
578     return new NodePair(npe.getBegin(),fn);
579   }
580
581   private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
582     // Three cases:
583     // left side is variable
584     // left side is field
585     // left side is array
586
587     Operation base=an.getOperation().getBaseOp();
588     boolean pre=base==null||(base.getOp()!=Operation.POSTINC&&base.getOp()!=Operation.POSTDEC);
589
590     if (!pre) {
591       //rewrite the base operation
592       base=base.getOp()==Operation.POSTINC ? new Operation(Operation.ADD) : new Operation(Operation.SUB);
593     }
594     FlatNode first=null;
595     FlatNode last=null;
596     TempDescriptor src_tmp = src_tmp=an.getSrc()==null ? TempDescriptor.tempFactory("srctmp",an.getDest().getType()) : TempDescriptor.tempFactory("srctmp",an.getSrc().getType());
597
598     //Get src value
599     if (an.getSrc()!=null) {
600       if(an.getSrc().getEval() != null) {
601         FlatLiteralNode fln=new FlatLiteralNode(an.getSrc().getType(), an.getSrc().getEval().longValue(), src_tmp);
602         fln.setNumLine(an.getSrc().getNumLine());
603         first = last =fln;
604       } else {
605         NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
606         first=np_src.getBegin();
607         last=np_src.getEnd();
608       }
609     } else if (!pre) {
610       FlatLiteralNode fln=new FlatLiteralNode(new TypeDescriptor(TypeDescriptor.INT),new Integer(1),src_tmp);
611       fln.setNumLine(an.getNumLine());
612       first=fln;
613       last=fln;
614     }
615
616     if (an.getDest().kind()==Kind.FieldAccessNode) {
617       //We are assigning an object field
618
619       FieldAccessNode fan=(FieldAccessNode)an.getDest();
620       ExpressionNode en=fan.getExpression();
621       TempDescriptor dst_tmp=null;
622       NodePair np_baseexp=null;
623       if(en.getType().isClassNameRef()) {
624         // static field dereference with class name
625         dst_tmp = new TempDescriptor(en.getType().getClassDesc().getSymbol(), en.getType());
626         FlatNop nop=new FlatNop();
627         np_baseexp = new NodePair(nop,nop);
628       } else {
629         dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
630         np_baseexp=flattenExpressionNode(en, dst_tmp);
631       }
632       if (first==null)
633         first=np_baseexp.getBegin();
634       else
635         last.addNext(np_baseexp.getBegin());
636       last=np_baseexp.getEnd();
637
638       //See if we need to perform an operation
639       if (base!=null) {
640         //If it is a preinc we need to store the initial value
641         TempDescriptor src_tmp2=pre ? TempDescriptor.tempFactory("src",an.getDest().getType()) : out_temp;
642         TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
643         FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
644         ffn.setNumLine(an.getNumLine());
645         last.addNext(ffn);
646         last=ffn;
647
648         if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
649           ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
650           MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
651           FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
652           fc.setNumLine(an.getNumLine());
653           src_tmp=tmp;
654           last.addNext(fc);
655           last=fc;
656         } else {
657           FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
658           fon.setNumLine(an.getNumLine());
659           src_tmp=tmp;
660           last.addNext(fon);
661           last=fon;
662         }
663       }
664
665       FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
666       fsfn.setNumLine(en.getNumLine());
667       last.addNext(fsfn);
668       last=fsfn;
669       if (pre) {
670         FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
671         fon2.setNumLine(an.getNumLine());
672         fsfn.addNext(fon2);
673         last=fon2;
674       }
675       return new NodePair(first, last);
676     } else if (an.getDest().kind()==Kind.ArrayAccessNode) {
677       //We are assigning an array element
678
679       ArrayAccessNode aan=(ArrayAccessNode)an.getDest();
680       ExpressionNode en=aan.getExpression();
681       ExpressionNode enindex=aan.getIndex();
682       TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
683       TempDescriptor index_tmp=TempDescriptor.tempFactory("index",enindex.getType());
684       NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
685       NodePair np_indexexp=flattenExpressionNode(enindex, index_tmp);
686       if (first==null)
687         first=np_baseexp.getBegin();
688       else
689         last.addNext(np_baseexp.getBegin());
690       np_baseexp.getEnd().addNext(np_indexexp.getBegin());
691       last=np_indexexp.getEnd();
692
693       //See if we need to perform an operation
694       if (base!=null) {
695         //If it is a preinc we need to store the initial value
696         TempDescriptor src_tmp2=pre ? TempDescriptor.tempFactory("src",an.getDest().getType()) : out_temp;
697         TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
698
699         if (aan.iswrapper()) {
700           TypeDescriptor arrayeltype=aan.getExpression().getType().dereference();
701           TempDescriptor src_tmp3=TempDescriptor.tempFactory("src3",arrayeltype);
702           FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp3);
703           fen.setNumLine(aan.getNumLine());
704           FlatFieldNode ffn=new FlatFieldNode((FieldDescriptor)arrayeltype.getClassDesc().getFieldTable().get("value"),src_tmp3,src_tmp2);
705           ffn.setNumLine(aan.getNumLine());
706           last.addNext(fen);
707           fen.addNext(ffn);
708           last=ffn;
709         } else {
710           FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp2);
711           fen.setNumLine(aan.getNumLine());
712           last.addNext(fen);
713           last=fen;
714         }
715         if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
716           ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
717           MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
718           FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
719           fc.setNumLine(an.getNumLine());
720           src_tmp=tmp;
721           last.addNext(fc);
722           last=fc;
723         } else {
724           FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
725           fon.setNumLine(an.getNumLine());
726           src_tmp=tmp;
727           last.addNext(fon);
728           last=fon;
729         }
730       }
731
732       if (aan.iswrapper()) { 
733         TypeDescriptor arrayeltype=aan.getExpression().getType().dereference();
734         TempDescriptor src_tmp3=TempDescriptor.tempFactory("src3",arrayeltype);
735         FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp3);
736         fen.setNumLine(aan.getNumLine());
737         FlatSetFieldNode fsfn=new FlatSetFieldNode(src_tmp3,(FieldDescriptor)arrayeltype.getClassDesc().getFieldTable().get("value"),src_tmp);
738         fsfn.setNumLine(aan.getExpression().getNumLine());
739         last.addNext(fen);
740         fen.addNext(fsfn);
741         last=fsfn;
742       } else { 
743         FlatSetElementNode fsen=new FlatSetElementNode(dst_tmp, index_tmp, src_tmp);
744         fsen.setNumLine(aan.getNumLine());
745         last.addNext(fsen);
746         last=fsen;
747       }
748       if (pre) {
749         FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
750         fon2.setNumLine(an.getNumLine());
751         last.addNext(fon2);
752         last=fon2;
753       }
754       return new NodePair(first, last);
755     } else if (an.getDest().kind()==Kind.NameNode) {
756       //We could be assigning a field or variable
757       NameNode nn=(NameNode)an.getDest();
758
759
760       if (nn.getExpression()!=null) {
761         //It is a field
762         FieldAccessNode fan=(FieldAccessNode)nn.getExpression();
763         ExpressionNode en=fan.getExpression();
764     TempDescriptor dst_tmp=null;
765     NodePair np_baseexp=null;
766     if(en.getType().isClassNameRef()) {
767       // static field dereference with class name
768       dst_tmp = new TempDescriptor(en.getType().getClassDesc().getSymbol(), en.getType());
769       FlatNop nop=new FlatNop();
770       np_baseexp = new NodePair(nop,nop);
771     } else {
772       dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
773       np_baseexp=flattenExpressionNode(en, dst_tmp);
774     }
775         if (first==null)
776           first=np_baseexp.getBegin();
777         else
778           last.addNext(np_baseexp.getBegin());
779         last=np_baseexp.getEnd();
780
781         //See if we need to perform an operation
782         if (base!=null) {
783           //If it is a preinc we need to store the initial value
784           TempDescriptor src_tmp2=pre ? TempDescriptor.tempFactory("src",an.getDest().getType()) : out_temp;
785           TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
786
787           FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
788           ffn.setNumLine(an.getNumLine());
789           last.addNext(ffn);
790           last=ffn;
791
792
793           if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
794             ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
795             MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
796             FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
797             fc.setNumLine(an.getNumLine());
798             src_tmp=tmp;
799             last.addNext(fc);
800             last=fc;
801           } else {
802             FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
803             fon.setNumLine(an.getNumLine());
804             src_tmp=tmp;
805             last.addNext(fon);
806             last=fon;
807           }
808         }
809
810
811         FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
812         fsfn.setNumLine(en.getNumLine());
813         last.addNext(fsfn);
814         last=fsfn;
815         if (pre) {
816           FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
817           fon2.setNumLine(an.getNumLine());
818           fsfn.addNext(fon2);
819           last=fon2;
820         }
821         return new NodePair(first, last);
822       } else {
823         if (nn.getField()!=null) {
824           //It is a field
825           //Get src value
826
827           //See if we need to perform an operation
828           if (base!=null) {
829             //If it is a preinc we need to store the initial value
830             TempDescriptor src_tmp2=pre ? TempDescriptor.tempFactory("src",an.getDest().getType()) : out_temp;
831             TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
832         
833         TempDescriptor ftmp= null;
834         if(state.MGC && (nn.getClassDesc() != null)) {
835           // this is a static field
836           ftmp = new TempDescriptor(nn.getClassDesc().getSymbol(), nn.getClassType());
837
838         } else {
839           ftmp=getTempforVar(nn.getVar());
840         }
841         FlatFieldNode ffn=new FlatFieldNode(nn.getField(), ftmp, src_tmp2);
842         ffn.setNumLine(an.getNumLine());
843
844             if (first==null)
845               first=ffn;
846             else {
847               last.addNext(ffn);
848             }
849             last=ffn;
850
851
852             if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
853               ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
854               MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
855               FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
856               fc.setNumLine(an.getNumLine());
857               src_tmp=tmp;
858               last.addNext(fc);
859               last=fc;
860             } else {
861               FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
862               fon.setNumLine(an.getNumLine());
863               src_tmp=tmp;
864               last.addNext(fon);
865               last=fon;
866             }
867           }
868
869       FlatSetFieldNode fsfn=null;
870       if(nn.getClassDesc()!=null) {
871         // this is a static field access inside of a static block
872         fsfn=new FlatSetFieldNode(new TempDescriptor("sfsb", nn.getClassType()), nn.getField(), src_tmp);
873         fsfn.setNumLine(nn.getNumLine());
874       } else {
875         fsfn=new FlatSetFieldNode(getTempforVar(nn.getVar()), nn.getField(), src_tmp);
876         fsfn.setNumLine(nn.getNumLine());
877       }
878           if (first==null) {
879             first=fsfn;
880           } else {
881             last.addNext(fsfn);
882           }
883           last=fsfn;
884           if (pre) {
885             FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
886             fon2.setNumLine(an.getNumLine());
887             fsfn.addNext(fon2);
888             last=fon2;
889           }
890           return new NodePair(first, last);
891         } else {
892           //It is a variable
893           //See if we need to perform an operation
894
895           if (base!=null) {
896             //If it is a preinc we need to store the initial value
897             TempDescriptor src_tmp2=getTempforVar(nn.getVar());
898             TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
899             if (!pre) {
900               FlatOpNode fon=new FlatOpNode(out_temp, src_tmp2, null, new Operation(Operation.ASSIGN));
901               fon.setNumLine(an.getNumLine());
902               if (first==null)
903                 first=fon;
904               else
905                 last.addNext(fon);
906               last=fon;
907             }
908
909
910             if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
911               ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
912               MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
913               FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
914               fc.setNumLine(an.getNumLine());
915               if (first==null)
916                 first=fc;
917               else
918                 last.addNext(fc);
919               src_tmp=tmp;
920               last=fc;
921             } else {
922               FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
923               fon.setNumLine(an.getNumLine());
924               if (first==null)
925                 first=fon;
926               else
927                 last.addNext(fon);
928               src_tmp=tmp;
929               last=fon;
930             }
931           }
932
933           FlatOpNode fon=new FlatOpNode(getTempforVar(nn.getVar()), src_tmp, null, new Operation(Operation.ASSIGN));
934           fon.setNumLine(an.getNumLine());
935
936           last.addNext(fon);
937           last=fon;
938           if (pre) {
939             FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
940             fon2.setNumLine(an.getNumLine());
941             fon.addNext(fon2);
942             last=fon2;
943           }
944           return new NodePair(first, last);
945         } //end of else
946       }
947     }
948
949     throw new Error();
950   }
951
952   private NodePair flattenNameNode(NameNode nn,TempDescriptor out_temp) {
953     if (nn.getExpression()!=null) {
954       /* Hack - use subtree instead */
955       return flattenExpressionNode(nn.getExpression(),out_temp);
956     } else if (nn.getField()!=null) {
957       TempDescriptor tmp= null;
958       if(state.MGC && (nn.getClassDesc() != null)) {
959         // this is a static field
960         tmp = new TempDescriptor(nn.getClassDesc().getSymbol(), nn.getClassType());
961         
962       } else {
963       tmp=getTempforVar(nn.getVar());
964       }
965       FlatFieldNode ffn=new FlatFieldNode(nn.getField(), tmp, out_temp);
966       ffn.setNumLine(nn.getNumLine());
967       return new NodePair(ffn,ffn);
968     } else {
969       TempDescriptor tmp=getTempforVar(nn.isTag() ? nn.getTagVar() : nn.getVar());
970       if (nn.isTag()) {
971         //propagate tag
972         out_temp.setTag(tmp.getTag());
973       }
974       FlatOpNode fon=new FlatOpNode(out_temp, tmp, null, new Operation(Operation.ASSIGN));
975       fon.setNumLine(nn.getNumLine());
976       return new NodePair(fon,fon);
977     }
978   }
979
980   private NodePair flattenOpNode(OpNode on,TempDescriptor out_temp) {
981     TempDescriptor temp_left=TempDescriptor.tempFactory("leftop",on.getLeft().getType());
982     TempDescriptor temp_right=null;
983
984     Operation op=on.getOp();
985
986     NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
987     NodePair right;
988     if (on.getRight()!=null) {
989       temp_right=TempDescriptor.tempFactory("rightop",on.getRight().getType());
990       right=flattenExpressionNode(on.getRight(),temp_right);
991     } else {
992       FlatNop nop=new FlatNop();
993       right=new NodePair(nop,nop);
994     }
995
996     if (op.getOp()==Operation.LOGIC_OR) {
997       /* Need to do shortcircuiting */
998       FlatCondBranch fcb=new FlatCondBranch(temp_left);
999       fcb.setNumLine(on.getNumLine());
1000       FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
1001       fon1.setNumLine(on.getNumLine());
1002       FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
1003       fon2.setNumLine(on.getNumLine());
1004       FlatNop fnop=new FlatNop();
1005       left.getEnd().addNext(fcb);
1006       fcb.addFalseNext(right.getBegin());
1007       right.getEnd().addNext(fon2);
1008       fon2.addNext(fnop);
1009       fcb.addTrueNext(fon1);
1010       fon1.addNext(fnop);
1011       return new NodePair(left.getBegin(), fnop);
1012     } else if (op.getOp()==Operation.LOGIC_AND) {
1013       /* Need to do shortcircuiting */
1014       FlatCondBranch fcb=new FlatCondBranch(temp_left);
1015       fcb.setNumLine(on.getNumLine());
1016       FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
1017       fon1.setNumLine(on.getNumLine());
1018       FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
1019       fon2.setNumLine(on.getNumLine());
1020       FlatNop fnop=new FlatNop();
1021       left.getEnd().addNext(fcb);
1022       fcb.addTrueNext(right.getBegin());
1023       right.getEnd().addNext(fon2);
1024       fon2.addNext(fnop);
1025       fcb.addFalseNext(fon1);
1026       fon1.addNext(fnop);
1027       return new NodePair(left.getBegin(), fnop);
1028     } else if (op.getOp()==Operation.ADD&&on.getLeft().getType().isString()) {
1029       //We have a string concatenate
1030       ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
1031       MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat", new TypeDescriptor[] {new TypeDescriptor(stringcd)});
1032       FlatCall fc=new FlatCall(concatmd, out_temp, temp_left, new TempDescriptor[] {temp_right});
1033       fc.setNumLine(on.getNumLine());
1034       left.getEnd().addNext(right.getBegin());
1035       right.getEnd().addNext(fc);
1036       return new NodePair(left.getBegin(), fc);
1037     }
1038
1039     FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
1040     fon.setNumLine(on.getNumLine());
1041     left.getEnd().addNext(right.getBegin());
1042     right.getEnd().addNext(fon);
1043     return new NodePair(left.getBegin(),fon);
1044   }
1045
1046   private NodePair flattenExpressionNode(ExpressionNode en, TempDescriptor out_temp) {
1047     switch(en.kind()) {
1048     case Kind.AssignmentNode:
1049       return flattenAssignmentNode((AssignmentNode)en,out_temp);
1050
1051     case Kind.CastNode:
1052       return flattenCastNode((CastNode)en,out_temp);
1053
1054     case Kind.CreateObjectNode:
1055       return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
1056
1057     case Kind.FieldAccessNode:
1058       return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
1059
1060     case Kind.ArrayAccessNode:
1061       return flattenArrayAccessNode((ArrayAccessNode)en,out_temp);
1062
1063     case Kind.LiteralNode:
1064       return flattenLiteralNode((LiteralNode)en,out_temp);
1065
1066     case Kind.MethodInvokeNode:
1067       return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
1068
1069     case Kind.NameNode:
1070       return flattenNameNode((NameNode)en,out_temp);
1071
1072     case Kind.OpNode:
1073       return flattenOpNode((OpNode)en,out_temp);      
1074
1075     case Kind.OffsetNode:
1076       return flattenOffsetNode((OffsetNode)en,out_temp);
1077
1078     case Kind.TertiaryNode:
1079       return flattenTertiaryNode((TertiaryNode)en,out_temp);
1080
1081     case Kind.InstanceOfNode:
1082       return flattenInstanceOfNode((InstanceOfNode)en,out_temp);
1083
1084     case Kind.ArrayInitializerNode:
1085       return flattenArrayInitializerNode((ArrayInitializerNode)en,out_temp);
1086     }
1087     throw new Error();
1088   }
1089
1090   private NodePair flattenDeclarationNode(DeclarationNode dn) {
1091     VarDescriptor vd=dn.getVarDescriptor();
1092     TempDescriptor td=getTempforVar(vd);
1093     if (dn.getExpression()!=null)
1094       return flattenExpressionNode(dn.getExpression(),td);
1095     else {
1096       FlatNop fn=new FlatNop();
1097       return new NodePair(fn,fn);
1098     }
1099   }
1100
1101   private NodePair flattenTagDeclarationNode(TagDeclarationNode dn) {
1102     TagVarDescriptor tvd=dn.getTagVarDescriptor();
1103     TagDescriptor tag=tvd.getTag();
1104     TempDescriptor tmp=getTempforVar(tvd);
1105     FlatTagDeclaration ftd=new FlatTagDeclaration(tag, tmp);
1106     ftd.setNumLine(dn.getNumLine());
1107     return new NodePair(ftd,ftd);
1108   }
1109
1110   private TempDescriptor getTempforParam(Descriptor d) {
1111     if (temptovar.containsKey(d))
1112       return (TempDescriptor)temptovar.get(d);
1113     else {
1114       if (d instanceof VarDescriptor) {
1115         VarDescriptor vd=(VarDescriptor)d;
1116         TempDescriptor td=TempDescriptor.paramtempFactory(vd.getName(),vd.getType());
1117         temptovar.put(vd,td);
1118         return td;
1119       } else if (d instanceof TagVarDescriptor) {
1120         TagVarDescriptor tvd=(TagVarDescriptor)d;
1121         TypeDescriptor tagtype=new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass));
1122         TempDescriptor td=TempDescriptor.paramtempFactory(tvd.getName(), tagtype, tvd.getTag());
1123         temptovar.put(tvd,td);
1124         return td;
1125       } else throw new Error("Unreconized Descriptor");
1126     }
1127   }
1128
1129   private TempDescriptor getTempforVar(Descriptor d) {
1130     if (temptovar.containsKey(d))
1131       return (TempDescriptor)temptovar.get(d);
1132     else {
1133       if (d instanceof VarDescriptor) {
1134         VarDescriptor vd=(VarDescriptor)d;
1135         TempDescriptor td=TempDescriptor.tempFactory(vd.getName(), vd.getType());
1136         temptovar.put(vd,td);
1137         return td;
1138       } else if (d instanceof TagVarDescriptor) {
1139         TagVarDescriptor tvd=(TagVarDescriptor)d;
1140         //BUGFIX TAGTYPE - add next line, modify following
1141         //line to tag this new type descriptor, modify
1142         //TempDescriptor constructor & factory to set type
1143         //using this Type To test, use any program with tags
1144         TypeDescriptor tagtype=new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass));
1145         TempDescriptor td=TempDescriptor.tempFactory(tvd.getName(),tagtype, tvd.getTag());
1146         temptovar.put(tvd,td);
1147         return td;
1148       } else throw new Error("Unrecognized Descriptor");
1149     }
1150   }
1151
1152   private NodePair flattenIfStatementNode(IfStatementNode isn) {
1153     TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
1154     NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
1155     FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1156     fcb.setNumLine(isn.getNumLine());
1157     NodePair true_np=flattenBlockNode(isn.getTrueBlock());
1158     NodePair false_np;
1159     FlatNop nopend=new FlatNop();
1160
1161     if (isn.getFalseBlock()!=null)
1162       false_np=flattenBlockNode(isn.getFalseBlock());
1163     else {
1164       FlatNop nop=new FlatNop();
1165       false_np=new NodePair(nop,nop);
1166     }
1167
1168     cond.getEnd().addNext(fcb);
1169     fcb.addTrueNext(true_np.getBegin());
1170     fcb.addFalseNext(false_np.getBegin());
1171     if (true_np.getEnd()!=null)
1172         true_np.getEnd().addNext(nopend);
1173     if (false_np.getEnd()!=null)
1174         false_np.getEnd().addNext(nopend);
1175     if (nopend.numPrev()==0)
1176       return new NodePair(cond.getBegin(), null);
1177
1178     return new NodePair(cond.getBegin(), nopend);
1179   }
1180   
1181   private NodePair flattenSwitchStatementNode(SwitchStatementNode ssn) {
1182     TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.INT));
1183     NodePair cond=flattenExpressionNode(ssn.getCondition(),cond_temp);
1184     FlatNop nopend=new FlatNop();
1185     NodePair sbody = flattenSwitchBodyNode(ssn.getSwitchBody(), cond_temp, nopend);
1186     
1187     cond.getEnd().addNext(sbody.getBegin());
1188
1189     return new NodePair(cond.getBegin(), sbody.getEnd());
1190   }
1191   
1192   private NodePair flattenSwitchBodyNode(BlockNode bn, TempDescriptor cond_temp, FlatNode endnode) {
1193     FlatNode begin=null;
1194     FlatNode end=endnode;
1195     NodePair prev_true_branch = null;
1196     NodePair prev_false_branch = null;
1197     for(int i=0; i<bn.size(); i++) {
1198       SwitchBlockNode sbn = (SwitchBlockNode)bn.get(i);
1199       HashSet oldbs=breakset;
1200       breakset=new HashSet();
1201       
1202       NodePair body=flattenBlockNode(sbn.getSwitchBlockStatement());
1203       Vector<SwitchLabelNode> slnv = sbn.getSwitchConditions();
1204       FlatNode cond_begin = null;
1205       NodePair prev_fnp = null;
1206       for(int j = 0; j < slnv.size(); j++) {
1207         SwitchLabelNode sln = slnv.elementAt(j);
1208         NodePair left = null;
1209         NodePair false_np = null;
1210         if(sln.isDefault()) {
1211           left = body;
1212         } else {
1213           TempDescriptor cond_tmp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
1214           TempDescriptor temp_left=TempDescriptor.tempFactory("leftop", sln.getCondition().getType());
1215           Operation op=new Operation(Operation.EQUAL);
1216           left=flattenExpressionNode(sln.getCondition(), temp_left);
1217           FlatOpNode fon=new FlatOpNode(cond_tmp, temp_left, cond_temp, op);
1218           fon.setNumLine(sln.getNumLine());
1219           left.getEnd().addNext(fon);
1220
1221           FlatCondBranch fcb=new FlatCondBranch(cond_tmp);
1222           fcb.setNumLine(bn.getNumLine());
1223           fcb.setTrueProb(State.TRUEPROB);
1224
1225           FlatNop nop=new FlatNop();
1226           false_np=new NodePair(nop,nop);
1227
1228           fon.addNext(fcb);
1229           fcb.addTrueNext(body.getBegin());
1230           fcb.addFalseNext(false_np.getBegin());
1231         }
1232         if((prev_fnp != null) && (prev_fnp.getEnd() != null)) {
1233           prev_fnp.getEnd().addNext(left.getBegin());
1234         }
1235         prev_fnp = false_np;
1236         
1237         if (begin==null) {
1238           begin = left.getBegin();
1239         }
1240         if(cond_begin == null) {
1241           cond_begin = left.getBegin();
1242         }
1243       }
1244       if((prev_false_branch != null) && (prev_false_branch.getEnd() != null)) {
1245         prev_false_branch.getEnd().addNext(cond_begin);
1246       }
1247       prev_false_branch = prev_fnp;
1248       if((prev_true_branch != null) && (prev_true_branch.getEnd() != null)) {
1249         prev_true_branch.getEnd().addNext(body.getBegin());
1250       }
1251       prev_true_branch = body;
1252       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
1253         FlatNode fn=(FlatNode)breakit.next();
1254         breakit.remove();
1255         fn.addNext(endnode);
1256       }
1257       breakset=oldbs;
1258     }
1259     if((prev_true_branch != null) && (prev_true_branch.getEnd() != null)) {
1260       prev_true_branch.getEnd().addNext(endnode);
1261     }
1262     if((prev_false_branch != null) && (prev_false_branch.getEnd() != null)) {
1263       prev_false_branch.getEnd().addNext(endnode);
1264     }
1265     if(begin == null) {
1266       end=begin=new FlatNop();
1267     }
1268     return new NodePair(begin,end);
1269   }
1270   
1271   private NodePair flattenLoopNode(LoopNode ln) {
1272     HashSet oldbs=breakset;
1273     HashSet oldcs=continueset;
1274     breakset=new HashSet();
1275     continueset=new HashSet();
1276     
1277     if (ln.getType()==LoopNode.FORLOOP) {
1278       NodePair initializer=flattenBlockNode(ln.getInitializer());
1279       TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
1280       NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
1281       NodePair update=flattenBlockNode(ln.getUpdate());
1282       NodePair body=flattenBlockNode(ln.getBody());
1283       FlatNode begin=initializer.getBegin();
1284       FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1285       fcb.setNumLine(ln.getNumLine());
1286       fcb.setTrueProb(State.TRUEPROB);
1287       fcb.setLoop();
1288       FlatNop nopend=new FlatNop();
1289       FlatBackEdge backedge=new FlatBackEdge();
1290
1291       FlatNop nop2=new FlatNop();
1292       initializer.getEnd().addNext(nop2);
1293       nop2.addNext(condition.getBegin());
1294       if (body.getEnd()!=null)
1295           body.getEnd().addNext(update.getBegin());
1296       update.getEnd().addNext(backedge);
1297       backedge.addNext(condition.getBegin());
1298       condition.getEnd().addNext(fcb);
1299       fcb.addFalseNext(nopend);
1300       fcb.addTrueNext(body.getBegin());
1301       for(Iterator contit=continueset.iterator();contit.hasNext();) {
1302           FlatNode fn=(FlatNode)contit.next();
1303           contit.remove();
1304           fn.addNext(update.getBegin());
1305       }
1306       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
1307           FlatNode fn=(FlatNode)breakit.next();
1308           breakit.remove();
1309           fn.addNext(nopend);
1310       }
1311       breakset=oldbs;
1312       continueset=oldcs;
1313       return new NodePair(begin,nopend);
1314     } else if (ln.getType()==LoopNode.WHILELOOP) {
1315       TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
1316       NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
1317       NodePair body=flattenBlockNode(ln.getBody());
1318       FlatNode begin=condition.getBegin();
1319       FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1320       fcb.setNumLine(ln.getNumLine());
1321       fcb.setTrueProb(State.TRUEPROB);
1322       fcb.setLoop();
1323       FlatNop nopend=new FlatNop();
1324       FlatBackEdge backedge=new FlatBackEdge();
1325
1326       if (body.getEnd()!=null)
1327         body.getEnd().addNext(backedge);
1328       backedge.addNext(condition.getBegin());
1329
1330       condition.getEnd().addNext(fcb);
1331       fcb.addFalseNext(nopend);
1332       fcb.addTrueNext(body.getBegin());
1333
1334       for(Iterator contit=continueset.iterator();contit.hasNext();) {
1335           FlatNode fn=(FlatNode)contit.next();
1336           contit.remove();
1337           fn.addNext(backedge);
1338       }
1339       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
1340           FlatNode fn=(FlatNode)breakit.next();
1341           breakit.remove();
1342           fn.addNext(nopend);
1343       }
1344       breakset=oldbs;
1345       continueset=oldcs;
1346       return new NodePair(begin,nopend);
1347     } else if (ln.getType()==LoopNode.DOWHILELOOP) {
1348       TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
1349       NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
1350       NodePair body=flattenBlockNode(ln.getBody());
1351       FlatNode begin=body.getBegin();
1352       FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1353       fcb.setNumLine(ln.getNumLine());
1354       fcb.setTrueProb(State.TRUEPROB);
1355       fcb.setLoop();
1356       FlatNop nopend=new FlatNop();
1357       FlatBackEdge backedge=new FlatBackEdge();
1358
1359       if (body.getEnd()!=null)
1360         body.getEnd().addNext(condition.getBegin());
1361       condition.getEnd().addNext(fcb);
1362       fcb.addFalseNext(nopend);
1363       fcb.addTrueNext(backedge);
1364       backedge.addNext(body.getBegin());
1365
1366       for(Iterator contit=continueset.iterator();contit.hasNext();) {
1367           FlatNode fn=(FlatNode)contit.next();
1368           contit.remove();
1369           fn.addNext(condition.getBegin());
1370       }
1371       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
1372           FlatNode fn=(FlatNode)breakit.next();
1373           breakit.remove();
1374           fn.addNext(nopend);
1375       }
1376       breakset=oldbs;
1377       continueset=oldcs;
1378       return new NodePair(begin,nopend);
1379     } else throw new Error();
1380   }
1381
1382   private NodePair flattenReturnNode(ReturnNode rntree) {
1383     TempDescriptor retval=null;
1384     NodePair cond=null;
1385     if (rntree.getReturnExpression()!=null) {
1386       retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
1387       cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
1388     }
1389
1390     FlatReturnNode rnflat=new FlatReturnNode(retval);
1391     rnflat.setNumLine(rntree.getNumLine());
1392     rnflat.addNext(fe);
1393     FlatNode ln=rnflat;
1394     if ((state.THREAD||state.MGC)&&!this.lockStack.isEmpty()) {
1395       FlatNode end = null;
1396       MethodDescriptor memdex=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
1397       for(int j = this.lockStack.size(); j > 0; j--) {
1398         TempDescriptor thistd = this.lockStack.elementAt(j-1);
1399         FlatCall fcunlock = new FlatCall(memdex, null, thistd, new TempDescriptor[0]);
1400         fcunlock.setNumLine(rntree.getNumLine());
1401         if(end != null) {
1402           end.addNext(fcunlock);
1403         }
1404         end = fcunlock;
1405       }
1406       end.addNext(ln);
1407       ln=end;
1408     }
1409     if (state.DSM&&currmd.getModifiers().isAtomic()) {
1410       FlatAtomicExitNode faen=new FlatAtomicExitNode(curran);
1411       faen.addNext(ln);
1412       ln=faen;
1413     }
1414
1415     if (cond!=null) {
1416       cond.getEnd().addNext(ln);
1417       return new NodePair(cond.getBegin(),null);
1418     } else
1419       return new NodePair(ln,null);
1420   }
1421
1422   private NodePair flattenTaskExitNode(TaskExitNode ten) {
1423     FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.TASKEXIT);
1424     ffan.setTaskExitIndex(ten.getTaskExitIndex());
1425     updateFlagActionNode(ffan, ten.getFlagEffects());
1426     NodePair fcn=flattenConstraintCheck(ten.getChecks());
1427     ffan.addNext(fcn.getBegin());
1428     FlatReturnNode rnflat=new FlatReturnNode(null);
1429     rnflat.setNumLine(ten.getNumLine());
1430     rnflat.addNext(fe);
1431     fcn.getEnd().addNext(rnflat);
1432     return new NodePair(ffan, null);
1433   }
1434
1435   private NodePair flattenConstraintCheck(Vector ccs) {
1436     FlatNode begin=new FlatNop();
1437     if (ccs==null)
1438       return new NodePair(begin,begin);
1439     FlatNode last=begin;
1440     for(int i=0; i<ccs.size(); i++) {
1441       ConstraintCheck cc=(ConstraintCheck) ccs.get(i);
1442       /* Flatten the arguments */
1443       TempDescriptor[] temps=new TempDescriptor[cc.numArgs()];
1444       String[] vars=new String[cc.numArgs()];
1445       for(int j=0; j<cc.numArgs(); j++) {
1446         ExpressionNode en=cc.getArg(j);
1447         TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
1448         temps[j]=td;
1449         vars[j]=cc.getVar(j);
1450         NodePair np=flattenExpressionNode(en, td);
1451         last.addNext(np.getBegin());
1452         last=np.getEnd();
1453       }
1454
1455       FlatCheckNode fcn=new FlatCheckNode(cc.getSpec(), vars, temps);
1456       last.addNext(fcn);
1457       last=fcn;
1458     }
1459     return new NodePair(begin,last);
1460   }
1461
1462   private NodePair flattenSubBlockNode(SubBlockNode sbn) {
1463     return flattenBlockNode(sbn.getBlockNode());
1464   }
1465
1466   private NodePair flattenSynchronizedNode(SynchronizedNode sbn) {
1467     TempDescriptor montmp=null;
1468     FlatNode first = null;
1469     FlatNode end = null;
1470     if(sbn.getExpr() instanceof ClassTypeNode) {
1471       montmp=new TempDescriptor("classobj", ((ClassTypeNode)sbn.getExpr()).getType().getClassDesc());
1472     } else {
1473       montmp = TempDescriptor.tempFactory("monitor",sbn.getExpr().getType());
1474       NodePair npexp=flattenExpressionNode(sbn.getExpr(), montmp);
1475       first = npexp.getBegin();
1476       end = npexp.getEnd();
1477     }
1478     this.lockStack.push(montmp);
1479     NodePair npblock=flattenBlockNode(sbn.getBlockNode());
1480
1481     MethodDescriptor menmd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorEnter");
1482     FlatCall fcen=new FlatCall(menmd, null, montmp, new TempDescriptor[0]);
1483     fcen.setNumLine(sbn.getNumLine());
1484
1485     MethodDescriptor mexmd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
1486     FlatCall fcex=new FlatCall(mexmd, null, montmp, new TempDescriptor[0]);
1487     fcex.setNumLine(sbn.getNumLine());
1488     
1489     this.lockStack.pop();
1490
1491     if(first != null) {
1492       end.addNext(fcen);
1493     } else {
1494       first = fcen;
1495     }
1496     fcen.addNext(npblock.getBegin());
1497     
1498     if (npblock.getEnd()!=null&&npblock.getEnd().kind()!=FKind.FlatReturnNode) {
1499       npblock.getEnd().addNext(fcex);
1500     }
1501     
1502     /*if(npblock.getEnd() != null) {
1503       npblock.getEnd().addNext(fcex);
1504     }*/
1505     return new NodePair(first, fcex);
1506   }
1507
1508   private NodePair flattenAtomicNode(AtomicNode sbn) {
1509     NodePair np=flattenBlockNode(sbn.getBlockNode());
1510     FlatAtomicEnterNode faen=new FlatAtomicEnterNode();
1511     faen.setNumLine(sbn.getNumLine());
1512     FlatAtomicExitNode faexn=new FlatAtomicExitNode(faen);
1513     faen.addNext(np.getBegin());
1514     np.getEnd().addNext(faexn);
1515     return new NodePair(faen, faexn);
1516   }
1517
1518   private NodePair flattenGenReachNode( GenReachNode grn ) {
1519     FlatGenReachNode fgrn = new FlatGenReachNode( grn.getGraphName() );
1520     return new NodePair( fgrn, fgrn );
1521   }
1522
1523   private NodePair flattenSESENode(SESENode sn) {
1524     if( sn.isStart() ) {
1525       FlatSESEEnterNode fsen=new FlatSESEEnterNode(sn);
1526       fsen.setNumLine(sn.getNumLine());
1527       sn.setFlatEnter(fsen);
1528       return new NodePair(fsen, fsen);
1529     }
1530
1531     FlatSESEExitNode fsexn=new FlatSESEExitNode(sn);
1532     sn.setFlatExit(fsexn);
1533     FlatSESEEnterNode fsen=sn.getStart().getFlatEnter();
1534     fsexn.setFlatEnter(fsen);    
1535     sn.getStart().getFlatEnter().setFlatExit( fsexn );
1536     
1537     return new NodePair(fsexn, fsexn);
1538   }
1539
1540   private NodePair flattenContinueBreakNode(ContinueBreakNode cbn) {
1541       FlatNop fn=new FlatNop();
1542       if (cbn.isBreak())
1543           breakset.add(fn);
1544       else
1545           continueset.add(fn);
1546       return new NodePair(fn,null);
1547   }
1548
1549   private NodePair flattenInstanceOfNode(InstanceOfNode tn, TempDescriptor out_temp) {
1550     TempDescriptor expr_temp=TempDescriptor.tempFactory("expr",tn.getExpr().getType());
1551     NodePair cond=flattenExpressionNode(tn.getExpr(), expr_temp);
1552     FlatInstanceOfNode fion=new FlatInstanceOfNode(tn.getExprType(), expr_temp, out_temp);
1553     fion.setNumLine(tn.getNumLine());
1554     cond.getEnd().addNext(fion);
1555     return new NodePair(cond.getBegin(),fion);
1556   }
1557
1558   private NodePair flattenArrayInitializerNode(ArrayInitializerNode ain, TempDescriptor out_temp) {
1559     boolean isGlobal = false;
1560     String disjointId = null;
1561     // get the type the array to be initialized
1562     TypeDescriptor td = ain.getType();
1563
1564     // create a new array of size equal to the array initializer
1565     FlatNode first=null;
1566     FlatNode last=null;
1567     TempDescriptor tmp=TempDescriptor.tempFactory("arg", new TypeDescriptor(TypeDescriptor.INT));
1568     FlatLiteralNode fln_tmp=new FlatLiteralNode(tmp.getType(), new Integer(ain.numVarInitializers()), tmp);
1569     fln_tmp.setNumLine(ain.getNumLine());
1570     first = last=fln_tmp;
1571     
1572     // create the new array
1573     FlatNew fn=new FlatNew(td, out_temp, tmp, isGlobal, disjointId);
1574     last.addNext(fn);
1575     last = fn;
1576     
1577     // initialize the new array
1578     for(int i = 0; i < ain.numVarInitializers(); i++) {
1579       ExpressionNode var_init_node = ain.getVarInitializer(i);
1580       TempDescriptor tmp_toinit = out_temp;
1581       TempDescriptor tmp_init=TempDescriptor.tempFactory("array_init", td.dereference());
1582       // index=i
1583       TempDescriptor index=TempDescriptor.tempFactory("index", new TypeDescriptor(TypeDescriptor.INT));
1584       FlatLiteralNode fln=new FlatLiteralNode(index.getType(), new Integer(i), index);
1585       fln.setNumLine(ain.getNumLine());
1586       // calculate the initial value
1587       NodePair np_init = flattenExpressionNode(var_init_node, tmp_init);
1588       // TODO wrapper class process is missing now
1589       /*if(td.isArray() && td.dereference().iswrapper()) {
1590       }*/
1591       FlatSetElementNode fsen=new FlatSetElementNode(tmp_toinit, index, tmp_init);
1592       fsen.setNumLine(ain.getNumLine());
1593       last.addNext(fln);
1594       fln.addNext(np_init.getBegin());
1595       np_init.getEnd().addNext(fsen);
1596       last = fsen;
1597     }
1598     
1599     return new NodePair(first, last);
1600   }
1601
1602   private NodePair flattenTertiaryNode(TertiaryNode tn, TempDescriptor out_temp) {
1603     TempDescriptor cond_temp=TempDescriptor.tempFactory("tert_cond",new TypeDescriptor(TypeDescriptor.BOOLEAN));
1604     TempDescriptor true_temp=TempDescriptor.tempFactory("tert_true",tn.getTrueExpr().getType());
1605     TempDescriptor fals_temp=TempDescriptor.tempFactory("tert_fals",tn.getFalseExpr().getType());
1606
1607     NodePair cond=flattenExpressionNode(tn.getCond(),cond_temp);
1608     FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1609     fcb.setNumLine(tn.getNumLine());
1610
1611     NodePair trueExpr=flattenExpressionNode(tn.getTrueExpr(),true_temp);
1612     FlatOpNode fonT=new FlatOpNode(out_temp, true_temp, null, new Operation(Operation.ASSIGN));
1613     fonT.setNumLine(tn.getNumLine());
1614
1615     NodePair falseExpr=flattenExpressionNode(tn.getFalseExpr(),fals_temp);
1616     FlatOpNode fonF=new FlatOpNode(out_temp, fals_temp, null, new Operation(Operation.ASSIGN));
1617     fonF.setNumLine(tn.getNumLine());
1618
1619     FlatNop nopend=new FlatNop();
1620
1621     cond.getEnd().addNext(fcb);
1622
1623     fcb.addTrueNext(trueExpr.getBegin());
1624     fcb.addFalseNext(falseExpr.getBegin());
1625
1626     trueExpr.getEnd().addNext(fonT);
1627     fonT.addNext(nopend);
1628
1629     falseExpr.getEnd().addNext(fonF);
1630     fonF.addNext(nopend);
1631     
1632     return new NodePair(cond.getBegin(), nopend);
1633   }
1634
1635   private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
1636     switch(bsn.kind()) {
1637     case Kind.BlockExpressionNode:
1638       return flattenBlockExpressionNode((BlockExpressionNode)bsn);
1639
1640     case Kind.DeclarationNode:
1641       return flattenDeclarationNode((DeclarationNode)bsn);
1642
1643     case Kind.TagDeclarationNode:
1644       return flattenTagDeclarationNode((TagDeclarationNode)bsn);
1645
1646     case Kind.IfStatementNode:
1647       return flattenIfStatementNode((IfStatementNode)bsn);
1648       
1649     case Kind.SwitchStatementNode:
1650       return flattenSwitchStatementNode((SwitchStatementNode)bsn);
1651
1652     case Kind.LoopNode:
1653       return flattenLoopNode((LoopNode)bsn);
1654
1655     case Kind.ReturnNode:
1656       return flattenReturnNode((IR.Tree.ReturnNode)bsn);
1657
1658     case Kind.TaskExitNode:
1659       return flattenTaskExitNode((IR.Tree.TaskExitNode)bsn);
1660
1661     case Kind.SubBlockNode:
1662       return flattenSubBlockNode((SubBlockNode)bsn);
1663
1664     case Kind.AtomicNode:
1665       return flattenAtomicNode((AtomicNode)bsn);
1666
1667     case Kind.SynchronizedNode:
1668       return flattenSynchronizedNode((SynchronizedNode)bsn);
1669
1670     case Kind.SESENode:
1671       return flattenSESENode((SESENode)bsn);
1672
1673     case Kind.GenReachNode:
1674       return flattenGenReachNode((GenReachNode)bsn);
1675
1676     case Kind.ContinueBreakNode:
1677       return flattenContinueBreakNode((ContinueBreakNode)bsn);
1678     }
1679     throw new Error();
1680   }
1681 }