示例#1
0
        public override List <Cmd> CreateUpdatesToRefinementVars(bool isMarkedCall)
        {
            var cmds          = new List <Cmd>();
            var pcOkUpdateLHS = new List <IdentifierExpr> {
                Expr.Ident(pc), Expr.Ident(ok)
            };

            if (isMarkedCall)
            {
                // assert !pc;
                // pc, ok := true, true;
                cmds.Add(CmdHelper.AssertCmd(tok, Expr.Not(Expr.Ident(pc)), $"Layer-{layerNum + 1} state modified before marked call"));
                var pcOkUpdateRHS = new List <Expr> {
                    Expr.True, Expr.True
                };
                cmds.Add(CmdHelper.AssignCmd(pcOkUpdateLHS, pcOkUpdateRHS));
            }
            else
            {
                // pc, ok := g_old == g ==> pc, transitionRelation(i, g_old, o, g) || (o_old == o && ok);
                var pcOkUpdateRHS = new List <Expr> {
                    Expr.Imp(OldEqualityExprForGlobals(), Expr.Ident(pc)),
                    Expr.Or(transitionRelation, Expr.And(OldEqualityExprForOutputs(), Expr.Ident(ok))),
                };
                cmds.Add(CmdHelper.AssignCmd(pcOkUpdateLHS, pcOkUpdateRHS));
            }

            CivlUtil.ResolveAndTypecheck(cmds);

            return(cmds);
        }
示例#2
0
 private AssertCmd GetCheck(Expr expr)
 {
     expr.Typecheck(new TypecheckingContext(null));
     return(CmdHelper.AssertCmd(
                inputAction.proc.tok,
                expr,
                $"IS {checkName} of {inputAction.proc.Name} failed"));
 }
示例#3
0
        private void CreateGatePreservationChecker(AtomicAction first, AtomicAction second)
        {
            if (!first.gateUsedGlobalVars.Intersect(second.modifiedGlobalVars).Any())
            {
                return;
            }
            if (!gatePreservationCheckerCache.Add(Tuple.Create(first, second)))
            {
                return;
            }

            HashSet <Variable> frame = new HashSet <Variable>();

            frame.UnionWith(first.gateUsedGlobalVars);
            frame.UnionWith(second.gateUsedGlobalVars);
            frame.UnionWith(second.actionUsedGlobalVars);

            var             linearTypeChecker = civlTypeChecker.linearTypeChecker;
            List <Requires> requires          = new List <Requires>
            {
                DisjointnessRequires(
                    first.firstImpl.InParams.Union(second.secondImpl.InParams)
                    .Where(v => linearTypeChecker.FindLinearKind(v) != LinearKind.LINEAR_OUT), frame)
            };

            foreach (AssertCmd assertCmd in first.firstGate.Union(second.secondGate))
            {
                requires.Add(new Requires(false, assertCmd.Expr));
            }

            string checkerName = $"GatePreservationChecker_{first.proc.Name}_{second.proc.Name}";

            List <Variable> inputs  = Enumerable.Union(first.firstImpl.InParams, second.secondImpl.InParams).ToList();
            List <Variable> outputs = Enumerable.Union(first.firstImpl.OutParams, second.secondImpl.OutParams).ToList();

            List <Cmd> cmds = new List <Cmd> {
                ActionCallCmd(second, second.secondImpl)
            };

            IEnumerable <Expr> linearityAssumes =
                linearTypeChecker.DisjointnessExprForEachDomain(first.firstImpl.InParams.Union(second.secondImpl.OutParams)
                                                                .Union(frame));

            foreach (AssertCmd assertCmd in first.firstGate)
            {
                cmds.Add(
                    CmdHelper.AssertCmd(
                        assertCmd.tok,
                        Expr.Imp(Expr.And(linearityAssumes), assertCmd.Expr),
                        $"Gate of {first.proc.Name} not preserved by {second.proc.Name}"
                        )
                    );
            }

            AddChecker(checkerName, inputs, outputs, new List <Variable>(), requires, cmds);
        }
        public static void AddCheckers(CivlTypeChecker civlTypeChecker)
        {
            foreach (var action in civlTypeChecker.AllAtomicActions.Where(a => a.HasPendingAsyncs))
            {
                var requires = action.gate.Select(g => new Requires(false, g.Expr)).ToList();

                var PAs     = Expr.Ident(action.impl.OutParams.Last(p => p.TypedIdent.Type.Equals(civlTypeChecker.pendingAsyncMultisetType)));
                var paBound = civlTypeChecker.BoundVariable("pa", civlTypeChecker.pendingAsyncType);
                var pa      = Expr.Ident(paBound);

                var nonnegativeExpr =
                    ExprHelper.ForallExpr(new List <Variable> {
                    paBound
                },
                                          Expr.Ge(Expr.Select(PAs, pa), Expr.Literal(0)));
                var correctTypeExpr = ExprHelper.ForallExpr(new List <Variable> {
                    paBound
                },
                                                            Expr.Imp(
                                                                Expr.Gt(Expr.Select(PAs, pa), Expr.Literal(0)),
                                                                Expr.Or(action.pendingAsyncs.Select(a => ExprHelper.FunctionCall(a.pendingAsyncCtor.membership, pa)))));

                CivlUtil.ResolveAndTypecheck(nonnegativeExpr);
                CivlUtil.ResolveAndTypecheck(correctTypeExpr);

                var cmds = new List <Cmd>
                {
                    CmdHelper.CallCmd(
                        action.proc,
                        action.impl.InParams.Select(Expr.Ident).ToList <Expr>(),
                        action.impl.OutParams.Select(Expr.Ident).ToList()),
                    CmdHelper.AssertCmd(
                        action.proc.tok,
                        nonnegativeExpr,
                        $"Action {action.proc.Name} might create negative pending asyncs"),
                    CmdHelper.AssertCmd(
                        action.proc.tok,
                        correctTypeExpr,
                        $"Action {action.proc.Name} might create undeclared pending asyncs")
                };
                var blocks = new List <Block>()
                {
                    BlockHelper.Block("init", cmds)
                };

                var proc = DeclHelper.Procedure(civlTypeChecker.AddNamePrefix($"PendingAsyncChecker_{action.proc.Name}"),
                                                action.impl.InParams, action.impl.OutParams,
                                                requires, action.proc.Modifies, new List <Ensures>());
                var impl = DeclHelper.Implementation(proc, proc.InParams, proc.OutParams, new List <Variable>(), blocks);

                civlTypeChecker.program.AddTopLevelDeclaration(proc);
                civlTypeChecker.program.AddTopLevelDeclaration(impl);
            }
        }
示例#5
0
        public override List <Cmd> CreateReturnAssertCmds()
        {
            AssertCmd assertCmd = CmdHelper.AssertCmd(
                tok,
                Expr.Ident(ok),
                "On some path no yield-to-yield fragment matched the refined atomic action");

            return(new List <Cmd> {
                assertCmd
            });
        }
示例#6
0
        public Tuple <Procedure, Implementation> GenerateChoiceChecker()
        {
            this.checkName = "choice";
            var requires = invariantAction.gate.Select(g => new Requires(false, g.Expr)).ToList();

            List <Cmd> cmds = new List <Cmd>();

            cmds.Add(GetCallCmd(invariantAction));
            cmds.Add(CmdHelper.AssumeCmd(ExistsElimPendingAsyncExpr));
            cmds.Add(CmdHelper.AssertCmd(
                         invariantAction.proc.tok,
                         ElimPendingAsyncExpr(choice),
                         $"Failed to validate choice in IS of {inputAction.proc.Name}"));

            return(GetCheckerTuple(requires, new List <Variable>(), cmds));
        }
示例#7
0
        private static Tuple <Procedure, Implementation> GenerateAbstractionChecker(CivlTypeChecker civlTypeChecker, AtomicAction action, AtomicAction abs)
        {
            var requires = abs.gate.Select(g => new Requires(false, g.Expr)).ToList();
            // TODO: check frame computation
            var frame = new HashSet <Variable>(
                action.modifiedGlobalVars
                .Union(action.gateUsedGlobalVars)
                .Union(abs.modifiedGlobalVars)
                .Union(abs.gateUsedGlobalVars));

            var        subst = InductiveSequentialization.GetSubstitution(action, abs);
            List <Cmd> cmds  = InductiveSequentialization.GetGateAsserts(action, subst,
                                                                         $"Abstraction {abs.proc.Name} fails gate of {action.proc.Name}").ToList <Cmd>();

            cmds.Add(
                CmdHelper.CallCmd(
                    action.proc,
                    abs.impl.InParams,
                    abs.impl.OutParams
                    ));
            cmds.Add(
                CmdHelper.AssertCmd(
                    abs.proc.tok,
                    TransitionRelationComputation.Refinement(civlTypeChecker, abs, frame),
                    $"Abstraction {abs.proc.Name} does not summarize {action.proc.Name}"
                    ));

            var blocks = new List <Block> {
                BlockHelper.Block("init", cmds)
            };

            var proc = DeclHelper.Procedure(
                civlTypeChecker.AddNamePrefix($"AbstractionCheck_{action.proc.Name}_{abs.proc.Name}"),
                abs.impl.InParams,
                abs.impl.OutParams,
                requires,
                action.proc.Modifies,
                new List <Ensures>());
            var impl = DeclHelper.Implementation(
                proc,
                proc.InParams,
                proc.OutParams,
                new List <Variable>(),
                blocks);

            return(Tuple.Create(proc, impl));
        }
示例#8
0
        public Tuple <Procedure, Implementation> GenerateConclusionChecker()
        {
            this.checkName = "conclusion";
            var subst    = GetSubstitution(outputAction, invariantAction);
            var requires = outputAction.gate.Select(g => new Requires(false, Substituter.Apply(subst, g.Expr))).ToList();

            List <Cmd> cmds = GetGateAsserts(invariantAction, null).ToList <Cmd>();

            cmds.Add(GetCallCmd(invariantAction));
            cmds.Add(CmdHelper.AssumeCmd(PendingAsyncsEliminatedExpr));
            cmds.Add(GetCheck(Substituter.Apply(subst, GetTransitionRelation(outputAction))));
            if (!outputAction.HasPendingAsyncs)
            {
                cmds.Add(CmdHelper.AssertCmd(
                             inputAction.proc.tok,
                             NoPendingAsyncs,
                             $"IS leaves pending asyncs not summarized by ${outputAction.proc.Name}"));
            }

            return(GetCheckerTuple(requires, new List <Variable>(), cmds));
        }
示例#9
0
        public override List <Cmd> CreateUnchangedAssertCmds()
        {
            AssertCmd globalsAssertCmd = CmdHelper.AssertCmd(
                tok,
                Expr.And(this.oldGlobalMap.Select(kvPair => Expr.Eq(Expr.Ident(kvPair.Key), Expr.Ident(kvPair.Value)))),
                $"A yield-to-yield fragment illegally modifies layer-{layerNum + 1} globals");

            CivlUtil.ResolveAndTypecheck(globalsAssertCmd);

            // assert pc ==> o_old == o;
            AssertCmd outputsAssertCmd = CmdHelper.AssertCmd(
                tok,
                Expr.Imp(Expr.Ident(pc), OldEqualityExprForOutputs()),
                $"A yield-to-yield fragment illegally modifies layer-{layerNum + 1} outputs");

            CivlUtil.ResolveAndTypecheck(outputsAssertCmd);

            return(new List <Cmd> {
                globalsAssertCmd, outputsAssertCmd
            });
        }
示例#10
0
        public override List <Cmd> CreateAssertCmds()
        {
            // assert pc || g_old == g || transitionRelation(i, g_old, o, g);
            var skipOrTransitionRelationAssertCmd = CmdHelper.AssertCmd(
                tok,
                Expr.Or(Expr.Ident(pc), Expr.Or(OldEqualityExprForGlobals(), transitionRelation)),
                $"A yield-to-yield fragment modifies layer-{layerNum + 1} state in a way that does not match the refined atomic action");

            CivlUtil.ResolveAndTypecheck(skipOrTransitionRelationAssertCmd);

            // assert pc ==> g_old == g && o_old == o;
            AssertCmd skipAssertCmd = CmdHelper.AssertCmd(
                tok,
                Expr.Imp(Expr.Ident(pc), Expr.And(OldEqualityExprForGlobals(), OldEqualityExprForOutputs())),
                $"A yield-to-yield fragment modifies layer-{layerNum + 1} state subsequent to a yield-to-yield fragment that already modified layer-{layerNum + 1} state");

            CivlUtil.ResolveAndTypecheck(skipAssertCmd);

            return(new List <Cmd> {
                skipOrTransitionRelationAssertCmd, skipAssertCmd
            });
        }
示例#11
0
        private void CreateCooperationChecker(Action action)
        {
            if (!action.HasAssumeCmd)
            {
                return;
            }

            string checkerName = $"CooperationChecker_{action.proc.Name}";

            Implementation     impl  = action.impl;
            HashSet <Variable> frame = new HashSet <Variable>();

            frame.UnionWith(action.gateUsedGlobalVars);
            frame.UnionWith(action.actionUsedGlobalVars);

            List <Requires> requires = new List <Requires>
            {
                DisjointnessRequires(impl.InParams.Where(v => civlTypeChecker.linearTypeChecker.FindLinearKind(v) != LinearKind.LINEAR_OUT),
                                     frame)
            };

            foreach (AssertCmd assertCmd in action.gate)
            {
                requires.Add(new Requires(false, assertCmd.Expr));
            }

            AssertCmd cooperationCheck = CmdHelper.AssertCmd(
                action.proc.tok,
                TransitionRelationComputation.Cooperation(civlTypeChecker, action, frame),
                $"Cooperation check for {action.proc.Name} failed");

            AddChecker(checkerName, new List <Variable>(impl.InParams), new List <Variable>(),
                       new List <Variable>(), requires, new List <Cmd> {
                cooperationCheck
            });
        }
示例#12
0
        private void CreateCommutativityChecker(AtomicAction first, AtomicAction second)
        {
            if (first == second && first.firstImpl.InParams.Count == 0 && first.firstImpl.OutParams.Count == 0)
            {
                return;
            }
            if (first.TriviallyCommutesWith(second))
            {
                return;
            }
            if (!commutativityCheckerCache.Add(Tuple.Create(first, second)))
            {
                return;
            }

            string checkerName = $"CommutativityChecker_{first.proc.Name}_{second.proc.Name}";

            HashSet <Variable> frame = new HashSet <Variable>();

            frame.UnionWith(first.gateUsedGlobalVars);
            frame.UnionWith(first.actionUsedGlobalVars);
            frame.UnionWith(second.gateUsedGlobalVars);
            frame.UnionWith(second.actionUsedGlobalVars);

            var             linearTypeChecker = civlTypeChecker.linearTypeChecker;
            List <Requires> requires          = new List <Requires>
            {
                DisjointnessRequires(
                    first.firstImpl.InParams.Union(second.secondImpl.InParams)
                    .Where(v => linearTypeChecker.FindLinearKind(v) != LinearKind.LINEAR_OUT),
                    frame)
            };

            foreach (AssertCmd assertCmd in Enumerable.Union(first.firstGate, second.secondGate))
            {
                requires.Add(new Requires(false, assertCmd.Expr));
            }

            var witnesses          = civlTypeChecker.commutativityHints.GetWitnesses(first, second);
            var transitionRelation = TransitionRelationComputation.Commutativity(civlTypeChecker, second, first, frame, witnesses);

            var secondInParamsFiltered =
                second.secondImpl.InParams.Where(v => linearTypeChecker.FindLinearKind(v) != LinearKind.LINEAR_IN);
            IEnumerable <Expr> linearityAssumes = Enumerable.Union(
                linearTypeChecker.DisjointnessExprForEachDomain(first.firstImpl.OutParams.Union(secondInParamsFiltered)
                                                                .Union(frame)),
                linearTypeChecker.DisjointnessExprForEachDomain(first.firstImpl.OutParams.Union(second.secondImpl.OutParams)
                                                                .Union(frame)));
            // TODO: add further disjointness expressions?
            AssertCmd commutativityCheck = CmdHelper.AssertCmd(
                first.proc.tok,
                Expr.Imp(Expr.And(linearityAssumes), transitionRelation),
                $"Commutativity check between {first.proc.Name} and {second.proc.Name} failed");

            List <Cmd> cmds = new List <Cmd>
            {
                ActionCallCmd(first, first.firstImpl),
                ActionCallCmd(second, second.secondImpl)
            };

            foreach (var lemma in civlTypeChecker.commutativityHints.GetLemmas(first, second))
            {
                cmds.Add(CmdHelper.AssumeCmd(ExprHelper.FunctionCall(lemma.function, lemma.args.ToArray())));
            }
            cmds.Add(commutativityCheck);

            List <Variable> inputs  = Enumerable.Union(first.firstImpl.InParams, second.secondImpl.InParams).ToList();
            List <Variable> outputs = Enumerable.Union(first.firstImpl.OutParams, second.secondImpl.OutParams).ToList();

            AddChecker(checkerName, inputs, outputs, new List <Variable>(), requires, cmds);
        }