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