示例#1
0
        ///////////////////////////////////////////////////////////////////////
        // MAKING ATOMIC STEPS
        ///////////////////////////////////////////////////////////////////////

        private void DetermineAtomicPaths()
        {
            allPCs = new List <ArmadaPC>();
            symbols.AllMethods.AppendAllPCs(allPCs);

            var tauPathPrefix = new AtomicPathPrefix(this, new List <NextRoutine> {
                symbols.TauNextRoutine
            }, true, null);

            tauPath     = new AtomicPath(tauPathPrefix);
            atomicPaths = new List <AtomicPath> {
                tauPath
            };
            rootPathPrefixesByPC = new Dictionary <ArmadaPC, List <AtomicPathPrefix> >();

            foreach (var startPC in allPCs)
            {
                rootPathPrefixesByPC[startPC] = new List <AtomicPathPrefix>();
                if (GetPCAtomicType(startPC) != PCAtomicType.Nonyielding)
                {
                    List <NextRoutine> nextRoutines;
                    if (pcToNextRoutines.TryGetValue(startPC, out nextRoutines))
                    {
                        foreach (var nextRoutine in nextRoutines)
                        {
                            var rootAtomicPathPrefix = new AtomicPathPrefix(this, new List <NextRoutine> {
                                nextRoutine
                            }, false, null);
                            rootPathPrefixesByPC[startPC].Add(rootAtomicPathPrefix);
                            PopulateAtomicPathPrefix(rootAtomicPathPrefix);
                        }
                    }
                }
            }
        }
示例#2
0
        protected override void GenerateLiftAtomicPathLemmaForTauPath(AtomicPath atomicPath, string typeComparison,
                                                                      string extraSignatureLines)
        {
            if (!canHideTau)
            {
                base.GenerateLiftAtomicPathLemmaForTauPath(atomicPath, typeComparison, extraSignatureLines);
                return;
            }

            var lpr = new PrefixedVarsPathPrinter(lAtomic);
            var hpr = new PrefixedVarsPathPrinter(hAtomic);

            string str = $@"
        lemma lemma_LiftAtomicPath_Tau(ls: LPlusState, lpath: LAtomic_Path, tid: Armada_ThreadHandle)
          requires InductiveInv(ls)
          requires LAtomic_ValidPath(ls, lpath, tid)
          requires lpath.LAtomic_Path_Tau?
          requires !IsSkippedTauPath(ls, lpath, tid)
          ensures  var ls' := LAtomic_GetStateAfterPath(ls, lpath, tid);
                   var hs := ConvertTotalState_LPlusH(ls);
                   var hpath := ConvertAtomicPath_LH(ls, lpath, tid);
                   var hs' := HAtomic_GetStateAfterPath(hs, hpath, tid);
                   var ty := LAtomic_GetPathType(lpath);
                   && HAtomic_GetPathType(hpath) == ty
                   && HAtomic_ValidPath(hs, hpath, tid)
                   && hs' == ConvertTotalState_LPlusH(ls')
                   && ls'.s.stop_reason.Armada_NotStopped? == hs'.stop_reason.Armada_NotStopped?
        {{
          { lpr.GetOpenValidPathInvocation(lAtomic.TauPath) }

          var ls' := LAtomic_GetStateAfterPath(ls, lpath, tid);
          var hs := ConvertTotalState_LPlusH(ls);
          var hpath := ConvertAtomicPath_LH(ls, lpath, tid);
          var hs' := ConvertTotalState_LPlusH(ls');

          { hpr.GetOpenPathInvocation(hAtomic.TauPath) }

          var lentry := ls.s.threads[tid].storeBuffer[0];
          assert CanConvertStoreBufferEntry_LH(lentry);
          var hentry := hs.threads[tid].storeBuffer[0];
          var lmem := ls.s.mem;
          var hmem1 := ConvertSharedMemory_LH(L.Armada_ApplyStoreBufferEntry(lmem, lentry));
          var hmem2 := H.Armada_ApplyStoreBufferEntry(ConvertSharedMemory_LH(lmem), hentry);
          lemma_ApplyStoreBufferEntryCommutesWithConvert(lmem, lentry, hentry, hmem1, hmem2);

          var alt_hs' := HAtomic_GetStateAfterPath(hs, hpath, tid);
          ProofCustomizationGoesHere();

          assert hs'.threads[tid] == alt_hs'.threads[tid];
          assert hs'.threads == alt_hs'.threads;
          assert hs' == alt_hs';

          /* { hpr.GetAssertValidPathInvocation(hAtomic.TauPath) } */
        }}
      ";

            pgp.AddLemma(str, "lift");
        }
示例#3
0
 public AtomicPathPrefix(AtomicSpec i_atomicSpec, ArmadaPC pc)
 {
     atomicSpec   = i_atomicSpec;
     nextRoutines = new List <NextRoutine>();
     tau          = false;
     startPC      = endPC = pc;
     startType    = endType = atomicSpec.GetPCAtomicType(pc);
     extensions   = new List <AtomicPathPrefix>();
     path         = null;
 }
示例#4
0
        protected override void GenerateLiftAtomicPathLemmaForNormalPath(AtomicPath atomicPath, string typeComparison,
                                                                         string extraSignatureLines, string extraProof)
        {
            var isValidStepLemmaInvocations = String.Concat(atomicPath.NextRoutines
                                                            .Where(nextRoutine => nextRoutine.stmt != null && nextRoutine.startPC != null && weakenedPCs.Contains(nextRoutine.startPC))
                                                            .Select((nextRoutine, idx) => $@"
             lemma_Step_{nextRoutine.NameSuffix}_ImpliesConvertedIsValidStep(
               lstates.s{idx}, lstates.s{idx+1}, lsteps.step{idx}, hsteps.step{idx}, tid);
          "));

            base.GenerateLiftAtomicPathLemmaForNormalPath(atomicPath, typeComparison, extraSignatureLines,
                                                          extraProof + "\n" + isValidStepLemmaInvocations);
        }
示例#5
0
        public string GetConstructorString(AtomicPath atomicPath)
        {
            if (atomicPath.NextRoutines.Where(r => r.HasFormals).Any())
            {
                // TODO: this does not work with introduced statements with *
                AH.PrintError(pgp.prog, "Armada currently doesn't support introducing a non-deterministic statement.");
            }

            var str = $"{prefix}_Path_{atomicPath.Name}({prefix}_PathSteps_{atomicPath.Name}(";

            str += String.Join(", ", atomicPath.NextRoutines.Select(r => $"{moduleName}.Armada_Step_{r.NameSuffix}()"));
            str += "))";
            return(str);
        }
示例#6
0
        public virtual string GetAssertValidPathInvocation(AtomicPath atomicPath)
        {
            string str = "";

            foreach (var i in Enumerable.Range(0, atomicPath.NumNextRoutines))
            {
                var nextRoutine = atomicPath.NextRoutines[i];
                var stepPrinter = new ModuleStepPrinter(ModuleName);
                stepPrinter.State     = atomicSpec.Low ? $"{States}.s{i}.s" :  $"{States}.s{i}";
                stepPrinter.NextState = atomicSpec.Low ? $"{States}.s{i + 1}.s" :  $"{States}.s{i + 1}";
                stepPrinter.Step      = $"{Steps}.step{i}";
                stepPrinter.Tid       = Tid;
                str += stepPrinter.GetAssertValidStepInvocation(nextRoutine);
            }
            str += $@"
        assert {Prefix}_ValidPath_{atomicPath.Name}({State}, {Tid}, {Steps});
        assert {Prefix}_ValidPath({State}, {Path}, {Tid});
        assert {NextState} == {Prefix}_GetStateAfterPath({State}, {Path}, {Tid});
      ";
            return(str);
        }
示例#7
0
        public virtual string GetOpenValidPathInvocation(AtomicPath atomicPath)
        {
            string str = $@"
         var {Steps}, {States} := lemma_{Prefix}_OpenPath_{atomicPath.Name}({State}, {Path}, {Tid});
      ";

/*
 *       assert {Path} == {Prefix}_Path_{atomicPath.Name}({Steps});
 *       assert {Prefix}_ValidPath_{atomicPath.Name}({State}, {Tid}, {Steps});
 *       assert {States} == {Prefix}_GetPathStates_{atomicPath.Name}({State}, {Tid}, {Steps});
 *       assert {Prefix}_GetStateAfterPath({State}, {Path}, {Tid}) == {States}.s{atomicPath.NumNextRoutines};
 */
            foreach (var i in Enumerable.Range(0, atomicPath.NumNextRoutines))
            {
                var nextRoutine = atomicPath.NextRoutines[i];
                var stepPrinter = new ModuleStepPrinter(ModuleName);
                stepPrinter.State = atomicSpec.Low ? $"{States}.s{i}.s" :  $"{States}.s{i}";
                stepPrinter.Step  = $"{Steps}.step{i}";
                stepPrinter.Tid   = Tid;
                str += stepPrinter.GetOpenValidStepInvocation(nextRoutine);
            }
            return(str);
        }
示例#8
0
        private void CreateFunctionsForAtomicPath(AtomicPath atomicPath)
        {
            var    nextRoutines = atomicPath.NextRoutines;
            string str;

            str  = $@"
        function {prefix}_GetPathStates_{atomicPath.Name}(
          s0: {typeState},
          tid: Armada_ThreadHandle,
          steps: {prefix}_PathSteps_{atomicPath.Name}
          ) : {prefix}_PathStates_{atomicPath.Name}
        {{
      ";
            str += String.Concat(
                Enumerable.Range(0, nextRoutines.Count).Select(i => $"    var s{i + 1} := {getNextState}(s{i}, steps.step{i}, tid);\n")
                );
            str += $"    {prefix}_PathStates_{atomicPath.Name}(";
            str += String.Join(", ", Enumerable.Range(0, nextRoutines.Count + 1).Select(i => $"s{i}"));
            str += ") }";
            pgp.AddFunction(str, auxName);

            str  = $@"
        predicate {prefix}_ValidPath_{atomicPath.Name}(
          s: {typeState},
          tid: Armada_ThreadHandle,
          steps: {prefix}_PathSteps_{atomicPath.Name}
          )
        {{
          var states := {prefix}_GetPathStates_{atomicPath.Name}(s, tid, steps);
      ";
            str += String.Concat(Enumerable.Range(0, nextRoutines.Count).Select(i => $@"
          && steps.step{i}.Armada_Step_{nextRoutines[i].NameSuffix}?
          && {validStep}(states.s{i}, steps.step{i}, tid)
      "));
            str += "}";
            pgp.AddPredicate(str, auxName);
        }
示例#9
0
        public AtomicPathPrefix(AtomicSpec i_atomicSpec, List <NextRoutine> i_nextRoutines, bool i_tau, AtomicPathPrefix parent)
        {
            atomicSpec   = i_atomicSpec;
            nextRoutines = new List <NextRoutine>(i_nextRoutines);
            tau          = i_tau;
            startPC      = nextRoutines[0].startPC;
            endPC        = nextRoutines[nextRoutines.Count - 1].endPC;
            startType    = atomicSpec.GetPCAtomicType(startPC);
            endType      = nextRoutines[nextRoutines.Count - 1].Stopping ? PCAtomicType.Stopping : atomicSpec.GetPCAtomicType(endPC);
            extensions   = new List <AtomicPathPrefix>();
            path         = null;

            if (parent != null)
            {
                parent.AddExtension(this);
            }

            if (tau)
            {
                name = "Tau";
            }
            else
            {
                name  = UndefinedBehavior ? "UB_" : "";
                name += $"From_{startPC.methodName}_{startPC.Name}";

                // It's possible for two atomic paths to have the same start
                // and end PCs.  But, every path has to have a distinct name,
                // so we sometimes have to name a path with more than just the
                // start and end PCs.
                //
                // One way for two atomic paths with the same start and end
                // PCs to differ is via returning to different PCs.  For
                // instance, consider the following code:
                //
                //   method {:atomic} A {
                //     S1;
                //   label L:
                //     S2;
                //   }
                //
                //   method B {
                //     atomic {
                //       A();
                //       A();
                //       A();
                //     }
                //   }
                //
                // Here, there are two ways to get from label L to label L:
                // (1) by returning from B's first call to A and then making
                // B's second call to A, and (2) by returning from B's second
                // call to A and then making B's third call to A.  So, to make
                // sure such paths have different names, we include in the
                // name every returned-to PC in a step other than the last one
                // in the path.
                //
                // Another way for two atomic paths with the same start and
                // end PCs to differ is via branch outcomes.  For instance,
                // consider the following code:
                //
                //   atomic {
                //     if P {
                //       S1;
                //     }
                //     S2;
                //   }
                //
                // Here, there are two ways to get from the beginning to the
                // end: via the true branch of the if (passing through
                // statement S1) or via the false branch.  So we distinguish
                // the names of such paths by the branch outcomes.

                bool justBranched = false;
                for (var i = 0; i < nextRoutines.Count; ++i)
                {
                    var nextRoutine = nextRoutines[i];
                    if (i < nextRoutines.Count - 1 && nextRoutine.nextType == NextType.Return)
                    {
                        var returnToPC = nextRoutine.endPC;
                        name        += $"_Via_{returnToPC.methodName}_{returnToPC.Name}";
                        justBranched = false;
                    }

                    bool branchOutcome;
                    if (nextRoutine.TryGetBranchOutcome(out branchOutcome))
                    {
                        if (!justBranched)
                        {
                            name += "_";
                        }
                        name        += (branchOutcome ? "T" : "F");
                        justBranched = true;
                    }
                }

                if (endPC == null)
                {
                    name += "_to_exit";
                }
                else
                {
                    name += $"_To_{endPC.methodName}_{endPC.Name}";
                }
            }
        }
示例#10
0
        public static PrioritizationAttributes GetPrioritizationAttributesForLiftAtomicPath(AtomicPath lowAtomicPath, AtomicPath highAtomicPath)
        {
            if (lowAtomicPath.NextRoutines.Select(nextRoutine => nextRoutine.armadaStatement == null ? null : Printer.StatementToString(nextRoutine.armadaStatement.Stmt)).SequenceEqual(
                    highAtomicPath.NextRoutines.Select(nextRoutine => nextRoutine.armadaStatement == null ? null : Printer.StatementToString(nextRoutine.armadaStatement.Stmt))))
            {
                return(new PrioritizationAttributes {
                    likelihoodOfFailure = 0
                });
            }

            return(new PrioritizationAttributes {
                likelihoodOfFailure = 3
            });

            /*
             * // TODO: this check assumes that corresponding nextRoutines with no associated armada statements are the same
             * if (lowAtomicPath.NextRoutines.Count == highAtomicPath.NextRoutines.Count)
             * {
             * bool stmtsEqual = false;
             * for (int i = 0; i < lowAtomicPath.NextRoutines.Count; i++) {
             *  if (stmtsEqual) {
             *    return new PrioritizationAttributes { likelihoodOfFailure = 0 };
             *  }
             * }
             * }
             * return new PrioritizationAttributes { likelihoodOfFailure = 3 };
             */
        }
示例#11
0
 public virtual string PathSteps(AtomicPath path)
 {
     return($"{State}, {Tid}, {Steps}");
 }
示例#12
0
 public virtual string PathFormals(AtomicPath path)
 {
     return($"{State}:{TotalStateType}, {Tid}:Armada_ThreadHandle, {Steps}:{StepsType(path)}");
 }
示例#13
0
 public virtual string CaseEntryWithUnderscores(AtomicPath path)
 {
     return($"case {Prefix}_Path_{path.Name}(_)");
 }
示例#14
0
 public virtual string CaseEntry(AtomicPath path)
 {
     return($"case {Prefix}_Path_{path.Name}({ParamsParam})");
 }
示例#15
0
 public virtual string StepsType(AtomicPath path)
 {
     return($"{Prefix}_PathSteps_{path.Name}");
 }