private void ParseProc(out AtomicAction action) { TryNext("Expected procedure name."); Procedure proc = ctc.program.FindProcedure(ld); if (proc is null) { Error("No procedure found with name of " + ld); action = null; } else { if (!ctc.procToAtomicAction.ContainsKey(proc)) { ctc.checkingContext.Warning(node, string.Format( "Procedure {0} does not have a mover type, witness function is ignored.", proc.Name)); // TODO: Add notes on this errorCount++; action = null; } else { action = ctc.procToAtomicAction[proc]; } } }
private AtomicActionDuplicator(string prefix, AtomicAction action) { this.prefix = prefix; subst = new Dictionary <Variable, Expr>(); bound = new Dictionary <Variable, Expr>(); inParamsCopy = new List <Variable>(); outParamsCopy = new List <Variable>(); localsCopy = new List <Variable>(); foreach (Variable x in action.impl.InParams) { Variable xCopy = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, prefix + x.Name, x.TypedIdent.Type), true, x.Attributes); inParamsCopy.Add(xCopy); subst[x] = Expr.Ident(xCopy); } foreach (Variable x in action.impl.OutParams) { Variable xCopy = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, prefix + x.Name, x.TypedIdent.Type), false, x.Attributes); outParamsCopy.Add(xCopy); subst[x] = Expr.Ident(xCopy); } foreach (Variable x in action.impl.LocVars) { Variable xCopy = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, prefix + x.Name, x.TypedIdent.Type)); subst[x] = Expr.Ident(xCopy); localsCopy.Add(xCopy); } }
private void VisitFunction(Function function) { Debug.Assert(function.OutParams.Count == 1); List <CommutativityHint> hints = new List <CommutativityHint>(); // First we collect all {:commutativity "first_action", "second_action"} attributes for (QKeyValue kv = function.Attributes; kv != null; kv = kv.Next) { if (kv.Key != CivlAttributes.COMMUTATIVITY) { continue; } if (kv.Params.Count == 2 && kv.Params[0] is string firstActionName && kv.Params[1] is string secondActionName) { firstAction = ctc.FindAtomicActionOrAbstraction(firstActionName); secondAction = ctc.FindAtomicActionOrAbstraction(secondActionName); if (firstAction == null) { ctc.Error(kv, $"Could not find atomic action {firstActionName}"); } if (secondAction == null) { ctc.Error(kv, $"Could not find atomic action {secondActionName}"); } if (firstAction != null && secondAction != null) { CheckInParams(function.InParams); } hints.Add(new CommutativityHint(function, firstAction, secondAction, args)); }
public static Expr Refinement(AtomicAction action, HashSet <Variable> frame) { return(ComputeTransitionRelation( action.impl, null, frame, null, null, false, string.Format("Transition relation of {0}", action.proc.Name))); }
private static void SubstituteBackwardAssignments(AtomicAction action) { foreach (Block block in action.impl.Blocks) { List <Cmd> cmds = new List <Cmd>(); foreach (Cmd cmd in block.cmds) { if (cmd is AssignCmd _assignCmd && QKeyValue.FindBoolAttribute(_assignCmd.Attributes, CivlAttributes.BACKWARD)) { AssignCmd assignCmd = _assignCmd.AsSimpleAssignCmd; var lhss = assignCmd.Lhss; var rhss = assignCmd.Rhss; var rhssVars = rhss.SelectMany(x => VariableCollector.Collect(x)); var lhssVars = lhss.SelectMany(x => VariableCollector.Collect(x)); if (rhssVars.Intersect(lhssVars).Any()) { // TODO throw new NotImplementedException("Substitution of backward assignment where lhs appears on rhs"); } else { List <Expr> assumeExprs = new List <Expr>(); for (int k = 0; k < lhss.Count; k++) { assumeExprs.Add(Expr.Eq(lhss[k].AsExpr, rhss[k])); } cmds.Add(new AssumeCmd(Token.NoToken, Expr.And(assumeExprs))); cmds.Add(new HavocCmd(Token.NoToken, lhss.Select(x => x.DeepAssignedIdentifier).ToList())); } }
public InductiveSequentialization(CivlTypeChecker civlTypeChecker, AtomicAction inputAction, AtomicAction outputAction, AtomicAction invariantAction, Dictionary <AtomicAction, AtomicAction> elim) { this.civlTypeChecker = civlTypeChecker; this.inputAction = inputAction; this.outputAction = outputAction; this.invariantAction = invariantAction; this.elim = elim; // TODO: check frame computation // We could compute a tighter frame per check. For example, base/conclusion checkers // don't have to take the eliminated actions into account. var frameVars = new List <AtomicAction> { invariantAction, outputAction, inputAction } .Union(elim.Select(kv => kv.Value)) .SelectMany(a => a.gateUsedGlobalVars.Union(a.modifiedGlobalVars)).Distinct(); this.frame = new HashSet <Variable>(frameVars); this.modifies = frame.Select(Expr.Ident).ToList(); newPAs = Expr.Ident(civlTypeChecker.LocalVariable("newPAs", civlTypeChecker.pendingAsyncMultisetType)); if (HasChoice) { choice = Expr.Ident(invariantAction.impl.OutParams.Last()); } else { choice = Expr.Ident(civlTypeChecker.LocalVariable("choice", civlTypeChecker.pendingAsyncType)); } }
public static Expr Nonblocking(AtomicAction action, HashSet <Variable> frame) { return(ComputeTransitionRelation( action.impl, null, frame, null, null, true, string.Format("Nonblocking expression of {0}", action.proc.Name))); }
private CallCmd GetCallCmd(AtomicAction callee) { return(CmdHelper.CallCmd( callee.proc, invariantAction.impl.InParams.Select(Expr.Ident).ToList <Expr>(), invariantAction.impl.OutParams.GetRange(0, callee.impl.OutParams.Count).Select(Expr.Ident).ToList() )); }
public CommutativityHint(Function function, AtomicAction firstAction, AtomicAction secondAction, List <Expr> args) { this.function = function; this.firstAction = firstAction; this.secondAction = secondAction; this.args = args; }
private CallCmd GetCallCmd(AtomicAction callee) { return(CmdHelper.CallCmd( callee.proc, invariantAction.impl.InParams, invariantAction.impl.OutParams.GetRange(0, callee.impl.OutParams.Count) )); }
public ActionProc(Procedure proc, AtomicAction refinedAction, int upperLayer, HashSet <Variable> hiddenFormals, List <CallCmd> yieldRequires, List <CallCmd> yieldEnsures) : base(proc, refinedAction.moverType, upperLayer, yieldRequires, yieldEnsures) { this.refinedAction = refinedAction; this.hiddenFormals = hiddenFormals; }
public IEnumerable <CommutativityWitness> GetWitnesses(AtomicAction first, AtomicAction second) { witnesses.TryGetValue(Key(first, second), out List <CommutativityWitness> list); if (list == null) { return(Enumerable.Empty <CommutativityWitness>()); } return(list); }
public IEnumerable <CommutativityHint> GetLemmas(AtomicAction first, AtomicAction second) { lemmas.TryGetValue(Key(first, second), out List <CommutativityHint> list); if (list == null) { return(Enumerable.Empty <CommutativityHint>()); } return(list); }
public WitnessFunction(Function function, Variable witnessedVariable, AtomicAction firstAction, AtomicAction secondAction, List <Expr> args) { this.function = function; this.witnessedVariable = witnessedVariable; this.firstAction = firstAction; this.secondAction = secondAction; this.args = args; }
private void CreateGatePreservationChecker(AtomicAction first, AtomicAction second) { if (!first.gateUsedGlobalVars.Intersect(second.modifiedGlobalVars).Any()) { return; } if (!gatePreservationCheckerCache.Add(Tuple.Create(first, second))) { return; } HashSet <Variable> frame = new HashSet <Variable>(); frame.UnionWith(first.gateUsedGlobalVars); frame.UnionWith(second.gateUsedGlobalVars); frame.UnionWith(second.actionUsedGlobalVars); var linearTypeChecker = civlTypeChecker.linearTypeChecker; List <Requires> requires = new List <Requires> { DisjointnessRequires( first.firstImpl.InParams.Union(second.secondImpl.InParams) .Where(v => linearTypeChecker.FindLinearKind(v) != LinearKind.LINEAR_OUT), frame) }; foreach (AssertCmd assertCmd in first.firstGate.Union(second.secondGate)) { requires.Add(new Requires(false, assertCmd.Expr)); } string checkerName = $"GatePreservationChecker_{first.proc.Name}_{second.proc.Name}"; List <Variable> inputs = Enumerable.Union(first.firstImpl.InParams, second.secondImpl.InParams).ToList(); List <Variable> outputs = Enumerable.Union(first.firstImpl.OutParams, second.secondImpl.OutParams).ToList(); List <Cmd> cmds = new List <Cmd> { ActionCallCmd(second, second.secondImpl) }; IEnumerable <Expr> linearityAssumes = linearTypeChecker.DisjointnessExprForEachDomain(first.firstImpl.InParams.Union(second.secondImpl.OutParams) .Union(frame)); foreach (AssertCmd assertCmd in first.firstGate) { cmds.Add( CmdHelper.AssertCmd( assertCmd.tok, Expr.Imp(Expr.And(linearityAssumes), assertCmd.Expr), $"Gate of {first.proc.Name} not preserved by {second.proc.Name}" ) ); } AddChecker(checkerName, inputs, outputs, new List <Variable>(), requires, cmds); }
public static Expr Commutativity(AtomicAction first, AtomicAction second, HashSet <Variable> frame, IEnumerable <CommutativityWitness> witnesses) { var triggers = first.triggerFunctions.Union(second.triggerFunctions).ToDictionary(kv => kv.Key, kv => kv.Value); return(ComputeTransitionRelation( first.secondImpl, second.firstImpl, frame, triggers, witnesses, false, string.Format("Transition relation of {0} ∘ {1}", first.proc.Name, second.proc.Name))); }
private Expr GetTransitionRelation(AtomicAction atomicAction) { if (!transitionRelationCache.ContainsKey(atomicAction)) { transitionRelationCache[atomicAction] = TransitionRelationComputation.Refinement(civlTypeChecker, atomicAction, new HashSet <Variable>(this.oldGlobalMap.Keys)); } return(transitionRelationCache[atomicAction]); }
private Expr GetTransitionRelation(AtomicAction action) { var tr = TransitionRelationComputation.Refinement(civlTypeChecker, action, frame); if (action == invariantAction && HasChoice) { return(new ChoiceEraser(invariantAction.impl.OutParams.Last()).VisitExpr(tr)); } return(tr); }
public WitnessFunction(Function function, GlobalVariable globalVar, AtomicAction firstAction, AtomicAction secondAction, List <int> layers) { this.function = function; this.globalVar = globalVar; this.firstAction = firstAction; this.secondAction = secondAction; this.layers = layers; this.InputArgs = new List <InputArgument>(); }
private static Tuple <Procedure, Implementation> GenerateAbstractionChecker(AtomicAction action, AtomicAction abs) { var requires = abs.gate.Select(g => new Requires(false, g.Expr)).ToList(); // TODO: check frame computation var frame = new HashSet <Variable>( action.modifiedGlobalVars .Union(action.gateUsedGlobalVars) .Union(abs.modifiedGlobalVars) .Union(abs.gateUsedGlobalVars)); var tr = TransitionRelationComputation.Refinement(abs, frame); var ensures = new List <Ensures> { new Ensures(false, tr) { ErrorData = $"Abstraction {abs.proc.Name} does not summarize {action.proc.Name}" } }; var subst = InductiveSequentialization.GetSubstitution(action, abs); List <Cmd> cmds = InductiveSequentialization.GetGateAsserts(action, subst, $"Abstraction {abs.proc.Name} fails gate of {action.proc.Name}").ToList <Cmd>(); cmds.Add( CmdHelper.CallCmd( action.proc, abs.impl.InParams.Select(Expr.Ident).ToList <Expr>(), abs.impl.OutParams.Select(Expr.Ident).ToList() )); var blocks = new List <Block> { new Block(Token.NoToken, "init", cmds, CmdHelper.ReturnCmd) }; var proc = new Procedure( Token.NoToken, $"AbstractionCheck_{action.proc.Name}_{abs.proc.Name}", new List <TypeVariable>(), abs.impl.InParams, abs.impl.OutParams, requires, action.proc.Modifies, ensures); var impl = new Implementation( Token.NoToken, proc.Name, new List <TypeVariable>(), proc.InParams, proc.OutParams, new List <Variable>(), blocks) { Proc = proc }; return(Tuple.Create(proc, impl)); }
public static IEnumerable <AssertCmd> GetGateAsserts(AtomicAction action, Substitution subst, string msg) { foreach (var gate in action.gate) { AssertCmd cmd = subst != null ? (AssertCmd)Substituter.Apply(subst, gate) : new AssertCmd(gate.tok, gate.Expr); cmd.ErrorData = msg; yield return(cmd); } }
public static void SetupCopy(AtomicAction action, ref List <AssertCmd> gateCopy, ref Implementation implCopy, string prefix) { var aad = new AtomicActionDuplicator(prefix, action); gateCopy = new List <AssertCmd>(); foreach (AssertCmd assertCmd in action.gate) { gateCopy.Add((AssertCmd)aad.Visit(assertCmd)); } implCopy = aad.VisitImplementation(action.impl); }
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)); }
private void CheckArg(AtomicAction action, Type type, string name) { var proc = action.proc; var v = proc.InParams.Union(proc.OutParams). FirstOrDefault(i => i.Name == name && i.TypedIdent.Type.Equals(type)); if (v is null) { Error(string.Format("No parameter {0}:{1} found in {2}", name, type, action.proc.Name)); } }
public static Substitution GetSubstitution(AtomicAction from, AtomicAction to) { Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); for (int i = 0; i < from.impl.InParams.Count; i++) { map[from.impl.InParams[i]] = Expr.Ident(to.impl.InParams[i]); } for (int i = 0; i < Math.Min(from.impl.OutParams.Count, to.impl.OutParams.Count); i++) { map[from.impl.OutParams[i]] = Expr.Ident(to.impl.OutParams[i]); } return(Substituter.SubstitutionFromHashtable(map)); }
private void CreateNonBlockingChecker(AtomicAction action) { if (!action.HasAssumeCmd) { return; } string checkerName = $"NonBlockingChecker_{action.proc.Name}"; Implementation impl = action.impl; HashSet <Variable> frame = new HashSet <Variable>(); frame.UnionWith(action.gateUsedGlobalVars); frame.UnionWith(action.actionUsedGlobalVars); List <Requires> requires = new List <Requires> { DisjointnessRequires(impl.InParams. Where(v => linearTypeChecker.FindLinearKind(v) != LinearKind.LINEAR_OUT), frame) }; foreach (AssertCmd assertCmd in action.gate) { requires.Add(new Requires(false, assertCmd.Expr)); } Expr nonBlockingExpr = TransitionRelationComputation. Nonblocking(action, frame); AssertCmd nonBlockingAssert = new AssertCmd(action.proc.tok, nonBlockingExpr) { ErrorData = $"Non-blocking check for {action.proc.Name} failed" }; Block block = new Block(action.proc.tok, "L", new List <Cmd> { nonBlockingAssert }, new ReturnCmd(Token.NoToken)); AddChecker(checkerName, new List <Variable>(impl.InParams), new List <Variable>(), new List <Variable>(), requires, new List <Ensures>(), new List <Block> { block }); }
private void VisitFunction(Function function) { Debug.Assert(function.OutParams.Count == 1); for (QKeyValue kv = function.Attributes; kv != null; kv = kv.Next) { if (kv.Key != CivlAttributes.WITNESS) { continue; } if (kv.Params.Count == 3 && kv.Params[0] is string witnessedVariableName && kv.Params[1] is string firstActionName && kv.Params[2] is string secondActionName) { witnessedVariable = ctc.sharedVariables.Find(v => v.Name == witnessedVariableName); if (witnessedVariable == null) { ctc.Error(kv, $"Could not find shared variable {witnessedVariableName}"); } else if (!function.OutParams[0].TypedIdent.Type.Equals(witnessedVariable.TypedIdent.Type)) { ctc.Error(function, "Result type does not match witnessed variable"); } firstAction = ctc.FindAtomicAction(firstActionName); secondAction = ctc.FindAtomicAction(secondActionName); if (firstAction == null) { ctc.Error(kv, $"Could not find atomic action {firstActionName}"); } if (secondAction == null) { ctc.Error(kv, $"Could not find atomic action {firstActionName}"); } if (firstAction != null && secondAction != null) { CheckInParams(function.InParams); } allWitnessFunctions.Add(new WitnessFunction(function, witnessedVariable, firstAction, secondAction, args)); }
private static Tuple <Procedure, Implementation> GenerateAbstractionChecker(CivlTypeChecker civlTypeChecker, AtomicAction action, AtomicAction abs) { var requires = abs.gate.Select(g => new Requires(false, g.Expr)).ToList(); // TODO: check frame computation var frame = new HashSet <Variable>( action.modifiedGlobalVars .Union(action.gateUsedGlobalVars) .Union(abs.modifiedGlobalVars) .Union(abs.gateUsedGlobalVars)); var subst = InductiveSequentialization.GetSubstitution(action, abs); List <Cmd> cmds = InductiveSequentialization.GetGateAsserts(action, subst, $"Abstraction {abs.proc.Name} fails gate of {action.proc.Name}").ToList <Cmd>(); cmds.Add( CmdHelper.CallCmd( action.proc, abs.impl.InParams, abs.impl.OutParams )); cmds.Add( CmdHelper.AssertCmd( abs.proc.tok, TransitionRelationComputation.Refinement(civlTypeChecker, abs, frame), $"Abstraction {abs.proc.Name} does not summarize {action.proc.Name}" )); var blocks = new List <Block> { BlockHelper.Block("init", cmds) }; var proc = DeclHelper.Procedure( civlTypeChecker.AddNamePrefix($"AbstractionCheck_{action.proc.Name}_{abs.proc.Name}"), abs.impl.InParams, abs.impl.OutParams, requires, action.proc.Modifies, new List <Ensures>()); var impl = DeclHelper.Implementation( proc, proc.InParams, proc.OutParams, new List <Variable>(), blocks); return(Tuple.Create(proc, impl)); }
private IEnumerable <AssertCmd> GetGateAsserts(AtomicAction action, Substitution subst) { return(GetGateAsserts(action, subst, $"Gate of {action.proc.Name} fails in IS {checkName} of {inputAction.proc.Name}")); }
private Tuple <AtomicAction, AtomicAction> Key(AtomicAction first, AtomicAction second) { return(Tuple.Create(first, second)); }