예제 #1
0
            private void ParseProc(out AtomicAction action)
            {
                TryNext("Expected procedure name.");
                Procedure proc = ctc.program.FindProcedure(ld);

                if (proc is null)
                {
                    Error("No procedure found with name of " + ld);
                    action = null;
                }
                else
                {
                    if (!ctc.procToAtomicAction.ContainsKey(proc))
                    {
                        ctc.checkingContext.Warning(node,
                                                    string.Format(
                                                        "Procedure {0} does not have a mover type, witness function is ignored.",
                                                        proc.Name));
                        // TODO: Add notes on this
                        errorCount++;
                        action = null;
                    }
                    else
                    {
                        action = ctc.procToAtomicAction[proc];
                    }
                }
            }
예제 #2
0
        private AtomicActionDuplicator(string prefix, AtomicAction action)
        {
            this.prefix = prefix;
            subst       = new Dictionary <Variable, Expr>();
            bound       = new Dictionary <Variable, Expr>();

            inParamsCopy  = new List <Variable>();
            outParamsCopy = new List <Variable>();
            localsCopy    = new List <Variable>();


            foreach (Variable x in action.impl.InParams)
            {
                Variable xCopy = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, prefix + x.Name, x.TypedIdent.Type), true, x.Attributes);
                inParamsCopy.Add(xCopy);
                subst[x] = Expr.Ident(xCopy);
            }
            foreach (Variable x in action.impl.OutParams)
            {
                Variable xCopy = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, prefix + x.Name, x.TypedIdent.Type), false, x.Attributes);
                outParamsCopy.Add(xCopy);
                subst[x] = Expr.Ident(xCopy);
            }

            foreach (Variable x in action.impl.LocVars)
            {
                Variable xCopy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, prefix + x.Name, x.TypedIdent.Type));
                subst[x] = Expr.Ident(xCopy);
                localsCopy.Add(xCopy);
            }
        }
예제 #3
0
        private void VisitFunction(Function function)
        {
            Debug.Assert(function.OutParams.Count == 1);
            List <CommutativityHint> hints = new List <CommutativityHint>();

            // First we collect all {:commutativity "first_action", "second_action"} attributes
            for (QKeyValue kv = function.Attributes; kv != null; kv = kv.Next)
            {
                if (kv.Key != CivlAttributes.COMMUTATIVITY)
                {
                    continue;
                }
                if (kv.Params.Count == 2 &&
                    kv.Params[0] is string firstActionName &&
                    kv.Params[1] is string secondActionName)
                {
                    firstAction  = ctc.FindAtomicActionOrAbstraction(firstActionName);
                    secondAction = ctc.FindAtomicActionOrAbstraction(secondActionName);
                    if (firstAction == null)
                    {
                        ctc.Error(kv, $"Could not find atomic action {firstActionName}");
                    }
                    if (secondAction == null)
                    {
                        ctc.Error(kv, $"Could not find atomic action {secondActionName}");
                    }
                    if (firstAction != null && secondAction != null)
                    {
                        CheckInParams(function.InParams);
                    }
                    hints.Add(new CommutativityHint(function, firstAction, secondAction, args));
                }
 public static Expr Refinement(AtomicAction action, HashSet <Variable> frame)
 {
     return(ComputeTransitionRelation(
                action.impl, null,
                frame, null, null, false,
                string.Format("Transition relation of {0}", action.proc.Name)));
 }
 private static void SubstituteBackwardAssignments(AtomicAction action)
 {
     foreach (Block block in action.impl.Blocks)
     {
         List <Cmd> cmds = new List <Cmd>();
         foreach (Cmd cmd in block.cmds)
         {
             if (cmd is AssignCmd _assignCmd &&
                 QKeyValue.FindBoolAttribute(_assignCmd.Attributes, CivlAttributes.BACKWARD))
             {
                 AssignCmd assignCmd = _assignCmd.AsSimpleAssignCmd;
                 var       lhss      = assignCmd.Lhss;
                 var       rhss      = assignCmd.Rhss;
                 var       rhssVars  = rhss.SelectMany(x => VariableCollector.Collect(x));
                 var       lhssVars  = lhss.SelectMany(x => VariableCollector.Collect(x));
                 if (rhssVars.Intersect(lhssVars).Any())
                 {
                     // TODO
                     throw new NotImplementedException("Substitution of backward assignment where lhs appears on rhs");
                 }
                 else
                 {
                     List <Expr> assumeExprs = new List <Expr>();
                     for (int k = 0; k < lhss.Count; k++)
                     {
                         assumeExprs.Add(Expr.Eq(lhss[k].AsExpr, rhss[k]));
                     }
                     cmds.Add(new AssumeCmd(Token.NoToken, Expr.And(assumeExprs)));
                     cmds.Add(new HavocCmd(Token.NoToken, lhss.Select(x => x.DeepAssignedIdentifier).ToList()));
                 }
             }
예제 #6
0
        public InductiveSequentialization(CivlTypeChecker civlTypeChecker, AtomicAction inputAction, AtomicAction outputAction,
                                          AtomicAction invariantAction, Dictionary <AtomicAction, AtomicAction> elim)
        {
            this.civlTypeChecker = civlTypeChecker;
            this.inputAction     = inputAction;
            this.outputAction    = outputAction;
            this.invariantAction = invariantAction;
            this.elim            = elim;

            // TODO: check frame computation
            // We could compute a tighter frame per check. For example, base/conclusion checkers
            // don't have to take the eliminated actions into account.
            var frameVars = new List <AtomicAction> {
                invariantAction, outputAction, inputAction
            }
            .Union(elim.Select(kv => kv.Value))
            .SelectMany(a => a.gateUsedGlobalVars.Union(a.modifiedGlobalVars)).Distinct();

            this.frame    = new HashSet <Variable>(frameVars);
            this.modifies = frame.Select(Expr.Ident).ToList();

            newPAs = Expr.Ident(civlTypeChecker.LocalVariable("newPAs", civlTypeChecker.pendingAsyncMultisetType));
            if (HasChoice)
            {
                choice = Expr.Ident(invariantAction.impl.OutParams.Last());
            }
            else
            {
                choice = Expr.Ident(civlTypeChecker.LocalVariable("choice", civlTypeChecker.pendingAsyncType));
            }
        }
 public static Expr Nonblocking(AtomicAction action, HashSet <Variable> frame)
 {
     return(ComputeTransitionRelation(
                action.impl, null,
                frame, null, null, true,
                string.Format("Nonblocking expression of {0}", action.proc.Name)));
 }
예제 #8
0
 private CallCmd GetCallCmd(AtomicAction callee)
 {
     return(CmdHelper.CallCmd(
                callee.proc,
                invariantAction.impl.InParams.Select(Expr.Ident).ToList <Expr>(),
                invariantAction.impl.OutParams.GetRange(0, callee.impl.OutParams.Count).Select(Expr.Ident).ToList()
                ));
 }
예제 #9
0
 public CommutativityHint(Function function,
                          AtomicAction firstAction, AtomicAction secondAction, List <Expr> args)
 {
     this.function     = function;
     this.firstAction  = firstAction;
     this.secondAction = secondAction;
     this.args         = args;
 }
예제 #10
0
 private CallCmd GetCallCmd(AtomicAction callee)
 {
     return(CmdHelper.CallCmd(
                callee.proc,
                invariantAction.impl.InParams,
                invariantAction.impl.OutParams.GetRange(0, callee.impl.OutParams.Count)
                ));
 }
예제 #11
0
 public ActionProc(Procedure proc, AtomicAction refinedAction, int upperLayer, HashSet <Variable> hiddenFormals,
                   List <CallCmd> yieldRequires,
                   List <CallCmd> yieldEnsures)
     : base(proc, refinedAction.moverType, upperLayer, yieldRequires, yieldEnsures)
 {
     this.refinedAction = refinedAction;
     this.hiddenFormals = hiddenFormals;
 }
예제 #12
0
 public IEnumerable <CommutativityWitness> GetWitnesses(AtomicAction first, AtomicAction second)
 {
     witnesses.TryGetValue(Key(first, second), out List <CommutativityWitness> list);
     if (list == null)
     {
         return(Enumerable.Empty <CommutativityWitness>());
     }
     return(list);
 }
예제 #13
0
 public IEnumerable <CommutativityHint> GetLemmas(AtomicAction first, AtomicAction second)
 {
     lemmas.TryGetValue(Key(first, second), out List <CommutativityHint> list);
     if (list == null)
     {
         return(Enumerable.Empty <CommutativityHint>());
     }
     return(list);
 }
예제 #14
0
 public WitnessFunction(Function function, Variable witnessedVariable,
                        AtomicAction firstAction, AtomicAction secondAction, List <Expr> args)
 {
     this.function          = function;
     this.witnessedVariable = witnessedVariable;
     this.firstAction       = firstAction;
     this.secondAction      = secondAction;
     this.args = args;
 }
예제 #15
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 Expr Commutativity(AtomicAction first, AtomicAction second,
                                         HashSet <Variable> frame, IEnumerable <CommutativityWitness> witnesses)
        {
            var triggers = first.triggerFunctions.Union(second.triggerFunctions).ToDictionary(kv => kv.Key, kv => kv.Value);

            return(ComputeTransitionRelation(
                       first.secondImpl, second.firstImpl,
                       frame, triggers, witnesses, false,
                       string.Format("Transition relation of {0} ∘ {1}", first.proc.Name, second.proc.Name)));
        }
예제 #17
0
        private Expr GetTransitionRelation(AtomicAction atomicAction)
        {
            if (!transitionRelationCache.ContainsKey(atomicAction))
            {
                transitionRelationCache[atomicAction] =
                    TransitionRelationComputation.Refinement(civlTypeChecker, atomicAction, new HashSet <Variable>(this.oldGlobalMap.Keys));
            }

            return(transitionRelationCache[atomicAction]);
        }
예제 #18
0
        private Expr GetTransitionRelation(AtomicAction action)
        {
            var tr = TransitionRelationComputation.Refinement(civlTypeChecker, action, frame);

            if (action == invariantAction && HasChoice)
            {
                return(new ChoiceEraser(invariantAction.impl.OutParams.Last()).VisitExpr(tr));
            }
            return(tr);
        }
예제 #19
0
 public WitnessFunction(Function function, GlobalVariable globalVar,
                        AtomicAction firstAction, AtomicAction secondAction, List <int> layers)
 {
     this.function     = function;
     this.globalVar    = globalVar;
     this.firstAction  = firstAction;
     this.secondAction = secondAction;
     this.layers       = layers;
     this.InputArgs    = new List <InputArgument>();
 }
        private static Tuple <Procedure, Implementation> GenerateAbstractionChecker(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 tr      = TransitionRelationComputation.Refinement(abs, frame);
            var ensures = new List <Ensures> {
                new Ensures(false, tr)
                {
                    ErrorData = $"Abstraction {abs.proc.Name} does not summarize {action.proc.Name}"
                }
            };

            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.Select(Expr.Ident).ToList <Expr>(),
                    abs.impl.OutParams.Select(Expr.Ident).ToList()
                    ));
            var blocks = new List <Block> {
                new Block(Token.NoToken, "init", cmds, CmdHelper.ReturnCmd)
            };

            var proc = new Procedure(
                Token.NoToken,
                $"AbstractionCheck_{action.proc.Name}_{abs.proc.Name}",
                new List <TypeVariable>(),
                abs.impl.InParams,
                abs.impl.OutParams,
                requires,
                action.proc.Modifies,
                ensures);
            var impl = new Implementation(
                Token.NoToken,
                proc.Name,
                new List <TypeVariable>(),
                proc.InParams,
                proc.OutParams,
                new List <Variable>(),
                blocks)
            {
                Proc = proc
            };

            return(Tuple.Create(proc, impl));
        }
예제 #21
0
 public static IEnumerable <AssertCmd> GetGateAsserts(AtomicAction action, Substitution subst, string msg)
 {
     foreach (var gate in action.gate)
     {
         AssertCmd cmd =
             subst != null
   ? (AssertCmd)Substituter.Apply(subst, gate)
   : new AssertCmd(gate.tok, gate.Expr);
         cmd.ErrorData = msg;
         yield return(cmd);
     }
 }
예제 #22
0
        public static void SetupCopy(AtomicAction action, ref List <AssertCmd> gateCopy, ref Implementation implCopy, string prefix)
        {
            var aad = new AtomicActionDuplicator(prefix, action);

            gateCopy = new List <AssertCmd>();
            foreach (AssertCmd assertCmd in action.gate)
            {
                gateCopy.Add((AssertCmd)aad.Visit(assertCmd));
            }

            implCopy = aad.VisitImplementation(action.impl);
        }
예제 #23
0
        public Tuple <Procedure, Implementation> GenerateStepChecker(AtomicAction pendingAsync, Function pendingAsyncAdd)
        {
            this.checkName = "step";
            var requires = invariantAction.gate.Select(g => new Requires(false, g.Expr)).ToList();
            var ensures  = new List <Ensures> {
                GetEnsures(GetTransitionRelation(invariantAction))
            };
            var locals = new List <Variable>();

            if (!HasChoice)
            {
                locals.Add(choice.Decl);
            }

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

            cmds.Add(GetCallCmd(invariantAction));
            cmds.Add(CmdHelper.AssumeCmd(ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, choice)));
            cmds.Add(CmdHelper.AssumeCmd(Expr.Gt(Expr.Select(PAs, choice), Expr.Literal(0))));
            cmds.Add(RemoveChoice);

            AtomicAction abs = elim[pendingAsync];
            Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>();
            List <Expr> inputExprs          = new List <Expr>();

            for (int i = 0; i < abs.impl.InParams.Count; i++)
            {
                var pendingAsyncParam = ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.selectors[i], choice);
                map[abs.impl.InParams[i]] = pendingAsyncParam;
                inputExprs.Add(pendingAsyncParam);
            }
            var subst = Substituter.SubstitutionFromHashtable(map);

            cmds.AddRange(GetGateAsserts(abs, subst));

            List <IdentifierExpr> outputVars = new List <IdentifierExpr>();

            if (abs.HasPendingAsyncs)
            {
                locals.Add(newPAs.Decl);
                outputVars.Add(newPAs);
            }
            cmds.Add(CmdHelper.CallCmd(abs.proc, inputExprs, outputVars));
            if (abs.HasPendingAsyncs)
            {
                cmds.Add(AddNewPAs(pendingAsyncAdd));
            }
            var blocks = new List <Block> {
                new Block(Token.NoToken, pendingAsync.proc.Name, cmds, CmdHelper.ReturnCmd)
            };

            return(GetCheckerTuple(requires, ensures, locals, blocks, "_" + abs.proc.Name));
        }
예제 #24
0
            private void CheckArg(AtomicAction action, Type type, string name)
            {
                var proc = action.proc;
                var v    = proc.InParams.Union(proc.OutParams).
                           FirstOrDefault(i => i.Name == name && i.TypedIdent.Type.Equals(type));

                if (v is null)
                {
                    Error(string.Format("No parameter {0}:{1} found in {2}",
                                        name, type, action.proc.Name));
                }
            }
예제 #25
0
        public static Substitution GetSubstitution(AtomicAction from, AtomicAction to)
        {
            Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>();

            for (int i = 0; i < from.impl.InParams.Count; i++)
            {
                map[from.impl.InParams[i]] = Expr.Ident(to.impl.InParams[i]);
            }
            for (int i = 0; i < Math.Min(from.impl.OutParams.Count, to.impl.OutParams.Count); i++)
            {
                map[from.impl.OutParams[i]] = Expr.Ident(to.impl.OutParams[i]);
            }
            return(Substituter.SubstitutionFromHashtable(map));
        }
예제 #26
0
        private void CreateNonBlockingChecker(AtomicAction action)
        {
            if (!action.HasAssumeCmd)
            {
                return;
            }

            string checkerName = $"NonBlockingChecker_{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 => linearTypeChecker.FindLinearKind(v) != LinearKind.LINEAR_OUT), frame)
            };

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

            Expr nonBlockingExpr = TransitionRelationComputation.
                                   Nonblocking(action, frame);
            AssertCmd nonBlockingAssert = new AssertCmd(action.proc.tok, nonBlockingExpr)
            {
                ErrorData = $"Non-blocking check for {action.proc.Name} failed"
            };

            Block block = new Block(action.proc.tok, "L", new List <Cmd> {
                nonBlockingAssert
            },
                                    new ReturnCmd(Token.NoToken));

            AddChecker(checkerName, new List <Variable>(impl.InParams), new List <Variable>(),
                       new List <Variable>(), requires, new List <Ensures>(), new List <Block> {
                block
            });
        }
예제 #27
0
 private void VisitFunction(Function function)
 {
     Debug.Assert(function.OutParams.Count == 1);
     for (QKeyValue kv = function.Attributes; kv != null; kv = kv.Next)
     {
         if (kv.Key != CivlAttributes.WITNESS)
         {
             continue;
         }
         if (kv.Params.Count == 3 &&
             kv.Params[0] is string witnessedVariableName &&
             kv.Params[1] is string firstActionName &&
             kv.Params[2] is string secondActionName)
         {
             witnessedVariable = ctc.sharedVariables.Find(v => v.Name == witnessedVariableName);
             if (witnessedVariable == null)
             {
                 ctc.Error(kv, $"Could not find shared variable {witnessedVariableName}");
             }
             else if (!function.OutParams[0].TypedIdent.Type.Equals(witnessedVariable.TypedIdent.Type))
             {
                 ctc.Error(function, "Result type does not match witnessed variable");
             }
             firstAction  = ctc.FindAtomicAction(firstActionName);
             secondAction = ctc.FindAtomicAction(secondActionName);
             if (firstAction == null)
             {
                 ctc.Error(kv, $"Could not find atomic action {firstActionName}");
             }
             if (secondAction == null)
             {
                 ctc.Error(kv, $"Could not find atomic action {firstActionName}");
             }
             if (firstAction != null && secondAction != null)
             {
                 CheckInParams(function.InParams);
             }
             allWitnessFunctions.Add(new WitnessFunction(function, witnessedVariable,
                                                         firstAction, secondAction, args));
         }
예제 #28
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));
        }
예제 #29
0
 private IEnumerable <AssertCmd> GetGateAsserts(AtomicAction action, Substitution subst)
 {
     return(GetGateAsserts(action, subst,
                           $"Gate of {action.proc.Name} fails in IS {checkName} of {inputAction.proc.Name}"));
 }
예제 #30
0
 private Tuple <AtomicAction, AtomicAction> Key(AtomicAction first, AtomicAction second)
 {
     return(Tuple.Create(first, second));
 }