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