/// <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.SubstitutionFromDictionary(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromDictionary(oldSubst), lambda.Body); var lambdaAttrs = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromDictionary(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromDictionary(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); }
public Cmd CopyCmd(Cmd cmd) { Contract.Requires(cmd != null); Contract.Ensures(Contract.Result<Cmd>() != null); if (Subst == null) { return cmd; } else if (OldSubst == null) { return Substituter.Apply(Subst, cmd); } else { return Substituter.ApplyReplacingOldExprs(Subst, OldSubst, cmd); } }
public Expr CopyExpr(Expr expr) { Contract.Requires(expr != null); Contract.Ensures(Contract.Result<Expr>() != null); if (Subst == null) { return expr; } else if (OldSubst == null) { return Substituter.Apply(Subst, expr); } else { return Substituter.ApplyReplacingOldExprs(Subst, OldSubst, expr); } }
public Cmd CopyCmd(Cmd cmd) { if (substMap == null) { return cmd; } var newCmd = BoundVarAndReplacingOldSubstituter.Apply(substMap, oldSubstMap, prefix, cmd); if (cmd is ICarriesAttributes attrCmd && attrCmd.Attributes != null) { var attrCopy = (QKeyValue) attrCmd.Attributes.Clone(); ((ICarriesAttributes) newCmd).Attributes = Substituter.ApplyReplacingOldExprs(PartialSubst, PartialOldSubst, attrCopy); } return newCmd; }
/// <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.SubstitutionFromDictionary(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromDictionary(oldSubst), lambda.Body); var lambdaAttrs = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromDictionary(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromDictionary(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.SubstitutionFromDictionary(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.SubstitutionFromDictionary(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.SubstitutionFromDictionary(subst), lambdaAttrs), trig, body)); } NAryExpr call = new NAryExpr(tok, fcall, callArgs); call.Type = res.TypedIdent.Type; call.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); return call; }
private void IntroduceIntermediateVars() { var oldSub = SubstitutionHelper.FromVariableMap(LatestCopies(trc.PreStateVars)); assignments = new List <Assignment>(); assumes = new List <Expr>(); for (int k = 0; k < trc.path.Count; k++) { if (trc.IsJoint && k == trc.transferIndex) { PopulateIntermediateFrameCopy(); oldSub = SubstitutionHelper.FromVariableMap(LatestCopies(trc.PreStateVars)); } Cmd cmd = trc.path[k]; if (cmd is AssignCmd assignCmd) { assignCmd = assignCmd.AsSimpleAssignCmd; var preState = LatestCopies(); foreach (var v in assignCmd.Lhss) { MakeNewCopy(v.DeepAssignedVariable); } var postState = LatestCopies(); if (QKeyValue.FindBoolAttribute(assignCmd.Attributes, CivlAttributes.BACKWARD)) { var tmp = preState; preState = postState; postState = tmp; } var rhsSub = SubstitutionHelper.FromVariableMap(preState); for (int i = 0; i < assignCmd.Lhss.Count; i++) { var var = postState[assignCmd.Lhss[i].DeepAssignedVariable]; var expr = Substituter.ApplyReplacingOldExprs(rhsSub, oldSub, assignCmd.Rhss[i]); assignments.Add(new Assignment(var, expr)); } } else if (cmd is AssumeCmd assumeCmd) { var sub = SubstitutionHelper.FromVariableMap(LatestCopies()); assumes.Add(Substituter.ApplyReplacingOldExprs(sub, oldSub, assumeCmd.Expr)); } else if (cmd is HavocCmd havocCmd) { foreach (var v in havocCmd.Vars) { MakeNewCopy(v.Decl); } } else { Debug.Assert(false); } } // In case there were no commands from the second action if (trc.IsJoint && trc.path.Count == trc.transferIndex) { PopulateIntermediateFrameCopy(); } }
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 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 }); }
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 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 ActionRefinementInstrumentation( CivlTypeChecker civlTypeChecker, Implementation impl, Implementation originalImpl, Dictionary <Variable, Variable> oldGlobalMap) : base(civlTypeChecker, civlTypeChecker.procToYieldingProc[originalImpl.Proc] as ActionProc, oldGlobalMap) { newLocalVars = new List <Variable>(); ActionProc actionProc = civlTypeChecker.procToYieldingProc[originalImpl.Proc] as ActionProc; int layerNum = actionProc.upperLayer; pc = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "og_pc", Type.Bool)); newLocalVars.Add(pc); ok = new LocalVariable(Token.NoToken, new TypedIdent(Token.NoToken, "og_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.sharedVariables) { 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; 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 transitionRelationExpr = GetTransitionRelation(atomicAction); transitionRelation = Substituter.ApplyReplacingOldExprs(always, forold, transitionRelationExpr); Expr gateExpr = Expr.And(atomicAction.gate.Select(g => g.Expr)); gateExpr.Type = Type.Bool; gate = Substituter.Apply(always, gateExpr); }
private void IntroduceIntermediateVars() { var oldSub = Substituter.SubstitutionFromHashtable(GetPreStateVars(). ToDictionary <Variable, Variable, Expr>(v => v, v => Expr.Ident(varCopies[0][v]))); newCmds = new List <Cmd>(); for (int k = 0; k < cmds.Count; k++) { if (IsJoint() && k == transitionRelationComputer.transferIndex) { PopulateIntermediateFrameCopy(); oldSub = Substituter.SubstitutionFromHashtable(GetPreStateVars(). ToDictionary <Variable, Variable, Expr>(v => v, v => Expr.Ident(varCopies[varLastCopyId[v]][v]))); } Cmd cmd = cmds[k]; if (cmd is AssignCmd) { AssignCmd assignCmd = ((AssignCmd)cmd).AsSimpleAssignCmd; var preState = GetVarCopiesFromIds(varLastCopyId); foreach (var v in assignCmd.Lhss) { MakeNewCopy(v.DeepAssignedVariable); } var postState = GetVarCopiesFromIds(varLastCopyId); Dictionary <Variable, Variable> lhsMap = postState, rhsMap = preState; if (QKeyValue.FindBoolAttribute(assignCmd.Attributes, CivlAttributes.BACKWARD)) { lhsMap = preState; rhsMap = postState; } var rhsSub = Substituter.SubstitutionFromHashtable( rhsMap.ToDictionary( kvp => kvp.Key, kvp => Expr.Ident(kvp.Value) as Expr )); List <AssignLhs> lhss = assignCmd.Lhss.Select(x => (AssignLhs) new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, lhsMap[x.DeepAssignedVariable]))).ToList(); List <Expr> rhss = assignCmd.Rhss.Select(x => Substituter.ApplyReplacingOldExprs(rhsSub, oldSub, x)).ToList(); newCmds.Add(new AssignCmd(Token.NoToken, lhss, rhss, assignCmd.Attributes)); } else if (cmd is AssumeCmd) { var sub = Substituter.SubstitutionFromHashtable( GetVarCopiesFromIds(varLastCopyId).ToDictionary( kvp => kvp.Key, kvp => Expr.Ident(kvp.Value) as Expr )); newCmds.Add(new AssumeCmd(cmd.tok, Substituter.ApplyReplacingOldExprs(sub, oldSub, ((AssumeCmd)cmd).Expr))); } else if (cmd is HavocCmd havocCmd) { foreach (var v in havocCmd.Vars) { MakeNewCopy(v.Decl); } } else { Debug.Assert(false); } } // TODO: Add note on this if (!IsJoint() || cmds.Count == transitionRelationComputer.transferIndex) { PopulateIntermediateFrameCopy(); } }
public static List <Declaration> CreateNoninterferenceCheckers( CivlTypeChecker civlTypeChecker, LinearTypeChecker linearTypeChecker, int layerNum, Dictionary <Absy, Absy> absyMap, Implementation impl, Dictionary <YieldCmd, List <PredicateCmd> > yields) { 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 impl.LocVars.Union(impl.InParams).Union(impl.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 = OldLocalLocal(g); locals.Add(copy); oldLocalMap[g] = Expr.Ident(copy); Formal f = OldGlobalFormal(g); inputs.Add(f); assumeMap[g] = Expr.Ident(f); } var linearPermissionInstrumentation = new LinearPermissionInstrumentation(civlTypeChecker, linearTypeChecker, layerNum, absyMap, domainNameToHoleVar, localVarMap); 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 yields) { var yieldCmd = kv.Key; var yieldPredicates = kv.Value; List <Cmd> newCmds = linearPermissionInstrumentation.DisjointnessAssumeCmds(yieldCmd, false); foreach (var predCmd in yieldPredicates) { var newExpr = Substituter.ApplyReplacingOldExprs(assumeSubst, oldSubst, predCmd.Expr); newCmds.Add(new AssumeCmd(Token.NoToken, newExpr)); } foreach (var predCmd in yieldPredicates) { 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 var noninterferenceCheckerName = $"NoninterferenceChecker_{impl.Name}"; var noninterferenceCheckerProc = new Procedure(Token.NoToken, noninterferenceCheckerName, impl.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, impl.TypeParameters, inputs, new List <Variable>(), locals, noninterferenceCheckerBlocks); noninterferenceCheckerImpl.Proc = noninterferenceCheckerProc; CivlUtil.AddInlineAttribute(noninterferenceCheckerImpl); return(new List <Declaration> { noninterferenceCheckerProc, noninterferenceCheckerImpl }); }
public static List <Declaration> CreateNoninterferenceCheckers( CivlTypeChecker civlTypeChecker, LinearTypeChecker linearTypeChecker, int layerNum, Dictionary <Absy, Absy> absyMap, DeclWithFormals decl, List <Variable> declLocalVariables) { 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 = OldLocalLocal(g); locals.Add(copy); oldLocalMap[g] = Expr.Ident(copy); Formal f = OldGlobalFormal(g); inputs.Add(f); assumeMap[g] = Expr.Ident(f); } var linearPermissionInstrumentation = new LinearPermissionInstrumentation(civlTypeChecker, linearTypeChecker, layerNum, absyMap, domainNameToHoleVar, localVarMap); List <Tuple <List <Cmd>, List <PredicateCmd> > > yieldInfo = null; if (decl is Implementation impl) { yieldInfo = CollectYields(civlTypeChecker, absyMap, layerNum, impl).Select(kv => new Tuple <List <Cmd>, List <PredicateCmd> >(linearPermissionInstrumentation.DisjointnessAssumeCmds(kv.Key, false), kv.Value)).ToList(); } else if (decl is Procedure proc) { yieldInfo = new List <Tuple <List <Cmd>, List <PredicateCmd> > >(); if (civlTypeChecker.procToYieldInvariant.ContainsKey(proc)) { 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(); yieldInfo.Add(new Tuple <List <Cmd>, List <PredicateCmd> >(disjointnessCmds, yieldPredicates)); } } else { 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(); yieldInfo.Add( new Tuple <List <Cmd>, List <PredicateCmd> >(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(); yieldInfo.Add( new Tuple <List <Cmd>, List <PredicateCmd> >(exitDisjointnessCmds, exitYieldPredicates)); } } } else { Debug.Assert(false); } 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 yieldInfo) { var disjointnessCmds = kv.Item1; var yieldPredicates = kv.Item2; var newCmds = new List <Cmd>(disjointnessCmds); foreach (var predCmd in yieldPredicates) { var newExpr = Substituter.ApplyReplacingOldExprs(assumeSubst, oldSubst, predCmd.Expr); newCmds.Add(new AssumeCmd(Token.NoToken, newExpr)); } foreach (var predCmd in yieldPredicates) { 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 var noninterferenceCheckerName = decl is Procedure ? $"NoninterferenceChecker_proc_{decl.Name}" : $"NoninterferenceChecker_impl_{decl.Name}"; 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 }); }