public static void Transform(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker) { List<Declaration> originalDecls = new List<Declaration>(); Program program = linearTypeChecker.program; foreach (var decl in program.TopLevelDeclarations) { Procedure proc = decl as Procedure; if (proc != null && civlTypeChecker.procToActionInfo.ContainsKey(proc)) { originalDecls.Add(proc); continue; } Implementation impl = decl as Implementation; if (impl != null && civlTypeChecker.procToActionInfo.ContainsKey(impl.Proc)) { originalDecls.Add(impl); } } List<Declaration> decls = new List<Declaration>(); if (!CommandLineOptions.Clo.TrustAtomicityTypes) { MoverCheck.AddCheckers(linearTypeChecker, civlTypeChecker, decls); } CivlRefinement.AddCheckers(linearTypeChecker, civlTypeChecker, decls); foreach (Declaration decl in decls) { decl.Attributes = CivlRefinement.RemoveYieldsAttribute(decl.Attributes); } program.RemoveTopLevelDeclarations(x => originalDecls.Contains(x)); program.AddTopLevelDeclarations(decls); }
public static void AddCheckers(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker, List<Declaration> decls) { Program program = linearTypeChecker.program; foreach (int layerNum in civlTypeChecker.AllImplementedLayerNums) { if (CommandLineOptions.Clo.TrustLayersDownto <= layerNum || layerNum <= CommandLineOptions.Clo.TrustLayersUpto) continue; MyDuplicator duplicator = new MyDuplicator(civlTypeChecker, layerNum); foreach (var proc in program.Procedures) { if (!civlTypeChecker.procToActionInfo.ContainsKey(proc)) continue; Procedure duplicateProc = duplicator.VisitProcedure(proc); decls.Add(duplicateProc); } decls.AddRange(duplicator.impls); CivlRefinement civlTransform = new CivlRefinement(linearTypeChecker, civlTypeChecker, duplicator); foreach (var impl in program.Implementations) { if (!civlTypeChecker.procToActionInfo.ContainsKey(impl.Proc) || civlTypeChecker.procToActionInfo[impl.Proc].createdAtLayerNum < layerNum) continue; Implementation duplicateImpl = duplicator.VisitImplementation(impl); civlTransform.TransformImpl(duplicateImpl); decls.Add(duplicateImpl); } decls.AddRange(civlTransform.Collect()); } }
private MoverCheck(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker, List<Declaration> decls) { this.linearTypeChecker = linearTypeChecker; this.civlTypeChecker = civlTypeChecker; this.decls = decls; this.commutativityCheckerCache = new HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>>(); this.gatePreservationCheckerCache = new HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>>(); this.failurePreservationCheckerCache = new HashSet<Tuple<AtomicActionInfo, AtomicActionInfo>>(); }
public MyDuplicator(CivlTypeChecker civlTypeChecker, int layerNum) { this.civlTypeChecker = civlTypeChecker; this.layerNum = layerNum; this.enclosingProc = null; this.enclosingImpl = null; this.procMap = new Dictionary<Procedure, Procedure>(); this.absyMap = new Dictionary<Absy, Absy>(); this.implMap = new Dictionary<Implementation, Implementation>(); this.yieldingProcs = new HashSet<Procedure>(); this.impls = new List<Implementation>(); }
private YieldTypeChecker(CivlTypeChecker civlTypeChecker, Implementation impl, int currLayerNum, IEnumerable<Block> loopHeaders) { this.civlTypeChecker = civlTypeChecker; this.impl = impl; this.currLayerNum = currLayerNum; this.loopHeaders = loopHeaders; this.stateCounter = 0; this.absyToNode = new Dictionary<Absy, int>(); this.initialState = 0; this.finalStates = new HashSet<int>(); this.edgeLabels = new Dictionary<Tuple<int, int>, int>(); foreach (Block block in impl.Blocks) { absyToNode[block] = stateCounter; stateCounter++; foreach (Cmd cmd in block.Cmds) { absyToNode[cmd] = stateCounter; stateCounter++; } absyToNode[block.TransferCmd] = stateCounter; stateCounter++; if (block.TransferCmd is ReturnCmd) { finalStates.Add(absyToNode[block.TransferCmd]); } } foreach (Block block in impl.Blocks) { Absy blockEntry = block.Cmds.Count == 0 ? (Absy)block.TransferCmd : (Absy)block.Cmds[0]; edgeLabels[new Tuple<int, int>(absyToNode[block], absyToNode[blockEntry])] = 'P'; GotoCmd gotoCmd = block.TransferCmd as GotoCmd; if (gotoCmd == null) continue; foreach (Block successor in gotoCmd.labelTargets) { edgeLabels[new Tuple<int, int>(absyToNode[gotoCmd], absyToNode[successor])] = 'P'; } } this.nodeToAbsy = new Dictionary<int, Absy>(); foreach (KeyValuePair<Absy, int> state in absyToNode) { this.nodeToAbsy[state.Value] = state.Key; } ComputeGraph(); IsYieldTypeSafe(); }
public CivlRefinement(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker, MyDuplicator duplicator) { this.linearTypeChecker = linearTypeChecker; this.civlTypeChecker = civlTypeChecker; this.absyMap = duplicator.absyMap; this.layerNum = duplicator.layerNum; this.implMap = duplicator.implMap; this.yieldingProcs = duplicator.yieldingProcs; Program program = linearTypeChecker.program; globalMods = new List<IdentifierExpr>(); foreach (Variable g in civlTypeChecker.SharedVariables) { globalMods.Add(Expr.Ident(g)); } asyncAndParallelCallDesugarings = new Dictionary<string, Procedure>(); yieldCheckerProcs = new List<Procedure>(); yieldCheckerImpls = new List<Implementation>(); yieldProc = null; }
public static void TypeCheck(CivlTypeChecker civlTypeChecker) { // Mover procedures can only call other mover procedures on the same layer. // Thus, the constructed call graph naturally forms disconnected components // w.r.t. layers and we can keep a single graph instead of one for each layer. var moverProcedureCallGraph = ConstructMoverProcedureCallGraph(civlTypeChecker); foreach (var impl in civlTypeChecker.program.Implementations.Where(impl => civlTypeChecker.procToYieldingProc.ContainsKey(impl.Proc))) { var yieldingProc = civlTypeChecker.procToYieldingProc[impl.Proc]; impl.PruneUnreachableBlocks(); Graph <Block> implGraph = Program.GraphFromImpl(impl); implGraph.ComputeLoops(); foreach (int layerNum in civlTypeChecker.allRefinementLayers.Where(l => l <= yieldingProc.upperLayer)) { new PerLayerYieldSufficiencyTypeChecker(civlTypeChecker, yieldingProc, impl, layerNum, implGraph, moverProcedureCallGraph) .TypeCheckLayer(); } } }
public static void Transform(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker) { Program program = linearTypeChecker.program; // Store the original declarations of yielding procedures, which will be removed after desugaring below. var origProc = program.TopLevelDeclarations.OfType <Procedure>().Where(p => civlTypeChecker.procToYieldingProc.ContainsKey(p)); var origImpl = program.TopLevelDeclarations.OfType <Implementation>().Where(i => civlTypeChecker.procToYieldingProc.ContainsKey(i.Proc)); List <Declaration> originalDecls = Enumerable.Union <Declaration>(origProc, origImpl).ToList(); // Commutativity checks List <Declaration> decls = new List <Declaration>(); if (!CommandLineOptions.Clo.TrustAtomicityTypes) { MoverCheck.AddCheckers(linearTypeChecker, civlTypeChecker, decls); } // Desugaring of yielding procedures YieldingProcChecker.AddCheckers(linearTypeChecker, civlTypeChecker, decls); // Linear type checks LinearTypeChecker.AddCheckers(linearTypeChecker, civlTypeChecker, decls); InductiveSequentializationChecker.AddChecks(civlTypeChecker); PendingAsyncChecker.AddCheckers(civlTypeChecker); foreach (AtomicAction action in civlTypeChecker.procToAtomicAction.Values.Union(civlTypeChecker.procToIsAbstraction.Values)) { action.AddTriggerAssumes(program); } // Remove original declarations and add new checkers generated above program.RemoveTopLevelDeclarations(x => originalDecls.Contains(x)); program.AddTopLevelDeclarations(decls); BackwardAssignmentSubstituter.SubstituteBackwardAssignments(civlTypeChecker.procToAtomicAction.Values); }
public static void Transform(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker) { Program program = linearTypeChecker.program; // Store the original declarations of yielding procedures, which will be removed after desugaring below. var origProc = program.TopLevelDeclarations.OfType <Procedure>().Where(p => civlTypeChecker.procToYieldingProc.ContainsKey(p)); var origImpl = program.TopLevelDeclarations.OfType <Implementation>().Where(i => civlTypeChecker.procToYieldingProc.ContainsKey(i.Proc)); List <Declaration> originalDecls = Enumerable.Union <Declaration>(origProc, origImpl).ToList(); // Commutativity checks List <Declaration> decls = new List <Declaration>(); if (!CommandLineOptions.Clo.TrustAtomicityTypes) { MoverCheck.AddCheckers(linearTypeChecker, civlTypeChecker, decls); } // Desugaring of yielding procedures CivlRefinement.AddCheckers(linearTypeChecker, civlTypeChecker, decls); // Trigger functions for existential vairables in transition relations decls.AddRange(civlTypeChecker.procToAtomicAction.Values.SelectMany(a => a.layerToActionCopy.Values.SelectMany(ac => ac.triggerFuns.Values))); // Linear type checks LinearTypeChecker.AddCheckers(linearTypeChecker, civlTypeChecker, decls); // Remove original declarations and add new checkers generated above program.RemoveTopLevelDeclarations(x => originalDecls.Contains(x)); program.AddTopLevelDeclarations(decls); foreach (AtomicAction atomicAction in civlTypeChecker.procToAtomicAction.Values) { program.RemoveTopLevelDeclaration(atomicAction.proc); program.RemoveTopLevelDeclaration(atomicAction.impl); } }
public static void AddCheckers(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker, List <Declaration> decls) { Program program = linearTypeChecker.program; // Generate the refinement checks for every layer foreach (int layerNum in civlTypeChecker.allRefinementLayers) { if (CommandLineOptions.Clo.TrustLayersDownto <= layerNum || layerNum <= CommandLineOptions.Clo.TrustLayersUpto) { continue; } YieldingProcDuplicator duplicator = new YieldingProcDuplicator(civlTypeChecker, linearTypeChecker, layerNum); foreach (var procToYieldingProc in civlTypeChecker.procToYieldingProc) { if (procToYieldingProc.Value.upperLayer >= layerNum) { duplicator.VisitProcedure(procToYieldingProc.Key); } } foreach (Implementation impl in program.Implementations) { if (civlTypeChecker.procToYieldingProc.TryGetValue(impl.Proc, out var yieldingProc) && yieldingProc.upperLayer >= layerNum) { duplicator.VisitImplementation(impl); } } decls.AddRange(duplicator.Collect()); } }
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 void PerformYieldSafeCheck(CivlTypeChecker civlTypeChecker) { foreach (var impl in civlTypeChecker.program.Implementations) { if (!civlTypeChecker.procToActionInfo.ContainsKey(impl.Proc)) continue; impl.PruneUnreachableBlocks(); Graph<Block> implGraph = Program.GraphFromImpl(impl); implGraph.ComputeLoops(); int specLayerNum = civlTypeChecker.procToActionInfo[impl.Proc].createdAtLayerNum; foreach (int layerNum in civlTypeChecker.AllImplementedLayerNums) { if (layerNum > specLayerNum) continue; YieldTypeChecker executor = new YieldTypeChecker(civlTypeChecker, impl, layerNum, implGraph.Headers); } } }
public YieldTypeChecker(CivlTypeChecker civlTypeChecker) { this.civlTypeChecker = civlTypeChecker; this.checkingContext = new CheckingContext(null); this.moverProcedureCallGraph = new Graph <MoverProc>(); }
public WitnessFunctionVisitor(CivlTypeChecker ctc) { this.ctc = ctc; allWitnessFunctions = new List <WitnessFunction>(); }
private static void AddCheck(CivlTypeChecker civlTypeChecker, Tuple <Procedure, Implementation> t) { civlTypeChecker.program.AddTopLevelDeclaration(t.Item1); civlTypeChecker.program.AddTopLevelDeclaration(t.Item2); }
public CommutativityHintVisitor(CivlTypeChecker ctc) { this.ctc = ctc; commutativityHints = new CommutativityHints(); }
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 YieldSufficiencyTypeChecker(CivlTypeChecker civlTypeChecker) { this.civlTypeChecker = civlTypeChecker; this.checkingContext = civlTypeChecker.checkingContext; this.moverProcedureCallGraph = new Graph <MoverProc>(); }
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 }); }
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; } }
private static void AddChecker(CivlTypeChecker civlTypeChecker, Action action, List<Declaration> decls) { var linearTypeChecker = civlTypeChecker.linearTypeChecker; // Note: The implementation should be used as the variables in the // gate are bound to implementation and not to the procedure. Implementation impl = action.impl; List<Variable> inputs = impl.InParams; List<Variable> outputs = impl.OutParams; List<Variable> locals = new List<Variable>(2); var paLocal1 = civlTypeChecker.LocalVariable("pa1", civlTypeChecker.pendingAsyncType); var paLocal2 = civlTypeChecker.LocalVariable("pa2", civlTypeChecker.pendingAsyncType); var pa1 = Expr.Ident(paLocal1); var pa2 = Expr.Ident(paLocal2); if (civlTypeChecker.pendingAsyncType != null) { locals.Add(paLocal1); locals.Add(paLocal2); } List<Requires> requires = action.gate.Select(a => new Requires(false, a.Expr)).ToList(); List<LinearityCheck> linearityChecks = new List<LinearityCheck>(); foreach (var domain in linearTypeChecker.linearDomains.Values) { // Linear in vars var inVars = inputs.Union(action.modifiedGlobalVars) .Where(x => linearTypeChecker.FindDomainName(x) == domain.domainName) .Where(x => InKinds.Contains(linearTypeChecker.FindLinearKind(x))) .Select(Expr.Ident) .ToList(); // Linear out vars var outVars = inputs.Union(outputs).Union(action.modifiedGlobalVars) .Where(x => linearTypeChecker.FindDomainName(x) == domain.domainName) .Where(x => OutKinds.Contains(linearTypeChecker.FindLinearKind(x))) .Select(Expr.Ident) .ToList(); // First kind // Permissions in linear output variables are a subset of permissions in linear input variables. if (outVars.Count > 0) { linearityChecks.Add(new LinearityCheck( null, OutPermsSubsetInPerms(domain, inVars, outVars), $"Potential linearity violation in outputs for domain {domain.domainName}.", "variables")); } if (action is AtomicAction atomicAction && atomicAction.HasPendingAsyncs) { var PAs = Expr.Ident(atomicAction.impl.OutParams.Last()); foreach (var pendingAsync in atomicAction.pendingAsyncs) { var pendingAsyncLinearParams = PendingAsyncLinearParams(linearTypeChecker, domain, pendingAsync, pa1); if (pendingAsyncLinearParams.Count == 0) continue; // Second kind // Permissions in linear output variables + linear inputs of a single pending async // are a subset of permissions in linear input variables. var exactlyOnePA = Expr.And( ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, pa1), Expr.Eq(Expr.Select(PAs, pa1), Expr.Literal(1))); var outSubsetInExpr = OutPermsSubsetInPerms(domain, inVars, pendingAsyncLinearParams.Union(outVars)); linearityChecks.Add(new LinearityCheck( exactlyOnePA, outSubsetInExpr, $"Potential linearity violation in outputs and pending async of {pendingAsync.proc.Name} for domain {domain.domainName}.", $"single_{pendingAsync.proc.Name}")); // Third kind // If there are two identical pending asyncs, then their input permissions mut be empty. var twoIdenticalPAs = Expr.And( ExprHelper.FunctionCall(pendingAsync.pendingAsyncCtor.membership, pa1), Expr.Ge(Expr.Select(PAs, pa1), Expr.Literal(2))); var emptyPerms = OutPermsSubsetInPerms(domain, Enumerable.Empty<Expr>(), pendingAsyncLinearParams); linearityChecks.Add(new LinearityCheck( twoIdenticalPAs, emptyPerms, $"Potential linearity violation in identical pending asyncs of {pendingAsync.proc.Name} for domain {domain.domainName}.", $"identical_{pendingAsync.proc.Name}")); } var pendingAsyncs = atomicAction.pendingAsyncs.ToList(); for (int i = 0; i < pendingAsyncs.Count; i++) { var pendingAsync1 = pendingAsyncs[i]; for (int j = i; j < pendingAsyncs.Count; j++) { var pendingAsync2 = pendingAsyncs[j]; var pendingAsyncLinearParams1 = PendingAsyncLinearParams(linearTypeChecker, domain, pendingAsync1, pa1); var pendingAsyncLinearParams2 = PendingAsyncLinearParams(linearTypeChecker, domain, pendingAsync2, pa2); if (pendingAsyncLinearParams1.Count == 0 || pendingAsyncLinearParams2.Count == 0) continue; // Fourth kind // Input permissions of two non-identical pending asyncs (possibly of the same action) // are a subset of permissions in linear input variables. var membership = Expr.And( Expr.Neq(pa1, pa2), Expr.And( ExprHelper.FunctionCall(pendingAsync1.pendingAsyncCtor.membership, pa1), ExprHelper.FunctionCall(pendingAsync2.pendingAsyncCtor.membership, pa2))); var existing = Expr.And( Expr.Ge(Expr.Select(PAs, pa1), Expr.Literal(1)), Expr.Ge(Expr.Select(PAs, pa2), Expr.Literal(1))); var noDuplication = OutPermsSubsetInPerms(domain, inVars, pendingAsyncLinearParams1.Union(pendingAsyncLinearParams2)); linearityChecks.Add(new LinearityCheck( Expr.And(membership, existing), noDuplication, $"Potential lnearity violation in pending asyncs of {pendingAsync1.proc.Name} and {pendingAsync2.proc.Name} for domain {domain.domainName}.", $"distinct_{pendingAsync1.proc.Name}_{pendingAsync2.proc.Name}")); } } } } if (linearityChecks.Count == 0) return; // Create checker blocks List<Block> checkerBlocks = new List<Block>(linearityChecks.Count); foreach (var lc in linearityChecks) { List<Cmd> cmds = new List<Cmd>(2); if (lc.assume != null) { cmds.Add(CmdHelper.AssumeCmd(lc.assume)); } cmds.Add(new AssertCmd(action.proc.tok, lc.assert) { ErrorData = lc.message }); var block = new Block(Token.NoToken, lc.name, cmds, CmdHelper.ReturnCmd); CivlUtil.ResolveAndTypecheck(block, ResolutionContext.State.Two); checkerBlocks.Add(block); } // Create init blocks List<Block> blocks = new List<Block>(linearityChecks.Count + 1); blocks.Add( new Block( Token.NoToken, "init", new List<Cmd> { CmdHelper.CallCmd(action.proc, inputs, outputs) }, new GotoCmd(Token.NoToken, checkerBlocks))); blocks.AddRange(checkerBlocks); // Create the whole check procedure string checkerName = civlTypeChecker.AddNamePrefix($"LinearityChecker_{action.proc.Name}"); Procedure linCheckerProc = new Procedure(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, requires, action.proc.Modifies, new List<Ensures>()); Implementation linCheckImpl = new Implementation(Token.NoToken, checkerName, new List<TypeVariable>(), inputs, outputs, locals, blocks); linCheckImpl.Proc = linCheckerProc; decls.Add(linCheckImpl); decls.Add(linCheckerProc); }
public 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); }
public static void AddCheckers(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker, List<Declaration> decls) { if (civlTypeChecker.procToActionInfo.Count == 0) return; List<ActionInfo> sortedByCreatedLayerNum = new List<ActionInfo>(civlTypeChecker.procToActionInfo.Values.Where(x => x is AtomicActionInfo && !x.isExtern)); sortedByCreatedLayerNum.Sort((x, y) => { return (x.createdAtLayerNum == y.createdAtLayerNum) ? 0 : (x.createdAtLayerNum < y.createdAtLayerNum) ? -1 : 1; }); List<ActionInfo> sortedByAvailableUptoLayerNum = new List<ActionInfo>(civlTypeChecker.procToActionInfo.Values.Where(x => x is AtomicActionInfo && !x.isExtern)); sortedByAvailableUptoLayerNum.Sort((x, y) => { return (x.availableUptoLayerNum == y.availableUptoLayerNum) ? 0 : (x.availableUptoLayerNum < y.availableUptoLayerNum) ? -1 : 1; }); Dictionary<int, HashSet<AtomicActionInfo>> pools = new Dictionary<int, HashSet<AtomicActionInfo>>(); int indexIntoSortedByCreatedLayerNum = 0; int indexIntoSortedByAvailableUptoLayerNum = 0; HashSet<AtomicActionInfo> currPool = new HashSet<AtomicActionInfo>(); while (indexIntoSortedByCreatedLayerNum < sortedByCreatedLayerNum.Count) { var currLayerNum = sortedByCreatedLayerNum[indexIntoSortedByCreatedLayerNum].createdAtLayerNum; pools[currLayerNum] = new HashSet<AtomicActionInfo>(currPool); while (indexIntoSortedByCreatedLayerNum < sortedByCreatedLayerNum.Count) { var actionInfo = sortedByCreatedLayerNum[indexIntoSortedByCreatedLayerNum] as AtomicActionInfo; if (actionInfo.createdAtLayerNum > currLayerNum) break; pools[currLayerNum].Add(actionInfo); indexIntoSortedByCreatedLayerNum++; } while (indexIntoSortedByAvailableUptoLayerNum < sortedByAvailableUptoLayerNum.Count) { var actionInfo = sortedByAvailableUptoLayerNum[indexIntoSortedByAvailableUptoLayerNum] as AtomicActionInfo; if (actionInfo.availableUptoLayerNum > currLayerNum) break; pools[currLayerNum].Remove(actionInfo); indexIntoSortedByAvailableUptoLayerNum++; } currPool = pools[currLayerNum]; } // No atomic action has mover type Top Debug.Assert(pools.All(l => l.Value.All(a => a.moverType != MoverType.Top))); Program program = civlTypeChecker.program; MoverCheck moverChecking = new MoverCheck(linearTypeChecker, civlTypeChecker, decls); var moverChecks = from layer in pools.Keys from first in pools[layer] from second in pools[layer] where first.moverType != MoverType.Atomic select new { First = first, Second = second }; foreach (var moverCheck in moverChecks) { var first = moverCheck.First; var second = moverCheck.Second; if (first.IsRightMover) { moverChecking.CreateCommutativityChecker(program, first, second); moverChecking.CreateGatePreservationChecker(program, second, first); } if (first.IsLeftMover) { moverChecking.CreateCommutativityChecker(program, second, first); moverChecking.CreateGatePreservationChecker(program, first, second); moverChecking.CreateFailurePreservationChecker(program, second, first); } } foreach (AtomicActionInfo atomicActionInfo in sortedByCreatedLayerNum) { if (atomicActionInfo.IsLeftMover && atomicActionInfo.hasAssumeCmd) { moverChecking.CreateNonBlockingChecker(program, atomicActionInfo); } } }
public PurityChecker(CivlTypeChecker civlTypeChecker) { this.civlTypeChecker = civlTypeChecker; }
private static Formal SnapshotGlobalFormal(CivlTypeChecker civlTypeChecker, Variable v) { return(civlTypeChecker.Formal($"snapshot_{v.Name}", v.TypedIdent.Type, true)); }
/// <summary> /// Resolves and type checks the given Boogie program. Any errors are reported to the /// console. Returns: /// - Done if no errors occurred, and command line specified no resolution or no type checking. /// - ResolutionError if a resolution error occurred /// - TypeCheckingError if a type checking error occurred /// - ResolvedAndTypeChecked if both resolution and type checking succeeded /// </summary> public static PipelineOutcome ResolveAndTypecheck(Program program, string bplFileName, out LinearTypeChecker linearTypeChecker, out CivlTypeChecker civlTypeChecker) { Contract.Requires(program != null); Contract.Requires(bplFileName != null); linearTypeChecker = null; civlTypeChecker = null; // ---------- Resolve ------------------------------------------------------------ if (CommandLineOptions.Clo.NoResolve) { return PipelineOutcome.Done; } int errorCount = program.Resolve(); if (errorCount != 0) { Console.WriteLine("{0} name resolution errors detected in {1}", errorCount, GetFileNameForConsole(bplFileName)); return PipelineOutcome.ResolutionError; } // ---------- Type check ------------------------------------------------------------ if (CommandLineOptions.Clo.NoTypecheck) { return PipelineOutcome.Done; } errorCount = program.Typecheck(); if (errorCount != 0) { Console.WriteLine("{0} type checking errors detected in {1}", errorCount, GetFileNameForConsole(bplFileName)); return PipelineOutcome.TypeCheckingError; } if (PolymorphismChecker.IsMonomorphic(program)) { CommandLineOptions.Clo.TypeEncodingMethod = CommandLineOptions.TypeEncoding.Monomorphic; } CollectModSets(program); civlTypeChecker = new CivlTypeChecker(program); civlTypeChecker.TypeCheck(); if (civlTypeChecker.errorCount != 0) { Console.WriteLine("{0} type checking errors detected in {1}", civlTypeChecker.errorCount, GetFileNameForConsole(bplFileName)); return PipelineOutcome.TypeCheckingError; } linearTypeChecker = new LinearTypeChecker(program); linearTypeChecker.TypeCheck(); if (linearTypeChecker.errorCount == 0) { linearTypeChecker.Transform(); } else { Console.WriteLine("{0} type checking errors detected in {1}", linearTypeChecker.errorCount, GetFileNameForConsole(bplFileName)); return PipelineOutcome.TypeCheckingError; } if (CommandLineOptions.Clo.PrintFile != null && CommandLineOptions.Clo.PrintDesugarings) { // if PrintDesugaring option is engaged, print the file here, after resolution and type checking PrintBplFile(CommandLineOptions.Clo.PrintFile, program, true, true, CommandLineOptions.Clo.PrettyPrint); } return PipelineOutcome.ResolvedAndTypeChecked; }
private static LocalVariable OldGlobalLocal(CivlTypeChecker civlTypeChecker, Variable v) { return(civlTypeChecker.LocalVariable($"old_{v.Name}", v.TypedIdent.Type)); }
internal static int Check(Function node, CivlTypeChecker ctc, WitnessFunction witnessFunction) { var checker = new WitnessFunctionChecker(node, ctc, witnessFunction); return(checker.errorCount); }
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 static void AddCheckers(LinearTypeChecker linearTypeChecker, CivlTypeChecker civlTypeChecker, List <Declaration> decls) { if (civlTypeChecker.procToActionInfo.Count == 0) { return; } List <ActionInfo> sortedByCreatedLayerNum = new List <ActionInfo>(civlTypeChecker.procToActionInfo.Values.Where(x => x is AtomicActionInfo && !x.isExtern)); sortedByCreatedLayerNum.Sort((x, y) => { return((x.createdAtLayerNum == y.createdAtLayerNum) ? 0 : (x.createdAtLayerNum < y.createdAtLayerNum) ? -1 : 1); }); List <ActionInfo> sortedByAvailableUptoLayerNum = new List <ActionInfo>(civlTypeChecker.procToActionInfo.Values.Where(x => x is AtomicActionInfo && !x.isExtern)); sortedByAvailableUptoLayerNum.Sort((x, y) => { return((x.availableUptoLayerNum == y.availableUptoLayerNum) ? 0 : (x.availableUptoLayerNum < y.availableUptoLayerNum) ? -1 : 1); }); Dictionary <int, HashSet <AtomicActionInfo> > pools = new Dictionary <int, HashSet <AtomicActionInfo> >(); int indexIntoSortedByCreatedLayerNum = 0; int indexIntoSortedByAvailableUptoLayerNum = 0; HashSet <AtomicActionInfo> currPool = new HashSet <AtomicActionInfo>(); while (indexIntoSortedByCreatedLayerNum < sortedByCreatedLayerNum.Count) { var currLayerNum = sortedByCreatedLayerNum[indexIntoSortedByCreatedLayerNum].createdAtLayerNum; pools[currLayerNum] = new HashSet <AtomicActionInfo>(currPool); while (indexIntoSortedByCreatedLayerNum < sortedByCreatedLayerNum.Count) { var actionInfo = sortedByCreatedLayerNum[indexIntoSortedByCreatedLayerNum] as AtomicActionInfo; if (actionInfo.createdAtLayerNum > currLayerNum) { break; } pools[currLayerNum].Add(actionInfo); indexIntoSortedByCreatedLayerNum++; } while (indexIntoSortedByAvailableUptoLayerNum < sortedByAvailableUptoLayerNum.Count) { var actionInfo = sortedByAvailableUptoLayerNum[indexIntoSortedByAvailableUptoLayerNum] as AtomicActionInfo; if (actionInfo.availableUptoLayerNum > currLayerNum) { break; } pools[currLayerNum].Remove(actionInfo); indexIntoSortedByAvailableUptoLayerNum++; } currPool = pools[currLayerNum]; } // No atomic action has mover type Top Debug.Assert(pools.All(l => l.Value.All(a => a.moverType != MoverType.Top))); Program program = civlTypeChecker.program; MoverCheck moverChecking = new MoverCheck(linearTypeChecker, civlTypeChecker, decls); var moverChecks = from layer in pools.Keys from first in pools[layer] from second in pools[layer] where first.moverType != MoverType.Atomic select new { First = first, Second = second }; foreach (var moverCheck in moverChecks) { var first = moverCheck.First; var second = moverCheck.Second; if (first.IsRightMover) { moverChecking.CreateCommutativityChecker(program, first, second); moverChecking.CreateGatePreservationChecker(program, second, first); } if (first.IsLeftMover) { moverChecking.CreateCommutativityChecker(program, second, first); moverChecking.CreateGatePreservationChecker(program, first, second); moverChecking.CreateFailurePreservationChecker(program, second, first); } } foreach (AtomicActionInfo atomicActionInfo in sortedByCreatedLayerNum) { if (atomicActionInfo.IsLeftMover && atomicActionInfo.hasAssumeCmd) { moverChecking.CreateNonBlockingChecker(program, atomicActionInfo); } } }
public static void AddChecks(CivlTypeChecker ctc) { foreach (var x in ctc.inductiveSequentializations) { var t = x.GenerateBaseCaseChecker(); ctc.program.AddTopLevelDeclaration(t.Item1); ctc.program.AddTopLevelDeclaration(t.Item2); t = x.GenerateConclusionChecker(); ctc.program.AddTopLevelDeclaration(t.Item1); ctc.program.AddTopLevelDeclaration(t.Item2); t = x.GenerateStepChecker(ctc.pendingAsyncAdd); ctc.program.AddTopLevelDeclaration(t.Item1); ctc.program.AddTopLevelDeclaration(t.Item2); } var absChecks = ctc.inductiveSequentializations.SelectMany(x => x.elim).Where(kv => kv.Key != kv.Value) .Distinct(); foreach (var absCheck in absChecks) { var action = absCheck.Key; var abs = absCheck.Value; var requires = abs.gate.Select(g => new Requires(false, g.Expr)).ToList(); // TODO: check frame computation var frame = new HashSet <Variable>(action.modifiedGlobalVars.Union(action.gateUsedGlobalVars) .Union(abs.modifiedGlobalVars).Union(abs.gateUsedGlobalVars)); var tr = TransitionRelationComputation.Refinement(abs, frame); var ensures = new List <Ensures> { new Ensures(false, tr) { ErrorData = $"Abstraction {abs.proc.Name} does not summarize {action.proc.Name}" } }; var subst = InductiveSequentialization.GetSubstitution(action, abs); List <Cmd> cmds = InductiveSequentialization.GetGateAsserts(action, subst, $"Abstraction {abs.proc.Name} fails gate of {action.proc.Name}").ToList <Cmd>(); cmds.Add( CmdHelper.CallCmd( action.proc, abs.impl.InParams.Select(Expr.Ident).ToList <Expr>(), abs.impl.OutParams.Select(Expr.Ident).ToList() )); var blocks = new List <Block> { new Block(Token.NoToken, "init", cmds, CmdHelper.ReturnCmd) }; var proc = new Procedure(Token.NoToken, $"AbstractionCheck_{action.proc.Name}_{abs.proc.Name}", new List <TypeVariable>(), abs.impl.InParams, abs.impl.OutParams, requires, action.proc.Modifies, ensures); var impl = new Implementation(Token.NoToken, proc.Name, new List <TypeVariable>(), proc.InParams, proc.OutParams, new List <Variable>(), blocks) { Proc = proc }; ctc.program.AddTopLevelDeclaration(proc); ctc.program.AddTopLevelDeclaration(impl); } }
public CommutativityHintVisitor(CivlTypeChecker civlTypeChecker) { this.civlTypeChecker = civlTypeChecker; commutativityHints = new CommutativityHints(); }