Example #1
0
        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(CmdHelper.AssumeCmd(Expr.And(assumeExprs)));
                            cmds.Add(CmdHelper.HavocCmd(lhss.Select(x => x.DeepAssignedIdentifier).ToList()));
                        }
                    }
Example #2
0
        private Block CreateUnchangedCheckerBlock()
        {
            var newCmds = new List <Cmd>();

            newCmds.AddRange(refinementInstrumentation.CreateUnchangedAssertCmds());
            newCmds.Add(CmdHelper.AssumeCmd(Expr.False));
            return(BlockHelper.Block(civlTypeChecker.AddNamePrefix("UnchangedChecker"), newCmds));
        }
Example #3
0
        private Block CreateNoninterferenceCheckerBlock()
        {
            var newCmds = new List <Cmd>();

            newCmds.AddRange(noninterferenceInstrumentation.CreateCallToYieldProc());
            newCmds.Add(CmdHelper.AssumeCmd(Expr.False));
            return(BlockHelper.Block(civlTypeChecker.AddNamePrefix("NoninterferenceChecker"), newCmds));
        }
        public List <Cmd> ProcDisjointnessAssumeCmds(Procedure proc, bool atEntry)
        {
            IEnumerable <Variable> availableVars = atEntry
        ? FilterInParams(proc.InParams)
        : FilterInOutParams(proc.InParams.Union(proc.OutParams));

            return(DisjointnessExprs(availableVars).Select(expr => CmdHelper.AssumeCmd(expr)).ToList <Cmd>());
        }
 public void AddTriggerAssumes(Program program)
 {
     foreach (Variable v in impl.LocVars)
     {
         var f = triggerFunctions[v];
         program.AddTopLevelDeclaration(f);
         var assume = CmdHelper.AssumeCmd(ExprHelper.FunctionCall(f, Expr.Ident(v)));
         impl.Blocks[0].Cmds.Insert(0, assume);
     }
 }
Example #6
0
        public override List <Cmd> CreateAssumeCmds()
        {
            // assume pc || gate(i, g);
            Expr assumeExpr = Expr.Or(Expr.Ident(pc), gate);

            assumeExpr.Type = Type.Bool;
            return(new List <Cmd> {
                CmdHelper.AssumeCmd(assumeExpr)
            });
        }
Example #7
0
        private Block CreateReturnCheckerBlock()
        {
            var returnBlockCmds = new List <Cmd>();

            returnBlockCmds.AddRange(refinementInstrumentation.CreateAssertCmds());
            returnBlockCmds.AddRange(refinementInstrumentation.CreateUpdatesToRefinementVars(false));
            returnBlockCmds.AddRange(refinementInstrumentation.CreateReturnAssertCmds());
            returnBlockCmds.Add(CmdHelper.AssumeCmd(Expr.False));
            return(BlockHelper.Block(civlTypeChecker.AddNamePrefix("ReturnChecker"), returnBlockCmds));
        }
Example #8
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));
        }
Example #9
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));
        }
Example #10
0
        public override List <Cmd> CreateInitCmds()
        {
            var lhss = new List <IdentifierExpr> {
                Expr.Ident(pc), Expr.Ident(ok)
            };
            var rhss = new List <Expr> {
                Expr.False, Expr.False
            };
            var cmds = new List <Cmd> {
                CmdHelper.AssignCmd(lhss, rhss)
            };

            cmds.AddRange(CreateUpdatesToOldOutputVars());
            // assume spec gate at procedure entry
            cmds.Add(CmdHelper.AssumeCmd(gate));
            return(cmds);
        }
        public override List <Cmd> CreateInitCmds()
        {
            List <AssignLhs> lhss = new List <AssignLhs> {
                new SimpleAssignLhs(Token.NoToken, Expr.Ident(pc)),
                new SimpleAssignLhs(Token.NoToken, Expr.Ident(ok))
            };
            List <Expr> rhss = new List <Expr> {
                Expr.False, Expr.False
            };
            var cmds = new List <Cmd> {
                new AssignCmd(Token.NoToken, lhss, rhss)
            };

            cmds.AddRange(CreateUpdatesToOldOutputVars());
            // assume spec gate at procedure entry
            cmds.Add(CmdHelper.AssumeCmd(gate));
            return(cmds);
        }
Example #12
0
        private Dictionary <Implementation, List <Cmd> > CreatePreconditions(
            LinearPermissionInstrumentation linearPermissionInstrumentation)
        {
            var implToInitCmds = new Dictionary <Implementation, List <Cmd> >();

            foreach (var impl in absyMap.Keys.OfType <Implementation>())
            {
                var initCmds = new List <Cmd>();
                if (civlTypeChecker.GlobalVariables.Count() > 0)
                {
                    initCmds.Add(CmdHelper.HavocCmd(
                                     civlTypeChecker.GlobalVariables.Select(v => Expr.Ident(v)).ToList()));
                    linearPermissionInstrumentation.DisjointnessExprs(impl, true).ForEach(
                        expr => initCmds.Add(CmdHelper.AssumeCmd(expr)));

                    Substitution procToImplInParams = Substituter.SubstitutionFromHashtable(impl.Proc.InParams
                                                                                            .Zip(impl.InParams).ToDictionary(x => x.Item1, x => (Expr)Expr.Ident(x.Item2)));

                    impl.Proc.Requires.ForEach(req =>
                                               initCmds.Add(new AssumeCmd(req.tok, Substituter.Apply(procToImplInParams, req.Condition))));

                    foreach (var callCmd in GetYieldingProc(impl).yieldRequires)
                    {
                        var yieldInvariant = civlTypeChecker.procToYieldInvariant[callCmd.Proc];
                        if (layerNum == yieldInvariant.LayerNum)
                        {
                            Substitution callFormalsToActuals = Substituter.SubstitutionFromHashtable(callCmd.Proc.InParams
                                                                                                      .Zip(callCmd.Ins)
                                                                                                      .ToDictionary(x => x.Item1, x => (Expr)ExprHelper.Old(x.Item2)));
                            callCmd.Proc.Requires.ForEach(req => initCmds.Add(new AssumeCmd(req.tok,
                                                                                            Substituter.Apply(procToImplInParams,
                                                                                                              Substituter.Apply(callFormalsToActuals, req.Condition)))));
                        }
                    }
                }

                implToInitCmds[impl] = initCmds;
            }

            return(implToInitCmds);
        }
Example #13
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));
        }
Example #14
0
        public static List <Declaration> CreateNoninterferenceCheckers(
            CivlTypeChecker civlTypeChecker,
            int layerNum,
            AbsyMap absyMap,
            DeclWithFormals decl,
            List <Variable> declLocalVariables)
        {
            var linearTypeChecker = civlTypeChecker.linearTypeChecker;
            Dictionary <string, Variable>   domainNameToHoleVar = new Dictionary <string, Variable>();
            Dictionary <Variable, Variable> localVarMap         = new Dictionary <Variable, Variable>();
            Dictionary <Variable, Expr>     map = new Dictionary <Variable, Expr>();
            List <Variable> locals = new List <Variable>();
            List <Variable> inputs = new List <Variable>();

            foreach (var domainName in linearTypeChecker.linearDomains.Keys)
            {
                var inParam = linearTypeChecker.LinearDomainInFormal(domainName);
                inputs.Add(inParam);
                domainNameToHoleVar[domainName] = inParam;
            }

            foreach (Variable local in declLocalVariables.Union(decl.InParams).Union(decl.OutParams))
            {
                var copy = CopyLocal(local);
                locals.Add(copy);
                localVarMap[local] = copy;
                map[local]         = Expr.Ident(copy);
            }

            Dictionary <Variable, Expr> oldLocalMap = new Dictionary <Variable, Expr>();
            Dictionary <Variable, Expr> assumeMap   = new Dictionary <Variable, Expr>(map);

            foreach (Variable g in civlTypeChecker.GlobalVariables)
            {
                var copy = OldGlobalLocal(civlTypeChecker, g);
                locals.Add(copy);
                oldLocalMap[g] = Expr.Ident(copy);
                Formal f = SnapshotGlobalFormal(civlTypeChecker, g);
                inputs.Add(f);
                assumeMap[g] = Expr.Ident(f);
            }

            var linearPermissionInstrumentation = new LinearPermissionInstrumentation(civlTypeChecker,
                                                                                      layerNum, absyMap, domainNameToHoleVar, localVarMap);
            List <YieldInfo> yieldInfos = null;
            string           noninterferenceCheckerName = null;

            if (decl is Implementation impl)
            {
                noninterferenceCheckerName = $"impl_{absyMap.Original(impl).Name}_{layerNum}";
                yieldInfos = CollectYields(civlTypeChecker, absyMap, layerNum, impl).Select(kv =>
                                                                                            new YieldInfo(linearPermissionInstrumentation.DisjointnessAssumeCmds(kv.Key, false), kv.Value)).ToList();
            }
            else if (decl is Procedure proc)
            {
                yieldInfos = new List <YieldInfo>();
                if (civlTypeChecker.procToYieldInvariant.ContainsKey(proc))
                {
                    noninterferenceCheckerName = $"yield_{proc.Name}";
                    if (proc.Requires.Count > 0)
                    {
                        var disjointnessCmds = linearPermissionInstrumentation.ProcDisjointnessAssumeCmds(proc, true);
                        var yieldPredicates  = proc.Requires.Select(requires =>
                                                                    requires.Free
                ? (PredicateCmd) new AssumeCmd(requires.tok, requires.Condition)
                : (PredicateCmd) new AssertCmd(requires.tok, requires.Condition)).ToList();
                        yieldInfos.Add(new YieldInfo(disjointnessCmds, yieldPredicates));
                    }
                }
                else
                {
                    noninterferenceCheckerName = $"proc_{absyMap.Original(proc).Name}_{layerNum}";
                    if (proc.Requires.Count > 0)
                    {
                        var entryDisjointnessCmds =
                            linearPermissionInstrumentation.ProcDisjointnessAssumeCmds(proc, true);
                        var entryYieldPredicates = proc.Requires.Select(requires =>
                                                                        requires.Free
                ? (PredicateCmd) new AssumeCmd(requires.tok, requires.Condition)
                : (PredicateCmd) new AssertCmd(requires.tok, requires.Condition)).ToList();
                        yieldInfos.Add(new YieldInfo(entryDisjointnessCmds, entryYieldPredicates));
                    }

                    if (proc.Ensures.Count > 0)
                    {
                        var exitDisjointnessCmds =
                            linearPermissionInstrumentation.ProcDisjointnessAssumeCmds(proc, false);
                        var exitYieldPredicates = proc.Ensures.Select(ensures =>
                                                                      ensures.Free
                ? (PredicateCmd) new AssumeCmd(ensures.tok, ensures.Condition)
                : (PredicateCmd) new AssertCmd(ensures.tok, ensures.Condition)).ToList();
                        yieldInfos.Add(new YieldInfo(exitDisjointnessCmds, exitYieldPredicates));
                    }
                }
            }
            else
            {
                Debug.Assert(false);
            }

            var filteredYieldInfos = yieldInfos.Where(info =>
                                                      info.invariantCmds.Any(predCmd => new GlobalAccessChecker().AccessesGlobal(predCmd.Expr)));

            if (filteredYieldInfos.Count() == 0)
            {
                return(new List <Declaration>());
            }

            Substitution assumeSubst = Substituter.SubstitutionFromDictionary(assumeMap);
            Substitution oldSubst    = Substituter.SubstitutionFromDictionary(oldLocalMap);
            Substitution subst       = Substituter.SubstitutionFromDictionary(map);
            List <Block> noninterferenceCheckerBlocks = new List <Block>();
            List <Block> labelTargets = new List <Block>();
            Block        noninterferenceCheckerBlock = BlockHelper.Block("exit", new List <Cmd>());

            labelTargets.Add(noninterferenceCheckerBlock);
            noninterferenceCheckerBlocks.Add(noninterferenceCheckerBlock);
            int yieldCount = 0;

            foreach (var kv in filteredYieldInfos)
            {
                var newCmds = new List <Cmd>(kv.disjointnessCmds);
                foreach (var predCmd in kv.invariantCmds)
                {
                    var newExpr = Substituter.ApplyReplacingOldExprs(assumeSubst, oldSubst, predCmd.Expr);
                    newCmds.Add(new AssumeCmd(predCmd.tok, newExpr));
                }

                foreach (var predCmd in kv.invariantCmds)
                {
                    if (predCmd is AssertCmd)
                    {
                        var       newExpr   = Substituter.ApplyReplacingOldExprs(subst, oldSubst, predCmd.Expr);
                        AssertCmd assertCmd = new AssertCmd(predCmd.tok, newExpr, predCmd.Attributes);
                        assertCmd.ErrorData = "Non-interference check failed";
                        newCmds.Add(assertCmd);
                    }
                }

                newCmds.Add(CmdHelper.AssumeCmd(Expr.False));
                noninterferenceCheckerBlock = BlockHelper.Block("L" + yieldCount++, newCmds);
                labelTargets.Add(noninterferenceCheckerBlock);
                noninterferenceCheckerBlocks.Add(noninterferenceCheckerBlock);
            }

            noninterferenceCheckerBlocks.Insert(0, BlockHelper.Block("enter", new List <Cmd>(), labelTargets));

            // Create the yield checker procedure
            noninterferenceCheckerName = civlTypeChecker.AddNamePrefix($"NoninterferenceChecker_{noninterferenceCheckerName}");
            var noninterferenceCheckerProc = DeclHelper.Procedure(noninterferenceCheckerName,
                                                                  inputs, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>());

            CivlUtil.AddInlineAttribute(noninterferenceCheckerProc);

            // Create the yield checker implementation
            var noninterferenceCheckerImpl = DeclHelper.Implementation(noninterferenceCheckerProc,
                                                                       inputs, new List <Variable>(), locals, noninterferenceCheckerBlocks);

            CivlUtil.AddInlineAttribute(noninterferenceCheckerImpl);
            return(new List <Declaration> {
                noninterferenceCheckerProc, noninterferenceCheckerImpl
            });
        }
Example #15
0
        public Tuple <Procedure, Implementation> GenerateStepChecker(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 (elim.Values.Any(a => a.HasPendingAsyncs))
            {
                locals.Add(newPAs.Decl);
            }

            List <Block> blocks = new List <Block>();

            foreach (var pendingAsync in elim.Keys)
            {
                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);
                List <IdentifierExpr> outputVars = new List <IdentifierExpr>();
                if (abs.HasPendingAsyncs)
                {
                    outputVars.Add(newPAs);
                }

                List <Cmd> cmds = new List <Cmd>();
                cmds.Add(CmdHelper.AssumeCmd(ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, choice)));
                cmds.AddRange(GetGateAsserts(abs, subst));
                cmds.Add(CmdHelper.CallCmd(abs.proc, inputExprs, outputVars));
                if (abs.HasPendingAsyncs)
                {
                    cmds.Add(AddNewPAs(pendingAsyncAdd));
                }
                var block = new Block(Token.NoToken, pendingAsync.proc.Name, cmds, CmdHelper.ReturnCmd);
                blocks.Add(block);
            }

            {
                List <Cmd> cmds = new List <Cmd>();
                cmds.Add(GetCallCmd(invariantAction));
                if (HasChoice)
                {
                    cmds.Add(new AssumeCmd(Token.NoToken, ValidChoiceExpr));
                    cmds.Add(
                        new AssertCmd(Token.NoToken, ElimPendingAsyncExpr(choice))
                    {
                        ErrorData = $"Failed to validate choice in IS of {inputAction.proc.Name}"
                    }
                        );
                }
                else
                {
                    locals.Add(choice.Decl);
                    cmds.Add(new AssumeCmd(Token.NoToken, ElimPendingAsyncExpr(choice)));
                }
                cmds.Add(RemoveChoice);
                var initBlock = new Block(Token.NoToken, "init", cmds, new GotoCmd(Token.NoToken, blocks.ToList()));
                blocks.Insert(0, initBlock);
            }

            return(GetCheckerTuple(requires, ensures, locals, blocks));
        }
Example #16
0
    private static void AddChecker(CivlTypeChecker civlTypeChecker, Action action, List<Declaration> decls)
    {
      var linearTypeChecker = civlTypeChecker.linearTypeChecker;
      // Note: The implementation should be used as the variables in the
      //       gate are bound to implementation and not to the procedure.
      Implementation impl = action.impl;
      List<Variable> inputs = impl.InParams;
      List<Variable> outputs = impl.OutParams;

      List<Variable> locals = new List<Variable>(2);
      var paLocal1 = civlTypeChecker.LocalVariable("pa1", civlTypeChecker.pendingAsyncType);
      var paLocal2 = civlTypeChecker.LocalVariable("pa2", civlTypeChecker.pendingAsyncType);
      var pa1 = Expr.Ident(paLocal1);
      var pa2 = Expr.Ident(paLocal2);
      
      if (civlTypeChecker.pendingAsyncType != null)
      {
        locals.Add(paLocal1);
        locals.Add(paLocal2);
      }

      List<Requires> requires = action.gate.Select(a => new Requires(false, a.Expr)).ToList();
      List<LinearityCheck> linearityChecks = new List<LinearityCheck>();

      foreach (var domain in linearTypeChecker.linearDomains.Values)
      {
        // Linear in vars
        var inVars = inputs.Union(action.modifiedGlobalVars)
          .Where(x => linearTypeChecker.FindDomainName(x) == domain.domainName)
          .Where(x => InKinds.Contains(linearTypeChecker.FindLinearKind(x)))
          .Select(Expr.Ident)
          .ToList();
        
        // Linear out vars
        var outVars = inputs.Union(outputs).Union(action.modifiedGlobalVars)
          .Where(x => linearTypeChecker.FindDomainName(x) == domain.domainName)
          .Where(x => OutKinds.Contains(linearTypeChecker.FindLinearKind(x)))
          .Select(Expr.Ident)
          .ToList();

        // First kind
        // Permissions in linear output variables are a subset of permissions in linear input variables.
        if (outVars.Count > 0)
        {
          linearityChecks.Add(new LinearityCheck(
            null,
            OutPermsSubsetInPerms(domain, inVars, outVars),
            $"Potential linearity violation in outputs for domain {domain.domainName}.",
            "variables"));
        }

        if (action is AtomicAction atomicAction && atomicAction.HasPendingAsyncs)
        {
          var PAs = Expr.Ident(atomicAction.impl.OutParams.Last());
          
          foreach (var pendingAsync in atomicAction.pendingAsyncs)
          {
            var pendingAsyncLinearParams = PendingAsyncLinearParams(linearTypeChecker, domain, pendingAsync, pa1);

            if (pendingAsyncLinearParams.Count == 0) continue;

            // Second kind
            // Permissions in linear output variables + linear inputs of a single pending async
            // are a subset of permissions in linear input variables.
            var exactlyOnePA = Expr.And(
              ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, pa1),
              Expr.Eq(Expr.Select(PAs, pa1), Expr.Literal(1)));
            var outSubsetInExpr = OutPermsSubsetInPerms(domain, inVars, pendingAsyncLinearParams.Union(outVars));
            linearityChecks.Add(new LinearityCheck(
              exactlyOnePA,
              outSubsetInExpr,
              $"Potential linearity violation in outputs and pending async of {pendingAsync.proc.Name} for domain {domain.domainName}.",
              $"single_{pendingAsync.proc.Name}"));

            // Third kind
            // If there are two identical pending asyncs, then their input permissions mut be empty.
            var twoIdenticalPAs = Expr.And(
              ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, pa1),
              Expr.Ge(Expr.Select(PAs, pa1), Expr.Literal(2)));
            var emptyPerms = OutPermsSubsetInPerms(domain, Enumerable.Empty<Expr>(), pendingAsyncLinearParams);
            linearityChecks.Add(new LinearityCheck(
              twoIdenticalPAs,
              emptyPerms,
              $"Potential linearity violation in identical pending asyncs of {pendingAsync.proc.Name} for domain {domain.domainName}.",
              $"identical_{pendingAsync.proc.Name}"));
          }

          var pendingAsyncs = atomicAction.pendingAsyncs.ToList();
          for (int i = 0; i < pendingAsyncs.Count; i++)
          {
            var pendingAsync1 = pendingAsyncs[i];
            for (int j = i; j < pendingAsyncs.Count; j++)
            {
              var pendingAsync2 = pendingAsyncs[j];

              var pendingAsyncLinearParams1 = PendingAsyncLinearParams(linearTypeChecker, domain, pendingAsync1, pa1);
              var pendingAsyncLinearParams2 = PendingAsyncLinearParams(linearTypeChecker, domain, pendingAsync2, pa2);
              
              if (pendingAsyncLinearParams1.Count == 0 || pendingAsyncLinearParams2.Count == 0) continue;

              // Fourth kind
              // Input permissions of two non-identical pending asyncs (possibly of the same action)
              // are a subset of permissions in linear input variables.
              var membership = Expr.And(
                Expr.Neq(pa1, pa2),
                Expr.And(
                  ExprHelper.FunctionCall(pendingAsync1.pendingAsyncCtor.membership, pa1),
                  ExprHelper.FunctionCall(pendingAsync2.pendingAsyncCtor.membership, pa2)));

              var existing = Expr.And(
                Expr.Ge(Expr.Select(PAs, pa1), Expr.Literal(1)),
                Expr.Ge(Expr.Select(PAs, pa2), Expr.Literal(1)));

              var noDuplication = OutPermsSubsetInPerms(domain, inVars, pendingAsyncLinearParams1.Union(pendingAsyncLinearParams2));

              linearityChecks.Add(new LinearityCheck(
                Expr.And(membership, existing),
                noDuplication,
                $"Potential lnearity violation in pending asyncs of {pendingAsync1.proc.Name} and {pendingAsync2.proc.Name} for domain {domain.domainName}.",
                $"distinct_{pendingAsync1.proc.Name}_{pendingAsync2.proc.Name}"));
            }
          }
        }
      }

      if (linearityChecks.Count == 0) return;

      // Create checker blocks
      List<Block> checkerBlocks = new List<Block>(linearityChecks.Count);
      foreach (var lc in linearityChecks)
      {
        List<Cmd> cmds = new List<Cmd>(2);
        if (lc.assume != null)
        {
          cmds.Add(CmdHelper.AssumeCmd(lc.assume));
        }
        cmds.Add(new AssertCmd(action.proc.tok, lc.assert) { ErrorData = lc.message });
        var block = new Block(Token.NoToken, lc.name, cmds, CmdHelper.ReturnCmd);
        CivlUtil.ResolveAndTypecheck(block, ResolutionContext.State.Two);
        checkerBlocks.Add(block);
      }
      
      // Create init blocks
      List<Block> blocks = new List<Block>(linearityChecks.Count + 1);
      blocks.Add(
        new Block(
          Token.NoToken,
          "init",
          new List<Cmd> { CmdHelper.CallCmd(action.proc, inputs, outputs) },
          new GotoCmd(Token.NoToken, checkerBlocks)));
      blocks.AddRange(checkerBlocks);

      // Create the whole check procedure
      string checkerName = civlTypeChecker.AddNamePrefix($"LinearityChecker_{action.proc.Name}");
      Procedure linCheckerProc = new Procedure(Token.NoToken, checkerName, new List<TypeVariable>(),
        inputs, outputs, requires, action.proc.Modifies, new List<Ensures>());
      Implementation linCheckImpl = new Implementation(Token.NoToken, checkerName,
        new List<TypeVariable>(), inputs, outputs, locals, blocks);
      linCheckImpl.Proc = linCheckerProc;
      decls.Add(linCheckImpl);
      decls.Add(linCheckerProc);
    }
        public List <Cmd> DisjointnessAssumeCmds(Absy absy, bool addGlobals)
        {
            var availableVars = AvailableLinearLocalVars(absy).Union(addGlobals ? LinearGlobalVars() : new List <Variable>());

            return(DisjointnessExprs(availableVars).Select(expr => CmdHelper.AssumeCmd(expr)).ToList <Cmd>());
        }
Example #18
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);

            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(second, first, frame, witnesses);

            List <Cmd> cmds = new List <Cmd>
            {
                new CallCmd(Token.NoToken,
                            first.proc.Name,
                            first.firstImpl.InParams.Select(Expr.Ident).ToList <Expr>(),
                            first.firstImpl.OutParams.Select(Expr.Ident).ToList()
                            )
                {
                    Proc = first.proc
                },
                new CallCmd(Token.NoToken,
                            second.proc.Name,
                            second.secondImpl.InParams.Select(Expr.Ident).ToList <Expr>(),
                            second.secondImpl.OutParams.Select(Expr.Ident).ToList()
                            )
                {
                    Proc = second.proc
                }
            };

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

            var block = new Block(Token.NoToken, "init", cmds, new ReturnCmd(Token.NoToken));

            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?
            Ensures ensureCheck =
                new Ensures(first.proc.tok, false, Expr.Imp(Expr.And(linearityAssumes), transitionRelation), null)
            {
                ErrorData = $"Commutativity check between {first.proc.Name} and {second.proc.Name} failed"
            };
            List <Ensures> ensures = new List <Ensures> {
                ensureCheck
            };

            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, ensures, new List <Block> {
                block
            });
        }