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 }); }
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); } } }
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 }); }
// 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); } }
/// <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) ) ) ) ) ) ); }
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); }
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) }); }
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); }
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); } }
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); }
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); }
private Expr OldEqualityExprForOutputs() { return(Expr.And(this.oldOutputMap.Select(kvPair => Expr.Eq(Expr.Ident(kvPair.Key), Expr.Ident(kvPair.Value))))); }
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); }
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); } } } }
private Requires DisjointnessRequires(IEnumerable <Variable> paramVars, HashSet <Variable> frame) { return(new Requires(false, Expr.And(linearTypeChecker.DisjointnessExprForEachDomain(paramVars.Union(frame))))); }
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 }); }
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()); } }
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; } }
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); }
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); }
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); }
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); }
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); } }
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 }); }