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