private List <Cmd> InlineYieldLoopInvariants(List <CallCmd> yieldInvariants) { var inlinedYieldInvariants = new List <Cmd>(); foreach (var callCmd in yieldInvariants) { var yieldInvariant = civlTypeChecker.procToYieldInvariant[callCmd.Proc]; if (layerNum == yieldInvariant.LayerNum) { Dictionary <Variable, Expr> map = callCmd.Proc.InParams.Zip(callCmd.Ins) .ToDictionary(x => x.Item1, x => x.Item2); Substitution subst = Substituter.SubstitutionFromHashtable(map); foreach (Requires req in callCmd.Proc.Requires) { var newExpr = Substituter.Apply(subst, req.Condition); if (req.Free) { inlinedYieldInvariants.Add(new AssumeCmd(req.tok, newExpr, req.Attributes)); } else { inlinedYieldInvariants.Add(new AssertCmd(req.tok, newExpr, req.Attributes)); } } } } return(inlinedYieldInvariants); }
public Expr TransitionRelationCompute(bool withOriginalInOutVariables = false) { Expr transitionRelation = Expr.Or(paths.Select(p => CalculatePathCondition(p))); ResolutionContext rc = new ResolutionContext(null); rc.StateMode = ResolutionContext.State.Two; transitionRelation.Resolve(rc); transitionRelation.Typecheck(new TypecheckingContext(null)); if (withOriginalInOutVariables) { Dictionary <Variable, Expr> invertedMap = new Dictionary <Variable, Expr>(); if (first != null) { foreach (var x in first.thatMap) { invertedMap[((IdentifierExpr)x.Value).Decl] = Expr.Ident(x.Key); } } if (second != null) { foreach (var x in second.thisMap) { invertedMap[((IdentifierExpr)x.Value).Decl] = Expr.Ident(x.Key); } } Substitution subst = Substituter.SubstitutionFromHashtable(invertedMap); return(Substituter.Apply(subst, transitionRelation)); } else { return(transitionRelation); } }
public Expr Compute() { Search(second.thatAction.Blocks[0], false); Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); List <Variable> boundVars = new List <Variable>(); if (first != null) { foreach (Variable v in first.thisAction.LocVars) { BoundVariable bv = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, v.Name, v.TypedIdent.Type)); map[v] = new IdentifierExpr(Token.NoToken, bv); boundVars.Add(bv); } } foreach (Variable v in second.thatAction.LocVars) { BoundVariable bv = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, v.Name, v.TypedIdent.Type)); map[v] = new IdentifierExpr(Token.NoToken, bv); boundVars.Add(bv); } Substitution subst = Substituter.SubstitutionFromHashtable(map); if (boundVars.Count > 0) { return(new ExistsExpr(Token.NoToken, boundVars, Substituter.Apply(subst, transitionRelation))); } else { return(transitionRelation); } }
private void TryElimination(IEnumerable <Variable> extraDefinedVariables) { bool Defined(Variable v) => varToExpr.ContainsKey(v) || extraDefinedVariables.Contains(v); bool changed; do { changed = false; var remainingAssignments = new List <Assignment>(); foreach (var assignment in assignments) { if (!Defined(assignment.Var) && VariableCollector.Collect(assignment.Expr). Intersect(AllIntroducedVariables).All(Defined)) { varToExpr[assignment.Var] = SubstitutionHelper.Apply(varToExpr, assignment.Expr); changed = true; } else { remainingAssignments.Add(assignment); } } Substitution sub = Substituter.SubstitutionFromHashtable(varToExpr); foreach (var assignment in remainingAssignments) { assignment.Expr = Substituter.Apply(sub, assignment.Expr); } assignments = remainingAssignments; assumes = SubstitutionHelper.Apply(sub, assumes).ToList(); } while (changed); }
/// <summary> /// Performs lambda lifting (see <see cref="LambdaHelper.ExpandLambdas"/>) by replacing with bound variables /// maximally large subexpressions of a lambda that do not contain any of the lambda's bound variables. /// </summary> /// <param name="lambda">A lambda expression /// <code>(lambda x1: T1 ... x_n: T_n :: t)</code> /// where <c>t</c> contains the subexpressions <c>e1</c>, ..., <c>e_m</c>. These are maximally large /// subexpressions that do not contain the lambda's bound variables. /// </param> /// <returns> /// <list type="bullet"> /// <item> /// A function application <c>f(y1, ..., y_m)</c> where <c>f</c>'s body is defined to be the result of /// replacing the expressions <c>e1</c>, ..., <c>e_m</c> in <c>t</c> with bound variables /// <c>b1</c>, ..., <c>b_m</c>. /// </item> /// <item> /// Adds a definition and axiom for <c>f</c> to <see cref="lambdaFunctions"/> and <see cref="lambdaAxioms"/>. /// Memoizes <c>f</c> as the lifted lambda for <para>lambda</para>. /// </item> /// </list> /// </returns> private Expr LiftLambdaMaxHoles(LambdaExpr lambda) { // We start by getting rid of `old` expressions. Instead, we replace the free variables `x_i` that are // nested inside of `old` expressions with `old(x_i)` expressions. var oldFinder = new OldFinder(); oldFinder.Visit(lambda); var oldSubst = new Dictionary<Variable, Expr>(); foreach (var v in oldFinder.FreeOldVars) if (v is GlobalVariable g) { oldSubst.Add(g, new OldExpr(g.tok, new IdentifierExpr(g.tok, g)) {Type = g.TypedIdent.Type}); } var lambdaBody = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromHashtable(oldSubst), lambda.Body); var lambdaAttrs = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromHashtable(oldSubst), lambda.Attributes); var newLambda = new LambdaExpr(lambda.tok, lambda.TypeParameters, lambda.Dummies, lambdaAttrs, lambdaBody) { Type = lambda.Type }; // We perform lambda lifting on the resulting lambda which now contains only `old` expressions of the form // `old(x)` where `x` is a variable that is free in the lambda. return new MaxHolesLambdaLifter( newLambda, liftedLambdas, FreshLambdaFunctionName(), lambdaFunctions, lambdaAxioms) .VisitLambdaExpr(newLambda); }
private void ReplacePreOrPostStateVars() { var preStateSub = GetPreStateVars(). ToDictionary <Variable, Variable, Expr>(v => varCopies[0][v], v => new OldExpr(Token.NoToken, new IdentifierExpr(Token.NoToken, v))); var frameCopiesSub = preStateSub; if (!IgnorePostState) { var postStateSub = GetPostStateVars(). ToDictionary <Variable, Variable, Expr>(v => varCopies[varLastCopyId[v]][v], v => Expr.Ident(v)); var notModifiedVars = new HashSet <Variable>(preStateSub.Keys.Intersect(postStateSub.Keys)); foreach (var v in notModifiedVars) { pathExprs.Add(Expr.Eq(preStateSub[v], postStateSub[v])); postStateSub.Remove(v); } frameCopiesSub = frameCopiesSub.Union(postStateSub).ToDictionary(k => k.Key, v => v.Value); } var finalSub = Substituter.SubstitutionFromHashtable(frameCopiesSub); pathExprs = pathExprs.Select(x => Substituter.Apply(finalSub, x)).ToList(); }
public CodeCopier(Dictionary<Variable, Expr> substMap, Dictionary<Variable, Expr> oldSubstMap) { Contract.Requires(oldSubstMap != null); Contract.Requires(substMap != null); Subst = Substituter.SubstitutionFromHashtable(substMap); OldSubst = Substituter.SubstitutionFromHashtable(oldSubstMap); }
public NormalSubstituter(Substitution subst) : base() { Contract.Requires(subst != null); this.always = subst; this.forold = Substituter.SubstitutionFromHashtable(new Dictionary <Variable, Expr>()); }
private void ComputeWitnessedTransitionRelationExprs() { witnessedTransitionRelations = new List <Expr>(); Dictionary <Variable, List <WitnessFunction> > varToWitnesses = FrameWithWitnesses. Where(x => NotEliminatedVars.Contains(frameIntermediateCopy[x])). ToDictionary( x => frameIntermediateCopy[x], x => transitionRelationComputer.globalVarToWitnesses[(GlobalVariable)x]); foreach (var witnessSet in varToWitnesses.Values.CartesianProduct()) { Dictionary <Variable, Expr> witnessSubst = new Dictionary <Variable, Expr>(); foreach (Tuple <Variable, WitnessFunction> pair in Enumerable.Zip(varToWitnesses.Keys, witnessSet, Tuple.Create)) { WitnessFunction witnessFunction = pair.Item2; List <Expr> args = new List <Expr>(); foreach (var arg in witnessFunction.InputArgs) { Expr expr = null; switch (arg.Kind) { case WitnessFunction.InputArgumentKind.FIRST_ARG: // TODO: Add note on the reason of using second expr = Expr.Ident(second.Params. First(x => x.Name == second.Prefix + arg.Name)); break; case WitnessFunction.InputArgumentKind.SECOND_ARG: expr = Expr.Ident(first.Params. First(x => x.Name == first.Prefix + arg.Name)); break; case WitnessFunction.InputArgumentKind.PRE_STATE: expr = ExprHelper.Old(Expr.Ident( frame.First(x => x.Name == arg.Name))); break; case WitnessFunction.InputArgumentKind.POST_STATE: expr = Expr.Ident(frame.First(x => x.Name == arg.Name)); break; default: Debug.Assert(false); break; } args.Add(expr); } witnessSubst[pair.Item1] = ExprHelper.FunctionCall( witnessFunction.function, args.ToArray() ); } var subst = Substituter.SubstitutionFromHashtable(witnessSubst); witnessedTransitionRelations.Add( Substituter.Apply(subst, TransitionRelationExpr)); } }
private Expr CalculatePathCondition(PathInfo path) { Expr returnExpr = Expr.True; HashSet <Variable> existsVars = path.existsVars; Dictionary <Variable, Expr> existsMap = new Dictionary <Variable, Expr>(); Dictionary <Variable, Expr> varToExpr = path.varToExpr; foreach (Variable v in varToExpr.Keys) { if (postExistVars.Contains(v)) { continue; } IdentifierExpr ie = varToExpr[v] as IdentifierExpr; if (ie != null && !existsMap.ContainsKey(ie.Decl) && existsVars.Contains(ie.Decl)) { existsMap[ie.Decl] = Expr.Ident(v); existsVars.Remove(ie.Decl); } else { returnExpr = Expr.And(returnExpr, Expr.Eq(Expr.Ident(v), (new MyDuplicator()).VisitExpr(varToExpr[v]))); returnExpr.Type = Type.Bool; } } List <Expr> pathExprs = new List <Expr>(); path.pathExprs.ForEach(x => pathExprs.Add((new MyDuplicator()).VisitExpr(x))); foreach (Expr x in pathExprs) { Variable boundVar; Expr boundVarExpr; if (InferSubstitution(x, out boundVar, out boundVarExpr) && existsVars.Contains(boundVar)) { existsMap[boundVar] = boundVarExpr; existsVars.Remove(boundVar); } else { returnExpr = Expr.And(returnExpr, x); returnExpr.Type = Type.Bool; } } returnExpr = Substituter.Apply(Substituter.SubstitutionFromHashtable(existsMap), returnExpr); if (existsVars.Count > 0) { returnExpr = new ExistsExpr(Token.NoToken, new List <Variable>(existsVars), returnExpr); } return(returnExpr); }
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 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 AddBoundVariablesForRemainingVars() { var remainingVars = NotEliminatedVars.Except(IntermediateFrameWithWitnesses); existsVarMap = new Dictionary <Variable, BoundVariable>(); foreach (var v in remainingVars) { existsVarMap[v] = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, v.Name, v.TypedIdent.Type)); } var varMap = existsVarMap.ToDictionary(kvp => kvp.Key, kvp => Expr.Ident(kvp.Value) as Expr); var varSubst = Substituter.SubstitutionFromHashtable(varMap); pathExprs = pathExprs.Select(x => Substituter.Apply(varSubst, x)).ToList(); }
public override BinderExpr VisitBinderExpr(BinderExpr node) { var subst = new Dictionary <Variable, Expr>(); var newBound = new List <Variable>(); foreach (var bv in node.Dummies) { var bvNew = boundVars[boundVarCount++, bv.TypedIdent.Type]; newBound.Add(bvNew); subst[bv] = new IdentifierExpr(Token.NoToken, bvNew); } node.Dummies = this.VisitVariableSeq(newBound); node.Body = this.VisitExpr(Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), node.Body)); return(node); }
private bool TryElimination(IEnumerable <Variable> extraDefinedVariables) { bool changed = false; var remainingCmds = new List <Cmd>(); foreach (var cmd in newCmds) { if (cmd is AssignCmd assignCmd) { var lhss = new List <AssignLhs>(); var rhss = new List <Expr>(); for (int k = 0; k < assignCmd.Lhss.Count; k++) { var lhs = assignCmd.Lhss[k]; var rhs = assignCmd.Rhss[k]; Variable assignedVar = lhs.DeepAssignedVariable; var allDefinedVars = varToExpr.Keys.Union(extraDefinedVariables); if (!allDefinedVars.Contains(assignedVar) && !VariableCollector.Collect(rhs).Intersect(AllIntroducedVariables). Except(allDefinedVars).Any()) { varToExpr[assignedVar] = rhs; changed = true; } else { lhss.Add(lhs); rhss.Add(rhs); } } if (lhss.Any()) { remainingCmds.Add(new AssignCmd(cmd.tok, lhss, rhss, assignCmd.Attributes)); } } else if (cmd is AssumeCmd) { remainingCmds.Add(cmd); } } Substitution sub = Substituter.SubstitutionFromHashtable(varToExpr); newCmds = remainingCmds.Select(cmd => ApplyOnRhss(sub, cmd)).ToList(); return(changed); }
private void PendingPropagate(HashSet <Variable> allExistsVars, Dictionary <Variable, Expr> existsSubstitutionMap, Variable eVar, Expr eVarSubstExpr, Dictionary <Variable, Expr> pendingMap) { var usedExistsVars = VariableCollector.Collect(eVarSubstExpr).Intersect(allExistsVars); if (usedExistsVars.Count() == 0) { existsSubstitutionMap[eVar] = eVarSubstExpr; } else if (usedExistsVars.Except(existsSubstitutionMap.Keys).Count() == 0) { Substitution subst = Substituter.SubstitutionFromHashtable(existsSubstitutionMap); existsSubstitutionMap[eVar] = Substituter.Apply(subst, eVarSubstExpr); } else { pendingMap[eVar] = eVarSubstExpr; } }
private void Substitute(Dictionary <Variable, Expr> map, ref List <Expr> pathExprs, ref Dictionary <Variable, Expr> varToExpr) { Substitution subst = Substituter.SubstitutionFromHashtable(map); List <Expr> oldPathExprs = pathExprs; pathExprs = new List <Expr>(); foreach (Expr pathExpr in oldPathExprs) { pathExprs.Add(Substituter.Apply(subst, pathExpr)); } Dictionary <Variable, Expr> oldVarToExpr = varToExpr; varToExpr = new Dictionary <Variable, Expr>(); foreach (Variable v in oldVarToExpr.Keys) { varToExpr[v] = Substituter.Apply(subst, oldVarToExpr[v]); } }
private void CalculatePathExpression() { pathExprs = new List <Expr>(); foreach (var cmd in newCmds.Where(x => x is AssumeCmd).Cast <AssumeCmd>()) { FlattenAnd(cmd.Expr, pathExprs); } foreach (AssignCmd cmd in newCmds.Where(x => x is AssignCmd).Cast <AssignCmd>()) { for (int k = 0; k < cmd.Lhss.Count; k++) { pathExprs.Add(Expr.Eq(Expr.Ident(cmd.Lhss[k].DeepAssignedVariable), cmd.Rhss[k])); } } var varMap = varToExpr.ToDictionary(kvp => kvp.Key, kvp => kvp.Value); var varSubst = Substituter.SubstitutionFromHashtable(varMap); pathExprs = pathExprs.Select(x => Substituter.Apply(varSubst, x)).ToList(); }
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(new HavocCmd(Token.NoToken, civlTypeChecker.GlobalVariables.Select(v => Expr.Ident(v)).ToList())); linearPermissionInstrumentation.DisjointnessExprs(impl, true).ForEach( expr => initCmds.Add(new AssumeCmd(Token.NoToken, 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) new OldExpr(Token.NoToken, 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); }
private void InlineYieldRequiresAndEnsures() { foreach (var impl in absyMap.Keys.OfType <Implementation>()) { var yieldingProc = GetYieldingProc(impl); foreach (var callCmd in yieldingProc.yieldRequires) { var yieldInvariant = civlTypeChecker.procToYieldInvariant[callCmd.Proc]; if (layerNum == yieldInvariant.LayerNum) { Dictionary <Variable, Expr> map = callCmd.Proc.InParams.Zip(callCmd.Ins) .ToDictionary(x => x.Item1, x => x.Item2); Substitution subst = Substituter.SubstitutionFromHashtable(map); foreach (Requires req in callCmd.Proc.Requires) { impl.Proc.Requires.Add(new Requires(req.tok, req.Free, Substituter.Apply(subst, req.Condition), null, req.Attributes)); } } } foreach (var callCmd in yieldingProc.yieldEnsures) { var yieldInvariant = civlTypeChecker.procToYieldInvariant[callCmd.Proc]; if (layerNum == yieldInvariant.LayerNum) { Dictionary <Variable, Expr> map = callCmd.Proc.InParams.Zip(callCmd.Ins) .ToDictionary(x => x.Item1, x => x.Item2); Substitution subst = Substituter.SubstitutionFromHashtable(map); foreach (Requires req in callCmd.Proc.Requires) { impl.Proc.Ensures.Add(new Ensures(req.tok, req.Free, Substituter.Apply(subst, req.Condition), null, req.Attributes)); } } } } }
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); }
/// <summary> /// Performs lambda lifting (see <see cref="LambdaHelper.ExpandLambdas"/>) by replacing the lambda's /// free variables with bound ones. /// </summary> /// <param name="lambda">A lambda expression /// <code>(lambda x1: T1 ... x_n: T_n :: t)</code> /// where <c>t</c> contains the free variables <c>y1</c>, ..., <c>y_m</c>. /// </param> /// <returns> /// <list type="bullet"> /// <item> /// A function application <c>f(y1, ..., y_m)</c> where <c>f</c>'s body is defined to be the result of /// replacing the free variables <c>y1</c>, ..., <c>y_m</c> in <c>t</c> with bound variables /// <c>b1</c>, ..., <c>b_m</c>. /// </item> /// <item> /// Adds a definition and axiom for <c>f</c> to <see cref="lambdaFunctions"/> and <see cref="lambdaAxioms"/>. /// Memoizes <c>f</c> as the lifted lambda for <para>lambda</para>. /// </item> /// </list> /// </returns> private Expr LiftLambdaFreeVars(LambdaExpr lambda) { // We start by getting rid of any use of "old" inside the lambda. This is done as follows. // For each variable "g" occurring inside lambda as "old(... g ...)", create a new name "og". // Replace each old occurrence of "g" with "og", removing the enclosing "old" wrappers. var oldFinder = new OldFinder(); oldFinder.Visit(lambda); var oldSubst = new Dictionary<Variable, Expr>(); // g -> g0 var callOldMapping = new Dictionary<Variable, Expr>(); // g0 -> old(g) foreach (var v in oldFinder.FreeOldVars) { var g = v as GlobalVariable; if (g != null) { var g0 = new GlobalVariable(g.tok, new TypedIdent(g.tok, g.TypedIdent.Name + "@old", g.TypedIdent.Type)); oldSubst.Add(g, new IdentifierExpr(g0.tok, g0)); callOldMapping.Add(g0, new OldExpr(g0.tok, new IdentifierExpr(g.tok, g))); } } var lambdaBody = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromHashtable(oldSubst), lambda.Body); var lambdaAttrs = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromHashtable(oldSubst), lambda.Attributes); if (0 < CommandLineOptions.Clo.VerifySnapshots && QKeyValue.FindStringAttribute(lambdaAttrs, "checksum") == null) { // Attach a dummy checksum to avoid issues in the dependency analysis. var checksumAttr = new QKeyValue(lambda.tok, "checksum", new List<object> {"lambda expression"}, null); if (lambdaAttrs == null) { lambdaAttrs = checksumAttr; } else { lambdaAttrs.AddLast(checksumAttr); } } // this is ugly, the output will depend on hashing order var subst = new Dictionary<Variable, Expr>(); var substFnAttrs = new Dictionary<Variable, Expr>(); var formals = new List<Variable>(); var callArgs = new List<Expr>(); var axCallArgs = new List<Expr>(); var dummies = new List<Variable>(lambda.Dummies); var freeTypeVars = new List<TypeVariable>(); var fnTypeVarActuals = new List<Type /*!*/>(); var freshTypeVars = new List<TypeVariable>(); // these are only used in the lambda@n function's definition // compute the free variables of the lambda expression, but with lambdaBody instead of lambda.Body Set freeVars = new Set(); BinderExpr.ComputeBinderFreeVariables(lambda.TypeParameters, lambda.Dummies, lambdaBody, null, lambdaAttrs, freeVars); foreach (object o in freeVars) { // 'o' is either a Variable or a TypeVariable. if (o is Variable) { var v = o as Variable; var ti = new TypedIdent(v.TypedIdent.tok, v.TypedIdent.Name, v.TypedIdent.Type); var f = new Formal(v.tok, ti, true); formals.Add(f); substFnAttrs.Add(v, new IdentifierExpr(f.tok, f)); var b = new BoundVariable(v.tok, ti); dummies.Add(b); if (callOldMapping.ContainsKey(v)) { callArgs.Add(callOldMapping[v]); } else { callArgs.Add(new IdentifierExpr(v.tok, v)); } Expr id = new IdentifierExpr(b.tok, b); subst.Add(v, id); axCallArgs.Add(id); } else { var tv = (TypeVariable) o; freeTypeVars.Add(tv); fnTypeVarActuals.Add(tv); freshTypeVars.Add(new TypeVariable(tv.tok, tv.Name)); } } var sw = new System.IO.StringWriter(); var wr = new TokenTextWriter(sw, true); lambda.Emit(wr); string lam_str = sw.ToString(); FunctionCall fcall; IToken tok = lambda.tok; Formal res = new Formal(tok, new TypedIdent(tok, TypedIdent.NoName, cce.NonNull(lambda.Type)), false); if (liftedLambdas.TryGetValue(lambda, out fcall)) { if (CommandLineOptions.Clo.TraceVerify) { Console.WriteLine("Old lambda: {0}", lam_str); } } else { if (CommandLineOptions.Clo.TraceVerify) { Console.WriteLine("New lambda: {0}", lam_str); } Function fn = new Function(tok, FreshLambdaFunctionName(), freshTypeVars, formals, res, "auto-generated lambda function", Substituter.Apply(Substituter.SubstitutionFromHashtable(substFnAttrs), lambdaAttrs)); fn.OriginalLambdaExprAsString = lam_str; fcall = new FunctionCall(new IdentifierExpr(tok, fn.Name)); fcall.Func = fn; // resolve here liftedLambdas[lambda] = fcall; List<Expr /*!*/> selectArgs = new List<Expr /*!*/>(); foreach (Variable /*!*/ v in lambda.Dummies) { Contract.Assert(v != null); selectArgs.Add(new IdentifierExpr(v.tok, v)); } NAryExpr axcall = new NAryExpr(tok, fcall, axCallArgs); axcall.Type = res.TypedIdent.Type; axcall.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); NAryExpr select = Expr.Select(axcall, selectArgs); select.Type = lambdaBody.Type; List<Type /*!*/> selectTypeParamActuals = new List<Type /*!*/>(); List<TypeVariable> forallTypeVariables = new List<TypeVariable>(); foreach (TypeVariable /*!*/ tp in lambda.TypeParameters) { Contract.Assert(tp != null); selectTypeParamActuals.Add(tp); forallTypeVariables.Add(tp); } forallTypeVariables.AddRange(freeTypeVars); select.TypeParameters = SimpleTypeParamInstantiation.From(lambda.TypeParameters, selectTypeParamActuals); Expr bb = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaBody); NAryExpr body = Expr.Eq(select, bb); body.Type = Type.Bool; body.TypeParameters = SimpleTypeParamInstantiation.EMPTY; Trigger trig = new Trigger(select.tok, true, new List<Expr> {select}); lambdaFunctions.Add(fn); lambdaAxioms.Add(new ForallExpr(tok, forallTypeVariables, dummies, Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaAttrs), trig, body)); } NAryExpr call = new NAryExpr(tok, fcall, callArgs); call.Type = res.TypedIdent.Type; call.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); return call; }
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; } }
public ActionInfo(Procedure proc, CodeExpr codeExpr, MoverType moverType, int phaseNum) { this.proc = proc; this.moverType = moverType; this.phaseNum = phaseNum; this.callerPhaseNums = new HashSet <int>(); this.thisGate = new List <AssertCmd>(); this.thisAction = codeExpr; this.thisInParams = new List <Variable>(); this.thisOutParams = new List <Variable>(); this.thatGate = new List <AssertCmd>(); this.thatInParams = new List <Variable>(); this.thatOutParams = new List <Variable>(); var cmds = thisAction.Blocks[0].Cmds; for (int i = 0; i < cmds.Count; i++) { AssertCmd assertCmd = cmds[i] as AssertCmd; if (assertCmd == null) { break; } thisGate.Add(assertCmd); cmds[i] = new AssumeCmd(assertCmd.tok, assertCmd.Expr); } Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); foreach (Variable x in proc.InParams) { this.thisInParams.Add(x); Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), true); this.thatInParams.Add(y); map[x] = new IdentifierExpr(Token.NoToken, y); } foreach (Variable x in proc.OutParams) { this.thisOutParams.Add(x); Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false); this.thatOutParams.Add(y); map[x] = new IdentifierExpr(Token.NoToken, y); } List <Variable> otherLocVars = new List <Variable>(); foreach (Variable x in thisAction.LocVars) { Variable y = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "that_" + x.Name, x.TypedIdent.Type), false); map[x] = new IdentifierExpr(Token.NoToken, y); otherLocVars.Add(y); } Contract.Assume(proc.TypeParameters.Count == 0); Substitution subst = Substituter.SubstitutionFromHashtable(map); foreach (AssertCmd assertCmd in thisGate) { thatGate.Add((AssertCmd)Substituter.Apply(subst, assertCmd)); } Dictionary <Block, Block> blockMap = new Dictionary <Block, Block>(); List <Block> otherBlocks = new List <Block>(); foreach (Block block in thisAction.Blocks) { List <Cmd> otherCmds = new List <Cmd>(); foreach (Cmd cmd in block.Cmds) { otherCmds.Add(Substituter.Apply(subst, cmd)); } Block otherBlock = new Block(); otherBlock.Cmds = otherCmds; otherBlock.Label = "that_" + block.Label; block.Label = "this_" + block.Label; otherBlocks.Add(otherBlock); blockMap[block] = otherBlock; if (block.TransferCmd is GotoCmd) { GotoCmd gotoCmd = block.TransferCmd as GotoCmd; for (int i = 0; i < gotoCmd.labelNames.Count; i++) { gotoCmd.labelNames[i] = "this_" + gotoCmd.labelNames[i]; } } } foreach (Block block in thisAction.Blocks) { if (block.TransferCmd is ReturnExprCmd) { block.TransferCmd = new ReturnCmd(block.TransferCmd.tok); blockMap[block].TransferCmd = new ReturnCmd(block.TransferCmd.tok); continue; } List <Block> otherGotoCmdLabelTargets = new List <Block>(); List <string> otherGotoCmdLabelNames = new List <string>(); GotoCmd gotoCmd = block.TransferCmd as GotoCmd; foreach (Block target in gotoCmd.labelTargets) { otherGotoCmdLabelTargets.Add(blockMap[target]); otherGotoCmdLabelNames.Add(blockMap[target].Label); } blockMap[block].TransferCmd = new GotoCmd(block.TransferCmd.tok, otherGotoCmdLabelNames, otherGotoCmdLabelTargets); } this.thatAction = new CodeExpr(otherLocVars, otherBlocks); }
protected void BeginInline(Implementation impl) { Contract.Requires(impl != null); Contract.Requires(impl.Proc != null); Contract.Requires(newModifies != null); Contract.Requires(newLocalVars != null); Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>(); Procedure proc = impl.Proc; foreach (Variable/*!*/ locVar in cce.NonNull(impl.OriginalLocVars)) { Contract.Assert(locVar != null); LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, locVar.Name), locVar.TypedIdent.Type, locVar.TypedIdent.WhereExpr)); localVar.Attributes = locVar.Attributes; // copy attributes newLocalVars.Add(localVar); IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar); substMap.Add(locVar, ie); } for (int i = 0; i < impl.InParams.Count; i++) { Variable inVar = cce.NonNull(impl.InParams[i]); LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, inVar.Name), inVar.TypedIdent.Type, inVar.TypedIdent.WhereExpr)); newLocalVars.Add(localVar); if (impl.Proc != null) localVar.Attributes = impl.Proc.InParams[i].Attributes; // copy attributes IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar); substMap.Add(inVar, ie); // also add a substitution from the corresponding formal occurring in the PROCEDURE declaration Variable procInVar = cce.NonNull(proc.InParams[i]); if (procInVar != inVar) { substMap.Add(procInVar, ie); } } for (int i = 0; i < impl.OutParams.Count; i++) { Variable outVar = cce.NonNull(impl.OutParams[i]); LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, outVar.Name), outVar.TypedIdent.Type, outVar.TypedIdent.WhereExpr)); if (impl.Proc != null) localVar.Attributes = impl.Proc.OutParams[i].Attributes; // copy attributes newLocalVars.Add(localVar); IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar); substMap.Add(outVar, ie); // also add a substitution from the corresponding formal occurring in the PROCEDURE declaration Variable procOutVar = cce.NonNull(proc.OutParams[i]); if (procOutVar != outVar) { substMap.Add(procOutVar, ie); } } Dictionary<Variable, Expr> substMapOld = new Dictionary<Variable, Expr>(); foreach (IdentifierExpr/*!*/ mie in proc.Modifies) { Contract.Assert(mie != null); Variable/*!*/ mVar = cce.NonNull(mie.Decl); LocalVariable localVar = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, GetProcVarName(proc.Name, mVar.Name), mVar.TypedIdent.Type)); newLocalVars.Add(localVar); IdentifierExpr ie = new IdentifierExpr(Token.NoToken, localVar); substMapOld.Add(mVar, ie); // FIXME why are we doing this? the modifies list should already include them. // add the modified variable to the modifies list of the procedure if (!newModifies.Contains(mie)) { newModifies.Add(mie); } } codeCopier.Subst = Substituter.SubstitutionFromHashtable(substMap); codeCopier.OldSubst = Substituter.SubstitutionFromHashtable(substMapOld); }
public List <Declaration> CreateYieldCheckerProcImpl( Implementation impl, IEnumerable <List <PredicateCmd> > yields) { Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); List <Variable> locals = new List <Variable>(); List <Variable> inputs = new List <Variable>(); foreach (Variable local in impl.LocVars.Union(impl.InParams).Union(impl.OutParams)) { var copy = CopyLocal(local); locals.Add(copy); map[local] = Expr.Ident(copy); } foreach (var domainName in linearTypeChecker.linearDomains.Keys) { var inParam = linearTypeChecker.LinearDomainInFormal(domainName); inputs.Add(inParam); map[linearTypeChecker.domainNameToHoleVar[domainName]] = Expr.Ident(inParam); } Dictionary <Variable, Expr> oldLocalMap = new Dictionary <Variable, Expr>(); Dictionary <Variable, Expr> assumeMap = new Dictionary <Variable, Expr>(map); foreach (Variable g in civlTypeChecker.sharedVariables) { var copy = OldLocalLocal(g); locals.Add(copy); oldLocalMap[g] = Expr.Ident(copy); Formal f = OldGlobalFormal(g); inputs.Add(f); assumeMap[g] = Expr.Ident(f); } Substitution assumeSubst = Substituter.SubstitutionFromHashtable(assumeMap); Substitution oldSubst = Substituter.SubstitutionFromHashtable(oldLocalMap); Substitution subst = Substituter.SubstitutionFromHashtable(map); List <Block> yieldCheckerBlocks = new List <Block>(); List <String> labels = new List <String>(); List <Block> labelTargets = new List <Block>(); Block yieldCheckerBlock = new Block(Token.NoToken, "exit", new List <Cmd>(), new ReturnCmd(Token.NoToken)); labels.Add(yieldCheckerBlock.Label); labelTargets.Add(yieldCheckerBlock); yieldCheckerBlocks.Add(yieldCheckerBlock); int yieldCount = 0; foreach (var cs in yields) { List <Cmd> newCmds = new List <Cmd>(); foreach (var predCmd in cs) { var newExpr = Substituter.ApplyReplacingOldExprs(assumeSubst, oldSubst, predCmd.Expr); newCmds.Add(new AssumeCmd(Token.NoToken, newExpr)); } foreach (var predCmd in cs) { 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); } /* * Disjointness assumes injected by LinearTypeChecker are dropped now because the * previous loop has already substituted the old global state in these assumes. * It would be unsound to have these assumes on the current global state. */ } newCmds.Add(new AssumeCmd(Token.NoToken, Expr.False)); yieldCheckerBlock = new Block(Token.NoToken, "L" + yieldCount++, newCmds, new ReturnCmd(Token.NoToken)); labels.Add(yieldCheckerBlock.Label); labelTargets.Add(yieldCheckerBlock); yieldCheckerBlocks.Add(yieldCheckerBlock); } yieldCheckerBlocks.Insert(0, new Block(Token.NoToken, "enter", new List <Cmd>(), new GotoCmd(Token.NoToken, labels, labelTargets))); // Create the yield checker procedure var yieldCheckerName = $"Impl_YieldChecker_{impl.Name}"; var yieldCheckerProc = new Procedure(Token.NoToken, yieldCheckerName, impl.TypeParameters, inputs, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>()); CivlUtil.AddInlineAttribute(yieldCheckerProc); // Create the yield checker implementation var yieldCheckerImpl = new Implementation(Token.NoToken, yieldCheckerName, impl.TypeParameters, inputs, new List <Variable>(), locals, yieldCheckerBlocks); yieldCheckerImpl.Proc = yieldCheckerProc; CivlUtil.AddInlineAttribute(yieldCheckerImpl); return(new List <Declaration> { yieldCheckerProc, yieldCheckerImpl }); }
private void DesugarParCallCmdInBlock(Block block, bool isBlockInYieldingLoop) { var parCallCmd = (ParCallCmd)block.Cmds[0]; List <Cmd> newCmds = new List <Cmd>(); if (!isBlockInYieldingLoop) { newCmds.AddRange(refinementInstrumentation.CreateUpdatesToRefinementVars(IsParCallMarked(parCallCmd))); } List <Expr> ins = new List <Expr>(); List <IdentifierExpr> outs = new List <IdentifierExpr>(); string procName = "ParallelCall"; foreach (CallCmd callCmd in parCallCmd.CallCmds) { // Use original procedure names to make aggregated name more readable procName = procName + "_" + absyMap.OriginalOrInput(callCmd.Proc).Name; ins.AddRange(callCmd.Ins); outs.AddRange(callCmd.Outs); } procName = civlTypeChecker.AddNamePrefix(procName) + "_" + layerNum; if (!parallelCallAggregators.ContainsKey(procName)) { List <Variable> inParams = new List <Variable>(); List <Variable> outParams = new List <Variable>(); List <Requires> requiresSeq = new List <Requires>(); List <Ensures> ensuresSeq = new List <Ensures>(); int count = 0; foreach (CallCmd callCmd in parCallCmd.CallCmds) { Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); foreach (Variable x in callCmd.Proc.InParams) { Variable y = ParCallDesugarFormal(x, count, true); inParams.Add(y); map[x] = Expr.Ident(y); } foreach (Variable x in callCmd.Proc.OutParams) { Variable y = ParCallDesugarFormal(x, count, false); outParams.Add(y); map[x] = Expr.Ident(y); } Contract.Assume(callCmd.Proc.TypeParameters.Count == 0); Substitution subst = Substituter.SubstitutionFromHashtable(map); foreach (Requires req in callCmd.Proc.Requires) { requiresSeq.Add(new Requires(req.tok, req.Free, Substituter.Apply(subst, req.Condition), null, req.Attributes)); } foreach (Ensures ens in callCmd.Proc.Ensures) { ensuresSeq.Add(new Ensures(ens.tok, ens.Free, Substituter.Apply(subst, ens.Condition), null, ens.Attributes)); } count++; } parallelCallAggregators[procName] = new Procedure(Token.NoToken, procName, new List <TypeVariable>(), inParams, outParams, requiresSeq, civlTypeChecker.GlobalVariables.Select(v => Expr.Ident(v)).ToList(), ensuresSeq); } Procedure proc = parallelCallAggregators[procName]; CallCmd checkerCallCmd = new CallCmd(parCallCmd.tok, proc.Name, ins, outs, parCallCmd.Attributes); checkerCallCmd.Proc = proc; newCmds.Add(checkerCallCmd); newCmds.AddRange(refinementInstrumentation.CreateAssumeCmds()); newCmds.AddRange(globalSnapshotInstrumentation.CreateUpdatesToOldGlobalVars()); newCmds.AddRange(refinementInstrumentation.CreateUpdatesToOldOutputVars()); newCmds.AddRange(noninterferenceInstrumentation.CreateUpdatesToPermissionCollector(parCallCmd)); newCmds.AddRange(block.cmds.GetRange(1, block.cmds.Count - 1)); block.cmds = newCmds; }
private void CreateFailurePreservationChecker(Program program, ActionInfo first, ActionInfo second) { Tuple <ActionInfo, ActionInfo> actionPair = new Tuple <ActionInfo, ActionInfo>(first, second); if (failurePreservationCheckerCache.Contains(actionPair)) { return; } failurePreservationCheckerCache.Add(actionPair); List <Variable> inputs = new List <Variable>(); inputs.AddRange(first.thisInParams); inputs.AddRange(second.thatInParams); Expr transitionRelation = (new TransitionRelationComputation(program, second)).Compute(); Expr expr = Expr.True; foreach (AssertCmd assertCmd in first.thisGate) { expr = Expr.And(assertCmd.Expr, expr); } List <Requires> requires = DisjointnessRequires(program, first, second); requires.Add(new Requires(false, Expr.Not(expr))); foreach (AssertCmd assertCmd in second.thatGate) { requires.Add(new Requires(false, assertCmd.Expr)); } Dictionary <Variable, Expr> map = new Dictionary <Variable, Expr>(); Dictionary <Variable, Expr> oldMap = new Dictionary <Variable, Expr>(); List <Variable> boundVars = new List <Variable>(); foreach (Variable v in program.GlobalVariables()) { BoundVariable bv = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "post_" + v.Name, v.TypedIdent.Type)); boundVars.Add(bv); map[v] = new IdentifierExpr(Token.NoToken, bv); } foreach (Variable v in second.thatOutParams) { { BoundVariable bv = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "post_" + v.Name, v.TypedIdent.Type)); boundVars.Add(bv); map[v] = new IdentifierExpr(Token.NoToken, bv); } { BoundVariable bv = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "pre_" + v.Name, v.TypedIdent.Type)); boundVars.Add(bv); oldMap[v] = new IdentifierExpr(Token.NoToken, bv); } } foreach (Variable v in second.thatAction.LocVars) { BoundVariable bv = new BoundVariable(Token.NoToken, new TypedIdent(Token.NoToken, "pre_" + v.Name, v.TypedIdent.Type)); boundVars.Add(bv); oldMap[v] = new IdentifierExpr(Token.NoToken, bv); } Expr ensuresExpr = Expr.And(transitionRelation, Expr.Not(expr)); if (boundVars.Count > 0) { Substitution subst = Substituter.SubstitutionFromHashtable(map); Substitution oldSubst = Substituter.SubstitutionFromHashtable(oldMap); ensuresExpr = new ExistsExpr(Token.NoToken, boundVars, (Expr) new MySubstituter(subst, oldSubst).Visit(ensuresExpr)); } List <Ensures> ensures = new List <Ensures>(); ensures.Add(new Ensures(false, ensuresExpr)); List <Block> blocks = new List <Block>(); blocks.Add(new Block(Token.NoToken, "L", new List <Cmd>(), new ReturnCmd(Token.NoToken))); string checkerName = string.Format("FailurePreservationChecker_{0}_{1}", first.proc.Name, second.proc.Name); List <IdentifierExpr> globalVars = new List <IdentifierExpr>(); program.GlobalVariables().Iter(x => globalVars.Add(new IdentifierExpr(Token.NoToken, x))); Procedure proc = new Procedure(Token.NoToken, checkerName, new List <TypeVariable>(), inputs, new List <Variable>(), requires, globalVars, ensures); Implementation impl = new Implementation(Token.NoToken, checkerName, new List <TypeVariable>(), inputs, new List <Variable>(), new List <Variable>(), blocks); impl.Proc = proc; this.decls.Add(impl); this.decls.Add(proc); }
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); }
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.SubstitutionFromHashtable(assumeMap); Substitution oldSubst = Substituter.SubstitutionFromHashtable(oldLocalMap); Substitution subst = Substituter.SubstitutionFromHashtable(map); List <Block> noninterferenceCheckerBlocks = new List <Block>(); List <String> labels = new List <String>(); List <Block> labelTargets = new List <Block>(); Block noninterferenceCheckerBlock = new Block(Token.NoToken, "exit", new List <Cmd>(), new ReturnCmd(Token.NoToken)); labels.Add(noninterferenceCheckerBlock.Label); 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(Token.NoToken, 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(new AssumeCmd(Token.NoToken, Expr.False)); noninterferenceCheckerBlock = new Block(Token.NoToken, "L" + yieldCount++, newCmds, new ReturnCmd(Token.NoToken)); labels.Add(noninterferenceCheckerBlock.Label); labelTargets.Add(noninterferenceCheckerBlock); noninterferenceCheckerBlocks.Add(noninterferenceCheckerBlock); } noninterferenceCheckerBlocks.Insert(0, new Block(Token.NoToken, "enter", new List <Cmd>(), new GotoCmd(Token.NoToken, labels, labelTargets))); // Create the yield checker procedure noninterferenceCheckerName = civlTypeChecker.AddNamePrefix($"NoninterferenceChecker_{noninterferenceCheckerName}"); var noninterferenceCheckerProc = new Procedure(Token.NoToken, noninterferenceCheckerName, decl.TypeParameters, inputs, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>()); CivlUtil.AddInlineAttribute(noninterferenceCheckerProc); // Create the yield checker implementation var noninterferenceCheckerImpl = new Implementation(Token.NoToken, noninterferenceCheckerName, decl.TypeParameters, inputs, new List <Variable>(), locals, noninterferenceCheckerBlocks); noninterferenceCheckerImpl.Proc = noninterferenceCheckerProc; CivlUtil.AddInlineAttribute(noninterferenceCheckerImpl); return(new List <Declaration> { noninterferenceCheckerProc, noninterferenceCheckerImpl }); }