private static void SubstituteBackwardAssignments(AtomicAction action) { foreach (Block block in action.impl.Blocks) { List <Cmd> cmds = new List <Cmd>(); foreach (Cmd cmd in block.cmds) { if (cmd is AssignCmd _assignCmd && QKeyValue.FindBoolAttribute(_assignCmd.Attributes, CivlAttributes.BACKWARD)) { AssignCmd assignCmd = _assignCmd.AsSimpleAssignCmd; var lhss = assignCmd.Lhss; var rhss = assignCmd.Rhss; var rhssVars = rhss.SelectMany(x => VariableCollector.Collect(x)); var lhssVars = lhss.SelectMany(x => VariableCollector.Collect(x)); if (rhssVars.Intersect(lhssVars).Any()) { // TODO throw new NotImplementedException("Substitution of backward assignment where lhs appears on rhs"); } else { List <Expr> assumeExprs = new List <Expr>(); for (int k = 0; k < lhss.Count; k++) { assumeExprs.Add(Expr.Eq(lhss[k].AsExpr, rhss[k])); } cmds.Add(CmdHelper.AssumeCmd(Expr.And(assumeExprs))); cmds.Add(CmdHelper.HavocCmd(lhss.Select(x => x.DeepAssignedIdentifier).ToList())); } }
private Block CreateUnchangedCheckerBlock() { var newCmds = new List <Cmd>(); newCmds.AddRange(refinementInstrumentation.CreateUnchangedAssertCmds()); newCmds.Add(CmdHelper.AssumeCmd(Expr.False)); return(BlockHelper.Block(civlTypeChecker.AddNamePrefix("UnchangedChecker"), newCmds)); }
private Block CreateNoninterferenceCheckerBlock() { var newCmds = new List <Cmd>(); newCmds.AddRange(noninterferenceInstrumentation.CreateCallToYieldProc()); newCmds.Add(CmdHelper.AssumeCmd(Expr.False)); return(BlockHelper.Block(civlTypeChecker.AddNamePrefix("NoninterferenceChecker"), newCmds)); }
public List <Cmd> ProcDisjointnessAssumeCmds(Procedure proc, bool atEntry) { IEnumerable <Variable> availableVars = atEntry ? FilterInParams(proc.InParams) : FilterInOutParams(proc.InParams.Union(proc.OutParams)); return(DisjointnessExprs(availableVars).Select(expr => CmdHelper.AssumeCmd(expr)).ToList <Cmd>()); }
public void AddTriggerAssumes(Program program) { foreach (Variable v in impl.LocVars) { var f = triggerFunctions[v]; program.AddTopLevelDeclaration(f); var assume = CmdHelper.AssumeCmd(ExprHelper.FunctionCall(f, Expr.Ident(v))); impl.Blocks[0].Cmds.Insert(0, assume); } }
public override List <Cmd> CreateAssumeCmds() { // assume pc || gate(i, g); Expr assumeExpr = Expr.Or(Expr.Ident(pc), gate); assumeExpr.Type = Type.Bool; return(new List <Cmd> { CmdHelper.AssumeCmd(assumeExpr) }); }
private Block CreateReturnCheckerBlock() { var returnBlockCmds = new List <Cmd>(); returnBlockCmds.AddRange(refinementInstrumentation.CreateAssertCmds()); returnBlockCmds.AddRange(refinementInstrumentation.CreateUpdatesToRefinementVars(false)); returnBlockCmds.AddRange(refinementInstrumentation.CreateReturnAssertCmds()); returnBlockCmds.Add(CmdHelper.AssumeCmd(Expr.False)); return(BlockHelper.Block(civlTypeChecker.AddNamePrefix("ReturnChecker"), returnBlockCmds)); }
public Tuple <Procedure, Implementation> GenerateStepChecker(AtomicAction pendingAsync, Function pendingAsyncAdd) { this.checkName = "step"; var requires = invariantAction.gate.Select(g => new Requires(false, g.Expr)).ToList(); var ensures = new List <Ensures> { GetEnsures(GetTransitionRelation(invariantAction)) }; var locals = new List <Variable>(); if (!HasChoice) { locals.Add(choice.Decl); } List <Cmd> cmds = new List <Cmd>(); cmds.Add(GetCallCmd(invariantAction)); cmds.Add(CmdHelper.AssumeCmd(ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, choice))); cmds.Add(CmdHelper.AssumeCmd(Expr.Gt(Expr.Select(PAs, choice), Expr.Literal(0)))); cmds.Add(RemoveChoice); AtomicAction abs = elim[pendingAsync]; Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); List <Expr> inputExprs = new List <Expr>(); for (int i = 0; i < abs.impl.InParams.Count; i++) { var pendingAsyncParam = ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.selectors[i], choice); map[abs.impl.InParams[i]] = pendingAsyncParam; inputExprs.Add(pendingAsyncParam); } var subst = Substituter.SubstitutionFromHashtable(map); cmds.AddRange(GetGateAsserts(abs, subst)); List <IdentifierExpr> outputVars = new List <IdentifierExpr>(); if (abs.HasPendingAsyncs) { locals.Add(newPAs.Decl); outputVars.Add(newPAs); } cmds.Add(CmdHelper.CallCmd(abs.proc, inputExprs, outputVars)); if (abs.HasPendingAsyncs) { cmds.Add(AddNewPAs(pendingAsyncAdd)); } var blocks = new List <Block> { new Block(Token.NoToken, pendingAsync.proc.Name, cmds, CmdHelper.ReturnCmd) }; return(GetCheckerTuple(requires, ensures, locals, blocks, "_" + abs.proc.Name)); }
public Tuple <Procedure, Implementation> GenerateChoiceChecker() { this.checkName = "choice"; var requires = invariantAction.gate.Select(g => new Requires(false, g.Expr)).ToList(); List <Cmd> cmds = new List <Cmd>(); cmds.Add(GetCallCmd(invariantAction)); cmds.Add(CmdHelper.AssumeCmd(ExistsElimPendingAsyncExpr)); cmds.Add(CmdHelper.AssertCmd( invariantAction.proc.tok, ElimPendingAsyncExpr(choice), $"Failed to validate choice in IS of {inputAction.proc.Name}")); return(GetCheckerTuple(requires, new List <Variable>(), cmds)); }
public override List <Cmd> CreateInitCmds() { var lhss = new List <IdentifierExpr> { Expr.Ident(pc), Expr.Ident(ok) }; var rhss = new List <Expr> { Expr.False, Expr.False }; var cmds = new List <Cmd> { CmdHelper.AssignCmd(lhss, rhss) }; cmds.AddRange(CreateUpdatesToOldOutputVars()); // assume spec gate at procedure entry cmds.Add(CmdHelper.AssumeCmd(gate)); return(cmds); }
public override List <Cmd> CreateInitCmds() { List <AssignLhs> lhss = new List <AssignLhs> { new SimpleAssignLhs(Token.NoToken, Expr.Ident(pc)), new SimpleAssignLhs(Token.NoToken, Expr.Ident(ok)) }; List <Expr> rhss = new List <Expr> { Expr.False, Expr.False }; var cmds = new List <Cmd> { new AssignCmd(Token.NoToken, lhss, rhss) }; cmds.AddRange(CreateUpdatesToOldOutputVars()); // assume spec gate at procedure entry cmds.Add(CmdHelper.AssumeCmd(gate)); return(cmds); }
private Dictionary <Implementation, List <Cmd> > CreatePreconditions( LinearPermissionInstrumentation linearPermissionInstrumentation) { var implToInitCmds = new Dictionary <Implementation, List <Cmd> >(); foreach (var impl in absyMap.Keys.OfType <Implementation>()) { var initCmds = new List <Cmd>(); if (civlTypeChecker.GlobalVariables.Count() > 0) { initCmds.Add(CmdHelper.HavocCmd( civlTypeChecker.GlobalVariables.Select(v => Expr.Ident(v)).ToList())); linearPermissionInstrumentation.DisjointnessExprs(impl, true).ForEach( expr => initCmds.Add(CmdHelper.AssumeCmd(expr))); Substitution procToImplInParams = Substituter.SubstitutionFromHashtable(impl.Proc.InParams .Zip(impl.InParams).ToDictionary(x => x.Item1, x => (Expr)Expr.Ident(x.Item2))); impl.Proc.Requires.ForEach(req => initCmds.Add(new AssumeCmd(req.tok, Substituter.Apply(procToImplInParams, req.Condition)))); foreach (var callCmd in GetYieldingProc(impl).yieldRequires) { var yieldInvariant = civlTypeChecker.procToYieldInvariant[callCmd.Proc]; if (layerNum == yieldInvariant.LayerNum) { Substitution callFormalsToActuals = Substituter.SubstitutionFromHashtable(callCmd.Proc.InParams .Zip(callCmd.Ins) .ToDictionary(x => x.Item1, x => (Expr)ExprHelper.Old(x.Item2))); callCmd.Proc.Requires.ForEach(req => initCmds.Add(new AssumeCmd(req.tok, Substituter.Apply(procToImplInParams, Substituter.Apply(callFormalsToActuals, req.Condition))))); } } } implToInitCmds[impl] = initCmds; } return(implToInitCmds); }
public Tuple <Procedure, Implementation> GenerateConclusionChecker() { this.checkName = "conclusion"; var subst = GetSubstitution(outputAction, invariantAction); var requires = outputAction.gate.Select(g => new Requires(false, Substituter.Apply(subst, g.Expr))).ToList(); List <Cmd> cmds = GetGateAsserts(invariantAction, null).ToList <Cmd>(); cmds.Add(GetCallCmd(invariantAction)); cmds.Add(CmdHelper.AssumeCmd(PendingAsyncsEliminatedExpr)); cmds.Add(GetCheck(Substituter.Apply(subst, GetTransitionRelation(outputAction)))); if (!outputAction.HasPendingAsyncs) { cmds.Add(CmdHelper.AssertCmd( inputAction.proc.tok, NoPendingAsyncs, $"IS leaves pending asyncs not summarized by ${outputAction.proc.Name}")); } return(GetCheckerTuple(requires, new List <Variable>(), cmds)); }
public static List <Declaration> CreateNoninterferenceCheckers( CivlTypeChecker civlTypeChecker, int layerNum, AbsyMap absyMap, DeclWithFormals decl, List <Variable> declLocalVariables) { var linearTypeChecker = civlTypeChecker.linearTypeChecker; Dictionary <string, Variable> domainNameToHoleVar = new Dictionary <string, Variable>(); Dictionary <Variable, Variable> localVarMap = new Dictionary <Variable, Variable>(); Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); List <Variable> locals = new List <Variable>(); List <Variable> inputs = new List <Variable>(); foreach (var domainName in linearTypeChecker.linearDomains.Keys) { var inParam = linearTypeChecker.LinearDomainInFormal(domainName); inputs.Add(inParam); domainNameToHoleVar[domainName] = inParam; } foreach (Variable local in declLocalVariables.Union(decl.InParams).Union(decl.OutParams)) { var copy = CopyLocal(local); locals.Add(copy); localVarMap[local] = copy; map[local] = Expr.Ident(copy); } Dictionary <Variable, Expr> oldLocalMap = new Dictionary <Variable, Expr>(); Dictionary <Variable, Expr> assumeMap = new Dictionary <Variable, Expr>(map); foreach (Variable g in civlTypeChecker.GlobalVariables) { var copy = OldGlobalLocal(civlTypeChecker, g); locals.Add(copy); oldLocalMap[g] = Expr.Ident(copy); Formal f = SnapshotGlobalFormal(civlTypeChecker, g); inputs.Add(f); assumeMap[g] = Expr.Ident(f); } var linearPermissionInstrumentation = new LinearPermissionInstrumentation(civlTypeChecker, layerNum, absyMap, domainNameToHoleVar, localVarMap); List <YieldInfo> yieldInfos = null; string noninterferenceCheckerName = null; if (decl is Implementation impl) { noninterferenceCheckerName = $"impl_{absyMap.Original(impl).Name}_{layerNum}"; yieldInfos = CollectYields(civlTypeChecker, absyMap, layerNum, impl).Select(kv => new YieldInfo(linearPermissionInstrumentation.DisjointnessAssumeCmds(kv.Key, false), kv.Value)).ToList(); } else if (decl is Procedure proc) { yieldInfos = new List <YieldInfo>(); if (civlTypeChecker.procToYieldInvariant.ContainsKey(proc)) { noninterferenceCheckerName = $"yield_{proc.Name}"; if (proc.Requires.Count > 0) { var disjointnessCmds = linearPermissionInstrumentation.ProcDisjointnessAssumeCmds(proc, true); var yieldPredicates = proc.Requires.Select(requires => requires.Free ? (PredicateCmd) new AssumeCmd(requires.tok, requires.Condition) : (PredicateCmd) new AssertCmd(requires.tok, requires.Condition)).ToList(); yieldInfos.Add(new YieldInfo(disjointnessCmds, yieldPredicates)); } } else { noninterferenceCheckerName = $"proc_{absyMap.Original(proc).Name}_{layerNum}"; if (proc.Requires.Count > 0) { var entryDisjointnessCmds = linearPermissionInstrumentation.ProcDisjointnessAssumeCmds(proc, true); var entryYieldPredicates = proc.Requires.Select(requires => requires.Free ? (PredicateCmd) new AssumeCmd(requires.tok, requires.Condition) : (PredicateCmd) new AssertCmd(requires.tok, requires.Condition)).ToList(); yieldInfos.Add(new YieldInfo(entryDisjointnessCmds, entryYieldPredicates)); } if (proc.Ensures.Count > 0) { var exitDisjointnessCmds = linearPermissionInstrumentation.ProcDisjointnessAssumeCmds(proc, false); var exitYieldPredicates = proc.Ensures.Select(ensures => ensures.Free ? (PredicateCmd) new AssumeCmd(ensures.tok, ensures.Condition) : (PredicateCmd) new AssertCmd(ensures.tok, ensures.Condition)).ToList(); yieldInfos.Add(new YieldInfo(exitDisjointnessCmds, exitYieldPredicates)); } } } else { Debug.Assert(false); } var filteredYieldInfos = yieldInfos.Where(info => info.invariantCmds.Any(predCmd => new GlobalAccessChecker().AccessesGlobal(predCmd.Expr))); if (filteredYieldInfos.Count() == 0) { return(new List <Declaration>()); } Substitution assumeSubst = Substituter.SubstitutionFromDictionary(assumeMap); Substitution oldSubst = Substituter.SubstitutionFromDictionary(oldLocalMap); Substitution subst = Substituter.SubstitutionFromDictionary(map); List <Block> noninterferenceCheckerBlocks = new List <Block>(); List <Block> labelTargets = new List <Block>(); Block noninterferenceCheckerBlock = BlockHelper.Block("exit", new List <Cmd>()); labelTargets.Add(noninterferenceCheckerBlock); noninterferenceCheckerBlocks.Add(noninterferenceCheckerBlock); int yieldCount = 0; foreach (var kv in filteredYieldInfos) { var newCmds = new List <Cmd>(kv.disjointnessCmds); foreach (var predCmd in kv.invariantCmds) { var newExpr = Substituter.ApplyReplacingOldExprs(assumeSubst, oldSubst, predCmd.Expr); newCmds.Add(new AssumeCmd(predCmd.tok, newExpr)); } foreach (var predCmd in kv.invariantCmds) { if (predCmd is AssertCmd) { var newExpr = Substituter.ApplyReplacingOldExprs(subst, oldSubst, predCmd.Expr); AssertCmd assertCmd = new AssertCmd(predCmd.tok, newExpr, predCmd.Attributes); assertCmd.ErrorData = "Non-interference check failed"; newCmds.Add(assertCmd); } } newCmds.Add(CmdHelper.AssumeCmd(Expr.False)); noninterferenceCheckerBlock = BlockHelper.Block("L" + yieldCount++, newCmds); labelTargets.Add(noninterferenceCheckerBlock); noninterferenceCheckerBlocks.Add(noninterferenceCheckerBlock); } noninterferenceCheckerBlocks.Insert(0, BlockHelper.Block("enter", new List <Cmd>(), labelTargets)); // Create the yield checker procedure noninterferenceCheckerName = civlTypeChecker.AddNamePrefix($"NoninterferenceChecker_{noninterferenceCheckerName}"); var noninterferenceCheckerProc = DeclHelper.Procedure(noninterferenceCheckerName, inputs, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>()); CivlUtil.AddInlineAttribute(noninterferenceCheckerProc); // Create the yield checker implementation var noninterferenceCheckerImpl = DeclHelper.Implementation(noninterferenceCheckerProc, inputs, new List <Variable>(), locals, noninterferenceCheckerBlocks); CivlUtil.AddInlineAttribute(noninterferenceCheckerImpl); return(new List <Declaration> { noninterferenceCheckerProc, noninterferenceCheckerImpl }); }
public Tuple <Procedure, Implementation> GenerateStepChecker(Function pendingAsyncAdd) { this.checkName = "step"; var requires = invariantAction.gate.Select(g => new Requires(false, g.Expr)).ToList(); var ensures = new List <Ensures> { GetEnsures(GetTransitionRelation(invariantAction)) }; var locals = new List <Variable>(); if (elim.Values.Any(a => a.HasPendingAsyncs)) { locals.Add(newPAs.Decl); } List <Block> blocks = new List <Block>(); foreach (var pendingAsync in elim.Keys) { AtomicAction abs = elim[pendingAsync]; Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); List <Expr> inputExprs = new List <Expr>(); for (int i = 0; i < abs.impl.InParams.Count; i++) { var pendingAsyncParam = ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.selectors[i], choice); map[abs.impl.InParams[i]] = pendingAsyncParam; inputExprs.Add(pendingAsyncParam); } var subst = Substituter.SubstitutionFromHashtable(map); List <IdentifierExpr> outputVars = new List <IdentifierExpr>(); if (abs.HasPendingAsyncs) { outputVars.Add(newPAs); } List <Cmd> cmds = new List <Cmd>(); cmds.Add(CmdHelper.AssumeCmd(ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, choice))); cmds.AddRange(GetGateAsserts(abs, subst)); cmds.Add(CmdHelper.CallCmd(abs.proc, inputExprs, outputVars)); if (abs.HasPendingAsyncs) { cmds.Add(AddNewPAs(pendingAsyncAdd)); } var block = new Block(Token.NoToken, pendingAsync.proc.Name, cmds, CmdHelper.ReturnCmd); blocks.Add(block); } { List <Cmd> cmds = new List <Cmd>(); cmds.Add(GetCallCmd(invariantAction)); if (HasChoice) { cmds.Add(new AssumeCmd(Token.NoToken, ValidChoiceExpr)); cmds.Add( new AssertCmd(Token.NoToken, ElimPendingAsyncExpr(choice)) { ErrorData = $"Failed to validate choice in IS of {inputAction.proc.Name}" } ); } else { locals.Add(choice.Decl); cmds.Add(new AssumeCmd(Token.NoToken, ElimPendingAsyncExpr(choice))); } cmds.Add(RemoveChoice); var initBlock = new Block(Token.NoToken, "init", cmds, new GotoCmd(Token.NoToken, blocks.ToList())); blocks.Insert(0, initBlock); } return(GetCheckerTuple(requires, ensures, locals, blocks)); }
private static void AddChecker(CivlTypeChecker civlTypeChecker, Action action, List<Declaration> decls) { var linearTypeChecker = civlTypeChecker.linearTypeChecker; // Note: The implementation should be used as the variables in the // gate are bound to implementation and not to the procedure. Implementation impl = action.impl; List<Variable> inputs = impl.InParams; List<Variable> outputs = impl.OutParams; List<Variable> locals = new List<Variable>(2); var paLocal1 = civlTypeChecker.LocalVariable("pa1", civlTypeChecker.pendingAsyncType); var paLocal2 = civlTypeChecker.LocalVariable("pa2", civlTypeChecker.pendingAsyncType); var pa1 = Expr.Ident(paLocal1); var pa2 = Expr.Ident(paLocal2); if (civlTypeChecker.pendingAsyncType != null) { locals.Add(paLocal1); locals.Add(paLocal2); } List<Requires> requires = action.gate.Select(a => new Requires(false, a.Expr)).ToList(); List<LinearityCheck> linearityChecks = new List<LinearityCheck>(); foreach (var domain in linearTypeChecker.linearDomains.Values) { // Linear in vars var inVars = inputs.Union(action.modifiedGlobalVars) .Where(x => linearTypeChecker.FindDomainName(x) == domain.domainName) .Where(x => InKinds.Contains(linearTypeChecker.FindLinearKind(x))) .Select(Expr.Ident) .ToList(); // Linear out vars var outVars = inputs.Union(outputs).Union(action.modifiedGlobalVars) .Where(x => linearTypeChecker.FindDomainName(x) == domain.domainName) .Where(x => OutKinds.Contains(linearTypeChecker.FindLinearKind(x))) .Select(Expr.Ident) .ToList(); // First kind // Permissions in linear output variables are a subset of permissions in linear input variables. if (outVars.Count > 0) { linearityChecks.Add(new LinearityCheck( null, OutPermsSubsetInPerms(domain, inVars, outVars), $"Potential linearity violation in outputs for domain {domain.domainName}.", "variables")); } if (action is AtomicAction atomicAction && atomicAction.HasPendingAsyncs) { var PAs = Expr.Ident(atomicAction.impl.OutParams.Last()); foreach (var pendingAsync in atomicAction.pendingAsyncs) { var pendingAsyncLinearParams = PendingAsyncLinearParams(linearTypeChecker, domain, pendingAsync, pa1); if (pendingAsyncLinearParams.Count == 0) continue; // Second kind // Permissions in linear output variables + linear inputs of a single pending async // are a subset of permissions in linear input variables. var exactlyOnePA = Expr.And( ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, pa1), Expr.Eq(Expr.Select(PAs, pa1), Expr.Literal(1))); var outSubsetInExpr = OutPermsSubsetInPerms(domain, inVars, pendingAsyncLinearParams.Union(outVars)); linearityChecks.Add(new LinearityCheck( exactlyOnePA, outSubsetInExpr, $"Potential linearity violation in outputs and pending async of {pendingAsync.proc.Name} for domain {domain.domainName}.", $"single_{pendingAsync.proc.Name}")); // Third kind // If there are two identical pending asyncs, then their input permissions mut be empty. var twoIdenticalPAs = Expr.And( ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, pa1), Expr.Ge(Expr.Select(PAs, pa1), Expr.Literal(2))); var emptyPerms = OutPermsSubsetInPerms(domain, Enumerable.Empty<Expr>(), pendingAsyncLinearParams); linearityChecks.Add(new LinearityCheck( twoIdenticalPAs, emptyPerms, $"Potential linearity violation in identical pending asyncs of {pendingAsync.proc.Name} for domain {domain.domainName}.", $"identical_{pendingAsync.proc.Name}")); } var pendingAsyncs = atomicAction.pendingAsyncs.ToList(); for (int i = 0; i < pendingAsyncs.Count; i++) { var pendingAsync1 = pendingAsyncs[i]; for (int j = i; j < pendingAsyncs.Count; j++) { var pendingAsync2 = pendingAsyncs[j]; var pendingAsyncLinearParams1 = PendingAsyncLinearParams(linearTypeChecker, domain, pendingAsync1, pa1); var pendingAsyncLinearParams2 = PendingAsyncLinearParams(linearTypeChecker, domain, pendingAsync2, pa2); if (pendingAsyncLinearParams1.Count == 0 || pendingAsyncLinearParams2.Count == 0) continue; // Fourth kind // Input permissions of two non-identical pending asyncs (possibly of the same action) // are a subset of permissions in linear input variables. var membership = Expr.And( Expr.Neq(pa1, pa2), Expr.And( ExprHelper.FunctionCall(pendingAsync1.pendingAsyncCtor.membership, pa1), ExprHelper.FunctionCall(pendingAsync2.pendingAsyncCtor.membership, pa2))); var existing = Expr.And( Expr.Ge(Expr.Select(PAs, pa1), Expr.Literal(1)), Expr.Ge(Expr.Select(PAs, pa2), Expr.Literal(1))); var noDuplication = OutPermsSubsetInPerms(domain, inVars, pendingAsyncLinearParams1.Union(pendingAsyncLinearParams2)); linearityChecks.Add(new LinearityCheck( Expr.And(membership, existing), noDuplication, $"Potential lnearity violation in pending asyncs of {pendingAsync1.proc.Name} and {pendingAsync2.proc.Name} for domain {domain.domainName}.", $"distinct_{pendingAsync1.proc.Name}_{pendingAsync2.proc.Name}")); } } } } if (linearityChecks.Count == 0) return; // Create checker blocks List<Block> checkerBlocks = new List<Block>(linearityChecks.Count); foreach (var lc in linearityChecks) { List<Cmd> cmds = new List<Cmd>(2); if (lc.assume != null) { cmds.Add(CmdHelper.AssumeCmd(lc.assume)); } cmds.Add(new AssertCmd(action.proc.tok, lc.assert) { ErrorData = lc.message }); var block = new Block(Token.NoToken, lc.name, cmds, CmdHelper.ReturnCmd); CivlUtil.ResolveAndTypecheck(block, ResolutionContext.State.Two); checkerBlocks.Add(block); } // Create init blocks List<Block> blocks = new List<Block>(linearityChecks.Count + 1); blocks.Add( new Block( Token.NoToken, "init", new List<Cmd> { CmdHelper.CallCmd(action.proc, inputs, outputs) }, new GotoCmd(Token.NoToken, checkerBlocks))); blocks.AddRange(checkerBlocks); // Create the whole check procedure string checkerName = civlTypeChecker.AddNamePrefix($"LinearityChecker_{action.proc.Name}"); Procedure linCheckerProc = new Procedure(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, requires, action.proc.Modifies, new List<Ensures>()); Implementation linCheckImpl = new Implementation(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, locals, blocks); linCheckImpl.Proc = linCheckerProc; decls.Add(linCheckImpl); decls.Add(linCheckerProc); }
public List <Cmd> DisjointnessAssumeCmds(Absy absy, bool addGlobals) { var availableVars = AvailableLinearLocalVars(absy).Union(addGlobals ? LinearGlobalVars() : new List <Variable>()); return(DisjointnessExprs(availableVars).Select(expr => CmdHelper.AssumeCmd(expr)).ToList <Cmd>()); }
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 }); }