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             if (td.getClassDesc().hasFlags()) {
205                 //          if (con.getFlagEffects()!=null) {
206                 FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.NEWOBJECT);
207                 FlagEffects fes=con.getFlagEffects();
208                 TempDescriptor flagtemp=out_temp;
209                 if (fes!=null) {
210                     for(int j=0;j<fes.numEffects();j++) {
211                         FlagEffect fe=fes.getEffect(j);
212                         ffan.addFlagAction(flagtemp, fe.getFlag(), fe.getStatus());
213                     } 
214                     for(int j=0;j<fes.numTagEffects();j++) {
215                         TagEffect te=fes.getTagEffect(j);
216                         TempDescriptor tagtemp=getTempforVar(te.getTag());
217                 
218                         ffan.addTagAction(flagtemp, te.getTag().getTag(), tagtemp, te.getStatus());
219                     }
220                 } else {
221                     ffan.addFlagAction(flagtemp, null, false);
222                 }
223                 last.addNext(ffan);
224                 last=ffan;
225             }
226             //Build arguments
227             for(int i=0;i<con.numArgs();i++) {
228                 ExpressionNode en=con.getArg(i);
229                 TempDescriptor tmp=TempDescriptor.tempFactory("arg",en.getType());
230                 temps[i]=tmp;
231                 NodePair np=flattenExpressionNode(en, tmp);
232                 last.addNext(np.getBegin());
233                 last=np.getEnd();
234             }
235             MethodDescriptor md=con.getConstructor();
236             //Call to constructor
237             FlatCall fc=new FlatCall(md, null, out_temp, temps);
238             last.addNext(fc);
239             last=fc;
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         //is index<temp[i]
286         TempDescriptor new_tmp=TempDescriptor.tempFactory("tmp",td);
287         FlatNew fn=new FlatNew(td, new_tmp, temparray[i+1], isglobal);
288         FlatSetElementNode fsen=new FlatSetElementNode(tmp,index,new_tmp);
289         // index=index+1
290         FlatOpNode fon=new FlatOpNode(index,index,tmpone,new Operation(Operation.ADD));
291         //jump out
292         fln.addNext(fln2);
293         fln2.addNext(fcomp);
294         fcomp.addNext(fcb);
295         fcb.addTrueNext(fn);
296         fcb.addFalseNext(fnop);
297         fn.addNext(fsen);
298         //Recursive call here
299         if ((i+2)<temparray.length) {
300             NodePair np2=generateNewArrayLoop(temparray, td.dereference(), new_tmp, i+1, isglobal);
301             fsen.addNext(np2.getBegin());
302             np2.getEnd().addNext(fon);
303         } else {
304             fsen.addNext(fon);
305         }
306         fon.addNext(fcomp);
307         return new NodePair(fln, fnop);
308     }
309
310     private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) {
311         TempDescriptor[] temps=new TempDescriptor[min.numArgs()];
312         FlatNode first=null;
313         FlatNode last=null;
314         TempDescriptor thisarg=null;
315
316         if (min.getExpression()!=null) {
317             thisarg=TempDescriptor.tempFactory("thisarg",min.getExpression().getType());
318             NodePair np=flattenExpressionNode(min.getExpression(),thisarg);
319             first=np.getBegin();
320             last=np.getEnd();
321         }
322         
323         //Build arguments
324         for(int i=0;i<min.numArgs();i++) {
325             ExpressionNode en=min.getArg(i);
326             TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
327             temps[i]=td;
328             NodePair np=flattenExpressionNode(en, td);
329             if (first==null)
330                 first=np.getBegin();
331             else 
332                 last.addNext(np.getBegin());
333             last=np.getEnd();
334         }
335
336         MethodDescriptor md=min.getMethod();
337         
338         //Call to constructor
339         
340         FlatCall fc;
341         if(md.getReturnType()==null||md.getReturnType().isVoid())
342             fc=new FlatCall(md, null, thisarg, temps);
343         else 
344             fc=new FlatCall(md, out_temp, thisarg, temps);
345         if (first==null) {
346             first=fc;
347         } else
348             last.addNext(fc);
349         return new NodePair(first,fc);
350     }
351
352     private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) {
353         TempDescriptor tmp=TempDescriptor.tempFactory("temp",fan.getExpression().getType());
354         NodePair npe=flattenExpressionNode(fan.getExpression(),tmp);
355         FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp);
356         npe.getEnd().addNext(fn);
357         return new NodePair(npe.getBegin(),fn);
358     }
359
360     private NodePair flattenArrayAccessNode(ArrayAccessNode aan,TempDescriptor out_temp) {
361         TempDescriptor tmp=TempDescriptor.tempFactory("temp",aan.getExpression().getType());
362         TempDescriptor tmpindex=TempDescriptor.tempFactory("temp",aan.getIndex().getType());
363         NodePair npe=flattenExpressionNode(aan.getExpression(),tmp);
364         NodePair npi=flattenExpressionNode(aan.getIndex(),tmpindex);
365         FlatElementNode fn=new FlatElementNode(tmp,tmpindex,out_temp);
366         npe.getEnd().addNext(npi.getBegin());
367         npi.getEnd().addNext(fn);
368         return new NodePair(npe.getBegin(),fn);
369     }
370
371     private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
372         // Three cases:
373         // left side is variable
374         // left side is field
375         // left side is array
376         
377         Operation base=an.getOperation().getBaseOp();
378         boolean pre=base==null||(base.getOp()!=Operation.POSTINC&&base.getOp()!=Operation.POSTDEC);
379         
380         if (!pre) {
381             //rewrite the base operation
382             base=base.getOp()==Operation.POSTINC?new Operation(Operation.ADD):new Operation(Operation.SUB);
383         }
384         FlatNode first=null;
385         FlatNode last=null;
386         TempDescriptor src_tmp=an.getSrc()==null?TempDescriptor.tempFactory("srctmp",an.getDest().getType()):TempDescriptor.tempFactory("srctmp",an.getSrc().getType());
387
388         //Get src value
389         if (an.getSrc()!=null) {
390             NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
391             first=np_src.getBegin();
392             last=np_src.getEnd();
393         } else if (!pre) {
394             FlatLiteralNode fln=new FlatLiteralNode(new TypeDescriptor(TypeDescriptor.INT) ,new Integer(1),src_tmp);
395             first=fln;
396             last=fln;
397         }
398         
399         if (an.getDest().kind()==Kind.FieldAccessNode) {
400             //We are assigning an object field
401
402             FieldAccessNode fan=(FieldAccessNode)an.getDest();
403             ExpressionNode en=fan.getExpression();
404             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
405             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
406             if (first==null)
407                 first=np_baseexp.getBegin();
408             else
409                 last.addNext(np_baseexp.getBegin());
410             last=np_baseexp.getEnd();
411
412             //See if we need to perform an operation
413             if (base!=null) {
414                 //If it is a preinc we need to store the initial value
415                 TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
416                 TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
417                 FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
418                 last.addNext(ffn);
419                 last=ffn;
420
421                 if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
422                     ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
423                     MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
424                     FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
425                     src_tmp=tmp;
426                     last.addNext(fc);
427                     last=fc;
428                 } else {
429                     FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
430                     src_tmp=tmp;
431                     last.addNext(fon);
432                     last=fon;
433                 }
434             }
435
436             FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
437             last.addNext(fsfn);
438             last=fsfn;
439             if (pre) {
440                 FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
441                 fsfn.addNext(fon2);
442                 last=fon2;
443             }
444             return new NodePair(first, last);
445         } else if (an.getDest().kind()==Kind.ArrayAccessNode) {
446             //We are assigning an array element
447
448
449             ArrayAccessNode aan=(ArrayAccessNode)an.getDest();
450             ExpressionNode en=aan.getExpression();
451             ExpressionNode enindex=aan.getIndex();
452             TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
453             TempDescriptor index_tmp=TempDescriptor.tempFactory("index",enindex.getType());
454             NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
455             NodePair np_indexexp=flattenExpressionNode(enindex, index_tmp);
456             if (first==null)
457                 first=np_baseexp.getBegin();
458             else
459                 last.addNext(np_baseexp.getBegin());
460             np_baseexp.getEnd().addNext(np_indexexp.getBegin());
461             last=np_indexexp.getEnd();
462
463             //See if we need to perform an operation
464             if (base!=null) {
465                 //If it is a preinc we need to store the initial value
466                 TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
467                 TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
468
469                 FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp2);
470                 last.addNext(fen);
471                 last=fen;
472
473                 if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
474                     ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
475                     MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
476                     FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
477                     src_tmp=tmp;
478                     last.addNext(fc);
479                     last=fc;
480                 } else {
481
482
483                     FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
484                     src_tmp=tmp;
485                     last.addNext(fon);
486                     last=fon;
487                 }
488             }
489
490
491             FlatSetElementNode fsen=new FlatSetElementNode(dst_tmp, index_tmp, src_tmp);
492             last.addNext(fsen);
493             last=fsen;
494             if (pre) {
495                 FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
496                 fsen.addNext(fon2);
497                 last=fon2;
498             }
499             return new NodePair(first, last);
500         } else if (an.getDest().kind()==Kind.NameNode) {
501             //We could be assigning a field or variable
502             NameNode nn=(NameNode)an.getDest();
503             if (nn.getExpression()!=null) {
504                 //It is a field
505                 FieldAccessNode fan=(FieldAccessNode)nn.getExpression();
506                 ExpressionNode en=fan.getExpression();
507                 TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
508                 NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
509                 if (first==null)
510                     first=np_baseexp.getBegin();
511                 else
512                     last.addNext(np_baseexp.getBegin());
513                 last=np_baseexp.getEnd();
514
515                 //See if we need to perform an operation
516                 if (base!=null) {
517                     //If it is a preinc we need to store the initial value
518                     TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
519                     TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
520                     
521                     FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
522                     last.addNext(ffn);
523                     last=ffn;
524
525                     
526                     if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
527                         ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
528                         MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
529                         FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
530                         src_tmp=tmp;
531                         last.addNext(fc);
532                         last=fc;
533                     } else {
534                         FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
535                         src_tmp=tmp;
536                         last.addNext(fon);
537                         last=fon;
538                     }
539                 }
540
541
542                 FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
543                 last.addNext(fsfn);
544                 last=fsfn;
545                 if (pre) {
546                     FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
547                     fsfn.addNext(fon2);
548                     last=fon2;
549                 }
550                 return new NodePair(first, last);
551             } else {
552                 if (nn.getField()!=null) {
553                     //It is a field
554                     //Get src value
555
556                     //See if we need to perform an operation
557                     if (base!=null) {
558                         //If it is a preinc we need to store the initial value
559                         TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
560                         TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
561                         
562                         FlatFieldNode ffn=new FlatFieldNode(nn.getField(), getTempforVar(nn.getVar()), src_tmp2);
563                         if (first==null)
564                             first=ffn;
565                         else {
566                             last.addNext(ffn);
567                         }
568                         last=ffn;
569
570                         
571                         if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
572                             ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
573                             MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
574                             FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
575                             src_tmp=tmp;
576                             last.addNext(fc);
577                             last=fc;
578                         } else {
579                             FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
580                             src_tmp=tmp;
581                             last.addNext(fon);
582                             last=fon;
583                         }
584                     }               
585
586                     FlatSetFieldNode fsfn=new FlatSetFieldNode(getTempforVar(nn.getVar()), nn.getField(), src_tmp);
587                     if (first==null) {
588                         first=fsfn;
589                     } else {
590                         last.addNext(fsfn);
591                     }
592                     last=fsfn;
593                     if (pre) {
594                         FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
595                         fsfn.addNext(fon2);
596                         last=fon2;
597                     }
598                     return new NodePair(first, last);
599                 } else {
600                     //It is a variable
601                     //See if we need to perform an operation
602
603                     if (base!=null) {
604                         //If it is a preinc we need to store the initial value
605                         TempDescriptor src_tmp2=getTempforVar(nn.getVar());
606                         TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
607                         if (!pre) {
608                             FlatOpNode fon=new FlatOpNode(out_temp, src_tmp2, null, new Operation(Operation.ASSIGN));
609                             if (first==null)
610                                 first=fon;
611                             else
612                                 last.addNext(fon);
613                             last=fon;
614                         }
615
616                         
617                         if (base.getOp()==Operation.ADD&&an.getDest().getType().isString()) {
618                             ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
619                             MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat2", new TypeDescriptor[] {new TypeDescriptor(stringcd), new TypeDescriptor(stringcd)});
620                             FlatCall fc=new FlatCall(concatmd, tmp, null, new TempDescriptor[] {src_tmp2, src_tmp});
621                             if (first==null)
622                                 first=fc;
623                             else
624                                 last.addNext(fc);
625                             src_tmp=tmp;
626                             last=fc;
627                         } else {
628                             FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
629                             if (first==null) 
630                                 first=fon;
631                             else 
632                                 last.addNext(fon);
633                             src_tmp=tmp;
634                             last=fon;
635                         }
636                     }
637
638                     FlatOpNode fon=new FlatOpNode(getTempforVar(nn.getVar()), src_tmp, null, new Operation(Operation.ASSIGN));
639                     last.addNext(fon);
640                     last=fon;
641                     if (pre) {
642                         FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
643                         fon.addNext(fon2);
644                         last=fon2;
645                     }
646                     return new NodePair(first, last);
647                 }
648             }
649         } 
650         throw new Error();
651     }
652
653     private NodePair flattenNameNode(NameNode nn,TempDescriptor out_temp) {
654         if (nn.getExpression()!=null) {
655             /* Hack - use subtree instead */
656             return flattenExpressionNode(nn.getExpression(),out_temp);
657         } else if (nn.getField()!=null) {
658             TempDescriptor tmp=getTempforVar(nn.getVar());
659             FlatFieldNode ffn=new FlatFieldNode(nn.getField(), tmp, out_temp); 
660             return new NodePair(ffn,ffn);
661         } else {
662             TempDescriptor tmp=getTempforVar(nn.isTag()?nn.getTagVar():nn.getVar());
663             if (nn.isTag()) {
664                 //propagate tag
665                 out_temp.setTag(tmp.getTag());
666             }
667             FlatOpNode fon=new FlatOpNode(out_temp, tmp, null, new Operation(Operation.ASSIGN));
668             return new NodePair(fon,fon);
669         }
670     }
671
672     private NodePair flattenOpNode(OpNode on,TempDescriptor out_temp) {
673         TempDescriptor temp_left=TempDescriptor.tempFactory("leftop",on.getLeft().getType());
674         TempDescriptor temp_right=null;
675
676         Operation op=on.getOp();
677
678         NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
679         NodePair right;
680         if (on.getRight()!=null) {
681             temp_right=TempDescriptor.tempFactory("rightop",on.getRight().getType());
682             right=flattenExpressionNode(on.getRight(),temp_right);
683         } else {
684             FlatNop nop=new FlatNop();
685             right=new NodePair(nop,nop);
686         }
687
688         if (op.getOp()==Operation.LOGIC_OR) {
689             /* Need to do shortcircuiting */
690             FlatCondBranch fcb=new FlatCondBranch(temp_left);
691             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
692             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
693             FlatNop fnop=new FlatNop();
694             left.getEnd().addNext(fcb);
695             fcb.addFalseNext(right.getBegin());
696             right.getEnd().addNext(fon2);
697             fon2.addNext(fnop);
698             fcb.addTrueNext(fon1);
699             fon1.addNext(fnop);
700             return new NodePair(left.getBegin(), fnop);
701         } else if (op.getOp()==Operation.LOGIC_AND) {
702             /* Need to do shortcircuiting */
703             FlatCondBranch fcb=new FlatCondBranch(temp_left);
704             FlatOpNode fon1=new FlatOpNode(out_temp,temp_left,null,new Operation(Operation.ASSIGN));
705             FlatOpNode fon2=new FlatOpNode(out_temp,temp_right,null,new Operation(Operation.ASSIGN));
706             FlatNop fnop=new FlatNop();
707             left.getEnd().addNext(fcb);
708             fcb.addTrueNext(right.getBegin());
709             right.getEnd().addNext(fon2);
710             fon2.addNext(fnop);
711             fcb.addFalseNext(fon1);
712             fon1.addNext(fnop);
713             return new NodePair(left.getBegin(), fnop);
714         } else if (op.getOp()==Operation.ADD&&on.getLeft().getType().isString()) {
715             //We have a string concatenate
716             ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
717             MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat", new TypeDescriptor[] {new TypeDescriptor(stringcd)});
718             FlatCall fc=new FlatCall(concatmd, out_temp, temp_left, new TempDescriptor[] {temp_right});
719             left.getEnd().addNext(right.getBegin());
720             right.getEnd().addNext(fc);
721             return new NodePair(left.getBegin(), fc);
722         }
723
724         FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
725         left.getEnd().addNext(right.getBegin());
726         right.getEnd().addNext(fon);
727         return new NodePair(left.getBegin(),fon);
728     }
729
730     private NodePair flattenExpressionNode(ExpressionNode en, TempDescriptor out_temp) {
731         switch(en.kind()) {
732         case Kind.AssignmentNode:
733             return flattenAssignmentNode((AssignmentNode)en,out_temp);
734         case Kind.CastNode:
735             return flattenCastNode((CastNode)en,out_temp);
736         case Kind.CreateObjectNode:
737             return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
738         case Kind.FieldAccessNode:
739             return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
740         case Kind.ArrayAccessNode:
741             return flattenArrayAccessNode((ArrayAccessNode)en,out_temp);
742         case Kind.LiteralNode:
743             return flattenLiteralNode((LiteralNode)en,out_temp);
744         case Kind.MethodInvokeNode:
745             return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
746         case Kind.NameNode:
747             return flattenNameNode((NameNode)en,out_temp);
748         case Kind.OpNode:
749             return flattenOpNode((OpNode)en,out_temp);
750         }
751         throw new Error();
752     }
753
754     private NodePair flattenDeclarationNode(DeclarationNode dn) {
755         VarDescriptor vd=dn.getVarDescriptor();
756         TempDescriptor td=getTempforVar(vd);
757         if (dn.getExpression()!=null)
758             return flattenExpressionNode(dn.getExpression(),td);
759         else {
760             FlatNop fn=new FlatNop();
761             return new NodePair(fn,fn);
762         }
763     }
764
765     private NodePair flattenTagDeclarationNode(TagDeclarationNode dn) {
766         TagVarDescriptor tvd=dn.getTagVarDescriptor();
767         TagDescriptor tag=tvd.getTag();
768         TempDescriptor tmp=getTempforVar(tvd);
769         FlatTagDeclaration ftd=new FlatTagDeclaration(tag, tmp);
770         return new NodePair(ftd,ftd);
771     }
772
773     private TempDescriptor getTempforParam(Descriptor d) {
774         if (temptovar.containsKey(d))
775             return (TempDescriptor)temptovar.get(d);
776         else {
777             if (d instanceof VarDescriptor) {
778                 VarDescriptor vd=(VarDescriptor)d;
779                 TempDescriptor td=TempDescriptor.paramtempFactory(vd.getName(),vd.getType());
780                 temptovar.put(vd,td);
781                 return td;
782             } else if (d instanceof TagVarDescriptor) {
783                 TagVarDescriptor tvd=(TagVarDescriptor)d;
784                 TypeDescriptor tagtype=new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass));
785                 TempDescriptor td=TempDescriptor.paramtempFactory(tvd.getName(), tagtype, tvd.getTag());
786                 temptovar.put(tvd,td);
787                 return td;
788             } else throw new Error("Unreconized Descriptor");
789         }
790     }
791     
792     private TempDescriptor getTempforVar(Descriptor d) {
793         if (temptovar.containsKey(d))
794             return (TempDescriptor)temptovar.get(d);
795         else {
796             if (d instanceof VarDescriptor) {
797                 VarDescriptor vd=(VarDescriptor)d;
798                 TempDescriptor td=TempDescriptor.tempFactory(vd.getName(), vd.getType());
799                 temptovar.put(vd,td);
800                 return td;
801             } else if (d instanceof TagVarDescriptor) {
802                 TagVarDescriptor tvd=(TagVarDescriptor)d;
803                 //BUGFIX TAGTYPE - add next line, modify following
804                 //line to tag this new type descriptor, modify
805                 //TempDescriptor constructor & factory to set type
806                 //using this Type To test, use any program with tags
807                 TypeDescriptor tagtype=new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass));
808                 TempDescriptor td=TempDescriptor.tempFactory(tvd.getName(),tagtype, tvd.getTag());
809                 temptovar.put(tvd,td);
810                 return td;
811             } else throw new Error("Unrecognized Descriptor");
812         }
813     }
814
815     private NodePair flattenIfStatementNode(IfStatementNode isn) {
816         TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
817         NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
818         FlatCondBranch fcb=new FlatCondBranch(cond_temp);
819         NodePair true_np=flattenBlockNode(isn.getTrueBlock());
820         NodePair false_np;
821         FlatNop nopend=new FlatNop();
822
823         if (isn.getFalseBlock()!=null)
824             false_np=flattenBlockNode(isn.getFalseBlock());
825         else {
826             FlatNop nop=new FlatNop();
827             false_np=new NodePair(nop,nop);
828         }
829
830         cond.getEnd().addNext(fcb);
831         fcb.addTrueNext(true_np.getBegin());
832         fcb.addFalseNext(false_np.getBegin());
833         true_np.getEnd().addNext(nopend);
834         false_np.getEnd().addNext(nopend);
835         return new NodePair(cond.getBegin(), nopend);
836     }
837             
838     private NodePair flattenLoopNode(LoopNode ln) {
839         if (ln.getType()==LoopNode.FORLOOP) {
840             NodePair initializer=flattenBlockNode(ln.getInitializer());
841             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
842             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
843             NodePair update=flattenBlockNode(ln.getUpdate());
844             NodePair body=flattenBlockNode(ln.getBody());
845             FlatNode begin=initializer.getBegin();
846             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
847             FlatNop nopend=new FlatNop();
848             FlatBackEdge backedge=new FlatBackEdge();
849
850             initializer.getEnd().addNext(condition.getBegin());
851             body.getEnd().addNext(update.getBegin());
852             update.getEnd().addNext(backedge);
853             backedge.addNext(condition.getBegin());
854             condition.getEnd().addNext(fcb);
855             fcb.addFalseNext(nopend);
856             fcb.addTrueNext(body.getBegin());
857             return new NodePair(begin,nopend);
858         } else if (ln.getType()==LoopNode.WHILELOOP) {
859             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
860             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
861             NodePair body=flattenBlockNode(ln.getBody());
862             FlatNode begin=condition.getBegin();
863             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
864             FlatNop nopend=new FlatNop();
865             FlatBackEdge backedge=new FlatBackEdge();
866
867             body.getEnd().addNext(backedge);
868             backedge.addNext(condition.getBegin());
869
870             condition.getEnd().addNext(fcb);
871             fcb.addFalseNext(nopend);
872             fcb.addTrueNext(body.getBegin());
873             return new NodePair(begin,nopend);
874         } else if (ln.getType()==LoopNode.DOWHILELOOP) {
875             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
876             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
877             NodePair body=flattenBlockNode(ln.getBody());
878             FlatNode begin=body.getBegin();
879             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
880             FlatNop nopend=new FlatNop();
881             FlatBackEdge backedge=new FlatBackEdge();
882
883             body.getEnd().addNext(condition.getBegin());
884             condition.getEnd().addNext(fcb);
885             fcb.addFalseNext(nopend);
886             fcb.addTrueNext(backedge);
887             backedge.addNext(body.getBegin());
888             return new NodePair(begin,nopend);
889         } else throw new Error();
890     }
891             
892     private NodePair flattenReturnNode(ReturnNode rntree) {
893         TempDescriptor retval=null;
894         NodePair cond=null;
895         if (rntree.getReturnExpression()!=null) {
896             retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
897             cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
898         }
899
900         FlatReturnNode rnflat=new FlatReturnNode(retval);
901         FlatNode ln=rnflat;
902         if (state.THREAD&&currmd.getModifiers().isSynchronized()) {
903             MethodDescriptor memd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
904             TempDescriptor thistd=getTempforVar(currmd.getThis());
905             FlatCall fc=new FlatCall(memd, null, thistd, new TempDescriptor[0]);
906             fc.addNext(ln);
907             ln=fc;
908         }
909         if (state.DSM&&currmd.getModifiers().isAtomic()) {
910             FlatAtomicExitNode faen=new FlatAtomicExitNode(curran);
911             faen.addNext(ln);
912             ln=faen;
913         }
914
915         if (cond!=null) {
916             cond.getEnd().addNext(ln);
917             return new NodePair(cond.getBegin(),rnflat);
918         } else
919             return new NodePair(ln,rnflat);
920     }
921
922     private NodePair flattenTaskExitNode(TaskExitNode ten) {
923         FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.TASKEXIT);
924         updateFlagActionNode(ffan, ten.getFlagEffects());
925         NodePair fcn=flattenConstraintCheck(ten.getChecks());
926         ffan.addNext(fcn.getBegin());
927         FlatReturnNode rnflat=new FlatReturnNode(null);
928         fcn.getEnd().addNext(rnflat);
929         return new NodePair(ffan, rnflat);
930     }
931
932     private NodePair flattenConstraintCheck(Vector ccs) {
933         FlatNode begin=new FlatNop();
934         if (ccs==null)
935             return new NodePair(begin,begin);
936         FlatNode last=begin;
937         for(int i=0;i<ccs.size();i++) {
938             ConstraintCheck cc=(ConstraintCheck) ccs.get(i);
939             /* Flatten the arguments */
940             TempDescriptor[] temps=new TempDescriptor[cc.numArgs()];
941             String[] vars=new String[cc.numArgs()];
942             for(int j=0;j<cc.numArgs();j++) {
943                 ExpressionNode en=cc.getArg(j);
944                 TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
945                 temps[j]=td;
946                 vars[j]=cc.getVar(j);
947                 NodePair np=flattenExpressionNode(en, td);
948                 last.addNext(np.getBegin());
949                 last=np.getEnd();
950             }
951             
952             FlatCheckNode fcn=new FlatCheckNode(cc.getSpec(), vars, temps);
953             last.addNext(fcn);
954             last=fcn;
955         }
956         return new NodePair(begin,last);
957     }
958
959     private NodePair flattenSubBlockNode(SubBlockNode sbn) {
960         return flattenBlockNode(sbn.getBlockNode());
961     }
962
963     private NodePair flattenAtomicNode(AtomicNode sbn) {
964         NodePair np=flattenBlockNode(sbn.getBlockNode());
965         FlatAtomicEnterNode faen=new FlatAtomicEnterNode();
966         FlatAtomicExitNode faexn=new FlatAtomicExitNode(faen);
967         faen.addNext(np.getBegin());
968         np.getEnd().addNext(faexn);
969         return new NodePair(faen, faexn);
970     }
971
972     private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
973         switch(bsn.kind()) {
974         case Kind.BlockExpressionNode:
975             return flattenBlockExpressionNode((BlockExpressionNode)bsn);
976             
977         case Kind.DeclarationNode:
978             return flattenDeclarationNode((DeclarationNode)bsn);
979
980         case Kind.TagDeclarationNode:
981             return flattenTagDeclarationNode((TagDeclarationNode)bsn);
982             
983         case Kind.IfStatementNode:
984             return flattenIfStatementNode((IfStatementNode)bsn);
985             
986         case Kind.LoopNode:
987             return flattenLoopNode((LoopNode)bsn);
988             
989         case Kind.ReturnNode:
990             return flattenReturnNode((IR.Tree.ReturnNode)bsn);
991
992         case Kind.TaskExitNode:
993             return flattenTaskExitNode((IR.Tree.TaskExitNode)bsn);
994             
995         case Kind.SubBlockNode:
996             return flattenSubBlockNode((SubBlockNode)bsn);
997
998         case Kind.AtomicNode:
999             return flattenAtomicNode((AtomicNode)bsn);
1000             
1001         }
1002         throw new Error();
1003     }
1004 }