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