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