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