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