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