示例#1
0
文件: Program.cs 项目: ggrov/tacny
        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);
        }
示例#2
0
        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());
            }
        }
示例#3
0
 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>>();
 }
示例#4
0
 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>();
 }
示例#5
0
        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();
        }
示例#6
0
 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;
 }
示例#7
0
        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();
                }
            }
        }
示例#8
0
        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);
        }
示例#9
0
        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);
            }
        }
示例#10
0
        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());
            }
        }
示例#11
0
        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);
        }
示例#12
0
 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);
         }
     }
 }
示例#13
0
 public YieldTypeChecker(CivlTypeChecker civlTypeChecker)
 {
     this.civlTypeChecker         = civlTypeChecker;
     this.checkingContext         = new CheckingContext(null);
     this.moverProcedureCallGraph = new Graph <MoverProc>();
 }
示例#14
0
 public WitnessFunctionVisitor(CivlTypeChecker ctc)
 {
     this.ctc            = ctc;
     allWitnessFunctions = new List <WitnessFunction>();
 }
示例#15
0
 private static void AddCheck(CivlTypeChecker civlTypeChecker, Tuple <Procedure, Implementation> t)
 {
     civlTypeChecker.program.AddTopLevelDeclaration(t.Item1);
     civlTypeChecker.program.AddTopLevelDeclaration(t.Item2);
 }
示例#16
0
 public CommutativityHintVisitor(CivlTypeChecker ctc)
 {
     this.ctc           = ctc;
     commutativityHints = new CommutativityHints();
 }
示例#17
0
        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
            });
        }
示例#18
0
 public YieldSufficiencyTypeChecker(CivlTypeChecker civlTypeChecker)
 {
     this.civlTypeChecker         = civlTypeChecker;
     this.checkingContext         = civlTypeChecker.checkingContext;
     this.moverProcedureCallGraph = new Graph <MoverProc>();
 }
示例#19
0
        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;
            }
        }
示例#21
0
    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);
    }
示例#22
0
        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);
        }
示例#23
0
        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);
                }
            }
        }
示例#24
0
 public PurityChecker(CivlTypeChecker civlTypeChecker)
 {
     this.civlTypeChecker = civlTypeChecker;
 }
示例#25
0
 private static Formal SnapshotGlobalFormal(CivlTypeChecker civlTypeChecker, Variable v)
 {
     return(civlTypeChecker.Formal($"snapshot_{v.Name}", v.TypedIdent.Type, true));
 }
示例#26
0
        /// <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;
        }
示例#27
0
 private static LocalVariable OldGlobalLocal(CivlTypeChecker civlTypeChecker, Variable v)
 {
     return(civlTypeChecker.LocalVariable($"old_{v.Name}", v.TypedIdent.Type));
 }
示例#28
0
            internal static int Check(Function node, CivlTypeChecker ctc, WitnessFunction witnessFunction)
            {
                var checker = new WitnessFunctionChecker(node, ctc, witnessFunction);

                return(checker.errorCount);
            }
示例#29
0
        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
            });
        }
示例#30
0
        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);
            }
        }
示例#32
0
 public CommutativityHintVisitor(CivlTypeChecker civlTypeChecker)
 {
     this.civlTypeChecker = civlTypeChecker;
     commutativityHints   = new CommutativityHints();
 }
示例#33
0
 public PurityChecker(CivlTypeChecker civlTypeChecker)
 {
     this.civlTypeChecker = civlTypeChecker;
 }