public static void AddCheckers(CivlTypeChecker civlTypeChecker) { foreach (var action in civlTypeChecker.AllAtomicActions.Where(a => a.HasPendingAsyncs)) { var requires = action.gate.Select(g => new Requires(false, g.Expr)).ToList(); var PAs = Expr.Ident(action.impl.OutParams.Last(p => p.TypedIdent.Type.Equals(civlTypeChecker.pendingAsyncMultisetType))); var paBound = civlTypeChecker.BoundVariable("pa", civlTypeChecker.pendingAsyncType); var pa = Expr.Ident(paBound); var nonnegativeExpr = ExprHelper.ForallExpr(new List <Variable> { paBound }, Expr.Ge(Expr.Select(PAs, pa), Expr.Literal(0))); var correctTypeExpr = ExprHelper.ForallExpr(new List <Variable> { paBound }, Expr.Imp( Expr.Gt(Expr.Select(PAs, pa), Expr.Literal(0)), Expr.Or(action.pendingAsyncs.Select(a => ExprHelper.FunctionCall(a.pendingAsyncCtor.membership, pa))))); CivlUtil.ResolveAndTypecheck(nonnegativeExpr); CivlUtil.ResolveAndTypecheck(correctTypeExpr); var cmds = new List <Cmd> { CmdHelper.CallCmd( action.proc, action.impl.InParams.Select(Expr.Ident).ToList <Expr>(), action.impl.OutParams.Select(Expr.Ident).ToList()), CmdHelper.AssertCmd( action.proc.tok, nonnegativeExpr, $"Action {action.proc.Name} might create negative pending asyncs"), CmdHelper.AssertCmd( action.proc.tok, correctTypeExpr, $"Action {action.proc.Name} might create undeclared pending asyncs") }; var blocks = new List <Block>() { BlockHelper.Block("init", cmds) }; var proc = DeclHelper.Procedure(civlTypeChecker.AddNamePrefix($"PendingAsyncChecker_{action.proc.Name}"), action.impl.InParams, action.impl.OutParams, requires, action.proc.Modifies, new List <Ensures>()); var impl = DeclHelper.Implementation(proc, proc.InParams, proc.OutParams, new List <Variable>(), blocks); civlTypeChecker.program.AddTopLevelDeclaration(proc); civlTypeChecker.program.AddTopLevelDeclaration(impl); } }
private YieldingProcInstrumentation( CivlTypeChecker civlTypeChecker, LinearPermissionInstrumentation linearPermissionInstrumentation, int layerNum, AbsyMap absyMap, Dictionary <CallCmd, Block> refinementBlocks) { this.civlTypeChecker = civlTypeChecker; this.layerNum = layerNum; this.absyMap = absyMap; this.linearPermissionInstrumentation = linearPermissionInstrumentation; this.refinementBlocks = refinementBlocks; parallelCallAggregators = new Dictionary <string, Procedure>(); noninterferenceCheckerDecls = new List <Declaration>(); var linearTypeChecker = civlTypeChecker.linearTypeChecker; List <Variable> inputs = new List <Variable>(); foreach (string domainName in linearTypeChecker.linearDomains.Keys) { inputs.Add(linearTypeChecker.LinearDomainInFormal(domainName)); } foreach (Variable g in civlTypeChecker.GlobalVariables) { inputs.Add(OldGlobalFormal(g)); } wrapperNoninterferenceCheckerProc = DeclHelper.Procedure( civlTypeChecker.AddNamePrefix($"Wrapper_NoninterferenceChecker_{layerNum}"), inputs, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>()); CivlUtil.AddInlineAttribute(wrapperNoninterferenceCheckerProc); // initialize globalSnapshotInstrumentation globalSnapshotInstrumentation = new GlobalSnapshotInstrumentation(civlTypeChecker); // initialize noninterferenceInstrumentation if (CommandLineOptions.Clo.TrustNoninterference) { noninterferenceInstrumentation = new NoneNoninterferenceInstrumentation(); } else { noninterferenceInstrumentation = new SomeNoninterferenceInstrumentation( civlTypeChecker, linearTypeChecker, linearPermissionInstrumentation, globalSnapshotInstrumentation.OldGlobalMap, wrapperNoninterferenceCheckerProc); } }
private void AddChecker(string checkerName, List <Variable> inputs, List <Variable> outputs, List <Variable> locals, List <Requires> requires, List <Cmd> cmds) { checkerName = civlTypeChecker.AddNamePrefix(checkerName); var blocks = new List <Block> { BlockHelper.Block("init", cmds) }; Procedure proc = DeclHelper.Procedure(checkerName, inputs, outputs, requires, civlTypeChecker.GlobalVariables.Select(v => Expr.Ident(v)).ToList(), new List <Ensures>()); Implementation impl = DeclHelper.Implementation(proc, inputs, outputs, locals, blocks); this.decls.Add(impl); this.decls.Add(proc); }
private static Tuple <Procedure, Implementation> GenerateAbstractionChecker(CivlTypeChecker civlTypeChecker, AtomicAction action, AtomicAction abs) { var requires = abs.gate.Select(g => new Requires(false, g.Expr)).ToList(); // TODO: check frame computation var frame = new HashSet <Variable>( action.modifiedGlobalVars .Union(action.gateUsedGlobalVars) .Union(abs.modifiedGlobalVars) .Union(abs.gateUsedGlobalVars)); var subst = InductiveSequentialization.GetSubstitution(action, abs); List <Cmd> cmds = InductiveSequentialization.GetGateAsserts(action, subst, $"Abstraction {abs.proc.Name} fails gate of {action.proc.Name}").ToList <Cmd>(); cmds.Add( CmdHelper.CallCmd( action.proc, abs.impl.InParams, abs.impl.OutParams )); cmds.Add( CmdHelper.AssertCmd( abs.proc.tok, TransitionRelationComputation.Refinement(civlTypeChecker, abs, frame), $"Abstraction {abs.proc.Name} does not summarize {action.proc.Name}" )); var blocks = new List <Block> { BlockHelper.Block("init", cmds) }; var proc = DeclHelper.Procedure( civlTypeChecker.AddNamePrefix($"AbstractionCheck_{action.proc.Name}_{abs.proc.Name}"), abs.impl.InParams, abs.impl.OutParams, requires, action.proc.Modifies, new List <Ensures>()); var impl = DeclHelper.Implementation( proc, proc.InParams, proc.OutParams, new List <Variable>(), blocks); return(Tuple.Create(proc, impl)); }
private Tuple <Procedure, Implementation> GetCheckerTuple( List <Requires> requires, List <Variable> locals, List <Cmd> cmds, string suffix = "") { var proc = DeclHelper.Procedure( civlTypeChecker.AddNamePrefix($"IS_{checkName}_{inputAction.proc.Name}{suffix}"), invariantAction.impl.InParams, invariantAction.impl.OutParams, requires, modifies, new List <Ensures>()); var impl = DeclHelper.Implementation( proc, proc.InParams, proc.OutParams, locals, new List <Block> { BlockHelper.Block(checkName, cmds) }); return(Tuple.Create(proc, impl)); }
private IEnumerable <Declaration> PendingAsyncNoninterferenceCheckers() { if (CommandLineOptions.Clo.TrustNoninterference) { yield break; } HashSet <AtomicAction> pendingAsyncsToCheck = new HashSet <AtomicAction>( civlTypeChecker.procToAtomicAction.Values .Where(a => a.layerRange.Contains(layerNum) && a.HasPendingAsyncs) .SelectMany(a => a.pendingAsyncs)); foreach (var action in pendingAsyncsToCheck) { var inputs = action.impl.InParams; var outputs = action.impl.OutParams; var requires = action.gate.Select(a => new Requires(false, a.Expr)).ToList(); var ensures = new List <Ensures>(); var modifies = civlTypeChecker.GlobalVariables.Select(Expr.Ident).ToList(); var locals = globalSnapshotInstrumentation.NewLocalVars.Union(noninterferenceInstrumentation.NewLocalVars).ToList(); var cmds = new List <Cmd>(); cmds.AddRange(globalSnapshotInstrumentation.CreateInitCmds()); cmds.AddRange(noninterferenceInstrumentation.CreateInitCmds(action.impl)); cmds.Add(CmdHelper.CallCmd(action.proc, inputs, outputs)); cmds.AddRange(noninterferenceInstrumentation.CreateCallToYieldProc()); var blocks = new List <Block> { BlockHelper.Block("init", cmds) }; var name = civlTypeChecker.AddNamePrefix($"PendingAsyncNoninterferenceChecker_{action.proc.Name}_{layerNum}"); var proc = DeclHelper.Procedure(name, inputs, outputs, requires, modifies, ensures); var impl = DeclHelper.Implementation(proc, inputs, outputs, locals, blocks); yield return(proc); yield return(impl); } }
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 }); }
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] = DeclHelper.Procedure( procName, 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) { 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; }