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