Enable Switch-case statement for mgc version
[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       FlatNode first=null;
364       FlatNode last=null;
365       TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
366       for (int i=0; i<con.numArgs(); i++) {
367         ExpressionNode en=con.getArg(i);
368         TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
369         temps[i]=tmp;
370         NodePair np=flattenExpressionNode(en, tmp);
371         if (first==null)
372           first=np.getBegin();
373         else
374           last.addNext(np.getBegin());
375         last=np.getEnd();
376
377         TempDescriptor tmp2=(i==0) ?
378                              out_temp :
379                              TempDescriptor.tempFactory("arg",en.getType());
380       }
381       FlatNew fn=new FlatNew(td, out_temp, temps[0], con.isGlobal(), con.getDisjointId());
382       last.addNext(fn);
383       if (temps.length>1) {
384         NodePair np=generateNewArrayLoop(temps, td.dereference(), out_temp, 0, con.isGlobal());
385         fn.addNext(np.getBegin());
386         return new NodePair(first,np.getEnd());
387       } else if (td.isArray()&&td.dereference().iswrapper()) {
388         NodePair np=generateNewArrayLoop(temps, td.dereference(), out_temp, 0, con.isGlobal());
389         fn.addNext(np.getBegin());
390         return new NodePair(first,np.getEnd());
391       } else
392         return new NodePair(first, fn);
393     }
394   }
395
396   private NodePair generateNewArrayLoop(TempDescriptor[] temparray, TypeDescriptor td, TempDescriptor tmp, int i, boolean isglobal) {
397     TempDescriptor index=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
398     TempDescriptor tmpone=TempDescriptor.tempFactory("index",new TypeDescriptor(TypeDescriptor.INT));
399     FlatNop fnop=new FlatNop();    //last node
400
401     //index=0
402     FlatLiteralNode fln=new FlatLiteralNode(index.getType(),new Integer(0),index);
403     //tmpone=1
404     FlatLiteralNode fln2=new FlatLiteralNode(tmpone.getType(),new Integer(1),tmpone);
405
406     TempDescriptor tmpbool=TempDescriptor.tempFactory("comp",new TypeDescriptor(TypeDescriptor.BOOLEAN));
407
408     FlatOpNode fcomp=new FlatOpNode(tmpbool,index,temparray[i],new Operation(Operation.LT));
409     FlatCondBranch fcb=new FlatCondBranch(tmpbool);
410     fcb.setTrueProb(State.TRUEPROB);
411     fcb.setLoop();
412     //is index<temp[i]
413     TempDescriptor new_tmp=TempDescriptor.tempFactory("tmp",td);
414     FlatNew fn=td.iswrapper()?new FlatNew(td, new_tmp, isglobal):new FlatNew(td, new_tmp, temparray[i+1], isglobal);
415     FlatSetElementNode fsen=new FlatSetElementNode(tmp,index,new_tmp);
416     // index=index+1
417     FlatOpNode fon=new FlatOpNode(index,index,tmpone,new Operation(Operation.ADD));
418     //jump out
419     fln.addNext(fln2);
420     fln2.addNext(fcomp);
421     fcomp.addNext(fcb);
422     fcb.addTrueNext(fn);
423     fcb.addFalseNext(fnop);
424     fn.addNext(fsen);
425     //Recursive call here
426     if ((i+2)<temparray.length) {
427       NodePair np2=generateNewArrayLoop(temparray, td.dereference(), new_tmp, i+1, isglobal);
428       fsen.addNext(np2.getBegin());
429       np2.getEnd().addNext(fon);
430     } else if (td.isArray()&&td.dereference().iswrapper()) {
431       NodePair np2=generateNewArrayLoop(temparray, td.dereference(), new_tmp, i+1, isglobal);
432       fsen.addNext(np2.getBegin());
433       np2.getEnd().addNext(fon);      
434     } else {
435       fsen.addNext(fon);
436     }
437     fon.addNext(fcomp);
438     return new NodePair(fln, fnop);
439   }
440
441   private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) {
442     TempDescriptor[] temps=new TempDescriptor[min.numArgs()];
443     FlatNode first=null;
444     FlatNode last=null;
445     TempDescriptor thisarg=null;
446
447     if (min.getExpression()!=null) {
448       thisarg=TempDescriptor.tempFactory("thisarg",min.getExpression().getType());
449       NodePair np=flattenExpressionNode(min.getExpression(),thisarg);
450       first=np.getBegin();
451       last=np.getEnd();
452     }
453
454     //Build arguments
455     for(int i=0; i<min.numArgs(); i++) {
456       ExpressionNode en=min.getArg(i);
457       TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
458       temps[i]=td;
459       NodePair np=flattenExpressionNode(en, td);
460       if (first==null)
461         first=np.getBegin();
462       else
463         last.addNext(np.getBegin());
464       last=np.getEnd();
465     }
466
467     MethodDescriptor md=min.getMethod();
468
469     //Call to constructor
470
471     FlatCall fc;
472     if(md.getReturnType()==null||md.getReturnType().isVoid())
473       fc=new FlatCall(md, null, thisarg, temps);
474     else
475       fc=new FlatCall(md, out_temp, thisarg, temps);
476     if (first==null) {
477       first=fc;
478     } else
479       last.addNext(fc);
480     return new NodePair(first,fc);
481   }
482
483   private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) {
484     TempDescriptor tmp=null;
485     if(fan.getExpression().getType().isStatic()) {
486       // static field dereference with class name
487       tmp = new TempDescriptor(fan.getExpression().getType().getClassDesc().getSymbol(), fan.getExpression().getType());
488       FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
489       return new NodePair(fn,fn);
490     } else {
491       tmp=TempDescriptor.tempFactory("temp",fan.getExpression().getType());
492       NodePair npe=flattenExpressionNode(fan.getExpression(),tmp);
493       FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
494       npe.getEnd().addNext(fn);
495       return new NodePair(npe.getBegin(),fn);
496     }
497   }
498
499   private NodePair flattenArrayAccessNode(ArrayAccessNode aan,TempDescriptor out_temp) {
500     TempDescriptor tmp=TempDescriptor.tempFactory("temp",aan.getExpression().getType());
501     TempDescriptor tmpindex=TempDescriptor.tempFactory("temp",aan.getIndex().getType());
502     NodePair npe=flattenExpressionNode(aan.getExpression(),tmp);
503     NodePair npi=flattenExpressionNode(aan.getIndex(),tmpindex);
504     TempDescriptor arraytmp=out_temp;
505     if (aan.iswrapper()) {
506       //have wrapper
507       arraytmp=TempDescriptor.tempFactory("temp", aan.getExpression().getType().dereference());
508     }
509     FlatNode fn=new FlatElementNode(tmp,tmpindex,arraytmp);
510     npe.getEnd().addNext(npi.getBegin());
511     npi.getEnd().addNext(fn);
512     if (aan.iswrapper()) {
513       FlatFieldNode ffn=new FlatFieldNode((FieldDescriptor)aan.getExpression().getType().dereference().getClassDesc().getFieldTable().get("value") ,arraytmp,out_temp);
514       fn.addNext(ffn);
515       fn=ffn;
516     }
517     return new NodePair(npe.getBegin(),fn);
518   }
519
520   private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
521     // Three cases:
522     // left side is variable
523     // left side is field
524     // left side is array
525
526     Operation base=an.getOperation().getBaseOp();
527     boolean pre=base==null||(base.getOp()!=Operation.POSTINC&&base.getOp()!=Operation.POSTDEC);
528
529     if (!pre) {
530       //rewrite the base operation
531       base=base.getOp()==Operation.POSTINC ? new Operation(Operation.ADD) : new Operation(Operation.SUB);
532     }
533     FlatNode first=null;
534     FlatNode last=null;
535     TempDescriptor src_tmp = src_tmp=an.getSrc()==null ? TempDescriptor.tempFactory("srctmp",an.getDest().getType()) : TempDescriptor.tempFactory("srctmp",an.getSrc().getType());
536
537     //Get src value
538     if (an.getSrc()!=null) {
539       NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
540       first=np_src.getBegin();
541       last=np_src.getEnd();
542     } else if (!pre) {
543       FlatLiteralNode fln=new FlatLiteralNode(new TypeDescriptor(TypeDescriptor.INT),new Integer(1),src_tmp);
544       first=fln;
545       last=fln;
546     }
547
548     if (an.getDest().kind()==Kind.FieldAccessNode) {
549       //We are assigning an object field
550
551       FieldAccessNode fan=(FieldAccessNode)an.getDest();
552       ExpressionNode en=fan.getExpression();
553       TempDescriptor dst_tmp=null;
554       NodePair np_baseexp=null;
555       if(en.getType().isStatic()) {
556         // static field dereference with class name
557         dst_tmp = new TempDescriptor(en.getType().getClassDesc().getSymbol(), en.getType());
558         FlatNop nop=new FlatNop();
559         np_baseexp = new NodePair(nop,nop);
560       } else {
561         dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
562         np_baseexp=flattenExpressionNode(en, dst_tmp);
563       }
564       if (first==null)
565         first=np_baseexp.getBegin();
566       else
567         last.addNext(np_baseexp.getBegin());
568       last=np_baseexp.getEnd();
569
570       //See if we need to perform an operation
571       if (base!=null) {
572         //If it is a preinc we need to store the initial value
573         TempDescriptor src_tmp2=pre ? TempDescriptor.tempFactory("src",an.getDest().getType()) : out_temp;
574         TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
575         FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
576         last.addNext(ffn);
577         last=ffn;
578
579         if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
580           ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
581           MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
582           FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
583           src_tmp=tmp;
584           last.addNext(fc);
585           last=fc;
586         } else {
587           FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
588           src_tmp=tmp;
589           last.addNext(fon);
590           last=fon;
591         }
592       }
593
594       FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
595       last.addNext(fsfn);
596       last=fsfn;
597       if (pre) {
598         FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
599         fsfn.addNext(fon2);
600         last=fon2;
601       }
602       return new NodePair(first, last);
603     } else if (an.getDest().kind()==Kind.ArrayAccessNode) {
604       //We are assigning an array element
605
606       ArrayAccessNode aan=(ArrayAccessNode)an.getDest();
607       ExpressionNode en=aan.getExpression();
608       ExpressionNode enindex=aan.getIndex();
609       TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
610       TempDescriptor index_tmp=TempDescriptor.tempFactory("index",enindex.getType());
611       NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
612       NodePair np_indexexp=flattenExpressionNode(enindex, index_tmp);
613       if (first==null)
614         first=np_baseexp.getBegin();
615       else
616         last.addNext(np_baseexp.getBegin());
617       np_baseexp.getEnd().addNext(np_indexexp.getBegin());
618       last=np_indexexp.getEnd();
619
620       //See if we need to perform an operation
621       if (base!=null) {
622         //If it is a preinc we need to store the initial value
623         TempDescriptor src_tmp2=pre ? TempDescriptor.tempFactory("src",an.getDest().getType()) : out_temp;
624         TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
625
626         if (aan.iswrapper()) {
627           TypeDescriptor arrayeltype=aan.getExpression().getType().dereference();
628           TempDescriptor src_tmp3=TempDescriptor.tempFactory("src3",arrayeltype);
629           FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp3);
630           FlatFieldNode ffn=new FlatFieldNode((FieldDescriptor)arrayeltype.getClassDesc().getFieldTable().get("value"),src_tmp3,src_tmp2);
631           last.addNext(fen);
632           fen.addNext(ffn);
633           last=ffn;
634         } else {
635           FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp2);
636           last.addNext(fen);
637           last=fen;
638         }
639         if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
640           ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
641           MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
642           FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
643           src_tmp=tmp;
644           last.addNext(fc);
645           last=fc;
646         } else {
647           FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
648           src_tmp=tmp;
649           last.addNext(fon);
650           last=fon;
651         }
652       }
653
654       if (aan.iswrapper()) { 
655         TypeDescriptor arrayeltype=aan.getExpression().getType().dereference();
656         TempDescriptor src_tmp3=TempDescriptor.tempFactory("src3",arrayeltype);
657         FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp3);
658         FlatSetFieldNode fsfn=new FlatSetFieldNode(src_tmp3,(FieldDescriptor)arrayeltype.getClassDesc().getFieldTable().get("value"),src_tmp);
659         last.addNext(fen);
660         fen.addNext(fsfn);
661         last=fsfn;
662       } else { 
663         FlatSetElementNode fsen=new FlatSetElementNode(dst_tmp, index_tmp, src_tmp);
664         last.addNext(fsen);
665         last=fsen;
666       }
667       if (pre) {
668         FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
669         last.addNext(fon2);
670         last=fon2;
671       }
672       return new NodePair(first, last);
673     } else if (an.getDest().kind()==Kind.NameNode) {
674       //We could be assigning a field or variable
675       NameNode nn=(NameNode)an.getDest();
676
677
678       if (nn.getExpression()!=null) {
679         //It is a field
680         FieldAccessNode fan=(FieldAccessNode)nn.getExpression();
681         ExpressionNode en=fan.getExpression();
682     TempDescriptor dst_tmp=null;
683     NodePair np_baseexp=null;
684     if(en.getType().isStatic()) {
685       // static field dereference with class name
686       dst_tmp = new TempDescriptor(en.getType().getClassDesc().getSymbol(), en.getType());
687       FlatNop nop=new FlatNop();
688       np_baseexp = new NodePair(nop,nop);
689     } else {
690       dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
691       np_baseexp=flattenExpressionNode(en, dst_tmp);
692     }
693         if (first==null)
694           first=np_baseexp.getBegin();
695         else
696           last.addNext(np_baseexp.getBegin());
697         last=np_baseexp.getEnd();
698
699         //See if we need to perform an operation
700         if (base!=null) {
701           //If it is a preinc we need to store the initial value
702           TempDescriptor src_tmp2=pre ? TempDescriptor.tempFactory("src",an.getDest().getType()) : out_temp;
703           TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
704
705           FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
706           last.addNext(ffn);
707           last=ffn;
708
709
710           if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
711             ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
712             MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
713             FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
714             src_tmp=tmp;
715             last.addNext(fc);
716             last=fc;
717           } else {
718             FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
719             src_tmp=tmp;
720             last.addNext(fon);
721             last=fon;
722           }
723         }
724
725
726         FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
727         last.addNext(fsfn);
728         last=fsfn;
729         if (pre) {
730           FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
731           fsfn.addNext(fon2);
732           last=fon2;
733         }
734         return new NodePair(first, last);
735       } else {
736         if (nn.getField()!=null) {
737           //It is a field
738           //Get src value
739
740           //See if we need to perform an operation
741           if (base!=null) {
742             //If it is a preinc we need to store the initial value
743             TempDescriptor src_tmp2=pre ? TempDescriptor.tempFactory("src",an.getDest().getType()) : out_temp;
744             TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
745
746             FlatFieldNode ffn=new FlatFieldNode(nn.getField(), getTempforVar(nn.getVar()), src_tmp2);
747             if (first==null)
748               first=ffn;
749             else {
750               last.addNext(ffn);
751             }
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       FlatSetFieldNode fsfn=null;
771       if(nn.getClassDesc()!=null) {
772         // this is a static field access inside of a static block
773         fsfn=new FlatSetFieldNode(new TempDescriptor("sfsb", nn.getClassType()), nn.getField(), src_tmp);
774       } else {
775         fsfn=new FlatSetFieldNode(getTempforVar(nn.getVar()), nn.getField(), src_tmp);
776       }
777           if (first==null) {
778             first=fsfn;
779           } else {
780             last.addNext(fsfn);
781           }
782           last=fsfn;
783           if (pre) {
784             FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
785             fsfn.addNext(fon2);
786             last=fon2;
787           }
788           return new NodePair(first, last);
789         } else {
790           //It is a variable
791           //See if we need to perform an operation
792
793           if (base!=null) {
794             //If it is a preinc we need to store the initial value
795             TempDescriptor src_tmp2=getTempforVar(nn.getVar());
796             TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3_",an.getDest().getType());
797             if (!pre) {
798               FlatOpNode fon=new FlatOpNode(out_temp, src_tmp2, null, new Operation(Operation.ASSIGN));
799               if (first==null)
800                 first=fon;
801               else
802                 last.addNext(fon);
803               last=fon;
804             }
805
806
807             if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
808               ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
809               MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
810               FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
811               if (first==null)
812                 first=fc;
813               else
814                 last.addNext(fc);
815               src_tmp=tmp;
816               last=fc;
817             } else {
818               FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
819               if (first==null)
820                 first=fon;
821               else
822                 last.addNext(fon);
823               src_tmp=tmp;
824               last=fon;
825             }
826           }
827
828           FlatOpNode fon=new FlatOpNode(getTempforVar(nn.getVar()), src_tmp, null, new Operation(Operation.ASSIGN));
829
830           last.addNext(fon);
831           last=fon;
832           if (pre) {
833             FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
834             fon.addNext(fon2);
835             last=fon2;
836           }
837           return new NodePair(first, last);
838         } //end of else
839       }
840     }
841
842     throw new Error();
843   }
844
845   private NodePair flattenNameNode(NameNode nn,TempDescriptor out_temp) {
846     if (nn.getExpression()!=null) {
847       /* Hack - use subtree instead */
848       return flattenExpressionNode(nn.getExpression(),out_temp);
849     } else if (nn.getField()!=null) {
850       TempDescriptor tmp=getTempforVar(nn.getVar());
851       FlatFieldNode ffn=new FlatFieldNode(nn.getField(), tmp, out_temp);
852       return new NodePair(ffn,ffn);
853     } else {
854       TempDescriptor tmp=getTempforVar(nn.isTag() ? nn.getTagVar() : nn.getVar());
855       if (nn.isTag()) {
856         //propagate tag
857         out_temp.setTag(tmp.getTag());
858       }
859       FlatOpNode fon=new FlatOpNode(out_temp, tmp, null, new Operation(Operation.ASSIGN));
860       return new NodePair(fon,fon);
861     }
862   }
863
864   private NodePair flattenOpNode(OpNode on,TempDescriptor out_temp) {
865     TempDescriptor temp_left=TempDescriptor.tempFactory("leftop",on.getLeft().getType());
866     TempDescriptor temp_right=null;
867
868     Operation op=on.getOp();
869
870     NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
871     NodePair right;
872     if (on.getRight()!=null) {
873       temp_right=TempDescriptor.tempFactory("rightop",on.getRight().getType());
874       right=flattenExpressionNode(on.getRight(),temp_right);
875     } else {
876       FlatNop nop=new FlatNop();
877       right=new NodePair(nop,nop);
878     }
879
880     if (op.getOp()==Operation.LOGIC_OR) {
881       /* Need to do shortcircuiting */
882       FlatCondBranch fcb=new FlatCondBranch(temp_left);
883       FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
884       FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
885       FlatNop fnop=new FlatNop();
886       left.getEnd().addNext(fcb);
887       fcb.addFalseNext(right.getBegin());
888       right.getEnd().addNext(fon2);
889       fon2.addNext(fnop);
890       fcb.addTrueNext(fon1);
891       fon1.addNext(fnop);
892       return new NodePair(left.getBegin(), fnop);
893     } else if (op.getOp()==Operation.LOGIC_AND) {
894       /* Need to do shortcircuiting */
895       FlatCondBranch fcb=new FlatCondBranch(temp_left);
896       FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
897       FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
898       FlatNop fnop=new FlatNop();
899       left.getEnd().addNext(fcb);
900       fcb.addTrueNext(right.getBegin());
901       right.getEnd().addNext(fon2);
902       fon2.addNext(fnop);
903       fcb.addFalseNext(fon1);
904       fon1.addNext(fnop);
905       return new NodePair(left.getBegin(), fnop);
906     } else if (op.getOp()==Operation.ADD&&on.getLeft().getType().isString()) {
907       //We have a string concatenate
908       ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
909       MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat", new TypeDescriptor[] {new TypeDescriptor(stringcd)});
910       FlatCall fc=new FlatCall(concatmd, out_temp, temp_left, new TempDescriptor[] {temp_right});
911       left.getEnd().addNext(right.getBegin());
912       right.getEnd().addNext(fc);
913       return new NodePair(left.getBegin(), fc);
914     }
915
916     FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
917     left.getEnd().addNext(right.getBegin());
918     right.getEnd().addNext(fon);
919     return new NodePair(left.getBegin(),fon);
920   }
921
922   private NodePair flattenExpressionNode(ExpressionNode en, TempDescriptor out_temp) {
923     switch(en.kind()) {
924     case Kind.AssignmentNode:
925       return flattenAssignmentNode((AssignmentNode)en,out_temp);
926
927     case Kind.CastNode:
928       return flattenCastNode((CastNode)en,out_temp);
929
930     case Kind.CreateObjectNode:
931       return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
932
933     case Kind.FieldAccessNode:
934       return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
935
936     case Kind.ArrayAccessNode:
937       return flattenArrayAccessNode((ArrayAccessNode)en,out_temp);
938
939     case Kind.LiteralNode:
940       return flattenLiteralNode((LiteralNode)en,out_temp);
941
942     case Kind.MethodInvokeNode:
943       return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
944
945     case Kind.NameNode:
946       return flattenNameNode((NameNode)en,out_temp);
947
948     case Kind.OpNode:
949       return flattenOpNode((OpNode)en,out_temp);      
950
951     case Kind.OffsetNode:
952       return flattenOffsetNode((OffsetNode)en,out_temp);
953
954     case Kind.TertiaryNode:
955       return flattenTertiaryNode((TertiaryNode)en,out_temp);
956
957     case Kind.InstanceOfNode:
958       return flattenInstanceOfNode((InstanceOfNode)en,out_temp);
959
960     case Kind.ArrayInitializerNode:
961       return flattenArrayInitializerNode((ArrayInitializerNode)en,out_temp);
962     }
963     throw new Error();
964   }
965
966   private NodePair flattenDeclarationNode(DeclarationNode dn) {
967     VarDescriptor vd=dn.getVarDescriptor();
968     TempDescriptor td=getTempforVar(vd);
969     if (dn.getExpression()!=null)
970       return flattenExpressionNode(dn.getExpression(),td);
971     else {
972       FlatNop fn=new FlatNop();
973       return new NodePair(fn,fn);
974     }
975   }
976
977   private NodePair flattenTagDeclarationNode(TagDeclarationNode dn) {
978     TagVarDescriptor tvd=dn.getTagVarDescriptor();
979     TagDescriptor tag=tvd.getTag();
980     TempDescriptor tmp=getTempforVar(tvd);
981     FlatTagDeclaration ftd=new FlatTagDeclaration(tag, tmp);
982     return new NodePair(ftd,ftd);
983   }
984
985   private TempDescriptor getTempforParam(Descriptor d) {
986     if (temptovar.containsKey(d))
987       return (TempDescriptor)temptovar.get(d);
988     else {
989       if (d instanceof VarDescriptor) {
990         VarDescriptor vd=(VarDescriptor)d;
991         TempDescriptor td=TempDescriptor.paramtempFactory(vd.getName(),vd.getType());
992         temptovar.put(vd,td);
993         return td;
994       } else if (d instanceof TagVarDescriptor) {
995         TagVarDescriptor tvd=(TagVarDescriptor)d;
996         TypeDescriptor tagtype=new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass));
997         TempDescriptor td=TempDescriptor.paramtempFactory(tvd.getName(), tagtype, tvd.getTag());
998         temptovar.put(tvd,td);
999         return td;
1000       } else throw new Error("Unreconized Descriptor");
1001     }
1002   }
1003
1004   private TempDescriptor getTempforVar(Descriptor d) {
1005     if (temptovar.containsKey(d))
1006       return (TempDescriptor)temptovar.get(d);
1007     else {
1008       if (d instanceof VarDescriptor) {
1009         VarDescriptor vd=(VarDescriptor)d;
1010         TempDescriptor td=TempDescriptor.tempFactory(vd.getName(), vd.getType());
1011         temptovar.put(vd,td);
1012         return td;
1013       } else if (d instanceof TagVarDescriptor) {
1014         TagVarDescriptor tvd=(TagVarDescriptor)d;
1015         //BUGFIX TAGTYPE - add next line, modify following
1016         //line to tag this new type descriptor, modify
1017         //TempDescriptor constructor & factory to set type
1018         //using this Type To test, use any program with tags
1019         TypeDescriptor tagtype=new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass));
1020         TempDescriptor td=TempDescriptor.tempFactory(tvd.getName(),tagtype, tvd.getTag());
1021         temptovar.put(tvd,td);
1022         return td;
1023       } else throw new Error("Unrecognized Descriptor");
1024     }
1025   }
1026
1027   private NodePair flattenIfStatementNode(IfStatementNode isn) {
1028     TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
1029     NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
1030     FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1031     NodePair true_np=flattenBlockNode(isn.getTrueBlock());
1032     NodePair false_np;
1033     FlatNop nopend=new FlatNop();
1034
1035     if (isn.getFalseBlock()!=null)
1036       false_np=flattenBlockNode(isn.getFalseBlock());
1037     else {
1038       FlatNop nop=new FlatNop();
1039       false_np=new NodePair(nop,nop);
1040     }
1041
1042     cond.getEnd().addNext(fcb);
1043     fcb.addTrueNext(true_np.getBegin());
1044     fcb.addFalseNext(false_np.getBegin());
1045     if (true_np.getEnd()!=null)
1046         true_np.getEnd().addNext(nopend);
1047     if (false_np.getEnd()!=null)
1048         false_np.getEnd().addNext(nopend);
1049     if (nopend.numPrev()==0)
1050       return new NodePair(cond.getBegin(), null);
1051
1052     return new NodePair(cond.getBegin(), nopend);
1053   }
1054   
1055   private NodePair flattenSwitchStatementNode(SwitchStatementNode ssn) {
1056     TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.INT));
1057     NodePair cond=flattenExpressionNode(ssn.getCondition(),cond_temp);
1058     FlatNop nopend=new FlatNop();
1059     NodePair sbody = flattenSwitchBodyNode(ssn.getSwitchBody(), cond_temp, nopend);
1060     
1061     cond.getEnd().addNext(sbody.getBegin());
1062
1063     return new NodePair(cond.getBegin(), sbody.getEnd());
1064   }
1065   
1066   private NodePair flattenSwitchBodyNode(BlockNode bn, TempDescriptor cond_temp, FlatNode endnode) {
1067     FlatNode begin=null;
1068     FlatNode end=endnode;
1069     NodePair prev_true_branch = null;
1070     NodePair prev_false_branch = null;
1071     for(int i=0; i<bn.size(); i++) {
1072       SwitchBlockNode sbn = (SwitchBlockNode)bn.get(i);
1073       HashSet oldbs=breakset;
1074       breakset=new HashSet();
1075       
1076       NodePair body=flattenBlockNode(sbn.getSwitchBlockStatement());
1077       Vector<SwitchLabelNode> slnv = sbn.getSwitchConditions();
1078       FlatNode cond_begin = null;
1079       NodePair prev_fnp = null;
1080       for(int j = 0; j < slnv.size(); j++) {
1081         SwitchLabelNode sln = slnv.elementAt(j);
1082         NodePair left = null;
1083         NodePair false_np = null;
1084         if(sln.isDefault()) {
1085           left = body;
1086         } else {
1087           TempDescriptor cond_tmp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
1088           TempDescriptor temp_left=TempDescriptor.tempFactory("leftop", sln.getCondition().getType());
1089           Operation op=new Operation(Operation.EQUAL);
1090           left=flattenExpressionNode(sln.getCondition(), temp_left);
1091           FlatOpNode fon=new FlatOpNode(cond_tmp, temp_left, cond_temp, op);
1092           left.getEnd().addNext(fon);
1093
1094           FlatCondBranch fcb=new FlatCondBranch(cond_tmp);
1095           fcb.setTrueProb(State.TRUEPROB);
1096
1097           FlatNop nop=new FlatNop();
1098           false_np=new NodePair(nop,nop);
1099
1100           fon.addNext(fcb);
1101           fcb.addTrueNext(body.getBegin());
1102           fcb.addFalseNext(false_np.getBegin());
1103         }
1104         if((prev_fnp != null) && (prev_fnp.getEnd() != null)) {
1105           prev_fnp.getEnd().addNext(left.getBegin());
1106         }
1107         prev_fnp = false_np;
1108         
1109         if (begin==null) {
1110           begin = left.getBegin();
1111         }
1112         if(cond_begin == null) {
1113           cond_begin = left.getBegin();
1114         }
1115       }
1116       if((prev_false_branch != null) && (prev_false_branch.getEnd() != null)) {
1117         prev_false_branch.getEnd().addNext(cond_begin);
1118       }
1119       prev_false_branch = prev_fnp;
1120       if((prev_true_branch != null) && (prev_true_branch.getEnd() != null)) {
1121         prev_true_branch.getEnd().addNext(body.getBegin());
1122       }
1123       prev_true_branch = body;
1124       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
1125         FlatNode fn=(FlatNode)breakit.next();
1126         breakit.remove();
1127         fn.addNext(endnode);
1128       }
1129       breakset=oldbs;
1130     }
1131     if((prev_true_branch != null) && (prev_true_branch.getEnd() != null)) {
1132       prev_true_branch.getEnd().addNext(endnode);
1133     }
1134     if((prev_false_branch != null) && (prev_false_branch.getEnd() != null)) {
1135       prev_false_branch.getEnd().addNext(endnode);
1136     }
1137     if(begin == null) {
1138       end=begin=new FlatNop();
1139     }
1140     return new NodePair(begin,end);
1141   }
1142   
1143   private NodePair flattenLoopNode(LoopNode ln) {
1144     HashSet oldbs=breakset;
1145     HashSet oldcs=continueset;
1146     breakset=new HashSet();
1147     continueset=new HashSet();
1148     
1149     if (ln.getType()==LoopNode.FORLOOP) {
1150       NodePair initializer=flattenBlockNode(ln.getInitializer());
1151       TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
1152       NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
1153       NodePair update=flattenBlockNode(ln.getUpdate());
1154       NodePair body=flattenBlockNode(ln.getBody());
1155       FlatNode begin=initializer.getBegin();
1156       FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1157       fcb.setTrueProb(State.TRUEPROB);
1158       fcb.setLoop();
1159       FlatNop nopend=new FlatNop();
1160       FlatBackEdge backedge=new FlatBackEdge();
1161
1162       FlatNop nop2=new FlatNop();
1163       initializer.getEnd().addNext(nop2);
1164       nop2.addNext(condition.getBegin());
1165       if (body.getEnd()!=null)
1166           body.getEnd().addNext(update.getBegin());
1167       update.getEnd().addNext(backedge);
1168       backedge.addNext(condition.getBegin());
1169       condition.getEnd().addNext(fcb);
1170       fcb.addFalseNext(nopend);
1171       fcb.addTrueNext(body.getBegin());
1172       for(Iterator contit=continueset.iterator();contit.hasNext();) {
1173           FlatNode fn=(FlatNode)contit.next();
1174           contit.remove();
1175           fn.addNext(update.getBegin());
1176       }
1177       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
1178           FlatNode fn=(FlatNode)breakit.next();
1179           breakit.remove();
1180           fn.addNext(nopend);
1181       }
1182       breakset=oldbs;
1183       continueset=oldcs;
1184       return new NodePair(begin,nopend);
1185     } else if (ln.getType()==LoopNode.WHILELOOP) {
1186       TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
1187       NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
1188       NodePair body=flattenBlockNode(ln.getBody());
1189       FlatNode begin=condition.getBegin();
1190       FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1191       fcb.setTrueProb(State.TRUEPROB);
1192       fcb.setLoop();
1193       FlatNop nopend=new FlatNop();
1194       FlatBackEdge backedge=new FlatBackEdge();
1195
1196       if (body.getEnd()!=null)
1197         body.getEnd().addNext(backedge);
1198       backedge.addNext(condition.getBegin());
1199
1200       condition.getEnd().addNext(fcb);
1201       fcb.addFalseNext(nopend);
1202       fcb.addTrueNext(body.getBegin());
1203
1204       for(Iterator contit=continueset.iterator();contit.hasNext();) {
1205           FlatNode fn=(FlatNode)contit.next();
1206           contit.remove();
1207           fn.addNext(backedge);
1208       }
1209       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
1210           FlatNode fn=(FlatNode)breakit.next();
1211           breakit.remove();
1212           fn.addNext(nopend);
1213       }
1214       breakset=oldbs;
1215       continueset=oldcs;
1216       return new NodePair(begin,nopend);
1217     } else if (ln.getType()==LoopNode.DOWHILELOOP) {
1218       TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
1219       NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
1220       NodePair body=flattenBlockNode(ln.getBody());
1221       FlatNode begin=body.getBegin();
1222       FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1223       fcb.setTrueProb(State.TRUEPROB);
1224       fcb.setLoop();
1225       FlatNop nopend=new FlatNop();
1226       FlatBackEdge backedge=new FlatBackEdge();
1227
1228       if (body.getEnd()!=null)
1229         body.getEnd().addNext(condition.getBegin());
1230       condition.getEnd().addNext(fcb);
1231       fcb.addFalseNext(nopend);
1232       fcb.addTrueNext(backedge);
1233       backedge.addNext(body.getBegin());
1234
1235       for(Iterator contit=continueset.iterator();contit.hasNext();) {
1236           FlatNode fn=(FlatNode)contit.next();
1237           contit.remove();
1238           fn.addNext(condition.getBegin());
1239       }
1240       for(Iterator breakit=breakset.iterator();breakit.hasNext();) {
1241           FlatNode fn=(FlatNode)breakit.next();
1242           breakit.remove();
1243           fn.addNext(nopend);
1244       }
1245       breakset=oldbs;
1246       continueset=oldcs;
1247       return new NodePair(begin,nopend);
1248     } else throw new Error();
1249   }
1250
1251   private NodePair flattenReturnNode(ReturnNode rntree) {
1252     TempDescriptor retval=null;
1253     NodePair cond=null;
1254     if (rntree.getReturnExpression()!=null) {
1255       retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
1256       cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
1257     }
1258
1259     FlatReturnNode rnflat=new FlatReturnNode(retval);
1260     rnflat.addNext(fe);
1261     FlatNode ln=rnflat;
1262     if ((state.THREAD||state.MGC)&&currmd.getModifiers().isSynchronized()) {
1263       MethodDescriptor memd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
1264       TempDescriptor thistd=getTempforVar(currmd.getThis());
1265       FlatCall fc=new FlatCall(memd, null, thistd, new TempDescriptor[0]);
1266       fc.addNext(ln);
1267       ln=fc;
1268     }
1269     if (state.DSM&&currmd.getModifiers().isAtomic()) {
1270       FlatAtomicExitNode faen=new FlatAtomicExitNode(curran);
1271       faen.addNext(ln);
1272       ln=faen;
1273     }
1274
1275     if (cond!=null) {
1276       cond.getEnd().addNext(ln);
1277       return new NodePair(cond.getBegin(),null);
1278     } else
1279       return new NodePair(ln,null);
1280   }
1281
1282   private NodePair flattenTaskExitNode(TaskExitNode ten) {
1283     FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.TASKEXIT);
1284     ffan.setTaskExitIndex(ten.getTaskExitIndex());
1285     updateFlagActionNode(ffan, ten.getFlagEffects());
1286     NodePair fcn=flattenConstraintCheck(ten.getChecks());
1287     ffan.addNext(fcn.getBegin());
1288     FlatReturnNode rnflat=new FlatReturnNode(null);
1289     rnflat.addNext(fe);
1290     fcn.getEnd().addNext(rnflat);
1291     return new NodePair(ffan, null);
1292   }
1293
1294   private NodePair flattenConstraintCheck(Vector ccs) {
1295     FlatNode begin=new FlatNop();
1296     if (ccs==null)
1297       return new NodePair(begin,begin);
1298     FlatNode last=begin;
1299     for(int i=0; i<ccs.size(); i++) {
1300       ConstraintCheck cc=(ConstraintCheck) ccs.get(i);
1301       /* Flatten the arguments */
1302       TempDescriptor[] temps=new TempDescriptor[cc.numArgs()];
1303       String[] vars=new String[cc.numArgs()];
1304       for(int j=0; j<cc.numArgs(); j++) {
1305         ExpressionNode en=cc.getArg(j);
1306         TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
1307         temps[j]=td;
1308         vars[j]=cc.getVar(j);
1309         NodePair np=flattenExpressionNode(en, td);
1310         last.addNext(np.getBegin());
1311         last=np.getEnd();
1312       }
1313
1314       FlatCheckNode fcn=new FlatCheckNode(cc.getSpec(), vars, temps);
1315       last.addNext(fcn);
1316       last=fcn;
1317     }
1318     return new NodePair(begin,last);
1319   }
1320
1321   private NodePair flattenSubBlockNode(SubBlockNode sbn) {
1322     return flattenBlockNode(sbn.getBlockNode());
1323   }
1324
1325   private NodePair flattenSynchronizedNode(SynchronizedNode sbn) {
1326     TempDescriptor montmp=TempDescriptor.tempFactory("monitor",sbn.getExpr().getType());
1327     NodePair npexp=flattenExpressionNode(sbn.getExpr(), montmp);
1328     NodePair npblock=flattenBlockNode(sbn.getBlockNode());
1329
1330     MethodDescriptor menmd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorEnter");
1331     FlatCall fcen=new FlatCall(menmd, null, montmp, new TempDescriptor[0]);
1332
1333     MethodDescriptor mexmd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
1334     FlatCall fcex=new FlatCall(mexmd, null, montmp, new TempDescriptor[0]);
1335
1336     npexp.getEnd().addNext(fcen);
1337     fcen.addNext(npblock.getBegin());
1338     npblock.getEnd().addNext(fcex);
1339     return new NodePair(npexp.getBegin(), fcex);
1340   }
1341
1342   private NodePair flattenAtomicNode(AtomicNode sbn) {
1343     NodePair np=flattenBlockNode(sbn.getBlockNode());
1344     FlatAtomicEnterNode faen=new FlatAtomicEnterNode();
1345     FlatAtomicExitNode faexn=new FlatAtomicExitNode(faen);
1346     faen.addNext(np.getBegin());
1347     np.getEnd().addNext(faexn);
1348     return new NodePair(faen, faexn);
1349   }
1350
1351   private NodePair flattenGenReachNode( GenReachNode grn ) {
1352     FlatGenReachNode fgrn = new FlatGenReachNode( grn.getGraphName() );
1353     return new NodePair( fgrn, fgrn );
1354   }
1355
1356   private NodePair flattenSESENode(SESENode sn) {
1357     if( sn.isStart() ) {
1358       FlatSESEEnterNode fsen=new FlatSESEEnterNode(sn);
1359       sn.setFlatEnter(fsen);
1360       return new NodePair(fsen, fsen);
1361     }
1362
1363     FlatSESEExitNode fsexn=new FlatSESEExitNode(sn);
1364     sn.setFlatExit(fsexn);
1365     FlatSESEEnterNode fsen=sn.getStart().getFlatEnter();
1366     fsexn.setFlatEnter(fsen);    
1367     sn.getStart().getFlatEnter().setFlatExit( fsexn );
1368     
1369     return new NodePair(fsexn, fsexn);
1370   }
1371
1372   private NodePair flattenContinueBreakNode(ContinueBreakNode cbn) {
1373       FlatNop fn=new FlatNop();
1374       if (cbn.isBreak())
1375           breakset.add(fn);
1376       else
1377           continueset.add(fn);
1378       return new NodePair(fn,null);
1379   }
1380
1381   private NodePair flattenInstanceOfNode(InstanceOfNode tn, TempDescriptor out_temp) {
1382     TempDescriptor expr_temp=TempDescriptor.tempFactory("expr",tn.getExpr().getType());
1383     NodePair cond=flattenExpressionNode(tn.getExpr(), expr_temp);
1384     FlatInstanceOfNode fion=new FlatInstanceOfNode(tn.getExprType(), expr_temp, out_temp);
1385     cond.getEnd().addNext(fion);
1386     return new NodePair(cond.getBegin(),fion);
1387   }
1388
1389   private NodePair flattenArrayInitializerNode(ArrayInitializerNode ain, TempDescriptor out_temp) {
1390     /*
1391     TempDescriptor expr_temp=TempDescriptor.tempFactory("arry_init",ain.getType());
1392
1393     // create a new array of size equal to the array initializer
1394     //FlatNode first=null;
1395     //FlatNode last=null;
1396     TempDescriptor[] temps=new TempDescriptor[ain.numVarInitializers()];
1397
1398       for (int i=0; i<con.numArgs(); i++) {
1399         ExpressionNode en=con.getArg(i);
1400         TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
1401         temps[i]=tmp;
1402         NodePair np=flattenExpressionNode(en, tmp);
1403         if (first==null)
1404           first=np.getBegin();
1405         else
1406           last.addNext(np.getBegin());
1407         last=np.getEnd();
1408
1409         TempDescriptor tmp2=(i==0) ?
1410                              out_temp :
1411                              TempDescriptor.tempFactory("arg",en.getType());
1412       }
1413       FlatNew fn=new FlatNew(td, out_temp, temps[0], con.isGlobal(), con.getDisjointId());
1414       last.addNext(fn);
1415
1416
1417     // assign each element of the new array to the flattened expression
1418
1419
1420     FlatOpNode fonAssignArray=new FlatOpNode(out_temp, newarry_temp, null, new Operation(Operation.ASSIGN));
1421     */
1422     //return new NodePair( , fonAssignArray );
1423     ain.printNode(0);
1424     System.out.println( "Array initializers not implemented yet." );
1425     System.exit( -1 );
1426     return null;
1427   }
1428
1429   private NodePair flattenTertiaryNode(TertiaryNode tn, TempDescriptor out_temp) {
1430     TempDescriptor cond_temp=TempDescriptor.tempFactory("tert_cond",new TypeDescriptor(TypeDescriptor.BOOLEAN));
1431     TempDescriptor true_temp=TempDescriptor.tempFactory("tert_true",tn.getTrueExpr().getType());
1432     TempDescriptor fals_temp=TempDescriptor.tempFactory("tert_fals",tn.getFalseExpr().getType());
1433
1434     NodePair cond=flattenExpressionNode(tn.getCond(),cond_temp);
1435     FlatCondBranch fcb=new FlatCondBranch(cond_temp);
1436
1437     NodePair trueExpr=flattenExpressionNode(tn.getTrueExpr(),true_temp);
1438     FlatOpNode fonT=new FlatOpNode(out_temp, true_temp, null, new Operation(Operation.ASSIGN));
1439
1440     NodePair falseExpr=flattenExpressionNode(tn.getFalseExpr(),fals_temp);
1441     FlatOpNode fonF=new FlatOpNode(out_temp, fals_temp, null, new Operation(Operation.ASSIGN));
1442
1443     FlatNop nopend=new FlatNop();
1444
1445     cond.getEnd().addNext(fcb);
1446
1447     fcb.addTrueNext(trueExpr.getBegin());
1448     fcb.addFalseNext(falseExpr.getBegin());
1449
1450     trueExpr.getEnd().addNext(fonT);
1451     fonT.addNext(nopend);
1452
1453     falseExpr.getEnd().addNext(fonF);
1454     fonF.addNext(nopend);
1455     
1456     return new NodePair(cond.getBegin(), nopend);
1457   }
1458
1459   private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
1460     switch(bsn.kind()) {
1461     case Kind.BlockExpressionNode:
1462       return flattenBlockExpressionNode((BlockExpressionNode)bsn);
1463
1464     case Kind.DeclarationNode:
1465       return flattenDeclarationNode((DeclarationNode)bsn);
1466
1467     case Kind.TagDeclarationNode:
1468       return flattenTagDeclarationNode((TagDeclarationNode)bsn);
1469
1470     case Kind.IfStatementNode:
1471       return flattenIfStatementNode((IfStatementNode)bsn);
1472       
1473     case Kind.SwitchStatementNode:
1474       return flattenSwitchStatementNode((SwitchStatementNode)bsn);
1475
1476     case Kind.LoopNode:
1477       return flattenLoopNode((LoopNode)bsn);
1478
1479     case Kind.ReturnNode:
1480       return flattenReturnNode((IR.Tree.ReturnNode)bsn);
1481
1482     case Kind.TaskExitNode:
1483       return flattenTaskExitNode((IR.Tree.TaskExitNode)bsn);
1484
1485     case Kind.SubBlockNode:
1486       return flattenSubBlockNode((SubBlockNode)bsn);
1487
1488     case Kind.AtomicNode:
1489       return flattenAtomicNode((AtomicNode)bsn);
1490
1491     case Kind.SynchronizedNode:
1492       return flattenSynchronizedNode((SynchronizedNode)bsn);
1493
1494     case Kind.SESENode:
1495       return flattenSESENode((SESENode)bsn);
1496
1497     case Kind.GenReachNode:
1498       return flattenGenReachNode((GenReachNode)bsn);
1499
1500     case Kind.ContinueBreakNode:
1501       return flattenContinueBreakNode((ContinueBreakNode)bsn);
1502     }
1503     throw new Error();
1504   }
1505 }