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