Exemple #1
0
    public static VCExpr Block(Block b, VCExpr N, VCContext ctxt)
      //modifies ctxt.*;
    {
      Contract.Requires(b != null);
      Contract.Requires(N != null);
      Contract.Requires(ctxt != null);
      Contract.Ensures(Contract.Result<VCExpr>() != null);

      VCExpressionGenerator gen = ctxt.Ctxt.ExprGen;
      Contract.Assert(gen != null);
      
      VCExpr res = N;

      for (int i = b.Cmds.Count; --i >= 0; )
      {
        res = Cmd(b, cce.NonNull( b.Cmds[i]), res, ctxt);
      }
      
      int id = b.UniqueId;
      if (ctxt.Label2absy != null) {
        ctxt.Label2absy[id] = b;
      }

      try {
        cce.BeginExpose(ctxt);
        if (ctxt.Label2absy == null) {
          return res;
        }
        else {
          return gen.Implies(gen.LabelPos(cce.NonNull(id.ToString()), VCExpressionGenerator.True), res);
        }
      } finally {
        cce.EndExpose();
      }
    }
Exemple #2
0
    public static List<Block/*!*/>/*!*/ UnrollLoops(Block start, int unrollMaxDepth, bool soundLoopUnrolling) {
      Contract.Requires(start != null);

      Contract.Requires(0 <= unrollMaxDepth);
      Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));
      Dictionary<Block, GraphNode/*!*/> gd = new Dictionary<Block, GraphNode/*!*/>();
      HashSet<Block> beingVisited = new HashSet<Block>();
      GraphNode gStart = GraphNode.ComputeGraphInfo(null, start, gd, beingVisited);

      // Compute SCCs
      StronglyConnectedComponents<GraphNode/*!*/> sccs =
        new StronglyConnectedComponents<GraphNode/*!*/>(gd.Values, Preds, Succs);
      Contract.Assert(sccs != null);
      sccs.Compute();
      Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>> containingSCC = new Dictionary<GraphNode/*!*/, SCC<GraphNode/*!*/>>();
      foreach (SCC<GraphNode/*!*/> scc in sccs) {
        foreach (GraphNode/*!*/ n in scc) {
          Contract.Assert(n != null);
          containingSCC[n] = scc;
        }
      }

      LoopUnroll lu = new LoopUnroll(unrollMaxDepth, soundLoopUnrolling, containingSCC, new List<Block/*!*/>());
      lu.Visit(gStart);
      lu.newBlockSeqGlobal.Reverse();
      return lu.newBlockSeqGlobal;
    }
  void PredicateCmd(Expr p, Expr pDom, List<Block> blocks, Block block, Cmd cmd, out Block nextBlock) {
    var cCmd = cmd as CallCmd;
    if (cCmd != null && !useProcedurePredicates(cCmd.Proc)) {
      if (p == null) {
        block.Cmds.Add(cmd);
        nextBlock = block;
        return;
      }

      var trueBlock = new Block();
      blocks.Add(trueBlock);
      trueBlock.Label = block.Label + ".call.true";
      trueBlock.Cmds.Add(new AssumeCmd(Token.NoToken, p));
      trueBlock.Cmds.Add(cmd);

      var falseBlock = new Block();
      blocks.Add(falseBlock);
      falseBlock.Label = block.Label + ".call.false";
      falseBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Not(p)));

      var contBlock = new Block();
      blocks.Add(contBlock);
      contBlock.Label = block.Label + ".call.cont";

      block.TransferCmd =
        new GotoCmd(Token.NoToken, new List<Block> { trueBlock, falseBlock });
      trueBlock.TransferCmd = falseBlock.TransferCmd =
        new GotoCmd(Token.NoToken, new List<Block> { contBlock });
      nextBlock = contBlock;
    } else {
      PredicateCmd(p, pDom, block.Cmds, cmd);
      nextBlock = block;
    }
  }
Exemple #4
0
        /////////////////////////////////////////////////////////////////////////////////////
        private BasicBlock addBlock(Block b)
        {
//            Console.WriteLine("\t\t\t\tAdding block: {0}",b.Label);
            var current = cfg.addNode(b.Label);

            //            System.Console.Out.WriteLine("Adding block: \"" + basicBlock.LabelName + "\"");

            addStatementsToBasicBlock(current, b.Cmds);
            setControlStatement(current, b.TransferCmd, null);
            Debug.Assert(current.getControlStatement() != null);
            return(current);
        }
Exemple #5
0
        /////////////////////////////////////////////////////////////////////////////////////
        IList <Block> topoSort(IEnumerable <Block> blocks, Block initial)
        {
            var result            = new List <Block>();
            var blockPredsMissing = new Dictionary <string, int>();

            foreach (var b in blocks)
            {
                blockPredsMissing[b.Label] = 0;
            }
            foreach (var b in blocks)
            {
                if (b.TransferCmd is GotoCmd)
                {
                    foreach (var sb in (b.TransferCmd as GotoCmd).labelTargets)
                    {
                        blockPredsMissing[sb.Label]++;
                    }
                }
            }

            var todo = new Queue <Block>();
            var done = new HashSet <string>();

            todo.Enqueue(initial);
            while (todo.Count > 0)
            {
                var b = todo.Dequeue();
                Debug.Assert(!done.Contains(b.Label));
                result.Add(b);
                var gotoCmd = b.TransferCmd as GotoCmd;
                if (gotoCmd != null)
                {
                    foreach (var sb in gotoCmd.labelTargets)
                    {
                        Debug.Assert(!done.Contains(sb.Label));
                        Debug.Assert(!todo.Contains(sb));
                        blockPredsMissing[sb.Label]--;
                        Debug.Assert(blockPredsMissing[sb.Label] >= 0);
                        if (blockPredsMissing[sb.Label] == 0)
                        {
                            blockPredsMissing.Remove(sb.Label);
                            todo.Enqueue(sb);
                        }
                    }
                }
                done.Add(b.Label);
            }
            return(result);
        }
Exemple #6
0
    static void Visit(Block b) {
      Contract.Requires(b != null);
      Contract.Assume(cce.IsExposable(b));
      if (b.TraversingStatus == Block.VisitState.BeingVisited) {
        cce.BeginExpose(b);
        // we got here through a back-edge
        b.widenBlock = true;
        cce.EndExpose();
      } else if (b.TraversingStatus == Block.VisitState.AlreadyVisited) {
        // do nothing... we already saw this node
      } else if (b.TransferCmd is GotoCmd) {
        Contract.Assert(b.TraversingStatus == Block.VisitState.ToVisit);

        GotoCmd g = (GotoCmd)b.TransferCmd;
        cce.BeginExpose(b);

        cce.BeginExpose(g);   //PM: required for the subsequent expose (g.labelTargets)
        b.TraversingStatus = Block.VisitState.BeingVisited;

        // labelTargets is made non-null by Resolve, which we assume
        // has already called in a prior pass.
        Contract.Assume(g.labelTargets != null);
        cce.BeginExpose(g.labelTargets);
        foreach (Block succ in g.labelTargets)
        //              invariant b.currentlyTraversed;
        //PM: The following loop invariant will work once properties are axiomatized
        //&& (g.labelNames != null && g.labelTargets != null ==> g.labelNames.Length == g.labelTargets.Length);
              {
          Contract.Assert(succ != null);
          Visit(succ);
        }
        cce.EndExpose();

        Contract.Assert(b.TraversingStatus == Block.VisitState.BeingVisited);
        //            System.Diagnostics.Debug.Assert(b.currentlyTraversed);

        b.TraversingStatus = Block.VisitState.AlreadyVisited;

        //PM: The folowing assumption is needed because we cannot prove that a simple field update
        //PM: leaves the value of a property unchanged.
        Contract.Assume(g.labelNames == null || g.labelNames.Count == g.labelTargets.Count);
        cce.EndExpose();
      } else {
        Contract.Assert(b.TransferCmd == null || b.TransferCmd is ReturnCmd);        // It must be a returnCmd;
      }
    }
Exemple #7
0
        /// <summary>
        /// Compute the blocks in the body loop. 
        /// <param name ="block"> Tt is the head of the loop. It must be a widen block </param>
        /// <return> The blocks that are in the loop from block </return>
        /// </summary>
        public static List<Block> ComputeLoopBodyFrom(Block block)
        {
            Contract.Requires(block.widenBlock);
              Contract.Requires(block != null);
              Contract.Ensures(cce.NonNullElements(Contract.Result<List<Block>>()));

              Contract.Assert(rootBlock == null);
              rootBlock = block;

              List<Block/*!*/> blocksInLoop = new List<Block/*!*/>();         // We use a list just because .net does not define a set
              List<Block/*!*/> visitingPath = new List<Block/*!*/>();         // The order is important, as we want paths

              blocksInLoop.Add(block);

              DoDFSVisit(block, visitingPath, blocksInLoop);

              visitingPath.Add(block);

              rootBlock = null;   // We reset the invariant

              return blocksInLoop;
        }
        // There is no default constructor, because these parameters are needed for most subclasses
        public DoomDetectionStrategy(Implementation imp, Block unifiedexit, List<Block> unreach) 
        {
            m_BlockH = new BlockHierachy(imp, unifiedexit);
            __DEBUG_EQCLeaf = m_BlockH.Leaves.Count;
            
            //foreach (BlockHierachyNode bhn in m_BlockH.Leaves)
            //{
            //    if (bhn.Content.Count > 0) __DEBUG_minelements.Add(bhn.Content[0]);
            //}
            //if (imp.Blocks.Count>0) m_GatherInfo(imp.Blocks[0], 0, 0,0);


            if (__DEBUGOUT)
            {
                Console.WriteLine("MaBranchingDepth {0}  MaxMinPP {1} ", m_MaxBranchingDepth, m_MaxK);

                Console.WriteLine("AvgLeaverPerPath {0} AvgPLen {1}", 0, 0);
            }

            MaxBlocks = imp.Blocks.Count;
            MinBlocks = imp.Blocks.Count;
            HACK_NewCheck = false;
            __DEBUG_BlocksTotal = imp.Blocks.Count;
        }
Exemple #9
0
        private void CreateYieldCheckerImpl(Implementation impl, List<List<Cmd>> yields)
        {
            if (yields.Count == 0) return;

            Dictionary<Variable, Expr> map = new Dictionary<Variable, Expr>();
            foreach (Variable local in impl.LocVars)
            {
                var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, local.Name, local.TypedIdent.Type));
                map[local] = Expr.Ident(copy);
            }

            Program program = linearTypeChecker.program;
            List<Variable> locals = new List<Variable>();
            List<Variable> inputs = new List<Variable>();
            foreach (IdentifierExpr ie in map.Values)
            {
                locals.Add(ie.Decl);
            }
            for (int i = 0; i < impl.InParams.Count - linearTypeChecker.linearDomains.Count; i++)
            {
                Variable inParam = impl.InParams[i];
                Variable copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name, inParam.TypedIdent.Type));
                locals.Add(copy);
                map[impl.InParams[i]] = Expr.Ident(copy);
            }
            {
                int i = impl.InParams.Count - linearTypeChecker.linearDomains.Count;
                foreach (string domainName in linearTypeChecker.linearDomains.Keys)
                {
                    Variable inParam = impl.InParams[i];
                    Variable copy = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, inParam.Name, inParam.TypedIdent.Type), true);
                    inputs.Add(copy);
                    map[impl.InParams[i]] = Expr.Ident(copy);
                    i++;
                }
            }
            for (int i = 0; i < impl.OutParams.Count; i++)
            {
                Variable outParam = impl.OutParams[i];
                var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, outParam.Name, outParam.TypedIdent.Type));
                locals.Add(copy);
                map[impl.OutParams[i]] = Expr.Ident(copy);
            }
            Dictionary<Variable, Expr> ogOldLocalMap = new Dictionary<Variable, Expr>();
            Dictionary<Variable, Expr> assumeMap = new Dictionary<Variable, Expr>(map);
            foreach (IdentifierExpr ie in globalMods)
            {
                Variable g = ie.Decl;
                var copy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_local_old_{0}", g.Name), g.TypedIdent.Type));
                locals.Add(copy);
                ogOldLocalMap[g] = Expr.Ident(copy);
                Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", g.Name), g.TypedIdent.Type), true);
                inputs.Add(f);
                assumeMap[g] = Expr.Ident(f);
            }

            Substitution assumeSubst = Substituter.SubstitutionFromHashtable(assumeMap);
            Substitution oldSubst = Substituter.SubstitutionFromHashtable(ogOldLocalMap);
            Substitution subst = Substituter.SubstitutionFromHashtable(map);
            List<Block> yieldCheckerBlocks = new List<Block>();
            List<String> labels = new List<String>();
            List<Block> labelTargets = new List<Block>();
            Block yieldCheckerBlock = new Block(Token.NoToken, "exit", new List<Cmd>(), new ReturnCmd(Token.NoToken));
            labels.Add(yieldCheckerBlock.Label);
            labelTargets.Add(yieldCheckerBlock);
            yieldCheckerBlocks.Add(yieldCheckerBlock);
            int yieldCount = 0;
            foreach (List<Cmd> cs in yields)
            {
                List<Cmd> newCmds = new List<Cmd>();
                foreach (Cmd cmd in cs)
                {
                    PredicateCmd predCmd = (PredicateCmd)cmd;
                    newCmds.Add(new AssumeCmd(Token.NoToken, Substituter.ApplyReplacingOldExprs(assumeSubst, oldSubst, predCmd.Expr)));
                }
                foreach (Cmd cmd in cs)
                {
                    PredicateCmd predCmd = (PredicateCmd)cmd;
                    var newExpr = Substituter.ApplyReplacingOldExprs(subst, oldSubst, predCmd.Expr);
                    if (predCmd is AssertCmd)
                    {
                        AssertCmd assertCmd = new AssertCmd(predCmd.tok, newExpr, predCmd.Attributes);
                        assertCmd.ErrorData = "Non-interference check failed";
                        newCmds.Add(assertCmd);
                    }
                    else
                    {
                        newCmds.Add(new AssumeCmd(Token.NoToken, newExpr));
                    }
                }
                newCmds.Add(new AssumeCmd(Token.NoToken, Expr.False));
                yieldCheckerBlock = new Block(Token.NoToken, "L" + yieldCount++, newCmds, new ReturnCmd(Token.NoToken));
                labels.Add(yieldCheckerBlock.Label);
                labelTargets.Add(yieldCheckerBlock);
                yieldCheckerBlocks.Add(yieldCheckerBlock);
            }
            yieldCheckerBlocks.Insert(0, new Block(Token.NoToken, "enter", new List<Cmd>(), new GotoCmd(Token.NoToken, labels, labelTargets)));

            // Create the yield checker procedure
            var yieldCheckerName = string.Format("{0}_YieldChecker_{1}", "Impl", impl.Name);
            var yieldCheckerProc = new Procedure(Token.NoToken, yieldCheckerName, impl.TypeParameters, inputs, new List<Variable>(), new List<Requires>(), new List<IdentifierExpr>(), new List<Ensures>());
            yieldCheckerProc.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
            yieldCheckerProcs.Add(yieldCheckerProc);

            // Create the yield checker implementation
            var yieldCheckerImpl = new Implementation(Token.NoToken, yieldCheckerName, impl.TypeParameters, inputs, new List<Variable>(), locals, yieldCheckerBlocks);
            yieldCheckerImpl.Proc = yieldCheckerProc;
            yieldCheckerImpl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
            yieldCheckerImpls.Add(yieldCheckerImpl);
        }
Exemple #10
0
 private void AddInitialBlock(Implementation impl, List<Variable> oldPcs, List<Variable> oldOks,
     Dictionary<string, Variable> domainNameToInputVar, Dictionary<string, Variable> domainNameToLocalVar, Dictionary<Variable, Variable> ogOldGlobalMap)
 {
     // Add initial block
     List<AssignLhs> lhss = new List<AssignLhs>();
     List<Expr> rhss = new List<Expr>();
     if (pc != null)
     {
         lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(pc)));
         rhss.Add(Expr.False);
         foreach (Variable oldPc in oldPcs)
         {
             lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldPc)));
             rhss.Add(Expr.False);
         }
         lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ok)));
         rhss.Add(Expr.False);
         foreach (Variable oldOk in oldOks)
         {
             lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(oldOk)));
             rhss.Add(Expr.False);
         }
     }
     Dictionary<string, Expr> domainNameToExpr = new Dictionary<string, Expr>();
     foreach (var domainName in linearTypeChecker.linearDomains.Keys)
     {
         domainNameToExpr[domainName] = Expr.Ident(domainNameToInputVar[domainName]);
     }
     for (int i = 0; i < impl.InParams.Count - linearTypeChecker.linearDomains.Count; i++)
     {
         Variable v = impl.InParams[i];
         var domainName = linearTypeChecker.FindDomainName(v);
         if (domainName == null) continue;
         if (!linearTypeChecker.linearDomains.ContainsKey(domainName)) continue;
         var domain = linearTypeChecker.linearDomains[domainName];
         if (!domain.collectors.ContainsKey(v.TypedIdent.Type)) continue;
         Expr ie = new NAryExpr(Token.NoToken, new FunctionCall(domain.collectors[v.TypedIdent.Type]), new List<Expr> { Expr.Ident(v) });
         domainNameToExpr[domainName] = new NAryExpr(Token.NoToken, new FunctionCall(domain.mapOrBool), new List<Expr> { ie, domainNameToExpr[domainName] });
     }
     foreach (string domainName in linearTypeChecker.linearDomains.Keys)
     {
         lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(domainNameToLocalVar[domainName])));
         rhss.Add(domainNameToExpr[domainName]);
     }
     foreach (Variable g in ogOldGlobalMap.Keys)
     {
         lhss.Add(new SimpleAssignLhs(Token.NoToken, Expr.Ident(ogOldGlobalMap[g])));
         rhss.Add(Expr.Ident(g));
     }
     if (lhss.Count > 0)
     {
         Block initBlock = new Block(Token.NoToken, "og_init", new List<Cmd> { new AssignCmd(Token.NoToken, lhss, rhss) }, new GotoCmd(Token.NoToken, new List<String> { impl.Blocks[0].Label }, new List<Block> { impl.Blocks[0] }));
         impl.Blocks.Insert(0, initBlock);
     }
 }
Exemple #11
0
        private void AddYieldProcAndImpl(List<Declaration> decls)
        {
            if (yieldProc == null) return;

            Program program = linearTypeChecker.program;
            List<Variable> inputs = new List<Variable>();
            foreach (string domainName in linearTypeChecker.linearDomains.Keys)
            {
                var domain = linearTypeChecker.linearDomains[domainName];
                Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "linear_" + domainName + "_in", new MapType(Token.NoToken, new List<TypeVariable>(), new List<Type> { domain.elementType }, Type.Bool)), true);
                inputs.Add(f);
            }
            foreach (IdentifierExpr ie in globalMods)
            {
                Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, string.Format("og_global_old_{0}", ie.Decl.Name), ie.Decl.TypedIdent.Type), true);
                inputs.Add(f);
            }
            List<Block> blocks = new List<Block>();
            TransferCmd transferCmd = new ReturnCmd(Token.NoToken);
            if (yieldCheckerProcs.Count > 0)
            {
                List<Block> blockTargets = new List<Block>();
                List<String> labelTargets = new List<String>();
                int labelCount = 0;
                foreach (Procedure proc in yieldCheckerProcs)
                {
                    List<Expr> exprSeq = new List<Expr>();
                    foreach (Variable v in inputs)
                    {
                        exprSeq.Add(Expr.Ident(v));
                    }
                    CallCmd callCmd = new CallCmd(Token.NoToken, proc.Name, exprSeq, new List<IdentifierExpr>());
                    callCmd.Proc = proc;
                    string label = string.Format("L_{0}", labelCount++);
                    Block block = new Block(Token.NoToken, label, new List<Cmd> { callCmd }, new ReturnCmd(Token.NoToken));
                    labelTargets.Add(label);
                    blockTargets.Add(block);
                    blocks.Add(block);
                }
                transferCmd = new GotoCmd(Token.NoToken, labelTargets, blockTargets);
            }
            blocks.Insert(0, new Block(Token.NoToken, "enter", new List<Cmd>(), transferCmd));

            var yieldImpl = new Implementation(Token.NoToken, yieldProc.Name, new List<TypeVariable>(), inputs, new List<Variable>(), new List<Variable>(), blocks);
            yieldImpl.Proc = yieldProc;
            yieldImpl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
            decls.Add(yieldProc);
            decls.Add(yieldImpl);
        }
Exemple #12
0
 GraphNode(Block b, List<Cmd> body) {
   Contract.Requires(body != null);
   Contract.Requires(b != null);
   this.Block = b;
   this.Body = body;
 }
Exemple #13
0
        public override Procedure VisitProcedure(Procedure node)
        {
            if (!civlTypeChecker.procToActionInfo.ContainsKey(node))
                return node;
            if (!procMap.ContainsKey(node))
            {
                enclosingProc = node;
                Procedure proc = (Procedure)node.Clone();
                proc.Name = string.Format("{0}_{1}", node.Name, layerNum);
                proc.InParams = this.VisitVariableSeq(node.InParams);
                proc.Modifies = this.VisitIdentifierExprSeq(node.Modifies);
                proc.OutParams = this.VisitVariableSeq(node.OutParams);

                ActionInfo actionInfo = civlTypeChecker.procToActionInfo[node];
                if (actionInfo.createdAtLayerNum < layerNum)
                {
                    proc.Requires = new List<Requires>();
                    proc.Ensures = new List<Ensures>();
                    Implementation impl;
                    AtomicActionInfo atomicActionInfo = actionInfo as AtomicActionInfo;
                    if (atomicActionInfo != null)
                    {
                        CodeExpr action = (CodeExpr)VisitCodeExpr(atomicActionInfo.action);
                        List<Cmd> cmds = new List<Cmd>();
                        foreach (AssertCmd assertCmd in atomicActionInfo.gate)
                        {
                            cmds.Add(new AssumeCmd(Token.NoToken, (Expr)Visit(assertCmd.Expr)));
                        }
                        Block newInitBlock = new Block(Token.NoToken, "_init", cmds,
                            new GotoCmd(Token.NoToken, new List<string>(new string[] { action.Blocks[0].Label }),
                                                       new List<Block>(new Block[] { action.Blocks[0] })));
                        List<Block> newBlocks = new List<Block>();
                        newBlocks.Add(newInitBlock);
                        newBlocks.AddRange(action.Blocks);
                        impl = new Implementation(Token.NoToken, proc.Name, node.TypeParameters, node.InParams, node.OutParams, action.LocVars, newBlocks);
                    }
                    else
                    {
                        Block newInitBlock = new Block(Token.NoToken, "_init", new List<Cmd>(), new ReturnCmd(Token.NoToken));
                        List<Block> newBlocks = new List<Block>();
                        newBlocks.Add(newInitBlock);
                        impl = new Implementation(Token.NoToken, proc.Name, node.TypeParameters, node.InParams, node.OutParams, new List<Variable>(), newBlocks);
                    }
                    impl.Proc = proc;
                    impl.Proc.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
                    impl.AddAttribute("inline", new LiteralExpr(Token.NoToken, Microsoft.Basetypes.BigNum.FromInt(1)));
                    impls.Add(impl);
                }
                else
                {
                    yieldingProcs.Add(proc);
                    proc.Requires = this.VisitRequiresSeq(node.Requires);
                    proc.Ensures = this.VisitEnsuresSeq(node.Ensures);
                }
                procMap[node] = proc;
                proc.Modifies = new List<IdentifierExpr>();
                civlTypeChecker.SharedVariables.Iter(x => proc.Modifies.Add(Expr.Ident(x)));
            }
            return procMap[node];
        }
Exemple #14
0
 private HashSet<Variable> PropagateAvailableLinearVarsAcrossBlock(Block b) {
     HashSet<Variable> start = new HashSet<Variable>(availableLinearVars[b]);
     foreach (Cmd cmd in b.Cmds)
     {
         if (cmd is AssignCmd)
         {
             AssignCmd assignCmd = (AssignCmd)cmd;
             for (int i = 0; i < assignCmd.Lhss.Count; i++)
             {
                 if (FindDomainName(assignCmd.Lhss[i].DeepAssignedVariable) == null) continue;
                 IdentifierExpr ie = assignCmd.Rhss[i] as IdentifierExpr;
                 if (!start.Contains(ie.Decl))
                 {
                     Error(ie, "unavailable source for a linear read"); 
                 }
                 else 
                 {
                     start.Remove(ie.Decl);
                 }
             }
             foreach (AssignLhs assignLhs in assignCmd.Lhss)
             {
                 if (FindDomainName(assignLhs.DeepAssignedVariable) == null) continue;
                 start.Add(assignLhs.DeepAssignedVariable);
             }
         }
         else if (cmd is CallCmd)
         {
             foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start))
             {
                 Error(cmd, string.Format("Global variable {0} must be available at a call", g.Name));
             }
             CallCmd callCmd = (CallCmd)cmd;
             for (int i = 0; i < callCmd.Proc.InParams.Count; i++)
             {
                 Variable param = callCmd.Proc.InParams[i];
                 if (FindDomainName(param) == null) continue;
                 IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr;
                 LinearKind paramKind = FindLinearKind(param);
                 if (start.Contains(ie.Decl))
                 {
                     if (callCmd.IsAsync || paramKind == LinearKind.LINEAR_IN)
                     {
                         start.Remove(ie.Decl);
                     }
                 }
                 else
                 {
                     if (paramKind == LinearKind.LINEAR_OUT)
                     {
                         start.Add(ie.Decl);
                     }
                     else
                     {
                         Error(ie, "unavailable source for a linear read");
                     }
                 }
             }
             availableLinearVars[callCmd] = new HashSet<Variable>(start);
             AddAvailableVars(callCmd, start);
         }
         else if (cmd is ParCallCmd)
         {
             foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start))
             {
                 Error(cmd, string.Format("Global variable {0} must be available at a call", g.Name));
             }
             ParCallCmd parCallCmd = (ParCallCmd)cmd;
             foreach (CallCmd callCmd in parCallCmd.CallCmds)
             {
                 for (int i = 0; i < callCmd.Proc.InParams.Count; i++)
                 {
                     Variable param = callCmd.Proc.InParams[i];
                     if (FindDomainName(param) == null) continue;
                     IdentifierExpr ie = callCmd.Ins[i] as IdentifierExpr;
                     LinearKind paramKind = FindLinearKind(param);
                     if (start.Contains(ie.Decl))
                     {
                         if (paramKind == LinearKind.LINEAR_IN)
                         {
                             start.Remove(ie.Decl);
                         }
                     }
                     else
                     {
                         if (paramKind == LinearKind.LINEAR_OUT)
                         {
                             start.Add(ie.Decl);
                         }
                         else
                         {
                             Error(ie, "unavailable source for a linear read");
                         }
                     }
                 }
             }
             availableLinearVars[parCallCmd] = new HashSet<Variable>(start);
             AddAvailableVars(parCallCmd, start);
         }
         else if (cmd is HavocCmd)
         {
             HavocCmd havocCmd = (HavocCmd)cmd;
             foreach (IdentifierExpr ie in havocCmd.Vars)
             {
                 if (FindDomainName(ie.Decl) == null) continue;
                 start.Remove(ie.Decl);
             }
         }
         else if (cmd is YieldCmd)
         {
             foreach (GlobalVariable g in globalVarToDomainName.Keys.Except(start))
             {
                 Error(cmd, string.Format("Global variable {0} must be available at a yield", g.Name));
             }
             availableLinearVars[cmd] = new HashSet<Variable>(start);
         }
     }
     return start;
 }
Exemple #15
0
 public override Block VisitBlock(Block node) {
   //Contract.Requires(node != null);
   Contract.Ensures(Contract.Result<Block>() != null);
   return base.VisitBlock((Block) node.Clone());
 }
Exemple #16
0
        private List<Block> CreateAssertsWithAssumes(List<List<Tuple<Variable, Expr, Expr>>> eqVarsGroups, List<Cmd> asserts)
        {
            int n = eqVarsGroups.Count();
            if (n == 0)
            {
                var b = new Block { Label = SectionLabelPrefix + "_" + _labelCounter++ };
                b.Cmds.AddRange(asserts);
                return new List<Block>() { b };
            }

            var result = new List<Block>();
            EnumerateAssumes(new List<Tuple<int, int>>(), n, asserts, eqVarsGroups, result);
            return result;
        }
Exemple #17
0
      public static GraphNode ComputeGraphInfo(GraphNode from, Block b, Dictionary<Block/*!*/, GraphNode/*!*/>/*!*/ gd, HashSet<Block> beingVisited) {
        Contract.Requires(beingVisited != null);
        Contract.Requires(b != null);
        Contract.Requires(cce.NonNullDictionaryAndValues(gd));
        Contract.Ensures(Contract.Result<GraphNode>() != null);
        GraphNode g;
        if (gd.TryGetValue(b, out g)) {
          Contract.Assume(from != null);
          Contract.Assert(g != null);
          if (beingVisited.Contains(b)) {
            // it's a cut point
            g.isCutPoint = true;
            from.BackEdges.Add(g);
            g.Predecessors.Add(from);
          } else {
            from.ForwardEdges.Add(g);
            g.Predecessors.Add(from);
          }

        } else {
          List<Cmd> body = GetOptimizedBody(b.Cmds);
          g = new GraphNode(b, body);
          gd.Add(b, g);
          if (from != null) {
            from.ForwardEdges.Add(g);
            g.Predecessors.Add(from);
          }

          if (body != b.Cmds) {
            // the body was optimized -- there is no way through this block
          } else {
            beingVisited.Add(b);

            GotoCmd gcmd = b.TransferCmd as GotoCmd;
            if (gcmd != null) {
              Contract.Assume(gcmd.labelTargets != null);
              foreach (Block/*!*/ succ in gcmd.labelTargets) {
                Contract.Assert(succ != null);
                ComputeGraphInfo(g, succ, gd, beingVisited);
              }
            }

            beingVisited.Remove(b);
          }
        }
        return g;
      }
 private IEnumerable<Block> LoopsExitedForwardEdge(Block dest, IEnumerator<Tuple<Block, bool>> i) {
   var headsSeen = new HashSet<Block>();
   while (i.MoveNext()) {
     var b = i.Current;
     if (b.Item1 == dest)
       yield break;
     else if (!b.Item2 && blockGraph.Headers.Contains(b.Item1))
       headsSeen.Add(b.Item1);
     else if (b.Item2 && !headsSeen.Contains(b.Item1))
       yield return b.Item1;
   }
   Debug.Assert(false);
 }
 public PartInfo(Expr p, Block r) { pred = p; realDest = r; }
 private IEnumerable<Block> LoopsExitedBackEdge(Block src, IEnumerator<Tuple<Block, bool>> i) {
   var headsSeen = new HashSet<Block>();
   while (i.MoveNext()) {
     var b = i.Current;
     if (!b.Item2 && blockGraph.Headers.Contains(b.Item1))
       headsSeen.Add(b.Item1);
     else if (b.Item2)
       headsSeen.Remove(b.Item1);
     if (b.Item1 == src)
       return headsSeen;
   }
   Debug.Assert(false);
   return null;
 }
 IEnumerable<Block> LoopsExited(Block src, Block dest) {
   var i = sortedBlocks.GetEnumerator();
   while (i.MoveNext()) {
     var b = i.Current;
     if (b.Item1 == src) {
       return LoopsExitedForwardEdge(dest, i);
     } else if (b.Item1 == dest) {
       return LoopsExitedBackEdge(src, i);
     }
   }
   Debug.Assert(false);
   return null;
 }
  // hasPredicatedRegion is true iff the block or its targets are predicated
  // (i.e. we enter, stay within or exit a predicated region).
  void PredicateTransferCmd(Expr p, Block src, List<Cmd> cmdSeq, TransferCmd cmd, out bool hasPredicatedRegion) {
    hasPredicatedRegion = predMap.ContainsKey(src);

    if (cmd is GotoCmd) {
      var gCmd = (GotoCmd)cmd;

      hasPredicatedRegion = hasPredicatedRegion ||
        gCmd.labelTargets.Cast<Block>().Any(b => predMap.ContainsKey(b));

      if (gCmd.labelTargets.Count == 1) {
        if (defMap.ContainsKey(gCmd.labelTargets[0])) {
          PredicateCmd(p, Expr.True, cmdSeq,
                       Cmd.SimpleAssign(Token.NoToken,
                                        Expr.Ident(predMap[gCmd.labelTargets[0]]), Expr.True));
        }
      } else {
        Debug.Assert(gCmd.labelTargets.Count > 1);
        Debug.Assert(gCmd.labelTargets.Cast<Block>().All(t => uni.IsUniform(impl.Name, t) ||
                                                              partInfo.ContainsKey(t)));
        foreach (Block target in gCmd.labelTargets) {
          if (!partInfo.ContainsKey(target))
            continue;

          // In this case we not only predicate with the current predicate p,
          // but also with the "part predicate"; this ensures that we do not
          // update a predicate twice when it occurs in both parts.
          var part = partInfo[target];
          if (defMap.ContainsKey(part.realDest)) {
            PredicateCmd(p == null ? part.pred : Expr.And(p, part.pred), Expr.True, cmdSeq,
                         Cmd.SimpleAssign(Token.NoToken,
                                          Expr.Ident(predMap[part.realDest]), part.pred));
          }
          var predsExitingLoop = new Dictionary<Block, List<Expr>>();
          foreach (Block exit in LoopsExited(src, target)) {
            List<Expr> predList;
            if (!predsExitingLoop.ContainsKey(exit))
              predList = predsExitingLoop[exit] = new List<Expr>();
            else
              predList = predsExitingLoop[exit];
            predList.Add(part.pred);
          }
          foreach (var pred in predsExitingLoop) {
            PredicateCmd(p == null ? part.pred : Expr.And(p, part.pred), Expr.True, cmdSeq,
                         Cmd.SimpleAssign(Token.NoToken,
                                          Expr.Ident(predMap[pred.Key]),
                                          Expr.Not(pred.Value.Aggregate(Expr.Or))));
          }
        }
      }
    } else if (cmd is ReturnCmd) {
      // Blocks which end in a return will never share a predicate with a block
      // which appears after it.  Furthermore, such a block cannot be part of a
      // loop.  So it is safe to do nothing here.
    } else {
      Console.WriteLine("Unsupported cmd: " + cmd.GetType().ToString());
    }
  }
Exemple #23
0
 private bool IsYieldingHeader(Graph<Block> graph, Block header)
 {
     foreach (Block backEdgeNode in graph.BackEdgeNodes(header))
     {
         foreach (Block x in graph.NaturalLoops(header, backEdgeNode))
         {
             foreach (Cmd cmd in x.Cmds)
             {
                 if (cmd is YieldCmd)
                     return true;
                 if (cmd is ParCallCmd)
                     return true;
                 CallCmd callCmd = cmd as CallCmd;
                 if (callCmd == null) continue;
                 if (yieldingProcs.Contains(callCmd.Proc))
                     return true;
             }
         }
     }
     return false;
 }
  void PredicateImplementation() {
    blockGraph = prog.ProcessLoops(impl);
    sortedBlocks = blockGraph.LoopyTopSort();

    AssignPredicates();
    partInfo = BuildPartitionInfo();

    if (myUseProcedurePredicates)
      fp = Expr.Ident(impl.InParams[0]);

    var newBlocks = new List<Block>();
    Block prevBlock = null;
    foreach (var n in sortedBlocks) {
      if (predMap.ContainsKey(n.Item1)) {
        var p = predMap[n.Item1];
        var pExpr = Expr.Ident(p);

        if (n.Item2) {
          var dominator = FindImmediateDominator(n.Item1);
          if (dominator != null && predMap.ContainsKey(dominator)) {
            AssumeCmd aCmd = new AssumeCmd(Token.NoToken, Expr.True);
            aCmd.Attributes = new QKeyValue(Token.NoToken, "dominator_predicate", new List<object>() { predMap[dominator].ToString() }, aCmd.Attributes);
            aCmd.Attributes = new QKeyValue(Token.NoToken, "predicate", new List<object>() { predMap[n.Item1].ToString() }, aCmd.Attributes);
            n.Item1.Cmds.Insert(0, aCmd);
          }

          var backedgeBlock = new Block();
          newBlocks.Add(backedgeBlock);

          backedgeBlock.Label = n.Item1.Label + ".backedge";
          backedgeBlock.Cmds = new List<Cmd> { new AssumeCmd(Token.NoToken, pExpr,
            new QKeyValue(Token.NoToken, "backedge", new List<object>(), null)) };
          backedgeBlock.TransferCmd = new GotoCmd(Token.NoToken,
                                                  new List<Block> { n.Item1 });

          var tailBlock = new Block();
          newBlocks.Add(tailBlock);

          tailBlock.Label = n.Item1.Label + ".tail";
          tailBlock.Cmds = new List<Cmd> { new AssumeCmd(Token.NoToken,
                                               Expr.Not(pExpr)) };

          if (uni != null && !uni.IsUniform(impl.Name, n.Item1)) {
            uni.AddNonUniform(impl.Name, backedgeBlock);
            uni.AddNonUniform(impl.Name, tailBlock);
          }

          if (prevBlock != null)
            prevBlock.TransferCmd = new GotoCmd(Token.NoToken,
                                          new List<Block> { backedgeBlock, tailBlock });
          prevBlock = tailBlock;
        } else {
          PredicateBlock(pExpr, n.Item1, newBlocks, ref prevBlock);
        }
      } else {
        if (!n.Item2) {
          PredicateBlock(null, n.Item1, newBlocks, ref prevBlock);
        }
      }
    }

    if (prevBlock != null)
      prevBlock.TransferCmd = new ReturnCmd(Token.NoToken);

    impl.Blocks = newBlocks;
  }
Exemple #25
0
 private void UnifyCallsToYieldProc(Implementation impl, Dictionary<Variable, Variable> ogOldGlobalMap, Dictionary<string, Variable> domainNameToLocalVar)
 {
     CallCmd yieldCallCmd = CallToYieldProc(Token.NoToken, ogOldGlobalMap, domainNameToLocalVar);
     Block yieldCheckBlock = new Block(Token.NoToken, "CallToYieldProc", new List<Cmd>(new Cmd[] { yieldCallCmd, new AssumeCmd(Token.NoToken, Expr.False) }), new ReturnCmd(Token.NoToken));
     List<Block> newBlocks = new List<Block>();
     foreach (Block b in impl.Blocks)
     {
         TransferCmd transferCmd = b.TransferCmd;
         List<Cmd> newCmds = new List<Cmd>();
         for (int i = b.Cmds.Count-1; i >= 0; i--)
         {
             CallCmd callCmd = b.Cmds[i] as CallCmd;
             if (callCmd == null || callCmd.Proc != yieldProc)
             {
                 newCmds.Insert(0, b.Cmds[i]);
             }
             else
             {
                 Block newBlock = new Block(Token.NoToken, b.Label + i, newCmds, transferCmd);
                 newCmds = new List<Cmd>();
                 transferCmd = new GotoCmd(Token.NoToken, new List<string>(new string[] { newBlock.Label, yieldCheckBlock.Label }),
                                                          new List<Block>(new Block[] { newBlock, yieldCheckBlock }));
                 newBlocks.Add(newBlock);
             }
         }
         b.Cmds = newCmds;
         b.TransferCmd = transferCmd;
     }
     impl.Blocks.AddRange(newBlocks);
     impl.Blocks.Add(yieldCheckBlock);
 }
  private void PredicateBlock(Expr pExpr, Block block, List<Block> newBlocks, ref Block prevBlock) {
    var firstBlock = block;

    var oldCmdSeq = block.Cmds;
    block.Cmds = new List<Cmd>();
    newBlocks.Add(block);
    if (prevBlock != null && !((prevBlock.TransferCmd is ReturnCmd) && uni != null && uni.IsUniform(impl.Name, block))) {
      prevBlock.TransferCmd = new GotoCmd(Token.NoToken, new List<Block> { block });
    }

    Block currentBlock = block;
    Expr pCurrentExpr = pExpr;
    while (parentMap.ContainsKey(currentBlock)) {
      Block parent = parentMap[currentBlock];
      Expr pParentExpr = null;
      if (predMap.ContainsKey(parent)) {
        var parentPred = predMap[parent];
        if (parentPred != null) {
          pParentExpr = Expr.Ident(parentPred);
          block.Cmds.Add(new AssertCmd(Token.NoToken,
                                          pCurrentExpr != null ? (Expr)Expr.Imp(pCurrentExpr, pParentExpr)
                                                               : pParentExpr));
        }
      }
      currentBlock = parent;
      pCurrentExpr = pParentExpr;
    }

    Block dominator = FindImmediateDominator(block);
    Expr pDomExpr = Expr.True;
    if (dominator != null && predMap.ContainsKey(dominator))
      pDomExpr = new IdentifierExpr(Token.NoToken, predMap[dominator]);
    var transferCmd = block.TransferCmd;
    foreach (Cmd cmd in oldCmdSeq)
      PredicateCmd(pExpr, pDomExpr, newBlocks, block, cmd, out block);

    if (ownedMap.ContainsKey(firstBlock)) {
      var owned = ownedMap[firstBlock];
      foreach (var v in owned)
        block.Cmds.Add(Cmd.SimpleAssign(Token.NoToken, Expr.Ident(v), Expr.False));
    }

    bool hasPredicatedRegion;
    PredicateTransferCmd(pExpr, block, block.Cmds, transferCmd, out hasPredicatedRegion);

    if (hasPredicatedRegion)
      prevBlock = block;
    else
      prevBlock = null;

    doneBlocks.Add(block);
  }
 private void AddNonUniformCandidateInvariant(List<Cmd> cs, Block header)
 {
     var loopNodes = new HashSet<Block>();
     foreach (var b in blockGraph.BackEdgeNodes(header))
       loopNodes.UnionWith(blockGraph.NaturalLoops(header, b));
     var exits = new HashSet<Expr>();
     foreach (var ln in loopNodes) {
       if (ln.TransferCmd is GotoCmd) {
     var gCmd = (GotoCmd) ln.TransferCmd;
     foreach (var exit in gCmd.labelTargets.Cast<Block>()
                          .Where(b => !loopNodes.Contains(b)))
       exits.Add(blockIds[exit]);
       }
       if (ln.TransferCmd is ReturnCmd)
     exits.Add(returnBlockId);
     }
     var curIsHeaderOrExit = exits.Aggregate((Expr)Expr.Eq(cur, blockIds[header]),
                                     (e, exit) => Expr.Or(e, Expr.Eq(cur, exit)));
     cs.Add(prog.CreateCandidateInvariant(
      CreateIfFPThenElse(curIsHeaderOrExit, Expr.Eq(cur, returnBlockId)),
      "non-uniform loop"));
 }
Exemple #28
0
 public override Block VisitBlock(Block node)
 {
     Block block = base.VisitBlock(node);
     absyMap[block] = node;
     return block;
 }
 /// <summary>
 /// Requires there to be a procedure context.
 /// </summary>
 /// <param name="block"></param>
 public void AddBlock(Block block)
 {
     Contract.Requires(block != null);
       Contract.Requires(HasProcedureContext);
       Contract.Assert(procedureContext != null);  // follows from precondition
       Hashtable/*!*/ /*string->Block!*/ blocks = procedureContext.Blocks;
       Contract.Assert(blocks != null);
       if (blocks[block.Label] != null) {
     Error(block, "more than one declaration of block name: {0}", block.Label);
       } else {
     blocks.Add(block.Label, block);
       }
 }
Exemple #30
0
    Block Visit(GraphNode node) {
      Contract.Requires(node != null);
      Contract.Ensures(Contract.Result<Block>() != null);
      Block orig = node.Block;
      Block nw;
      if (newBlocks.TryGetValue(orig, out nw)) {
        Contract.Assert(nw != null);

      } else {
        List<Cmd> body;
        TransferCmd tcmd;
        Contract.Assert(orig.TransferCmd != null);

        if (next == null && node.IsCutPoint) {
          // as the body, use the assert/assume commands that make up the loop invariant
          body = new List<Cmd>();
          foreach (Cmd/*!*/ c in node.Body) {
            Contract.Assert(c != null);
            if (c is PredicateCmd || c is CommentCmd) {
              body.Add(c);
            } else {
              break;
            }
          }
          if (soundLoopUnrolling) {
            body.Add(new AssertCmd(orig.tok, Bpl.Expr.False));
          } else {
            body.Add(new AssumeCmd(orig.tok, Bpl.Expr.False));
          }
          tcmd = new ReturnCmd(orig.TransferCmd.tok);

        } else {
          body = node.Body;
          List<Block> newSuccs = new List<Block>();

          foreach (GraphNode succ in node.ForwardEdges) {
            Block s;
            if (containingSCC[node] == containingSCC[succ]) {
              s = Visit(succ);
            } else {
              Contract.Assert(head != null); // follows from object invariant
              s = head.Visit(succ);
            }
            newSuccs.Add(s);
          }

          Contract.Assert(next != null || node.BackEdges.Count == 0);  // follows from if-else test above and the GraphNode invariant
          foreach (GraphNode succ in node.BackEdges) {
            Contract.Assert(next != null);  // since if we get here, node.BackEdges.Count != 0
            Block s = next.Visit(succ);
            newSuccs.Add(s);
          }

          if (newSuccs.Count == 0) {
            tcmd = new ReturnCmd(orig.TransferCmd.tok);
          } else {
            tcmd = new GotoCmd(orig.TransferCmd.tok, newSuccs);
          }
        }

        nw = new Block(orig.tok, orig.Label + "#" + this.c, body, tcmd);
        newBlocks.Add(orig, nw);
        newBlockSeqGlobal.Add(nw);
      }

      return nw;
    }
Exemple #31
0
        private void EnumerateAssumes(List<Tuple<int, int>> pick, int depth, List<Cmd> asserts,
            List<List<Tuple<Variable, Expr, Expr>>> eqVarsGroups, List<Block> result)
        {
            // if we the number of asserts exceeds twice the maximum amount of asserts, the tracelet is hopeless, so generate empty output and don't try to solve
            if (_numOverallAsserts >= MaxAsserts)
            {
                // TODO: magic
                Utils.ErrorAndDie($"Sorry, can't handle very long programs (max {MaxAsserts} assertions allowed, {_numOverallAsserts} reached)");
            }

            if (depth == 0)
            {
                var usedExprs = new HashSet<string>();
                var eqVarsPick = new List<Variable>();
                foreach (Tuple<int, int> t in pick)
                {
                    var tuple = eqVarsGroups[t.Item1][t.Item2];
                    if (usedExprs.Contains(tuple.Item3.ToString()))
                        return;
                    usedExprs.Add(tuple.Item3.ToString());
                    eqVarsPick.Add(tuple.Item1);
                }

                var b = new Block { Label = SectionLabelPrefix + "_" + _labelCounter++ };
                foreach (var eqv in eqVarsPick)
                    b.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.Ident(eqv)));
                b.Cmds.AddRange(asserts);
                b.TransferCmd = new ReturnCmd(Token.NoToken);
                result.Add(b);
                return;
            }

            // always start from the next group
            for (var i = (pick.Count > 0) ? pick.Last().Item1 + 1 : 0; i < eqVarsGroups.Count; ++i)
            {
                // inside the group, try all candidates
                for (int j = 0; j < eqVarsGroups[i].Count; ++j)
                {
                    var l = new List<Tuple<int, int>>(pick) { new Tuple<int, int>(i, j) };
                    EnumerateAssumes(l, depth - 1, asserts, eqVarsGroups, result);
                }
            }
        }
 Block FindImmediateDominator(Block block) {
   Block predecessor = null;
   foreach(var pred in blockGraph.Predecessors(block)) {
     if (!blockGraph.DominatorMap.DominatedBy(pred, block)) {
       if (predecessor == null)
         predecessor = pred;
       else
         predecessor = blockGraph.DominatorMap.LeastCommonAncestor(pred, predecessor);
     }
   }
   return predecessor;
 }