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
            });
        }
        public override List <Cmd> CreateAssertCmds()
        {
            Expr assertExpr;

            // assert pc || g_old == g || transitionRelation(i, g_old, o, g);
            assertExpr = Expr.Or(Expr.Ident(pc), Expr.Or(OldEqualityExprForGlobals(), transitionRelation));
            assertExpr.Typecheck(new TypecheckingContext(null));
            var skipOrTransitionRelationAssertCmd = new AssertCmd(Token.NoToken, assertExpr);

            skipOrTransitionRelationAssertCmd.ErrorData = "Transition invariant violated in initial state";

            // assert pc ==> g_old == g && o_old == o;
            assertExpr = Expr.Imp(Expr.Ident(pc), Expr.And(OldEqualityExprForGlobals(), OldEqualityExprForOutputs()));
            assertExpr.Typecheck(new TypecheckingContext(null));
            AssertCmd skipAssertCmd = new AssertCmd(Token.NoToken, assertExpr);

            skipAssertCmd.ErrorData = "Transition invariant violated in final state";
            return(new List <Cmd> {
                skipOrTransitionRelationAssertCmd, skipAssertCmd
            });
        }
Esempio n. 3
0
        protected IExpr ParseLogicalExpression()
        {
            IExpr result = ParseCompareExpression();

            for (;;)
            {
                if (Consume('&') && ConsumeOrFail('&'))
                {
                    IExpr right = ParseCompareExpression();
                    result = Expr.And(result, right);
                }
                else if (Consume('|') && ConsumeOrFail('|'))
                {
                    IExpr right = ParseCompareExpression();
                    result = Expr.Or(result, right);
                }
                else
                {
                    return(result);
                }
            }
        }
Esempio n. 4
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
            });
        }
Esempio n. 5
0
        // Restricts a program to a single trace.
        //
        // Returns the new name of trace.procName.
        // Adds resultant declarations to output program
        public string addTrace(ErrorTrace trace)
        {
            var ret = addTraceRec(trace);

            // uninterpreted constants

            // Gather the uninterpreted sorts
            var sorts = new Dictionary <string, Microsoft.Boogie.Type>();

            uvalueToConstants.Values
            .Iter(s => s
                  .Iter(c => sorts[c.TypedIdent.Type.AsCtor.Decl.Name] = c.TypedIdent.Type));

            foreach (var sort in sorts.Values)
            {
                var uvalueToUniqueConst = new Dictionary <string, Constant>();
                var cnt = 0;
                foreach (var v in uvalueToConstants.Keys)
                {
                    var uconst = new Constant(Token.NoToken, new TypedIdent(Token.NoToken,
                                                                            "uc__" + sort.ToString() + "__" + (cnt++), sort), true);
                    uvalueToUniqueConst.Add(v, uconst);
                }
                output.AddTopLevelDeclarations(uvalueToUniqueConst.Values);
                foreach (var tup in uvalueToConstants)
                {
                    Expr expr   = Expr.True;
                    var  uconst = uvalueToUniqueConst[tup.Key];
                    tup.Value.Where(c => c.TypedIdent.Type.AsCtor.Decl.Name == sort.AsCtor.Decl.Name)
                    .Iter(c => expr = Expr.And(expr, Expr.Eq(Expr.Ident(c), Expr.Ident(uconst))));
                    if (expr != Expr.True)
                    {
                        output.AddTopLevelDeclaration(new Axiom(Token.NoToken, expr));
                    }
                }
            }

            return(ret);
        }
 private void ComputeTransitionRelationExpr()
 {
     CalculatePathExpression();
     AddBoundVariablesForRemainingVars();
     ReplacePreOrPostStateVars();
     TransitionRelationExpr = Expr.And(pathExprs);
     if (trc.IsJoint)
     {
         ComputeWitnessedTransitionRelationExprs();
         if (witnessedTransitionRelations.Count > 0)
         {
             TransitionRelationExpr = Expr.Or(witnessedTransitionRelations);
         }
     }
     if (existsVarMap.Any())
     {
         Trigger trigger = null;
         if (trc.IsJoint)
         {
             var exprs = new List <Expr>();
             foreach (var v in existsVarMap.Keys)
             {
                 var orig = copyToOriginalVar[v];
                 if (v == varCopies[orig].First() && trc.triggers.ContainsKey(orig))
                 {
                     var f = trc.triggers[orig];
                     exprs.Add(ExprHelper.FunctionCall(f, Expr.Ident(existsVarMap[v])));
                 }
             }
             if (exprs.Count == existsVarMap.Count)
             {
                 trigger = new Trigger(Token.NoToken, true, exprs);
             }
         }
         TransitionRelationExpr = new ExistsExpr(Token.NoToken,
                                                 existsVarMap.Values.ToList <Variable>(), trigger, TransitionRelationExpr);
     }
 }
Esempio n. 7
0
        /// <summary>
        /// Creates the body of Equals(object).
        /// </summary>
        private void CreateGenericEquals()
        {
            var eq = CreateMethod(
                "Equals",
                "bool",
                new[] { Expr.Arg <object>("obj") },
                false,
                true
                );

            // if(this.ReferenceEquals null obj)
            //    false
            // else
            //    (this.ReferenceEquals this obj) || ( (obj.GetType () == this.GetType()) && (this.Equals obj as <Name>))

            eq.Body.Add(
                Expr.If(
                    Expr.Invoke(Expr.This(), "ReferenceEquals", Expr.Null(), Expr.Get("obj")),
                    Expr.Block(Expr.False()),
                    Expr.Block(
                        Expr.Or(
                            Expr.Invoke(Expr.This(), "ReferenceEquals", Expr.This(), Expr.Get("obj")),
                            Expr.And(
                                Expr.Equal(
                                    Expr.Invoke(Expr.Get("obj"), "GetType"),
                                    Expr.Invoke(Expr.This(), "GetType")
                                    ),
                                Expr.Invoke(
                                    Expr.This(),
                                    "Equals",
                                    Expr.Cast(Expr.Get("obj"), Name)
                                    )
                                )
                            )
                        )
                    )
                );
        }
Esempio n. 8
0
    public Expr DisjointnessExprForPermissions(string domainName, IEnumerable<Expr> permissionsExprs)
    {
      Expr expr = Expr.True;
      if (permissionsExprs.Count() > 1)
      {
        int count = 0;
        List<Expr> subsetExprs = new List<Expr>();
        LinearDomain domain = linearDomains[domainName];
        BoundVariable partition = new BoundVariable(Token.NoToken,
          new TypedIdent(Token.NoToken, $"partition_{domainName}", domain.mapTypeInt));
        foreach (Expr e in permissionsExprs)
        {
          subsetExprs.Add(SubsetExpr(domain, e, partition, count));
          count++;
        }

        expr = new ExistsExpr(Token.NoToken, new List<Variable> {partition}, Expr.And(subsetExprs));
      }

      expr.Resolve(new ResolutionContext(null));
      expr.Typecheck(new TypecheckingContext(null));
      return expr;
    }
        internal override List <AssumeCmd> GetInstantiationCmds()
        {
            var result = new List <AssumeCmd>();

            foreach (var Instantiation in InstantiationExprs)
            {
                foreach (var Thread in new int[] { 1, 2 })
                {
                    var vd = new VariableDualiser(Thread, Dualiser.verifier.uniformityAnalyser, ProcName);
                    var ti = new ThreadInstantiator(Instantiation, Thread,
                                                    Dualiser.verifier.uniformityAnalyser, ProcName);

                    var Assume = new AssumeCmd(Token.NoToken,
                                               Expr.Imp(vd.VisitExpr(Predicate),
                                                        Expr.Imp(Expr.And(
                                                                     NonNegative(Instantiation),
                                                                     NotTooLarge(Instantiation)),
                                                                 ti.VisitExpr(BarrierInvariant))));
                    result.Add(vd.VisitAssumeCmd(Assume) as AssumeCmd);
                }
            }
            return(result);
        }
Esempio n. 10
0
        public override List <Cmd> CreateUpdatesToRefinementVars()
        {
            // pc := g_old == g ==> pc;
            // ok := transitionRelation(i, g_old, o, g) || (o_old == o && ok);
            List <AssignLhs> pcUpdateLHS = new List <AssignLhs>
            {
                new SimpleAssignLhs(Token.NoToken, Expr.Ident(pc)),
                new SimpleAssignLhs(Token.NoToken, Expr.Ident(ok))
            };
            List <Expr> pcUpdateRHS = new List <Expr>(
                new Expr[]
            {
                Expr.Imp(OldEqualityExprForGlobals(), Expr.Ident(pc)),
                Expr.Or(transitionRelation, Expr.And(OldEqualityExprForOutputs(), Expr.Ident(ok))),
            });

            foreach (Expr e in pcUpdateRHS)
            {
                e.Typecheck(new TypecheckingContext(null));
            }
            return(new List <Cmd> {
                new AssignCmd(Token.NoToken, pcUpdateLHS, pcUpdateRHS)
            });
        }
Esempio n. 11
0
        public override List <Cmd> CreateUpdatesToRefinementVars(bool isMarkedCall)
        {
            var cmds = new List <Cmd>();
            List <AssignLhs> pcOkUpdateLHS = new List <AssignLhs>
            {
                new SimpleAssignLhs(Token.NoToken, Expr.Ident(pc)),
                new SimpleAssignLhs(Token.NoToken, Expr.Ident(ok))
            };

            if (isMarkedCall)
            {
                // assert !pc;
                // pc, ok := true, true;
                cmds.Add(new AssertCmd(Token.NoToken, Expr.Not(Expr.Ident(pc))));
                List <Expr> pcOkUpdateRHS = new List <Expr>(new Expr[] { Expr.True, Expr.True });
                cmds.Add(new AssignCmd(Token.NoToken, pcOkUpdateLHS, pcOkUpdateRHS));
            }
            else
            {
                // pc, ok := g_old == g ==> pc, transitionRelation(i, g_old, o, g) || (o_old == o && ok);
                List <Expr> pcOkUpdateRHS = new List <Expr>(
                    new Expr[]
                {
                    Expr.Imp(OldEqualityExprForGlobals(), Expr.Ident(pc)),
                    Expr.Or(transitionRelation, Expr.And(OldEqualityExprForOutputs(), Expr.Ident(ok))),
                });
                cmds.Add(new AssignCmd(Token.NoToken, pcOkUpdateLHS, pcOkUpdateRHS));
            }

            foreach (var cmd in cmds)
            {
                cmd.Typecheck(new TypecheckingContext(null));
            }

            return(cmds);
        }
Esempio n. 12
0
        static void FKScanChildren(Parse parse, SrcList src, Table table, Index index, FKey fkey, int[] cols, int regDataId, int incr)
        {
            Context ctx    = parse.Ctx; // Database handle
            Vdbe    v      = parse.GetVdbe();
            Expr    where_ = null;      // WHERE clause to scan with

            Debug.Assert(index == null || index.Table == table);
            int fkIfZero = 0; // Address of OP_FkIfZero

            if (incr < 0)
            {
                fkIfZero = v.AddOp2(OP.FkIfZero, fkey.IsDeferred, 0);
            }

            // Create an Expr object representing an SQL expression like:
            //
            //   <parent-key1> = <child-key1> AND <parent-key2> = <child-key2> ...
            //
            // The collation sequence used for the comparison should be that of the parent key columns. The affinity of the parent key column should
            // be applied to each child key value before the comparison takes place.
            for (int i = 0; i < fkey.Cols.length; i++)
            {
                int  col;                                      // Index of column in child table
                Expr left = Expr.Expr(ctx, TK.REGISTER, null); // Value from parent table row
                if (left != null)
                {
                    // Set the collation sequence and affinity of the LHS of each TK_EQ expression to the parent key column defaults.
                    if (index != null)
                    {
                        col = index.Columns[i];
                        Column colObj = table.Cols[col];
                        if (table.PKey == col)
                        {
                            col = -1;
                        }
                        left.TableId = regDataId + col + 1;
                        left.Aff     = colObj.Affinity;
                        string collName = colObj.Coll;
                        if (collName == null)
                        {
                            collName = ctx.DefaultColl.Name;
                        }
                        left = Expr.AddCollateString(parse, left, collName);
                    }
                    else
                    {
                        left.TableId = regDataId;
                        left.Aff     = AFF.INTEGER;
                    }
                }
                col = (cols != null ? cols[i] : fkey.Cols[0].From);
                Debug.Assert(col >= 0);
                string colName = fkey.From.Cols[col].Name;                 // Name of column in child table
                Expr   right   = Expr.Expr(ctx, TK.ID, colName);           // Column ref to child table
                Expr   eq      = Expr.PExpr(parse, TK.EQ, left, right, 0); // Expression (pLeft = pRight)
                where_ = Expr.And(ctx, where_, eq);
            }

            // If the child table is the same as the parent table, and this scan is taking place as part of a DELETE operation (operation D.2), omit the
            // row being deleted from the scan by adding ($rowid != rowid) to the WHERE clause, where $rowid is the rowid of the row being deleted.
            if (table == fkey.From && incr > 0)
            {
                Expr left  = Expr.Expr(ctx, TK.REGISTER, null); // Value from parent table row
                Expr right = Expr.Expr(ctx, TK.COLUMN, null);   // Column ref to child table
                if (left != null && right != null)
                {
                    left.TableId   = regDataId;
                    left.Aff       = AFF.INTEGER;
                    right.TableId  = src.Ids[0].Cursor;
                    right.ColumnId = -1;
                }
                Expr eq = Expr.PExpr(parse, TK.NE, left, right, 0); // Expression (pLeft = pRight)
                where_ = Expr.And(ctx, where_, eq);
            }

            // Resolve the references in the WHERE clause.
            NameContext nameContext;                 // Context used to resolve WHERE clause

            nameContext         = new NameContext(); // memset( &sNameContext, 0, sizeof( NameContext ) );
            nameContext.SrcList = src;
            nameContext.Parse   = parse;
            ResolveExprNames(nameContext, ref where_);

            // Create VDBE to loop through the entries in src that match the WHERE clause. If the constraint is not deferred, throw an exception for
            // each row found. Otherwise, for deferred constraints, increment the deferred constraint counter by incr for each row selected.
            ExprList  dummy     = null;
            WhereInfo whereInfo = Where.Begin(parse, src, where_, ref dummy, 0); // Context used by sqlite3WhereXXX()

            if (incr > 0 && !fkey.IsDeferred)
            {
                E.Parse_Toplevel(parse).MayAbort = true;
            }
            v.AddOp2(OP.FkCounter, fkey.IsDeferred, incr);
            if (whereInfo != null)
            {
                Where.End(whereInfo);
            }

            // Clean up the WHERE clause constructed above.
            Expr.Delete(ctx, ref where_);
            if (fkIfZero != 0)
            {
                v.JumpHere(fkIfZero);
            }
        }
Esempio n. 13
0
        public Implementation Inject(Implementation implementation, Program programInCachedSnapshot)
        {
            Contract.Requires(implementation != null && programInCachedSnapshot != null);

            this.programInCachedSnapshot = programInCachedSnapshot;
            assumptionVariableCount      = 0;
            temporaryVariableCount       = 0;
            currentImplementation        = implementation;

            #region Introduce explict assumption about the precondition.

            var oldProc = programInCachedSnapshot.FindProcedure(currentImplementation.Proc.Name);
            if (oldProc != null &&
                oldProc.DependencyChecksum != currentImplementation.Proc.DependencyChecksum &&
                currentImplementation.ExplicitAssumptionAboutCachedPrecondition == null)
            {
                var  axioms      = new List <Axiom>();
                var  after       = new List <Cmd>();
                Expr assumedExpr = new LiteralExpr(Token.NoToken, false);
                var  canUseSpecs = DependencyCollector.CanExpressOldSpecs(oldProc, Program, true);
                if (canUseSpecs && oldProc.SignatureEquals(currentImplementation.Proc))
                {
                    var always = Substituter.SubstitutionFromHashtable(currentImplementation.GetImplFormalMap(), true,
                                                                       currentImplementation.Proc);
                    var forOld  = Substituter.SubstitutionFromHashtable(new Dictionary <Variable, Expr>());
                    var clauses = oldProc.Requires.Select(r =>
                                                          Substituter.FunctionCallReresolvingApply(always, forOld, r.Condition, Program));
                    var conj = Expr.And(clauses, true);
                    assumedExpr = conj != null
            ? FunctionExtractor.Extract(conj, Program, axioms)
            : new LiteralExpr(Token.NoToken, true);
                }

                if (assumedExpr != null)
                {
                    var lv = new LocalVariable(Token.NoToken,
                                               new TypedIdent(Token.NoToken, string.Format("a##cached##{0}", FreshAssumptionVariableName), Type.Bool),
                                               new QKeyValue(Token.NoToken, "assumption", new List <object>(), null));
                    currentImplementation.InjectAssumptionVariable(lv, !canUseSpecs);
                    var lhs     = new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, lv));
                    var rhs     = LiteralExpr.And(new IdentifierExpr(Token.NoToken, lv), assumedExpr);
                    var assumed = new AssignCmd(currentImplementation.tok, new List <AssignLhs> {
                        lhs
                    }, new List <Expr> {
                        rhs
                    });
                    assumed.IrrelevantForChecksumComputation = true;
                    currentImplementation.ExplicitAssumptionAboutCachedPrecondition = assumed;
                    after.Add(assumed);
                }

                if (CommandLineOptions.Clo.TraceCachingForTesting || CommandLineOptions.Clo.TraceCachingForBenchmarking)
                {
                    using (var tokTxtWr = new TokenTextWriter("<console>", Console.Out, false, false))
                    {
                        var loc = currentImplementation.tok != null && currentImplementation.tok != Token.NoToken
              ? string.Format("{0}({1},{2})", currentImplementation.tok.filename, currentImplementation.tok.line,
                              currentImplementation.tok.col)
              : "<unknown location>";
                        Console.Out.WriteLine("Processing implementation {0} (at {1}):", currentImplementation.Name, loc);
                        foreach (var a in axioms)
                        {
                            Console.Out.Write("  >>> added axiom: ");
                            a.Expr.Emit(tokTxtWr);
                            Console.Out.WriteLine();
                        }

                        foreach (var b in after)
                        {
                            Console.Out.Write("  >>> added after assuming the current precondition: ");
                            b.Emit(tokTxtWr, 0);
                        }
                    }
                }
            }

            #endregion

            var result = VisitImplementation(currentImplementation);
            currentImplementation        = null;
            this.programInCachedSnapshot = null;
            return(result);
        }
Esempio n. 14
0
        public ActionRefinementInstrumentation(
            CivlTypeChecker civlTypeChecker,
            Implementation impl,
            Implementation originalImpl,
            Dictionary <Variable, Variable> oldGlobalMap)
        {
            this.civlTypeChecker = civlTypeChecker;
            this.tok             = impl.tok;
            this.oldGlobalMap    = new Dictionary <Variable, Variable>();
            ActionProc actionProc = civlTypeChecker.procToYieldingProc[originalImpl.Proc] as ActionProc;

            this.layerNum = actionProc.upperLayer;
            foreach (Variable v in civlTypeChecker.GlobalVariables)
            {
                var layerRange = civlTypeChecker.GlobalVariableLayerRange(v);
                if (layerRange.lowerLayerNum <= layerNum && layerNum < layerRange.upperLayerNum)
                {
                    this.oldGlobalMap[v] = oldGlobalMap[v];
                }
            }

            this.newLocalVars = new List <Variable>();
            pc = civlTypeChecker.LocalVariable("pc", Type.Bool);
            newLocalVars.Add(pc);
            ok = civlTypeChecker.LocalVariable("ok", Type.Bool);
            newLocalVars.Add(ok);

            this.transitionRelationCache = new Dictionary <AtomicAction, Expr>();

            oldOutputMap = new Dictionary <Variable, Variable>();
            foreach (Variable f in impl.OutParams)
            {
                LocalVariable copy = Old(f);
                newLocalVars.Add(copy);
                oldOutputMap[f] = copy;
            }

            Dictionary <Variable, Expr> foroldMap = new Dictionary <Variable, Expr>();

            foreach (Variable g in civlTypeChecker.GlobalVariables)
            {
                foroldMap[g] = Expr.Ident(oldGlobalMap[g]);
            }

            // The parameters of an atomic action come from the implementation that denotes the atomic action specification.
            // To use the transition relation computed below in the context of the yielding procedure of the refinement check,
            // we need to substitute the parameters.
            AtomicAction   atomicAction           = actionProc.refinedAction;
            Implementation atomicActionImpl       = atomicAction.impl;
            Dictionary <Variable, Expr> alwaysMap = new Dictionary <Variable, Expr>();

            for (int i = 0, j = 0; i < impl.InParams.Count; i++)
            {
                if (civlTypeChecker.FormalRemainsInAction(actionProc, actionProc.proc.InParams[i]))
                {
                    alwaysMap[atomicActionImpl.InParams[j]] = Expr.Ident(impl.InParams[i]);
                    j++;
                }
            }

            for (int i = 0, j = 0; i < impl.OutParams.Count; i++)
            {
                if (civlTypeChecker.FormalRemainsInAction(actionProc, actionProc.proc.OutParams[i]))
                {
                    alwaysMap[atomicActionImpl.OutParams[j]] = Expr.Ident(impl.OutParams[i]);
                    j++;
                }
            }

            if (atomicAction.HasPendingAsyncs)
            {
                Variable collectedPAs = civlTypeChecker.implToPendingAsyncCollector[originalImpl];
                alwaysMap[atomicActionImpl.OutParams.Last()] = Expr.Ident(collectedPAs);
                LocalVariable copy = Old(collectedPAs);
                newLocalVars.Add(copy);
                oldOutputMap[collectedPAs] = copy;
            }

            Substitution always = Substituter.SubstitutionFromHashtable(alwaysMap);
            Substitution forold = Substituter.SubstitutionFromHashtable(foroldMap);
            Expr         transitionRelationExpr = GetTransitionRelation(atomicAction);

            transitionRelation = Substituter.ApplyReplacingOldExprs(always, forold, transitionRelationExpr);
            Expr gateExpr = Expr.And(atomicAction.gate.Select(g => g.Expr));

            gateExpr.Type = Type.Bool;
            gate          = Substituter.Apply(always, gateExpr);
        }
Esempio n. 15
0
 private Expr OldEqualityExprForOutputs()
 {
     return(Expr.And(this.oldOutputMap.Select(kvPair => Expr.Eq(Expr.Ident(kvPair.Key), Expr.Ident(kvPair.Value)))));
 }
Esempio n. 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);
    }
Esempio n. 17
0
        private void InstrumentWriteAccessInvariantsInEntryPointRegion(InstrumentationRegion region)
        {
            foreach (var pair in region.GetResourceAccesses())
            {
                var waVars = base.WriteAccessCheckingVariables.FindAll(val =>
                                                                       val.Name.Contains(pair.Key + "_$"));

                if (this.EP.ForceWriteResource.Contains(pair.Key))
                {
                    continue;
                }
                if (!this.EP.HasWriteAccess.ContainsKey(pair.Key))
                {
                    foreach (var variable in waVars)
                    {
                        base.InstrumentEnsures(region, variable, false);
                        foreach (var block in region.LoopHeaders())
                        {
                            base.InstrumentAssert(block, variable, false);
                        }
                    }

                    continue;
                }

                Expr nonWatchedExpr = null;
                foreach (var watchedVar in base.AccessWatchdogConstants)
                {
                    if (!watchedVar.Name.EndsWith(pair.Key))
                    {
                        continue;
                    }

                    foreach (var access in pair.Value)
                    {
                        var watchedExpr = Expr.Eq(new IdentifierExpr(watchedVar.tok, watchedVar), access);

                        foreach (var variable in waVars)
                        {
                            base.InstrumentImpliesEnsuresCandidate(region, watchedExpr, variable, false, true);
                            foreach (var block in region.LoopHeaders())
                            {
                                base.InstrumentImpliesAssertCandidate(block, watchedExpr, variable, false, true);
                            }
                        }

                        if (nonWatchedExpr == null)
                        {
                            nonWatchedExpr = Expr.Neq(new IdentifierExpr(watchedVar.tok, watchedVar), access);
                        }
                        else
                        {
                            nonWatchedExpr = Expr.And(nonWatchedExpr,
                                                      Expr.Neq(new IdentifierExpr(watchedVar.tok, watchedVar), access));
                        }
                    }
                }

                foreach (var variable in waVars)
                {
                    base.InstrumentImpliesEnsuresCandidate(region, nonWatchedExpr, variable, false, true);
                    foreach (var block in region.LoopHeaders())
                    {
                        base.InstrumentImpliesAssertCandidate(block, nonWatchedExpr, variable, false, true);
                    }
                }
            }
        }
Esempio n. 18
0
 private Requires DisjointnessRequires(IEnumerable <Variable> paramVars, HashSet <Variable> frame)
 {
     return(new Requires(false, Expr.And(linearTypeChecker.DisjointnessExprForEachDomain(paramVars.Union(frame)))));
 }
Esempio n. 19
0
        private void CreateFailurePreservationChecker(AtomicAction first, AtomicAction second)
        {
            if (!first.gateUsedGlobalVars.Intersect(second.modifiedGlobalVars).Any())
            {
                return;
            }
            if (!failurePreservationCheckerCache.Add(Tuple.Create(first, second)))
            {
                return;
            }

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

            frame.UnionWith(first.gateUsedGlobalVars);
            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)
            };
            Expr firstNegatedGate = Expr.Not(Expr.And(first.firstGate.Select(a => a.Expr)));

            firstNegatedGate.Type = Type.Bool; // necessary?
            requires.Add(new Requires(false, firstNegatedGate));
            foreach (AssertCmd assertCmd in second.secondGate)
            {
                requires.Add(new Requires(false, assertCmd.Expr));
            }

            IEnumerable <Expr> linearityAssumes =
                linearTypeChecker.DisjointnessExprForEachDomain(first.firstImpl.InParams.Union(second.secondImpl.OutParams)
                                                                .Union(frame));
            Ensures ensureCheck =
                new Ensures(first.proc.tok, false, Expr.Imp(Expr.And(linearityAssumes), firstNegatedGate), null)
            {
                ErrorData = $"Gate failure of {first.proc.Name} not preserved by {second.proc.Name}"
            };
            List <Ensures> ensures = new List <Ensures> {
                ensureCheck
            };

            string checkerName = $"FailurePreservationChecker_{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();
            var             block   = new Block(Token.NoToken, "init",
                                                new List <Cmd>
            {
                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
                }
            },
                                                new ReturnCmd(Token.NoToken));

            AddChecker(checkerName, inputs, outputs, new List <Variable>(), requires, ensures, new List <Block> {
                block
            });
        }
Esempio n. 20
0
        private static void GenerateCandidateForEnabledness(GPUVerifier verifier, Implementation impl, IRegion region)
        {
            Block header = region.Header();

            if (verifier.UniformityAnalyser.IsUniform(impl.Name, header))
            {
                return;
            }

            var cfg = Program.GraphFromImpl(impl);
            Dictionary <Block, HashSet <Block> > controlDependence = cfg.ControlDependence();

            controlDependence.TransitiveClosure();
            cfg.ComputeLoops();
            var loopNodes = cfg.BackEdgeNodes(header).Select(item => cfg.NaturalLoops(header, item)).SelectMany(item => item);

            Expr guardEnclosingLoop = null;

            foreach (var b in controlDependence.Keys.Where(item => controlDependence[item].Contains(region.Header())))
            {
                foreach (var succ in cfg.Successors(b).Where(item => cfg.DominatorMap.DominatedBy(header, item)))
                {
                    var guard = MaybeExtractGuard(verifier, impl, succ);
                    if (guard != null)
                    {
                        guardEnclosingLoop = guardEnclosingLoop == null ? guard : Expr.And(guardEnclosingLoop, guard);
                        break;
                    }
                }
            }

            if (guardEnclosingLoop != null)
            {
                verifier.AddCandidateInvariant(
                    region,
                    Expr.Imp(Expr.Ident(verifier.FindOrCreateEnabledVariable()), guardEnclosingLoop),
                    "conditionsImpliedByEnabledness");
            }

            var   cfgDual = cfg.Dual(new Block());
            Block loopConditionDominator = header;

            // The dominator might have multiple successors
            while (cfg.Successors(loopConditionDominator).Count(item => loopNodes.Contains(item)) > 1)
            {
                // Find the immediate post-dominator of the successors
                Block block = null;
                foreach (var succ in cfg.Successors(loopConditionDominator).Where(item => loopNodes.Contains(item)))
                {
                    if (block == null)
                    {
                        block = succ;
                    }
                    else
                    {
                        block = cfgDual.DominatorMap.LeastCommonAncestor(block, succ);
                    }
                }

                // Use the immediate post-dominator
                loopConditionDominator = block;
            }

            Expr guardIncludingLoopCondition = null;

            foreach (var succ in cfg.Successors(loopConditionDominator).Where(item => loopNodes.Contains(item)))
            {
                var guard = MaybeExtractGuard(verifier, impl, succ);
                if (guard != null)
                {
                    // There is at most one successor, so it's safe not use GuardIncludingLoopCondition on the rhs
                    guardIncludingLoopCondition = guardEnclosingLoop == null ? guard : Expr.And(guardEnclosingLoop, guard);
                    break;
                }
            }

            if (guardIncludingLoopCondition != null)
            {
                verifier.AddCandidateInvariant(
                    region, Expr.Imp(guardIncludingLoopCondition, Expr.Ident(verifier.FindOrCreateEnabledVariable())), "conditionsImplyingEnabledness", "do_not_predicate");
            }
        }
        // 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());
            }
        }
Esempio n. 22
0
 private Requires DisjointnessRequires(Program program, IEnumerable <Variable> paramVars, HashSet <Variable> frame)
 {
     return(new Requires(false, Expr.And(DisjointnessExpr(program, paramVars, frame))));
 }
        public SomeRefinementInstrumentation(
            CivlTypeChecker civlTypeChecker,
            Implementation impl,
            Implementation originalImpl,
            Dictionary <Variable, Variable> oldGlobalMap,
            HashSet <Block> yieldingLoopHeaders)
        {
            newLocalVars = new List <Variable>();
            YieldingProc yieldingProc = civlTypeChecker.procToYieldingProc[originalImpl.Proc];
            int          layerNum     = yieldingProc.upperLayer;

            pc = Pc();
            newLocalVars.Add(pc);
            ok = Ok();
            newLocalVars.Add(ok);

            this.transitionRelationCache = new Dictionary <AtomicAction, Expr>();

            this.oldGlobalMap = new Dictionary <Variable, Variable>();
            foreach (Variable v in civlTypeChecker.sharedVariables)
            {
                var layerRange = civlTypeChecker.GlobalVariableLayerRange(v);
                if (layerRange.lowerLayerNum <= yieldingProc.upperLayer && yieldingProc.upperLayer < layerRange.upperLayerNum)
                {
                    this.oldGlobalMap[v] = oldGlobalMap[v];
                }
            }

            oldOutputMap = new Dictionary <Variable, Variable>();
            foreach (Variable f in impl.OutParams)
            {
                LocalVariable copy = Old(f);
                newLocalVars.Add(copy);
                oldOutputMap[f] = copy;
            }

            Dictionary <Variable, Expr> foroldMap = new Dictionary <Variable, Expr>();

            foreach (Variable g in civlTypeChecker.sharedVariables)
            {
                foroldMap[g] = Expr.Ident(oldGlobalMap[g]);
            }
            if (yieldingProc is ActionProc actionProc)
            {
                // The parameters of an atomic action come from the implementation that denotes the atomic action specification.
                // To use the transition relation computed below in the context of the yielding procedure of the refinement check,
                // we need to substitute the parameters.
                AtomicAction   atomicAction           = actionProc.refinedAction;
                Implementation atomicActionImpl       = atomicAction.impl;
                Dictionary <Variable, Expr> alwaysMap = new Dictionary <Variable, Expr>();
                for (int i = 0; i < impl.InParams.Count; i++)
                {
                    alwaysMap[atomicActionImpl.InParams[i]] = Expr.Ident(impl.InParams[i]);
                }

                for (int i = 0; i < impl.OutParams.Count; i++)
                {
                    alwaysMap[atomicActionImpl.OutParams[i]] = Expr.Ident(impl.OutParams[i]);
                }
                if (atomicAction.HasPendingAsyncs)
                {
                    Variable collectedPAs = civlTypeChecker.implToPendingAsyncCollector[originalImpl];
                    alwaysMap[atomicActionImpl.OutParams.Last()] = Expr.Ident(collectedPAs);
                    LocalVariable copy = Old(collectedPAs);
                    newLocalVars.Add(copy);
                    oldOutputMap[collectedPAs] = copy;
                }

                Substitution always   = Substituter.SubstitutionFromHashtable(alwaysMap);
                Substitution forold   = Substituter.SubstitutionFromHashtable(foroldMap);
                Expr         betaExpr = GetTransitionRelation(atomicAction);
                beta = Substituter.ApplyReplacingOldExprs(always, forold, betaExpr);
                Expr alphaExpr = Expr.And(atomicAction.gate.Select(g => g.Expr));
                alphaExpr.Type = Type.Bool;
                alpha          = Substituter.Apply(always, alphaExpr);
            }
            else
            {
                beta  = Expr.And(this.oldGlobalMap.Keys.Select(v => Expr.Eq(Expr.Ident(v), foroldMap[v])));
                alpha = Expr.True;
            }

            pcsForYieldingLoopsHeaders = new Dictionary <Block, Variable>();
            oksForYieldingLoopHeaders  = new Dictionary <Block, Variable>();
            foreach (Block header in yieldingLoopHeaders)
            {
                var pcForYieldingLoopHeader = PcForYieldingLoopHeader(header);
                newLocalVars.Add(pcForYieldingLoopHeader);
                pcsForYieldingLoopsHeaders[header] = pcForYieldingLoopHeader;
                var okForYieldingLoopHeader = OkForYieldingLoopHeader(header);
                newLocalVars.Add(okForYieldingLoopHeader);
                oksForYieldingLoopHeaders[header] = okForYieldingLoopHeader;
            }
        }
Esempio n. 24
0
        private void CreateFailurePreservationChecker(Program program, AtomicActionInfo first, AtomicActionInfo second)
        {
            if (first.gateUsedGlobalVars.Intersect(second.modifiedGlobalVars).Count() == 0)
            {
                return;
            }
            Tuple <AtomicActionInfo, AtomicActionInfo> actionPair = new Tuple <AtomicActionInfo, AtomicActionInfo>(first, second);

            if (failurePreservationCheckerCache.Contains(actionPair))
            {
                return;
            }
            failurePreservationCheckerCache.Add(actionPair);

            List <Variable> inputs = new List <Variable>();

            inputs.AddRange(first.thatInParams);
            inputs.AddRange(second.thisInParams);
            List <Variable> outputs = new List <Variable>();

            outputs.AddRange(first.thatOutParams);
            outputs.AddRange(second.thisOutParams);
            List <Variable> locals = new List <Variable>();

            locals.AddRange(second.thisAction.LocVars);
            List <Block>       secondBlocks = CloneBlocks(second.thisAction.Blocks);
            HashSet <Variable> frame        = new HashSet <Variable>();

            frame.UnionWith(first.gateUsedGlobalVars);
            frame.UnionWith(second.gateUsedGlobalVars);
            frame.UnionWith(second.actionUsedGlobalVars);
            List <Requires> requires = DisjointnessRequires(program, first, second, frame);
            Expr            gateExpr = Expr.True;

            foreach (AssertCmd assertCmd in first.thatGate)
            {
                gateExpr      = Expr.And(gateExpr, assertCmd.Expr);
                gateExpr.Type = Type.Bool;
            }
            gateExpr      = Expr.Not(gateExpr);
            gateExpr.Type = Type.Bool;
            requires.Add(new Requires(false, gateExpr));
            List <Ensures> ensures     = new List <Ensures>();
            Ensures        ensureCheck = new Ensures(false, gateExpr);

            ensureCheck.ErrorData = string.Format("Gate failure of {0} not preserved by {1}", first.proc.Name, second.proc.Name);
            ensures.Add(ensureCheck);
            foreach (AssertCmd assertCmd in second.thisGate)
            {
                requires.Add(new Requires(false, assertCmd.Expr));
            }
            string checkerName = string.Format("FailurePreservationChecker_{0}_{1}", first.proc.Name, second.proc.Name);
            List <IdentifierExpr> globalVars = new List <IdentifierExpr>();

            moverTypeChecker.SharedVariables.Iter(x => globalVars.Add(Expr.Ident(x)));
            Procedure      proc = new Procedure(Token.NoToken, checkerName, new List <TypeVariable>(), inputs, outputs, requires, globalVars, ensures);
            Implementation impl = new Implementation(Token.NoToken, checkerName, new List <TypeVariable>(), inputs, outputs, locals, secondBlocks);

            impl.Proc = proc;
            this.decls.Add(impl);
            this.decls.Add(proc);
        }
Esempio n. 25
0
        private void CreateCommutativityChecker(Program program, AtomicActionInfo first, AtomicActionInfo second)
        {
            if (first == second && first.thatInParams.Count == 0 && first.thatOutParams.Count == 0)
            {
                return;
            }
            if (first.CommutesWith(second))
            {
                return;
            }
            if (!commutativityCheckerCache.Add(new Tuple <AtomicActionInfo, AtomicActionInfo>(first, second)))
            {
                return;
            }

            List <Variable> inputs       = Enumerable.Union(first.thatInParams, second.thisInParams).ToList();
            List <Variable> outputs      = Enumerable.Union(first.thatOutParams, second.thisOutParams).ToList();
            List <Variable> locals       = Enumerable.Union(first.thatAction.LocVars, second.thisAction.LocVars).ToList();
            List <Block>    firstBlocks  = CloneBlocks(first.thatAction.Blocks);
            List <Block>    secondBlocks = CloneBlocks(second.thisAction.Blocks);

            foreach (Block b in firstBlocks.Where(b => b.TransferCmd is ReturnCmd))
            {
                List <Block> bs = new List <Block>  {
                    secondBlocks[0]
                };
                List <string> ls = new List <string> {
                    secondBlocks[0].Label
                };
                b.TransferCmd = new GotoCmd(Token.NoToken, ls, bs);
            }
            List <Block>       blocks = Enumerable.Union(firstBlocks, secondBlocks).ToList();
            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>();

            requires.Add(DisjointnessRequires(program, first.thatInParams.Union(second.thisInParams), frame));
            foreach (AssertCmd assertCmd in Enumerable.Union(first.thatGate, second.thisGate))
            {
                requires.Add(new Requires(false, assertCmd.Expr));
            }

            var  transitionRelationComputation = new TransitionRelationComputation(program, first, second, frame, new HashSet <Variable>());
            Expr transitionRelation            = transitionRelationComputation.TransitionRelationCompute();
            {
                List <Block> bs = new List <Block> {
                    blocks[0]
                };
                List <string> ls = new List <string> {
                    blocks[0].Label
                };
                var initBlock = new Block(Token.NoToken, string.Format("{0}_{1}_init", first.proc.Name, second.proc.Name), transitionRelationComputation.TriggerAssumes(), new GotoCmd(Token.NoToken, ls, bs));
                blocks.Insert(0, initBlock);
            }

            var thisInParamsFiltered            = second.thisInParams.Where(v => linearTypeChecker.FindLinearKind(v) != LinearKind.LINEAR_IN);
            IEnumerable <Expr> linearityAssumes = Enumerable.Union(
                DisjointnessExpr(program, first.thatOutParams.Union(thisInParamsFiltered), frame),
                DisjointnessExpr(program, first.thatOutParams.Union(second.thisOutParams), frame));
            // TODO: add further disjointness expressions?
            Ensures ensureCheck = new Ensures(false, Expr.Imp(Expr.And(linearityAssumes), transitionRelation));

            ensureCheck.ErrorData = string.Format("Commutativity check between {0} and {1} failed", first.proc.Name, second.proc.Name);
            List <Ensures> ensures = new List <Ensures> {
                ensureCheck
            };

            string checkerName = string.Format("CommutativityChecker_{0}_{1}", first.proc.Name, second.proc.Name);
            List <IdentifierExpr> globalVars = civlTypeChecker.SharedVariables.Select(x => Expr.Ident(x)).ToList();

            Procedure      proc = new Procedure(Token.NoToken, checkerName, new List <TypeVariable>(), inputs, outputs, requires, globalVars, ensures);
            Implementation impl = new Implementation(Token.NoToken, checkerName, new List <TypeVariable>(), inputs, outputs, locals, blocks);

            impl.Proc = proc;
            this.decls.Add(impl);
            this.decls.Add(proc);
        }
Esempio n. 26
0
        static Trigger FKActionTrigger(Parse parse, Table table, FKey fkey, ExprList changes)
        {
            Context ctx      = parse.Ctx;                 // Database handle
            int     actionId = (changes != null ? 1 : 0); // 1 for UPDATE, 0 for DELETE
            OE      action   = fkey.Actions[actionId];    // One of OE_None, OE_Cascade etc.
            Trigger trigger  = fkey.Triggers[actionId];   // Trigger definition to return

            if (action != OE.None && trigger == null)
            {
                Index index = null; // Parent key index for this FK
                int[] cols  = null; // child table cols . parent key cols
                if (LocateFkeyIndex(parse, table, fkey, out index, out cols) != 0)
                {
                    return(null);
                }
                Debug.Assert(cols != null || fkey.Cols.length == 1);

                Expr     where_ = null; // WHERE clause of trigger step
                Expr     when   = null; // WHEN clause for the trigger
                ExprList list   = null; // Changes list if ON UPDATE CASCADE
                for (int i = 0; i < fkey.Cols.length; i++)
                {
                    Token oldToken = new Token("old", 3);                         // Literal "old" token
                    Token newToken = new Token("new", 3);                         // Literal "new" token

                    int fromColId = (cols != null ? cols[i] : fkey.Cols[0].From); // Idx of column in child table
                    Debug.Assert(fromColId >= 0);
                    Token fromCol = new Token();                                  // Name of column in child table
                    Token toCol   = new Token();                                  // Name of column in parent table
                    toCol.data     = (index != null ? table.Cols[index.Columns[i]].Name : "oid");
                    fromCol.data   = fkey.From.Cols[fromColId].Name;
                    toCol.length   = (uint)toCol.data.Length;
                    fromCol.length = (uint)fromCol.data.Length;

                    // Create the expression "OLD.zToCol = zFromCol". It is important that the "OLD.zToCol" term is on the LHS of the = operator, so
                    // that the affinity and collation sequence associated with the parent table are used for the comparison.
                    Expr eq = Expr.PExpr(parse, TK.EQ,
                                         Expr.PExpr(parse, TK.DOT,
                                                    Expr.PExpr(parse, TK.ID, null, null, oldToken),
                                                    Expr.PExpr(parse, TK.ID, null, null, toCol)
                                                    , 0),
                                         Expr.PExpr(parse, TK.ID, null, null, fromCol)
                                         , 0); // tFromCol = OLD.tToCol
                    where_ = Expr.And(ctx, where_, eq);

                    // For ON UPDATE, construct the next term of the WHEN clause. The final WHEN clause will be like this:
                    //
                    //    WHEN NOT(old.col1 IS new.col1 AND ... AND old.colN IS new.colN)
                    if (changes != null)
                    {
                        eq = Expr.PExpr(parse, TK.IS,
                                        Expr.PExpr(parse, TK.DOT,
                                                   Expr.PExpr(parse, TK.ID, null, null, oldToken),
                                                   Expr.PExpr(parse, TK.ID, null, null, toCol),
                                                   0),
                                        Expr.PExpr(parse, TK.DOT,
                                                   Expr.PExpr(parse, TK.ID, null, null, newToken),
                                                   Expr.PExpr(parse, TK.ID, null, null, toCol),
                                                   0),
                                        0);
                        when = Expr.And(ctx, when, eq);
                    }

                    if (action != OE.Restrict && (action != OE.Cascade || changes != null))
                    {
                        Expr newExpr;
                        if (action == OE.Cascade)
                        {
                            newExpr = Expr.PExpr(parse, TK.DOT,
                                                 Expr.PExpr(parse, TK.ID, null, null, newToken),
                                                 Expr.PExpr(parse, TK.ID, null, null, toCol)
                                                 , 0);
                        }
                        else if (action == OE.SetDflt)
                        {
                            Expr dfltExpr = fkey.From.Cols[fromColId].Dflt;
                            if (dfltExpr != null)
                            {
                                newExpr = Expr.Dup(ctx, dfltExpr, 0);
                            }
                            else
                            {
                                newExpr = Expr.PExpr(parse, TK.NULL, 0, 0, 0);
                            }
                        }
                        else
                        {
                            newExpr = Expr.PExpr(parse, TK.NULL, 0, 0, 0);
                        }
                        list = Expr.ListAppend(parse, list, newExpr);
                        Expr.ListSetName(parse, list, fromCol, 0);
                    }
                }
                C._tagfree(ctx, ref cols);

                string fromName       = fkey.From.Name;  // Name of child table
                int    fromNameLength = fromName.Length; // Length in bytes of zFrom

                Select select = null;                    // If RESTRICT, "SELECT RAISE(...)"
                if (action == OE.Restrict)
                {
                    Token from = new Token();
                    from.data   = fromName;
                    from.length = fromNameLength;
                    Expr raise = Expr.Expr(ctx, TK.RAISE, "foreign key constraint failed");
                    if (raise != null)
                    {
                        raise.Affinity = OE.Abort;
                    }
                    select = Select.New(parse,
                                        Expr.ListAppend(parse, 0, raise),
                                        SrcListAppend(ctx, 0, from, null),
                                        where_,
                                        null, null, null, 0, null, null);
                    where_ = null;
                }

                // Disable lookaside memory allocation
                bool enableLookaside = ctx.Lookaside.Enabled; // Copy of ctx->lookaside.bEnabled
                ctx.Lookaside.Enabled = false;

                trigger = new Trigger();
                //: trigger = (Trigger *)_tagalloc(ctx,
                //:    sizeof(Trigger) + // Trigger
                //:    sizeof(TriggerStep) + // Single step in trigger program
                //:    fromNameLength + 1 // Space for pStep->target.z
                //:    , true);
                TriggerStep step = null; // First (only) step of trigger program
                if (trigger != null)
                {
                    step               = trigger.StepList = new TriggerStep(); //: (TriggerStep)trigger[1];
                    step.Target.data   = fromName;                             //: (char *)&step[1];
                    step.Target.length = fromNameLength;
                    //: _memcpy((const char *)step->Target.data, fromName, fromNameLength);

                    step.Where    = Expr.Dup(ctx, where_, EXPRDUP_REDUCE);
                    step.ExprList = Expr.ListDup(ctx, list, EXPRDUP_REDUCE);
                    step.Select   = Select.Dup(ctx, select, EXPRDUP_REDUCE);
                    if (when != null)
                    {
                        when         = Expr.PExpr(parse, TK.NOT, when, 0, 0);
                        trigger.When = Expr.Dup(ctx, when, EXPRDUP_REDUCE);
                    }
                }

                // Re-enable the lookaside buffer, if it was disabled earlier.
                ctx.Lookaside.Enabled = enableLookaside;

                Expr.Delete(ctx, ref where_);
                Expr.Delete(ctx, ref when);
                Expr.ListDelete(ctx, ref list);
                Select.Delete(ctx, ref select);
                if (ctx.MallocFailed)
                {
                    FKTriggerDelete(ctx, trigger);
                    return(null);
                }

                switch (action)
                {
                case OE.Restrict:
                    step.OP = TK.SELECT;
                    break;

                case OE.Cascade:
                    if (changes == null)
                    {
                        step.OP = TK.DELETE;
                        break;
                    }
                    goto default;

                default:
                    step.OP = TK.UPDATE;
                    break;
                }
                step.Trigger            = trigger;
                trigger.Schema          = table.Schema;
                trigger.TabSchema       = table.Schema;
                fkey.Triggers[actionId] = trigger;
                trigger.OP = (TK)(changes != null ? TK.UPDATE : TK.DELETE);
            }

            return(trigger);
        }
Esempio n. 27
0
        private void AddAccessFuncs(AccessType access)
        {
            foreach (var mr in SharedStateAnalyser.GetMemoryRegions(this.EP))
            {
                List <Variable> inParams = new List <Variable>();

                if (mr.TypedIdent.Type.IsMap)
                {
                    inParams.Add(new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "ptr",
                                                                                 this.AC.MemoryModelType)));
                }

                Procedure proc = new Procedure(Token.NoToken, this.MakeAccessFuncName(access, mr.Name),
                                               new List <TypeVariable>(), inParams, new List <Variable>(),
                                               new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>());
                proc.AddAttribute("inline", new object[] { new LiteralExpr(Token.NoToken, BigNum.FromInt(1)) });

                this.AC.TopLevelDeclarations.Add(proc);
                this.AC.ResContext.AddProcedure(proc);

                var cmds = new List <Cmd>();

                foreach (var ls in this.AC.MemoryLocksets)
                {
                    if (!ls.TargetName.Equals(mr.Name))
                    {
                        continue;
                    }
                    if (this.ShouldSkipLockset(ls))
                    {
                        continue;
                    }

                    foreach (var cls in this.AC.CurrentLocksets)
                    {
                        if (!cls.Lock.Name.Equals(ls.Lock.Name))
                        {
                            continue;
                        }

                        IdentifierExpr lsExpr = new IdentifierExpr(ls.Id.tok, ls.Id);

                        cmds.Add(new AssignCmd(Token.NoToken,
                                               new List <AssignLhs>()
                        {
                            new SimpleAssignLhs(Token.NoToken, lsExpr)
                        }, new List <Expr> {
                            Expr.And(new IdentifierExpr(cls.Id.tok, cls.Id), lsExpr)
                        }));

                        proc.Modifies.Add(lsExpr);
                        break;
                    }
                }

                if (access == AccessType.WRITE)
                {
                    foreach (var acv in this.AC.GetWriteAccessCheckingVariables())
                    {
                        if (!acv.Name.Split('_')[1].Equals(mr.Name))
                        {
                            continue;
                        }

                        var wacs = this.AC.GetWriteAccessCheckingVariables().Find(val =>
                                                                                  val.Name.Contains(this.AC.GetWriteAccessVariableName(this.EP, mr.Name)));
                        var wacsExpr = new IdentifierExpr(wacs.tok, wacs);

                        cmds.Add(new AssignCmd(Token.NoToken,
                                               new List <AssignLhs>()
                        {
                            new SimpleAssignLhs(Token.NoToken, wacsExpr)
                        }, new List <Expr> {
                            Expr.True
                        }));

                        proc.Modifies.Add(wacsExpr);
                    }
                }
                else if (access == AccessType.READ)
                {
                    foreach (var acv in this.AC.GetReadAccessCheckingVariables())
                    {
                        if (!acv.Name.Split('_')[1].Equals(mr.Name))
                        {
                            continue;
                        }

                        var racs = this.AC.GetReadAccessCheckingVariables().Find(val =>
                                                                                 val.Name.Contains(this.AC.GetReadAccessVariableName(this.EP, mr.Name)));
                        var racsExpr = new IdentifierExpr(racs.tok, racs);

                        cmds.Add(new AssignCmd(Token.NoToken,
                                               new List <AssignLhs>()
                        {
                            new SimpleAssignLhs(Token.NoToken, racsExpr)
                        }, new List <Expr> {
                            Expr.True
                        }));

                        proc.Modifies.Add(racsExpr);
                    }
                }

                List <BigBlock> blocks = null;
                if (mr.TypedIdent.Type.IsMap)
                {
                    var ptr = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "ptr",
                                                                              this.AC.MemoryModelType));
                    var watchdog = this.AC.GetAccessWatchdogConstants().Find(val =>
                                                                             val.Name.Contains(this.AC.GetAccessWatchdogConstantName(mr.Name)));

                    var ptrExpr      = new IdentifierExpr(ptr.tok, ptr);
                    var watchdogExpr = new IdentifierExpr(watchdog.tok, watchdog);
                    var guardExpr    = Expr.Eq(watchdogExpr, ptrExpr);

                    var ifStmts = new StmtList(new List <BigBlock> {
                        new BigBlock(Token.NoToken, null, cmds, null, null)
                    }, Token.NoToken);
                    var ifCmd = new IfCmd(Token.NoToken, guardExpr, ifStmts, null, null);

                    blocks = new List <BigBlock> {
                        new BigBlock(Token.NoToken, "_" + access.ToString(), new List <Cmd>(), ifCmd, null)
                    };
                }
                else
                {
                    blocks = new List <BigBlock> {
                        new BigBlock(Token.NoToken, "_" + access.ToString(), cmds, null, null)
                    };
                }

                Implementation impl = new Implementation(Token.NoToken, this.MakeAccessFuncName(access, mr.Name),
                                                         new List <TypeVariable>(), inParams, new List <Variable>(), new List <Variable>(),
                                                         new StmtList(blocks, Token.NoToken));

                impl.Proc = proc;
                impl.AddAttribute("inline", new object[] { new LiteralExpr(Token.NoToken, BigNum.FromInt(1)) });

                this.AC.TopLevelDeclarations.Add(impl);
            }
        }
        private AssertCmd CreateRaceCheckingAssertion(Thread t1, Thread t2, Variable mr)
        {
            Variable wacs1 = this.AC.GetWriteAccessCheckingVariables().Find(val =>
                                                                            val.Name.Contains(this.AC.GetWriteAccessVariableName(t1, mr.Name)));
            Variable wacs2 = this.AC.GetWriteAccessCheckingVariables().Find(val =>
                                                                            val.Name.Contains(this.AC.GetWriteAccessVariableName(t2, mr.Name)));
            Variable racs1 = this.AC.GetReadAccessCheckingVariables().Find(val =>
                                                                           val.Name.Contains(this.AC.GetReadAccessVariableName(t1, mr.Name)));
            Variable racs2 = this.AC.GetReadAccessCheckingVariables().Find(val =>
                                                                           val.Name.Contains(this.AC.GetReadAccessVariableName(t2, mr.Name)));

            if (wacs1 == null || wacs2 == null || racs1 == null || racs2 == null)
            {
                return(null);
            }

            IdentifierExpr wacsExpr1 = new IdentifierExpr(wacs1.tok, wacs1);
            IdentifierExpr wacsExpr2 = new IdentifierExpr(wacs2.tok, wacs2);
            IdentifierExpr racsExpr1 = new IdentifierExpr(racs1.tok, racs1);
            IdentifierExpr racsExpr2 = new IdentifierExpr(racs2.tok, racs2);

            Expr accessesExpr = null;

            if (t1.Name.Equals(t2.Name))
            {
                accessesExpr = wacsExpr1;
            }
            else
            {
                accessesExpr = Expr.Or(Expr.Or(Expr.And(wacsExpr1, wacsExpr2),
                                               Expr.And(wacsExpr1, racsExpr2)), Expr.And(racsExpr1, wacsExpr2));
            }

            Expr checkExpr = null;

            foreach (var l in this.AC.Locks)
            {
                var ls1 = this.AC.MemoryLocksets.Find(val => val.Lock.Name.Equals(l.Name) &&
                                                      val.TargetName.Equals(mr.Name) && val.Thread.Name.Equals(t1.Name));
                var ls2 = this.AC.MemoryLocksets.Find(val => val.Lock.Name.Equals(l.Name) &&
                                                      val.TargetName.Equals(mr.Name) && val.Thread.Name.Equals(t2.Name));

                IdentifierExpr lsExpr1 = new IdentifierExpr(ls1.Id.tok, ls1.Id);
                IdentifierExpr lsExpr2 = new IdentifierExpr(ls2.Id.tok, ls2.Id);

                Expr lsAndExpr = null;
                if (t1.Name.Equals(t2.Name))
                {
                    lsAndExpr = lsExpr1;
                }
                else
                {
                    lsAndExpr = Expr.And(lsExpr1, lsExpr2);
                }

                if (checkExpr == null)
                {
                    checkExpr = lsAndExpr;
                }
                else
                {
                    checkExpr = Expr.Or(checkExpr, lsAndExpr);
                }
            }

            if (this.AC.Locks.Count == 0)
            {
                checkExpr = Expr.False;
            }

            Expr acsImpExpr = Expr.Imp(accessesExpr, checkExpr);

            AssertCmd assert = new AssertCmd(Token.NoToken, acsImpExpr);

            assert.Attributes = new QKeyValue(Token.NoToken, "resource",
                                              new List <object>()
            {
                mr.Name
            }, assert.Attributes);
            assert.Attributes = new QKeyValue(Token.NoToken, "race_checking",
                                              new List <object>(), assert.Attributes);

            return(assert);
        }
Esempio n. 29
0
        private void MakeDual(List <Cmd> cs, Cmd c)
        {
            if (c is CallCmd)
            {
                CallCmd Call = c as CallCmd;

                if (QKeyValue.FindBoolAttribute(Call.Proc.Attributes, "barrier_invariant"))
                {
                    // There may be a predicate, and there must be an invariant expression and at least one instantiation
                    Debug.Assert(Call.Ins.Count >= (2 + (verifier.uniformityAnalyser.IsUniform(Call.callee) ? 0 : 1)));
                    var BIDescriptor = new UnaryBarrierInvariantDescriptor(
                        verifier.uniformityAnalyser.IsUniform(Call.callee) ? Expr.True : Call.Ins[0],
                        Expr.Neq(Call.Ins[verifier.uniformityAnalyser.IsUniform(Call.callee) ? 0 : 1],
                                 verifier.Zero(1)),
                        Call.Attributes,
                        this, procName, verifier);
                    for (var i = 1 + (verifier.uniformityAnalyser.IsUniform(Call.callee) ? 0 : 1); i < Call.Ins.Count; i++)
                    {
                        BIDescriptor.AddInstantiationExpr(Call.Ins[i]);
                    }
                    BarrierInvariantDescriptors.Add(BIDescriptor);
                    return;
                }

                if (QKeyValue.FindBoolAttribute(Call.Proc.Attributes, "binary_barrier_invariant"))
                {
                    // There may be a predicate, and there must be an invariant expression and at least one pair of
                    // instantiation expressions
                    Debug.Assert(Call.Ins.Count >= (3 + (verifier.uniformityAnalyser.IsUniform(Call.callee) ? 0 : 1)));
                    var BIDescriptor = new BinaryBarrierInvariantDescriptor(
                        verifier.uniformityAnalyser.IsUniform(Call.callee) ? Expr.True : Call.Ins[0],
                        Expr.Neq(Call.Ins[verifier.uniformityAnalyser.IsUniform(Call.callee) ? 0 : 1],
                                 verifier.Zero(1)),
                        Call.Attributes,
                        this, procName, verifier);
                    for (var i = 1 + (verifier.uniformityAnalyser.IsUniform(Call.callee) ? 0 : 1); i < Call.Ins.Count; i += 2)
                    {
                        BIDescriptor.AddInstantiationExprPair(Call.Ins[i], Call.Ins[i + 1]);
                    }
                    BarrierInvariantDescriptors.Add(BIDescriptor);
                    return;
                }


                if (GPUVerifier.IsBarrier(Call.Proc))
                {
                    // Assert barrier invariants
                    foreach (var BIDescriptor in BarrierInvariantDescriptors)
                    {
                        QKeyValue SourceLocationInfo = BIDescriptor.GetSourceLocationInfo();
                        cs.Add(BIDescriptor.GetAssertCmd());
                        var vd = new VariableDualiser(1, verifier.uniformityAnalyser, procName);
                        if (GPUVerifyVCGenCommandLineOptions.BarrierAccessChecks)
                        {
                            foreach (Expr AccessExpr in BIDescriptor.GetAccessedExprs())
                            {
                                var Assert = new AssertCmd(Token.NoToken, AccessExpr, MakeThreadSpecificAttributes(SourceLocationInfo, 1));
                                Assert.Attributes = new QKeyValue(Token.NoToken, "barrier_invariant_access_check",
                                                                  new List <object> {
                                    Expr.True
                                }, Assert.Attributes);
                                cs.Add(vd.VisitAssertCmd(Assert));
                            }
                        }
                    }
                }

                List <Expr> uniformNewIns    = new List <Expr>();
                List <Expr> nonUniformNewIns = new List <Expr>();

                for (int i = 0; i < Call.Ins.Count; i++)
                {
                    if (verifier.uniformityAnalyser.knowsOf(Call.callee) && verifier.uniformityAnalyser.IsUniform(Call.callee, verifier.uniformityAnalyser.GetInParameter(Call.callee, i)))
                    {
                        uniformNewIns.Add(Call.Ins[i]);
                    }
                    else if (!verifier.OnlyThread2.Contains(Call.callee))
                    {
                        nonUniformNewIns.Add(new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(Call.Ins[i]));
                    }
                }
                for (int i = 0; i < Call.Ins.Count; i++)
                {
                    if (
                        !(verifier.uniformityAnalyser.knowsOf(Call.callee) && verifier.uniformityAnalyser.IsUniform(Call.callee, verifier.uniformityAnalyser.GetInParameter(Call.callee, i))) &&
                        !verifier.OnlyThread1.Contains(Call.callee))
                    {
                        nonUniformNewIns.Add(new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitExpr(Call.Ins[i]));
                    }
                }

                List <Expr> newIns = uniformNewIns;
                newIns.AddRange(nonUniformNewIns);

                List <IdentifierExpr> uniformNewOuts    = new List <IdentifierExpr>();
                List <IdentifierExpr> nonUniformNewOuts = new List <IdentifierExpr>();
                for (int i = 0; i < Call.Outs.Count; i++)
                {
                    if (verifier.uniformityAnalyser.knowsOf(Call.callee) && verifier.uniformityAnalyser.IsUniform(Call.callee, verifier.uniformityAnalyser.GetOutParameter(Call.callee, i)))
                    {
                        uniformNewOuts.Add(Call.Outs[i]);
                    }
                    else
                    {
                        nonUniformNewOuts.Add(new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitIdentifierExpr(Call.Outs[i].Clone() as IdentifierExpr) as IdentifierExpr);
                    }
                }
                for (int i = 0; i < Call.Outs.Count; i++)
                {
                    if (!(verifier.uniformityAnalyser.knowsOf(Call.callee) && verifier.uniformityAnalyser.IsUniform(Call.callee, verifier.uniformityAnalyser.GetOutParameter(Call.callee, i))))
                    {
                        nonUniformNewOuts.Add(new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitIdentifierExpr(Call.Outs[i].Clone() as IdentifierExpr) as IdentifierExpr);
                    }
                }

                List <IdentifierExpr> newOuts = uniformNewOuts;
                newOuts.AddRange(nonUniformNewOuts);

                CallCmd NewCallCmd = new CallCmd(Call.tok, Call.callee, newIns, newOuts);

                NewCallCmd.Proc = Call.Proc;

                NewCallCmd.Attributes = Call.Attributes;

                if (NewCallCmd.callee.StartsWith("_LOG_ATOMIC"))
                {
                    QKeyValue curr = NewCallCmd.Attributes;
                    if (curr.Key.StartsWith("arg"))
                    {
                        NewCallCmd.Attributes = new QKeyValue(Token.NoToken, curr.Key, new List <object>(new object[] { Dualise(curr.Params[0] as Expr, 1) }), curr.Next);
                    }
                    for (curr = NewCallCmd.Attributes; curr.Next != null; curr = curr.Next)
                    {
                        if (curr.Next.Key.StartsWith("arg"))
                        {
                            curr.Next = new QKeyValue(Token.NoToken, curr.Next.Key, new List <object>(new object[] { Dualise(curr.Next.Params[0] as Expr, 1) }), curr.Next.Next);
                        }
                    }
                }
                else if (NewCallCmd.callee.StartsWith("_CHECK_ATOMIC"))
                {
                    QKeyValue curr = NewCallCmd.Attributes;
                    if (curr.Key.StartsWith("arg"))
                    {
                        NewCallCmd.Attributes = new QKeyValue(Token.NoToken, curr.Key, new List <object>(new object[] { Dualise(curr.Params[0] as Expr, 2) }), curr.Next);
                    }
                    for (curr = NewCallCmd.Attributes; curr.Next != null; curr = curr.Next)
                    {
                        if (curr.Next.Key.StartsWith("arg"))
                        {
                            curr.Next = new QKeyValue(Token.NoToken, curr.Next.Key, new List <object>(new object[] { Dualise(curr.Next.Params[0] as Expr, 2) }), curr.Next.Next);
                        }
                    }
                }

                cs.Add(NewCallCmd);

                if (GPUVerifier.IsBarrier(Call.Proc))
                {
                    foreach (var BIDescriptor in BarrierInvariantDescriptors)
                    {
                        foreach (var Instantiation in BIDescriptor.GetInstantiationCmds())
                        {
                            cs.Add(Instantiation);
                        }
                    }
                    BarrierInvariantDescriptors.Clear();
                }
            }
            else if (c is AssignCmd)
            {
                AssignCmd assign = c as AssignCmd;

                var vd1 = new VariableDualiser(1, verifier.uniformityAnalyser, procName);
                var vd2 = new VariableDualiser(2, verifier.uniformityAnalyser, procName);

                List <AssignLhs> lhss1 = new List <AssignLhs>();
                List <AssignLhs> lhss2 = new List <AssignLhs>();

                List <Expr> rhss1 = new List <Expr>();
                List <Expr> rhss2 = new List <Expr>();

                foreach (var pair in assign.Lhss.Zip(assign.Rhss))
                {
                    if (pair.Item1 is SimpleAssignLhs &&
                        verifier.uniformityAnalyser.IsUniform(procName,
                                                              (pair.Item1 as SimpleAssignLhs).AssignedVariable.Name))
                    {
                        lhss1.Add(pair.Item1);
                        rhss1.Add(pair.Item2);
                    }
                    else
                    {
                        lhss1.Add(vd1.Visit(pair.Item1.Clone() as AssignLhs) as AssignLhs);
                        lhss2.Add(vd2.Visit(pair.Item1.Clone() as AssignLhs) as AssignLhs);
                        rhss1.Add(vd1.VisitExpr(pair.Item2.Clone() as Expr));
                        rhss2.Add(vd2.VisitExpr(pair.Item2.Clone() as Expr));
                    }
                }

                Debug.Assert(lhss1.Count > 0);
                cs.Add(new AssignCmd(Token.NoToken, lhss1, rhss1));

                if (lhss2.Count > 0)
                {
                    cs.Add(new AssignCmd(Token.NoToken, lhss2, rhss2));
                }
            }
            else if (c is HavocCmd)
            {
                HavocCmd havoc = c as HavocCmd;
                Debug.Assert(havoc.Vars.Count() == 1);

                HavocCmd newHavoc;

                newHavoc = new HavocCmd(havoc.tok, new List <IdentifierExpr>(new IdentifierExpr[] {
                    (IdentifierExpr)(new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitIdentifierExpr(havoc.Vars[0].Clone() as IdentifierExpr)),
                    (IdentifierExpr)(new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitIdentifierExpr(havoc.Vars[0].Clone() as IdentifierExpr))
                }));

                cs.Add(newHavoc);
            }
            else if (c is AssertCmd)
            {
                AssertCmd a = c as AssertCmd;

                if (QKeyValue.FindBoolAttribute(a.Attributes, "sourceloc") ||
                    QKeyValue.FindBoolAttribute(a.Attributes, "block_sourceloc") ||
                    QKeyValue.FindBoolAttribute(a.Attributes, "array_bounds"))
                {
                    // This is just a location marker, so we do not dualise it
                    cs.Add(new AssertCmd(Token.NoToken, new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(a.Expr.Clone() as Expr),
                                         (QKeyValue)a.Attributes.Clone()));
                }
                else
                {
                    var isUniform = verifier.uniformityAnalyser.IsUniform(procName, a.Expr);
                    cs.Add(MakeThreadSpecificAssert(a, 1));
                    if (!GPUVerifyVCGenCommandLineOptions.AsymmetricAsserts && !ContainsAsymmetricExpression(a.Expr) && !isUniform)
                    {
                        cs.Add(MakeThreadSpecificAssert(a, 2));
                    }
                }
            }
            else if (c is AssumeCmd)
            {
                AssumeCmd ass = c as AssumeCmd;

                if (QKeyValue.FindStringAttribute(ass.Attributes, "captureState") != null)
                {
                    cs.Add(c);
                }
                else if (QKeyValue.FindBoolAttribute(ass.Attributes, "backedge"))
                {
                    AssumeCmd newAss = new AssumeCmd(c.tok, Expr.Or(new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr),
                                                                    new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr)));
                    newAss.Attributes = ass.Attributes;
                    cs.Add(newAss);
                }
                else if (QKeyValue.FindBoolAttribute(ass.Attributes, "atomic_refinement"))
                {
                    // Generate the following:
                    // havoc v$1, v$2;
                    // assume !_USED[offset$1][v$1];
                    // _USED[offset$1][v$1] := true;
                    // assume !_USED[offset$2][v$2];
                    // _USED[offset$2][v$2] := true;

                    Expr variable = QKeyValue.FindExprAttribute(ass.Attributes, "variable");
                    Expr offset   = QKeyValue.FindExprAttribute(ass.Attributes, "offset");

                    List <Expr>    offsets  = (new int[] { 1, 2 }).Select(x => new VariableDualiser(x, verifier.uniformityAnalyser, procName).VisitExpr(offset.Clone() as Expr)).ToList();
                    List <Expr>    vars     = (new int[] { 1, 2 }).Select(x => new VariableDualiser(x, verifier.uniformityAnalyser, procName).VisitExpr(variable.Clone() as Expr)).ToList();
                    IdentifierExpr arrayref = new IdentifierExpr(Token.NoToken, verifier.FindOrCreateUsedMap(QKeyValue.FindStringAttribute(ass.Attributes, "arrayref"), vars[0].Type));

                    foreach (int i in (new int[] { 0, 1 }))
                    {
                        AssumeCmd newAss = new AssumeCmd(c.tok, Expr.Not(new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
                                                                                      new List <Expr> {
                            new NAryExpr(Token.NoToken, new MapSelect(Token.NoToken, 1),
                                         new List <Expr> {
                                arrayref, offsets[i]
                            }),
                            vars[i]
                        })));

                        cs.Add(newAss);

                        var lhs = new MapAssignLhs(Token.NoToken, new MapAssignLhs(Token.NoToken, new SimpleAssignLhs(Token.NoToken, arrayref),
                                                                                   new List <Expr> {
                            offsets[i]
                        }), new List <Expr> {
                            vars[i]
                        });
                        AssignCmd assign = new AssignCmd(c.tok,
                                                         new List <AssignLhs> {
                            lhs
                        },
                                                         new List <Expr> {
                            Expr.True
                        });

                        cs.Add(assign);
                    }
                }
                else
                {
                    var       isUniform = verifier.uniformityAnalyser.IsUniform(procName, ass.Expr);
                    AssumeCmd newAss    = new AssumeCmd(c.tok, new VariableDualiser(1, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr));
                    if (!ContainsAsymmetricExpression(ass.Expr) && !isUniform)
                    {
                        newAss.Expr = Expr.And(newAss.Expr, new VariableDualiser(2, verifier.uniformityAnalyser, procName).VisitExpr(ass.Expr.Clone() as Expr));
                    }
                    newAss.Attributes = ass.Attributes;
                    cs.Add(newAss);
                }
            }
            else
            {
                Debug.Assert(false);
            }
        }
Esempio n. 30
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
            });
        }