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