start of new file
[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     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         case Kind.CastNode:
737             return flattenCastNode((CastNode)en,out_temp);
738         case Kind.CreateObjectNode:
739             return flattenCreateObjectNode((CreateObjectNode)en,out_temp);
740         case Kind.FieldAccessNode:
741             return flattenFieldAccessNode((FieldAccessNode)en,out_temp);
742         case Kind.ArrayAccessNode:
743             return flattenArrayAccessNode((ArrayAccessNode)en,out_temp);
744         case Kind.LiteralNode:
745             return flattenLiteralNode((LiteralNode)en,out_temp);
746         case Kind.MethodInvokeNode:
747             return flattenMethodInvokeNode((MethodInvokeNode)en,out_temp);
748         case Kind.NameNode:
749             return flattenNameNode((NameNode)en,out_temp);
750         case Kind.OpNode:
751             return flattenOpNode((OpNode)en,out_temp);
752         }
753         throw new Error();
754     }
755
756     private NodePair flattenDeclarationNode(DeclarationNode dn) {
757         VarDescriptor vd=dn.getVarDescriptor();
758         TempDescriptor td=getTempforVar(vd);
759         if (dn.getExpression()!=null)
760             return flattenExpressionNode(dn.getExpression(),td);
761         else {
762             FlatNop fn=new FlatNop();
763             return new NodePair(fn,fn);
764         }
765     }
766
767     private NodePair flattenTagDeclarationNode(TagDeclarationNode dn) {
768         TagVarDescriptor tvd=dn.getTagVarDescriptor();
769         TagDescriptor tag=tvd.getTag();
770         TempDescriptor tmp=getTempforVar(tvd);
771         FlatTagDeclaration ftd=new FlatTagDeclaration(tag, tmp);
772         return new NodePair(ftd,ftd);
773     }
774
775     private TempDescriptor getTempforParam(Descriptor d) {
776         if (temptovar.containsKey(d))
777             return (TempDescriptor)temptovar.get(d);
778         else {
779             if (d instanceof VarDescriptor) {
780                 VarDescriptor vd=(VarDescriptor)d;
781                 TempDescriptor td=TempDescriptor.paramtempFactory(vd.getName(),vd.getType());
782                 temptovar.put(vd,td);
783                 return td;
784             } else if (d instanceof TagVarDescriptor) {
785                 TagVarDescriptor tvd=(TagVarDescriptor)d;
786                 TypeDescriptor tagtype=new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass));
787                 TempDescriptor td=TempDescriptor.paramtempFactory(tvd.getName(), tagtype, tvd.getTag());
788                 temptovar.put(tvd,td);
789                 return td;
790             } else throw new Error("Unreconized Descriptor");
791         }
792     }
793     
794     private TempDescriptor getTempforVar(Descriptor d) {
795         if (temptovar.containsKey(d))
796             return (TempDescriptor)temptovar.get(d);
797         else {
798             if (d instanceof VarDescriptor) {
799                 VarDescriptor vd=(VarDescriptor)d;
800                 TempDescriptor td=TempDescriptor.tempFactory(vd.getName(), vd.getType());
801                 temptovar.put(vd,td);
802                 return td;
803             } else if (d instanceof TagVarDescriptor) {
804                 TagVarDescriptor tvd=(TagVarDescriptor)d;
805                 //BUGFIX TAGTYPE - add next line, modify following
806                 //line to tag this new type descriptor, modify
807                 //TempDescriptor constructor & factory to set type
808                 //using this Type To test, use any program with tags
809                 TypeDescriptor tagtype=new TypeDescriptor(typeutil.getClass(TypeUtil.TagClass));
810                 TempDescriptor td=TempDescriptor.tempFactory(tvd.getName(),tagtype, tvd.getTag());
811                 temptovar.put(tvd,td);
812                 return td;
813             } else throw new Error("Unrecognized Descriptor");
814         }
815     }
816
817     private NodePair flattenIfStatementNode(IfStatementNode isn) {
818         TempDescriptor cond_temp=TempDescriptor.tempFactory("condition",new TypeDescriptor(TypeDescriptor.BOOLEAN));
819         NodePair cond=flattenExpressionNode(isn.getCondition(),cond_temp);
820         FlatCondBranch fcb=new FlatCondBranch(cond_temp);
821         NodePair true_np=flattenBlockNode(isn.getTrueBlock());
822         NodePair false_np;
823         FlatNop nopend=new FlatNop();
824
825         if (isn.getFalseBlock()!=null)
826             false_np=flattenBlockNode(isn.getFalseBlock());
827         else {
828             FlatNop nop=new FlatNop();
829             false_np=new NodePair(nop,nop);
830         }
831
832         cond.getEnd().addNext(fcb);
833         fcb.addTrueNext(true_np.getBegin());
834         fcb.addFalseNext(false_np.getBegin());
835         true_np.getEnd().addNext(nopend);
836         false_np.getEnd().addNext(nopend);
837         return new NodePair(cond.getBegin(), nopend);
838     }
839             
840     private NodePair flattenLoopNode(LoopNode ln) {
841         if (ln.getType()==LoopNode.FORLOOP) {
842             NodePair initializer=flattenBlockNode(ln.getInitializer());
843             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
844             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
845             NodePair update=flattenBlockNode(ln.getUpdate());
846             NodePair body=flattenBlockNode(ln.getBody());
847             FlatNode begin=initializer.getBegin();
848             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
849             fcb.setTrueProb(State.TRUEPROB);
850             fcb.setLoop();
851             FlatNop nopend=new FlatNop();
852             FlatBackEdge backedge=new FlatBackEdge();
853
854             FlatNop nop2=new FlatNop();
855             initializer.getEnd().addNext(nop2);
856             nop2.addNext(condition.getBegin());
857             body.getEnd().addNext(update.getBegin());
858             update.getEnd().addNext(backedge);
859             backedge.addNext(condition.getBegin());
860             condition.getEnd().addNext(fcb);
861             fcb.addFalseNext(nopend);
862             fcb.addTrueNext(body.getBegin());
863             return new NodePair(begin,nopend);
864         } else if (ln.getType()==LoopNode.WHILELOOP) {
865             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
866             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
867             NodePair body=flattenBlockNode(ln.getBody());
868             FlatNode begin=condition.getBegin();
869             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
870             fcb.setTrueProb(State.TRUEPROB);
871             fcb.setLoop();
872             FlatNop nopend=new FlatNop();
873             FlatBackEdge backedge=new FlatBackEdge();
874
875             body.getEnd().addNext(backedge);
876             backedge.addNext(condition.getBegin());
877
878             condition.getEnd().addNext(fcb);
879             fcb.addFalseNext(nopend);
880             fcb.addTrueNext(body.getBegin());
881             return new NodePair(begin,nopend);
882         } else if (ln.getType()==LoopNode.DOWHILELOOP) {
883             TempDescriptor cond_temp=TempDescriptor.tempFactory("condition", new TypeDescriptor(TypeDescriptor.BOOLEAN));
884             NodePair condition=flattenExpressionNode(ln.getCondition(),cond_temp);
885             NodePair body=flattenBlockNode(ln.getBody());
886             FlatNode begin=body.getBegin();
887             FlatCondBranch fcb=new FlatCondBranch(cond_temp);
888             fcb.setTrueProb(State.TRUEPROB);
889             fcb.setLoop();
890             FlatNop nopend=new FlatNop();
891             FlatBackEdge backedge=new FlatBackEdge();
892
893             body.getEnd().addNext(condition.getBegin());
894             condition.getEnd().addNext(fcb);
895             fcb.addFalseNext(nopend);
896             fcb.addTrueNext(backedge);
897             backedge.addNext(body.getBegin());
898             return new NodePair(begin,nopend);
899         } else throw new Error();
900     }
901             
902     private NodePair flattenReturnNode(ReturnNode rntree) {
903         TempDescriptor retval=null;
904         NodePair cond=null;
905         if (rntree.getReturnExpression()!=null) {
906             retval=TempDescriptor.tempFactory("ret_value", rntree.getReturnExpression().getType());
907             cond=flattenExpressionNode(rntree.getReturnExpression(),retval);
908         }
909
910         FlatReturnNode rnflat=new FlatReturnNode(retval);
911         FlatNode ln=rnflat;
912         if (state.THREAD&&currmd.getModifiers().isSynchronized()) {
913             MethodDescriptor memd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
914             TempDescriptor thistd=getTempforVar(currmd.getThis());
915             FlatCall fc=new FlatCall(memd, null, thistd, new TempDescriptor[0]);
916             fc.addNext(ln);
917             ln=fc;
918         }
919         if (state.DSM&&currmd.getModifiers().isAtomic()) {
920             FlatAtomicExitNode faen=new FlatAtomicExitNode(curran);
921             faen.addNext(ln);
922             ln=faen;
923         }
924
925         if (cond!=null) {
926             cond.getEnd().addNext(ln);
927             return new NodePair(cond.getBegin(),rnflat);
928         } else
929             return new NodePair(ln,rnflat);
930     }
931
932     private NodePair flattenTaskExitNode(TaskExitNode ten) {
933         FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.TASKEXIT);
934         updateFlagActionNode(ffan, ten.getFlagEffects());
935         NodePair fcn=flattenConstraintCheck(ten.getChecks());
936         ffan.addNext(fcn.getBegin());
937         FlatReturnNode rnflat=new FlatReturnNode(null);
938         fcn.getEnd().addNext(rnflat);
939         return new NodePair(ffan, rnflat);
940     }
941
942     private NodePair flattenConstraintCheck(Vector ccs) {
943         FlatNode begin=new FlatNop();
944         if (ccs==null)
945             return new NodePair(begin,begin);
946         FlatNode last=begin;
947         for(int i=0;i<ccs.size();i++) {
948             ConstraintCheck cc=(ConstraintCheck) ccs.get(i);
949             /* Flatten the arguments */
950             TempDescriptor[] temps=new TempDescriptor[cc.numArgs()];
951             String[] vars=new String[cc.numArgs()];
952             for(int j=0;j<cc.numArgs();j++) {
953                 ExpressionNode en=cc.getArg(j);
954                 TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
955                 temps[j]=td;
956                 vars[j]=cc.getVar(j);
957                 NodePair np=flattenExpressionNode(en, td);
958                 last.addNext(np.getBegin());
959                 last=np.getEnd();
960             }
961             
962             FlatCheckNode fcn=new FlatCheckNode(cc.getSpec(), vars, temps);
963             last.addNext(fcn);
964             last=fcn;
965         }
966         return new NodePair(begin,last);
967     }
968
969     private NodePair flattenSubBlockNode(SubBlockNode sbn) {
970         return flattenBlockNode(sbn.getBlockNode());
971     }
972
973     private NodePair flattenAtomicNode(AtomicNode sbn) {
974         NodePair np=flattenBlockNode(sbn.getBlockNode());
975         FlatAtomicEnterNode faen=new FlatAtomicEnterNode();
976         FlatAtomicExitNode faexn=new FlatAtomicExitNode(faen);
977         faen.addNext(np.getBegin());
978         np.getEnd().addNext(faexn);
979         return new NodePair(faen, faexn);
980     }
981
982     private NodePair flattenBlockStatementNode(BlockStatementNode bsn) {
983         switch(bsn.kind()) {
984         case Kind.BlockExpressionNode:
985             return flattenBlockExpressionNode((BlockExpressionNode)bsn);
986             
987         case Kind.DeclarationNode:
988             return flattenDeclarationNode((DeclarationNode)bsn);
989
990         case Kind.TagDeclarationNode:
991             return flattenTagDeclarationNode((TagDeclarationNode)bsn);
992             
993         case Kind.IfStatementNode:
994             return flattenIfStatementNode((IfStatementNode)bsn);
995             
996         case Kind.LoopNode:
997             return flattenLoopNode((LoopNode)bsn);
998             
999         case Kind.ReturnNode:
1000             return flattenReturnNode((IR.Tree.ReturnNode)bsn);
1001
1002         case Kind.TaskExitNode:
1003             return flattenTaskExitNode((IR.Tree.TaskExitNode)bsn);
1004             
1005         case Kind.SubBlockNode:
1006             return flattenSubBlockNode((SubBlockNode)bsn);
1007
1008         case Kind.AtomicNode:
1009             return flattenAtomicNode((AtomicNode)bsn);
1010             
1011         }
1012         throw new Error();
1013     }
1014 }