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