changes
[IRC.git] / Robust / src / IR / Flat / BuildFlat.java
index 7cead58fdeaa9dc588c6fc2a49d4f976b6e37d01..088e9c2e0239d639ddfcbc4c9ac8aba0aaf2510d 100644 (file)
@@ -6,10 +6,13 @@ import java.util.*;
 public class BuildFlat {
     State state;
     Hashtable temptovar;
+    MethodDescriptor currmd;
+    TypeUtil typeutil;
 
-    public BuildFlat(State st) {
+    public BuildFlat(State st, TypeUtil typeutil) {
        state=st;
        temptovar=new Hashtable();
+       this.typeutil=typeutil;
     }
 
     public Hashtable getMap() {
@@ -33,12 +36,17 @@ public class BuildFlat {
     private void flattenTask(TaskDescriptor td) {
        BlockNode bn=state.getMethodBody(td);
        FlatNode fn=flattenBlockNode(bn).getBegin();
-       FlatFlagActionNode ffan=new FlatFlagActionNode();
+       FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.PRE);
        ffan.addNext(fn);
+
        FlatMethod fm=new FlatMethod(td, ffan);
 
        for(int i=0;i<td.numParameters();i++) {
-           fm.addParameterTemp(getTempforVar(td.getParameter(i)));
+           VarDescriptor paramvd=td.getParameter(i);
+           fm.addParameterTemp(getTempforVar(paramvd));
+           //Don't need to get temps for tag variables
+           //If they are used, this will be done automatically
+           //If they aren't we won't pass them in
        }
 
        /* Flatten Vector of Flag Effects */
@@ -51,30 +59,54 @@ public class BuildFlat {
 
     /* This method transforms a vector of FlagEffects into the FlatFlagActionNode */
     private void updateFlagActionNode(FlatFlagActionNode ffan, Vector flags) {
+       if (flags==null) // Do nothing if the flag effects vector is empty
+           return;
+
        for(int i=0;i<flags.size();i++) {
            FlagEffects fes=(FlagEffects)flags.get(i);
            TempDescriptor flagtemp=getTempforVar(fes.getVar());
+           // Process the flags
            for(int j=0;j<fes.numEffects();j++) {
                FlagEffect fe=fes.getEffect(j);
                ffan.addFlagAction(flagtemp, fe.getFlag(), fe.getStatus());
            }
+           // Process the tags
+           for(int j=0;j<fes.numTagEffects();j++) {
+               TagEffect te=fes.getTagEffect(j);
+               TempDescriptor tagtemp=getTempforVar(te.getTag());
+               
+               ffan.addTagAction(flagtemp, te.getTag().getTag(), tagtemp, te.getStatus());
+           }
        }
     }
 
     private void flattenClass(ClassDescriptor cn) {
        Iterator methodit=cn.getMethods();
        while(methodit.hasNext()) {
-           MethodDescriptor md=(MethodDescriptor)methodit.next();
-           BlockNode bn=state.getMethodBody(md);
-           FlatNode fn=flattenBlockNode(bn).getBegin();
-           FlatMethod fm=new FlatMethod(md, fn);
-           if (!md.isStatic())
-               fm.addParameterTemp(getTempforVar(md.getThis()));
-           for(int i=0;i<md.numParameters();i++) {
-               fm.addParameterTemp(getTempforVar(md.getParameter(i)));
+           currmd=(MethodDescriptor)methodit.next();
+           BlockNode bn=state.getMethodBody(currmd);
+           NodePair np=flattenBlockNode(bn);
+           FlatNode fn=np.getBegin();
+           if (state.THREAD&&currmd.getModifiers().isSynchronized()) {
+               MethodDescriptor memd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorEnter");
+               TempDescriptor thistd=getTempforVar(currmd.getThis());
+               FlatCall fc=new FlatCall(memd, null, thistd, new TempDescriptor[0]);
+               fc.addNext(fn);
+               fn=fc;
+               if (np.getEnd().kind()!=FKind.FlatReturnNode) {
+                   MethodDescriptor memdex=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
+                   FlatCall fcunlock=new FlatCall(memdex, null, thistd, new TempDescriptor[0]);
+                   np.getEnd().addNext(fcunlock);
+               }
+           }
+
+           FlatMethod fm=new FlatMethod(currmd, fn);
+           if (!currmd.isStatic())
+               fm.addParameterTemp(getTempforParam(currmd.getThis()));
+           for(int i=0;i<currmd.numParameters();i++) {
+               fm.addParameterTemp(getTempforParam(currmd.getParameter(i)));
            }
-           System.out.println(fm.printMethod());
-           state.addFlatCode(md,fm);
+           state.addFlatCode(currmd,fm);
        }
     }
 
@@ -125,6 +157,28 @@ public class BuildFlat {
            FlatNew fn=new FlatNew(td, out_temp);
            TempDescriptor[] temps=new TempDescriptor[con.numArgs()];
            FlatNode last=fn;
+           if (td.getClassDesc().hasFlags()) {
+               //          if (con.getFlagEffects()!=null) {
+               FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.NEWOBJECT);
+               FlagEffects fes=con.getFlagEffects();
+               TempDescriptor flagtemp=out_temp;
+               if (fes!=null) {
+                   for(int j=0;j<fes.numEffects();j++) {
+                       FlagEffect fe=fes.getEffect(j);
+                       ffan.addFlagAction(flagtemp, fe.getFlag(), fe.getStatus());
+                   } 
+                   for(int j=0;j<fes.numTagEffects();j++) {
+                       TagEffect te=fes.getTagEffect(j);
+                       TempDescriptor tagtemp=getTempforVar(te.getTag());
+               
+                       ffan.addTagAction(flagtemp, te.getTag().getTag(), tagtemp, te.getStatus());
+                   }
+               } else {
+                   ffan.addFlagAction(flagtemp, null, false);
+               }
+               last.addNext(ffan);
+               last=ffan;
+           }
            //Build arguments
            for(int i=0;i<con.numArgs();i++) {
                ExpressionNode en=con.getArg(i);
@@ -138,7 +192,8 @@ public class BuildFlat {
            //Call to constructor
            FlatCall fc=new FlatCall(md, null, out_temp, temps);
            last.addNext(fc);
-           return new NodePair(fn,fc); 
+           last=fc;
+           return new NodePair(fn,last); 
        } else {
            FlatNode first=null;
            FlatNode last=null;
@@ -270,35 +325,74 @@ public class BuildFlat {
     }
 
     private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) {
-       // Two cases:
+       // Three cases:
        // left side is variable
        // left side is field
+       // left side is array
        
        Operation base=an.getOperation().getBaseOp();
-       TempDescriptor src_tmp=TempDescriptor.tempFactory("src",an.getSrc().getType());
-       NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
-       FlatNode last=np_src.getEnd();
-       if (base!=null) {
-           TempDescriptor src_tmp2=TempDescriptor.tempFactory("tmp", an.getDest().getType());
-           NodePair np_dst_init=flattenExpressionNode(an.getDest(),src_tmp2);
-           last.addNext(np_dst_init.getBegin());
-           TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst_tmp",an.getDest().getType());
-           FlatOpNode fon=new FlatOpNode(dst_tmp, src_tmp,src_tmp2, base);
-           np_dst_init.getEnd().addNext(fon);
-           last=fon;
-           src_tmp=dst_tmp;
+       boolean pre=base==null||(base.getOp()!=Operation.POSTINC&&base.getOp()!=Operation.POSTDEC);
+       
+       if (!pre) {
+           //rewrite the base operation
+           base=base.getOp()==Operation.POSTINC?new Operation(Operation.ADD):new Operation(Operation.SUB);
+       }
+       FlatNode first=null;
+       FlatNode last=null;
+       TempDescriptor src_tmp=an.getSrc()==null?TempDescriptor.tempFactory("srctmp",an.getDest().getType()):TempDescriptor.tempFactory("srctmp",an.getSrc().getType());
+
+       //Get src value
+       if (an.getSrc()!=null) {
+           NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp);
+           first=np_src.getBegin();
+           last=np_src.getEnd();
+       } else if (!pre) {
+           FlatLiteralNode fln=new FlatLiteralNode(new TypeDescriptor(TypeDescriptor.INT) ,new Integer(1),src_tmp);
+           first=fln;
+           last=fln;
        }
        
        if (an.getDest().kind()==Kind.FieldAccessNode) {
+           //We are assigning an object field
+
            FieldAccessNode fan=(FieldAccessNode)an.getDest();
            ExpressionNode en=fan.getExpression();
            TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
            NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
-           last.addNext(np_baseexp.getBegin());
+           if (first==null)
+               first=np_baseexp.getBegin();
+           else
+               last.addNext(np_baseexp.getBegin());
+           last=np_baseexp.getEnd();
+
+           //See if we need to perform an operation
+           if (base!=null) {
+               //If it is a preinc we need to store the initial value
+               TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
+               TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
+
+               FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
+               last.addNext(ffn);
+               last=ffn;
+               FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
+               src_tmp=tmp;
+               last.addNext(fon);
+               last=fon;
+           }
+
            FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
-           np_baseexp.getEnd().addNext(fsfn);
-           return new NodePair(np_src.getBegin(), fsfn);
+           last.addNext(fsfn);
+           last=fsfn;
+           if (pre) {
+               FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
+               fsfn.addNext(fon2);
+               last=fon2;
+           }
+           return new NodePair(first, last);
        } else if (an.getDest().kind()==Kind.ArrayAccessNode) {
+           //We are assigning an array element
+
+
            ArrayAccessNode aan=(ArrayAccessNode)an.getDest();
            ExpressionNode en=aan.getExpression();
            ExpressionNode enindex=aan.getIndex();
@@ -306,31 +400,150 @@ public class BuildFlat {
            TempDescriptor index_tmp=TempDescriptor.tempFactory("index",enindex.getType());
            NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
            NodePair np_indexexp=flattenExpressionNode(enindex, index_tmp);
-           last.addNext(np_baseexp.getBegin());
+           if (first==null)
+               first=np_baseexp.getBegin();
+           else
+               last.addNext(np_baseexp.getBegin());
            np_baseexp.getEnd().addNext(np_indexexp.getBegin());
+           last=np_indexexp.getEnd();
+
+           //See if we need to perform an operation
+           if (base!=null) {
+               //If it is a preinc we need to store the initial value
+               TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
+               TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
+
+               FlatElementNode fen=new FlatElementNode(dst_tmp, index_tmp, src_tmp2);
+               last.addNext(fen);
+               last=fen;
+               FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
+               src_tmp=tmp;
+               last.addNext(fon);
+               last=fon;
+           }
+
+
            FlatSetElementNode fsen=new FlatSetElementNode(dst_tmp, index_tmp, src_tmp);
-           np_indexexp.getEnd().addNext(fsen);
-           return new NodePair(np_src.getBegin(), fsen);
+           last.addNext(fsen);
+           last=fsen;
+           if (pre) {
+               FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
+               fsen.addNext(fon2);
+               last=fon2;
+           }
+           return new NodePair(first, last);
        } else if (an.getDest().kind()==Kind.NameNode) {
+           //We could be assigning a field or variable
            NameNode nn=(NameNode)an.getDest();
            if (nn.getExpression()!=null) {
+               //It is a field
                FieldAccessNode fan=(FieldAccessNode)nn.getExpression();
                ExpressionNode en=fan.getExpression();
                TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst",en.getType());
                NodePair np_baseexp=flattenExpressionNode(en, dst_tmp);
-               last.addNext(np_baseexp.getBegin());
+               if (first==null)
+                   first=np_baseexp.getBegin();
+               else
+                   last.addNext(np_baseexp.getBegin());
+               last=np_baseexp.getEnd();
+
+               //See if we need to perform an operation
+               if (base!=null) {
+                   //If it is a preinc we need to store the initial value
+                   TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
+                   TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
+                   
+                   FlatFieldNode ffn=new FlatFieldNode(fan.getField(), dst_tmp, src_tmp2);
+                   last.addNext(ffn);
+                   last=ffn;
+                   FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
+                   src_tmp=tmp;
+                   last.addNext(fon);
+                   last=fon;
+               }
+
+
                FlatSetFieldNode fsfn=new FlatSetFieldNode(dst_tmp, fan.getField(), src_tmp);
-               np_baseexp.getEnd().addNext(fsfn);
-               return new NodePair(np_src.getBegin(), fsfn);
+               last.addNext(fsfn);
+               last=fsfn;
+               if (pre) {
+                   FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
+                   fsfn.addNext(fon2);
+                   last=fon2;
+               }
+               return new NodePair(first, last);
            } else {
                if (nn.getField()!=null) {
+                   //It is a field
+                   //Get src value
+
+                   //See if we need to perform an operation
+                   if (base!=null) {
+                       //If it is a preinc we need to store the initial value
+                       TempDescriptor src_tmp2=pre?TempDescriptor.tempFactory("src",an.getDest().getType()):out_temp;
+                       TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
+                       
+                       FlatFieldNode ffn=new FlatFieldNode(nn.getField(), getTempforVar(nn.getVar()), src_tmp2);
+                       if (first==null)
+                           first=ffn;
+                       else {
+                           last.addNext(ffn);
+                       }
+                       last=ffn;
+                       FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
+                       src_tmp=tmp;
+                       last.addNext(fon);
+                       last=fon;
+                   }               
+
                    FlatSetFieldNode fsfn=new FlatSetFieldNode(getTempforVar(nn.getVar()), nn.getField(), src_tmp);
-                   last.addNext(fsfn);
-                   return new NodePair(np_src.getBegin(), fsfn);
+                   if (first==null) {
+                       first=fsfn;
+                   } else {
+                       last.addNext(fsfn);
+                   }
+                   last=fsfn;
+                   if (pre) {
+                       FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
+                       fsfn.addNext(fon2);
+                       last=fon2;
+                   }
+                   return new NodePair(first, last);
                } else {
+                   //It is a variable
+                   //See if we need to perform an operation
+
+                   if (base!=null) {
+                       //If it is a preinc we need to store the initial value
+                       TempDescriptor src_tmp2=getTempforVar(nn.getVar());
+                       TempDescriptor tmp=TempDescriptor.tempFactory("srctmp3",an.getDest().getType());
+                       if (!pre) {
+                           FlatOpNode fon=new FlatOpNode(out_temp, src_tmp2, null, new Operation(Operation.ASSIGN));
+                           if (first==null)
+                               first=fon;
+                           else
+                               last.addNext(fon);
+                           last=fon;
+                       }
+
+                       FlatOpNode fon=new FlatOpNode(tmp, src_tmp2, src_tmp, base);
+                       if (first==null) 
+                           first=fon;
+                       else 
+                           last.addNext(fon);
+                       src_tmp=tmp;
+                       last=fon;
+                   }
+
                    FlatOpNode fon=new FlatOpNode(getTempforVar(nn.getVar()), src_tmp, null, new Operation(Operation.ASSIGN));
                    last.addNext(fon);
-                   return new NodePair(np_src.getBegin(),fon);
+                   last=fon;
+                   if (pre) {
+                       FlatOpNode fon2=new FlatOpNode(out_temp, src_tmp, null, new Operation(Operation.ASSIGN));
+                       fon.addNext(fon2);
+                       last=fon2;
+                   }
+                   return new NodePair(first, last);
                }
            }
        } 
@@ -357,16 +570,22 @@ public class BuildFlat {
        TempDescriptor temp_right=null;
 
        Operation op=on.getOp();
+       /* We've moved this to assignment nodes
+
        if (op.getOp()==Operation.POSTINC||
            op.getOp()==Operation.POSTDEC||
            op.getOp()==Operation.PREINC||
            op.getOp()==Operation.PREDEC) {
            LiteralNode ln=new LiteralNode("int",new Integer(1));
            ln.setType(new TypeDescriptor(TypeDescriptor.INT));
-           AssignmentNode an=new AssignmentNode(on.getLeft(),ln,
-                              new AssignOperation((op.getOp()==Operation.POSTINC||op.getOp()==Operation.PREINC)?AssignOperation.PLUSEQ:AssignOperation.MINUSEQ));
+           
+           AssignmentNode an=new AssignmentNode(on.getLeft(),
+                                                new OpNode(on.getLeft(),ln, 
+                                                           new Operation((op.getOp()==Operation.POSTINC||op.getOp()==Operation.PREINC)?Operation.PLUS:Operation.MINUS))
+                                                );
            if (op.getOp()==Operation.POSTINC||
                op.getOp()==Operation.POSTDEC) {
+               //Can't do, this could have side effects
                NodePair left=flattenExpressionNode(on.getLeft(),out_temp);
                NodePair assign=flattenAssignmentNode(an,temp_left);
                left.getEnd().addNext(assign.getBegin());
@@ -375,7 +594,7 @@ public class BuildFlat {
                NodePair assign=flattenAssignmentNode(an,out_temp);
                return assign;
            }
-       } 
+           } */
        
        NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
        NodePair right;
@@ -455,14 +674,48 @@ public class BuildFlat {
            return new NodePair(fn,fn);
        }
     }
-        
-    private TempDescriptor getTempforVar(VarDescriptor vd) {
-       if (temptovar.containsKey(vd))
-           return (TempDescriptor)temptovar.get(vd);
+
+    private NodePair flattenTagDeclarationNode(TagDeclarationNode dn) {
+       TagVarDescriptor tvd=dn.getTagVarDescriptor();
+       TagDescriptor tag=tvd.getTag();
+       TempDescriptor tmp=getTempforVar(tvd);
+       FlatTagDeclaration ftd=new FlatTagDeclaration(tag, tmp);
+       return new NodePair(ftd,ftd);
+    }
+
+    private TempDescriptor getTempforParam(Descriptor d) {
+       if (temptovar.containsKey(d))
+           return (TempDescriptor)temptovar.get(d);
+       else {
+           if (d instanceof VarDescriptor) {
+               VarDescriptor vd=(VarDescriptor)d;
+               TempDescriptor td=TempDescriptor.paramtempFactory(vd.getName(),vd.getType());
+               temptovar.put(vd,td);
+               return td;
+           } else if (d instanceof TagVarDescriptor) {
+               TagVarDescriptor tvd=(TagVarDescriptor)d;
+               TempDescriptor td=TempDescriptor.paramtempFactory(tvd.getName(),tvd.getTag());
+               temptovar.put(tvd,td);
+               return td;
+           } else throw new Error("Unreconized Descriptor");
+       }
+    }
+    
+    private TempDescriptor getTempforVar(Descriptor d) {
+       if (temptovar.containsKey(d))
+           return (TempDescriptor)temptovar.get(d);
        else {
-           TempDescriptor td=TempDescriptor.tempFactory(vd.getName(),vd.getType());
-           temptovar.put(vd,td);
-           return td;
+           if (d instanceof VarDescriptor) {
+               VarDescriptor vd=(VarDescriptor)d;
+               TempDescriptor td=TempDescriptor.tempFactory(vd.getName(),vd.getType());
+               temptovar.put(vd,td);
+               return td;
+           } else if (d instanceof TagVarDescriptor) {
+               TagVarDescriptor tvd=(TagVarDescriptor)d;
+               TempDescriptor td=TempDescriptor.tempFactory(tvd.getName(),tvd.getTag());
+               temptovar.put(tvd,td);
+               return td;
+           } else throw new Error("Unrecognized Descriptor");
        }
     }
 
@@ -499,10 +752,12 @@ public class BuildFlat {
            FlatNode begin=initializer.getBegin();
            FlatCondBranch fcb=new FlatCondBranch(cond_temp);
            FlatNop nopend=new FlatNop();
+           FlatBackEdge backedge=new FlatBackEdge();
 
            initializer.getEnd().addNext(condition.getBegin());
            body.getEnd().addNext(update.getBegin());
-           update.getEnd().addNext(condition.getBegin());
+           update.getEnd().addNext(backedge);
+           backedge.addNext(condition.getBegin());
            condition.getEnd().addNext(fcb);
            fcb.addFalseNext(nopend);
            fcb.addTrueNext(body.getBegin());
@@ -514,8 +769,11 @@ public class BuildFlat {
            FlatNode begin=condition.getBegin();
            FlatCondBranch fcb=new FlatCondBranch(cond_temp);
            FlatNop nopend=new FlatNop();
+           FlatBackEdge backedge=new FlatBackEdge();
+
+           body.getEnd().addNext(backedge);
+           backedge.addNext(condition.getBegin());
 
-           body.getEnd().addNext(condition.getBegin());
            condition.getEnd().addNext(fcb);
            fcb.addFalseNext(nopend);
            fcb.addTrueNext(body.getBegin());
@@ -527,11 +785,13 @@ public class BuildFlat {
            FlatNode begin=body.getBegin();
            FlatCondBranch fcb=new FlatCondBranch(cond_temp);
            FlatNop nopend=new FlatNop();
+           FlatBackEdge backedge=new FlatBackEdge();
 
            body.getEnd().addNext(condition.getBegin());
            condition.getEnd().addNext(fcb);
            fcb.addFalseNext(nopend);
-           fcb.addTrueNext(body.getBegin());
+           fcb.addTrueNext(backedge);
+           backedge.addNext(body.getBegin());
            return new NodePair(begin,nopend);
        } else throw new Error();
     }
@@ -545,19 +805,59 @@ public class BuildFlat {
        }
 
        FlatReturnNode rnflat=new FlatReturnNode(retval);
+       FlatNode ln=rnflat;
+       if (state.THREAD&&currmd.getModifiers().isSynchronized()) {
+           MethodDescriptor memd=(MethodDescriptor)typeutil.getClass("Object").getMethodTable().get("MonitorExit");
+           TempDescriptor thistd=getTempforVar(currmd.getThis());
+           FlatCall fc=new FlatCall(memd, null, thistd, new TempDescriptor[0]);
+           fc.addNext(rnflat);
+           ln=fc;
+       }
 
        if (cond!=null) {
-           cond.getEnd().addNext(rnflat);
+           cond.getEnd().addNext(ln);
            return new NodePair(cond.getBegin(),rnflat);
        } else
-           return new NodePair(rnflat,rnflat);
+           return new NodePair(ln,rnflat);
     }
 
     private NodePair flattenTaskExitNode(TaskExitNode ten) {
-       FlatTaskExitNode tenflat=new FlatTaskExitNode();
-       return new NodePair(tenflat,tenflat);
+       FlatFlagActionNode ffan=new FlatFlagActionNode(FlatFlagActionNode.TASKEXIT);
+       updateFlagActionNode(ffan, ten.getFlagEffects());
+       NodePair fcn=flattenConstraintCheck(ten.getChecks());
+       ffan.addNext(fcn.getBegin());
+       FlatReturnNode rnflat=new FlatReturnNode(null);
+       fcn.getEnd().addNext(rnflat);
+       return new NodePair(ffan, rnflat);
     }
+
+    private NodePair flattenConstraintCheck(Vector ccs) {
+       FlatNode begin=new FlatNop();
+       if (ccs==null)
+           return new NodePair(begin,begin);
+       FlatNode last=begin;
+       for(int i=0;i<ccs.size();i++) {
+           ConstraintCheck cc=(ConstraintCheck) ccs.get(i);
+           /* Flatten the arguments */
+           TempDescriptor[] temps=new TempDescriptor[cc.numArgs()];
+           String[] vars=new String[cc.numArgs()];
+           for(int j=0;j<cc.numArgs();j++) {
+               ExpressionNode en=cc.getArg(j);
+               TempDescriptor td=TempDescriptor.tempFactory("arg",en.getType());
+               temps[j]=td;
+               vars[j]=cc.getVar(j);
+               NodePair np=flattenExpressionNode(en, td);
+               last.addNext(np.getBegin());
+               last=np.getEnd();
+           }
            
+           FlatCheckNode fcn=new FlatCheckNode(cc.getSpec(), vars, temps);
+           last.addNext(fcn);
+           last=fcn;
+       }
+       return new NodePair(begin,last);
+    }
+
     private NodePair flattenSubBlockNode(SubBlockNode sbn) {
        return flattenBlockNode(sbn.getBlockNode());
     }
@@ -569,6 +869,9 @@ public class BuildFlat {
            
        case Kind.DeclarationNode:
            return flattenDeclarationNode((DeclarationNode)bsn);
+
+       case Kind.TagDeclarationNode:
+           return flattenTagDeclarationNode((TagDeclarationNode)bsn);
            
        case Kind.IfStatementNode:
            return flattenIfStatementNode((IfStatementNode)bsn);