Пример #1
0
        protected override string GetStepCaseForNormalNextRoutine_LH(NextRoutine nextRoutine)
        {
            var bvs = nextRoutine.HasFormals ? $"params: L.Armada_StepParams_{nextRoutine.NameSuffix}" : "";
            var ps  = nextRoutine.Formals.Select(f => $"params.{f.LocalVarName}").ToList();

            if (nextRoutine.nextType == NextType.Call &&
                ((ArmadaCallStatement)nextRoutine.armadaStatement).CalleeName == strategy.MethodName ||
                nextRoutine.nextType == NextType.CreateThread &&
                ((nextRoutine.stmt as UpdateStmt).Rhss[0] as CreateThreadRhs).MethodName.val == strategy.MethodName)
            {
                var highRoutine = LiftNextRoutine(nextRoutine);
                var highFormals = new List <NextFormal>(highRoutine.Formals);
                for (var i = 0; i < highFormals.Count(); ++i)
                {
                    if (!nextRoutine.Formals.Any(f => f.LocalVarName == highFormals[i].LocalVarName))
                    {
                        ps.Insert(i, strategy.InitializationExpression);
                        break;
                    }
                }
            }

            var    hNextRoutine = LiftNextRoutine(nextRoutine);
            string hname        = hNextRoutine.NameSuffix;
            var    caseBody     = hNextRoutine.HasFormals ? $"H.Armada_Step_{hname}(H.Armada_StepParams_{hname}({AH.CombineStringsWithCommas(ps)}))"
                                             : $"H.Armada_Step_{hname}";

            return($"case Armada_Step_{nextRoutine.NameSuffix}({bvs}) => {caseBody}\n");
        }
Пример #2
0
 public ArmadaSymbolTable(Program i_prog, ArmadaStructs i_structs)
 {
     prog            = i_prog;
     globalVariables = new ArmadaGlobalVariableSymbolTable();
     localVariables  = new ArmadaMethodLocalVariableSymbolTable();
     defaultClass    = null;
     if (i_structs == null)
     {
         structs = new ArmadaStructs(null);
     }
     else
     {
         structs = i_structs;
     }
     threadRoutines = new HashSet <string> {
         "main"
     };
     functionNames         = new List <string> {
     };
     nextRoutines          = new List <NextRoutine>();
     allMethodsInfo        = new AllMethodsInfo(prog);
     tauNextRoutine        = null;
     methodAndLabelToPCMap = new Dictionary <string, ArmadaPC>();
     pcToLabelMap          = new Dictionary <ArmadaPC, string>();
     globalInvariants      = new Dictionary <string, GlobalInvariantInfo>();
     yieldPredicates       = new Dictionary <string, YieldPredicateInfo>();
 }
Пример #3
0
        private void GenerateConvertImpliesValidStepLemma(NextRoutine nextRoutine)
        {
            var nextRoutineName = nextRoutine.NameSuffix;

            NextRoutine highNextRoutine     = nextRoutineMap[nextRoutine];
            string      highNextRoutineName = highNextRoutine.NameSuffix;

            var lstep_params = String.Join("", nextRoutine.Formals.Select(f => $", lentry.{f.GloballyUniqueVarName}"));
            var hstep_params = String.Join("", highNextRoutine.Formals.Select(f => $", hentry.{f.GloballyUniqueVarName}"));

            string body = "";

            foreach (var globalVarName in strategy.GlobalVars)
            {
                body += $@"
          DoesNotAppearInStoreBufferImpliesThreadLocalViewOf_GlobalStaticVar_{globalVarName}_AlwaysMatchesGlobalView();
        ";
            }

            var str = $@"
        lemma lemma_TraceEntry_{nextRoutineName}_ImpliesConvertedIsValidStep(wr: WRequest, lps: LPlusState, lps': LPlusState, lentry: L.Armada_TraceEntry, hentry: H.Armada_TraceEntry)
          requires wr == GetStarWeakeningRequest()
          requires LPlus_NextOneStep(lps, lps', lentry)
          requires lentry.Armada_TraceEntry_{nextRoutineName}?
          requires lps in wr.inv
          requires hentry == ConvertTraceEntry_LH(lps.s, lentry);
          ensures H.Armada_ValidStep_{highNextRoutineName}(ConvertTotalState_LPlusH(lps), lentry.tid{hstep_params});
        {{
          lemma_GetThreadLocalViewAlwaysCommutesWithConvert();
          {body}
        }}
      ";

            pgp.AddLemma(str);
        }
Пример #4
0
        private void GenerateLiftStepLemmaForSuppressedNextRoutine(NextRoutine nextRoutine)
        {
            var nextRoutineName = nextRoutine.NameSuffix;

            var lstep_params = String.Join("", nextRoutine.Formals.Select(f => $", lstep.{f.GloballyUniqueVarName}"));
            var hstep_params = String.Join("", nextRoutine.Formals.Select(f => $", hstep.{TranslateFormalNameUsingPcMap(f, nextRoutine.pc, pcMap)}"));

            var str = $@"
        lemma lemma_LiftNext_{nextRoutineName}(vr:VHRequest, ls:LPlusState, ls':LPlusState, lstep:L.Armada_TraceEntry)
            requires vr == GetVarHidingRequest()
            requires LPlus_NextOneStep(ls, ls', lstep)
            requires lstep.Armada_TraceEntry_{nextRoutineName}?
            ensures  ShouldSuppressTraceEntry(ls.s, lstep)
            ensures  vr.hider(ls) == vr.hider(ls')
        {{
            var hs := vr.hider(ls);
            var hs' := vr.hider(ls');
            var tid := lstep.tid;
            var hstep := ConvertTraceEntry_LH(lstep);

            assert hs'.stop_reason == hs.stop_reason;
            assert hs'.threads[tid] == hs.threads[tid];
            assert hs' == hs;
        }}
      ";

            pgp.AddLemma(str);
        }
Пример #5
0
        protected virtual void GenerateLiftStepLemmaForInnerNextRoutine(NextRoutine nextRoutine)
        {
            var nextRoutineName = nextRoutine.NameSuffix;

            var str = $@"
        lemma lemma_LiftStep_{nextRoutineName}(ls:LPlusState, lstep:L.Armada_TraceEntry)
          requires InductiveInv(ls)
          requires LPlus_ValidStep(ls, lstep)
          requires lstep.Armada_TraceEntry_{nextRoutineName}?
          requires var tid := lstep.tid; tid in ls.s.threads ==> !IsInnerPC(ls.s.threads[tid].pc)
          requires var tid := lstep.tid;
                   var ls' := LPlus_GetNextStateAlways(ls, lstep); 
                   tid in ls'.s.threads ==> !IsInnerPC(ls'.s.threads[tid].pc)
          ensures  var ls' := LPlus_GetNextStateAlways(ls, lstep);
                   var hs := ConvertTotalState_LPlusH(ls);
                   var hstep := ConvertTraceEntry_LH(lstep);
                   && hstep.tid == lstep.tid
                   && hstep.Armada_TraceEntry_Tau? == lstep.Armada_TraceEntry_Tau?
                   && H.Armada_ValidStep(hs, hstep)
                   && H.Armada_GetNextStateAlways(hs, hstep) == ConvertTotalState_LPlusH(ls')
        {{
          var tid := lstep.tid;
          var ls' := LPlus_GetNextStateAlways(ls, lstep); 
          assert tid in ls.s.threads;
          assert tid in ls'.s.threads;
          assert IsInnerPC(ls.s.threads[tid].pc) || IsInnerPC(ls'.s.threads[tid].pc);
          assert false;
        }}
      ";

            pgp.AddLemma(str);
        }
Пример #6
0
 public WhilePCNode(ArmadaPC i_pc, NextRoutine i_nextRoutineWhenTrue, NextRoutine i_nextRoutineWhenFalse, PCNode i_successorWhenTrue,
                    PCNode i_successorWhenFalse) : base(i_pc)
 {
     nextRoutineWhenTrue  = i_nextRoutineWhenTrue;
     nextRoutineWhenFalse = i_nextRoutineWhenFalse;
     successorWhenTrue    = i_successorWhenTrue;
     successorWhenFalse   = i_successorWhenFalse;
 }
Пример #7
0
   public virtual string GetAssertValidStepInvocation(NextRoutine nextRoutine)
   {
       return($@"
   assert {ValidStepInvocation(nextRoutine)};
   assert {moduleName}.Armada_ValidStep({State}, {Step}, {Tid});
   assert {NextState} == {moduleName}.Armada_GetNextState({State}, {Step}, {Tid});
 ");
   }
Пример #8
0
        public virtual string GetOpenValidStepInvocation(NextRoutine nextRoutine)
        {
            return($@"
        lemma_OpenStep_{moduleName}_{nextRoutine.NameSuffix}({State}, {Step}, {Tid});
      ");

            /*
             * assert {ValidStepInvocation(nextRoutine)};
             * assert {moduleName}.Armada_GetNextState({State}, {Step}, {Tid}) == {GetNextStateInvocation(nextRoutine)};
             */
        }
Пример #9
0
        ////////////////////////////////////////////////////////////////////////
        /// Lifting routines
        ////////////////////////////////////////////////////////////////////////

        protected override MatchCaseExpr GetTraceEntryCaseForNextRoutine_LH(NextRoutine nextRoutine)
        {
            if (IsSuppressedNextRoutine(nextRoutine))
            {
                // This is the case of an update statement that gets suppressed because it only updates hidden variables.
                return(GetTraceEntryCaseForSuppressedNextRoutine_LH(nextRoutine));
            }
            else
            {
                return(GetTraceEntryCaseForNormalNextRoutine_LH(nextRoutine));
            }
        }
Пример #10
0
        protected override string GetStepCaseForNormalNextRoutine_LH(NextRoutine nextRoutine)
        {
            var bvs = nextRoutine.HasFormals ? $"params: L.Armada_StepParams_{nextRoutine.NameSuffix}" : "";
            var ps  = nextRoutine.Formals.Select(f => $"params.{f.LocalVarName}");

            var    hNextRoutine = nextRoutineMap[nextRoutine];
            string hname        = hNextRoutine.NameSuffix;
            var    caseBody     = hNextRoutine.HasFormals ? $"H.Armada_Step_{hname}(H.Armada_StepParams_{hname}({AH.CombineStringsWithCommas(ps)}))"
                                             : $"H.Armada_Step_{hname}";

            return($"case Armada_Step_{nextRoutine.NameSuffix}({bvs}) => {caseBody}\n");
        }
Пример #11
0
        protected override void GenerateLiftStepLemmaForNormalNextRoutine(NextRoutine nextRoutine)
        {
            var nextRoutineName = nextRoutine.NameSuffix;

            NextRoutine highNextRoutine     = nextRoutineMap[nextRoutine];
            string      highNextRoutineName = highNextRoutine.NameSuffix;

            var lstep_params = String.Join("", nextRoutine.Formals.Select(f => $", lentry.{f.GloballyUniqueVarName}"));
            var hstep_params = String.Join("", highNextRoutine.Formals.Select(f => $", hstep.{f.GloballyUniqueVarName}"));

            bool needIsValidStepLemma = false;

            if (nextRoutine.stmt != null && nextRoutine.pc != null && weakenedPCs.Contains(nextRoutine.pc))
            {
                needIsValidStepLemma = true;
                GenerateConvertImpliesValidStepLemma(nextRoutine);
            }

            var str = $@"
        lemma lemma_LiftNext_{nextRoutineName}(wr: WRequest, lps: LPlusState, lps':LPlusState, lentry: L.Armada_TraceEntry)
          requires wr == GetStarWeakeningRequest()
          requires LPlus_NextOneStep(lps, lps', lentry)
          requires lentry.Armada_TraceEntry_{nextRoutineName}?
          requires lps in wr.inv
          ensures H.Armada_NextOneStep(ConvertTotalState_LPlusH(lps), ConvertTotalState_LPlusH(lps'), ConvertTraceEntry_LH(lps.s, lentry))
        {{
          var hs := wr.converter(lps);
          var hs' := wr.converter(lps');
          var tid := lentry.tid;
          var hstep := ConvertTraceEntry_LH(lps.s, lentry);
          lemma_GetThreadLocalViewAlwaysCommutesWithConvert();
          lemma_StoreBufferAppendAlwaysCommutesWithConvert();
          { (needIsValidStepLemma ? $@"lemma_TraceEntry_{nextRoutineName}_ImpliesConvertedIsValidStep(wr, lps, lps', lentry, hstep);" : "" )}
          assert H.Armada_ValidStep_{highNextRoutineName}(hs, tid{hstep_params});
          if L.Armada_UndefinedBehaviorAvoidance_{nextRoutineName}(lps.s, tid{lstep_params}) {{
            assert H.Armada_UndefinedBehaviorAvoidance_{highNextRoutineName}(hs, tid{hstep_params});
            var alt_hs' := H.Armada_GetNextState_{highNextRoutineName}(hs, tid{hstep_params});
            assert hs'.stop_reason == alt_hs'.stop_reason;
            if tid in hs'.threads {{
              assert hs'.threads[tid] == alt_hs'.threads[tid];
            }}
            assert hs'.threads == alt_hs'.threads;
            assert hs'.mem == alt_hs'.mem;
            assert hs' == alt_hs';
            assert H.Armada_Next_{highNextRoutineName}(hs, hs', tid{hstep_params});
          }} else {{
            assert !H.Armada_UndefinedBehaviorAvoidance_{highNextRoutineName}(hs, tid{hstep_params});
          }}
        }}
      ";

            pgp.AddLemma(str);
        }
Пример #12
0
        protected MatchCaseExpr GetTraceEntryCaseForUpdateToUpdateNextRoutine_LH(NextRoutine nextRoutine)
        {
            var highNextRoutine = nextRoutineMap[nextRoutine];
            var lowStmt         = (UpdateStmt)nextRoutine.armadaStatement.Stmt;
            var lowExprs        = lowStmt.Lhss;

            var highStmt  = (UpdateStmt)highNextRoutine.armadaStatement.Stmt;
            var highExprs = highStmt.Lhss;

            var pi = GetMatchingLowLevelLhssForHighLevelLhss(lowExprs, highExprs);

            var bvs = new List <BoundVar> {
                AH.MakeBoundVar("tid", "Armada_ThreadHandle")
            };

            bvs.AddRange(nextRoutine.Formals.Select(f => AH.MakeBoundVar(f.LocalVarName, AddModuleNameToArmadaType(f.VarType, "L"))));

            var ps = new List <Expression> {
                AH.MakeNameSegment("tid", "Armada_ThreadHandle")
            };

            // ps.AddRange(nextRoutine.Formals.Select(f => AH.MakeNameSegment(f.LocalVarName, f.VarType))); // Use the tid (and any other) parameters from the bound vars in the case statement

            for (int i = 0; i < highExprs.Count; i++)
            {
                var context = new NormalResolutionContext(nextRoutine, pgp.symbolsLow);
                // Add the pi[i]'th rhs from the low-level update statement
                var        rhs = lowStmt.Rhss.ElementAt(pi[i]);
                Expression newRhs;
                if (rhs is ExprRhs)
                {
                    var erhs         = (ExprRhs)rhs;
                    var newRhsRValue = context.ResolveAsRValue(erhs.Expr);
                    newRhs = newRhsRValue.Val;
                }
                else // rhs must be HavocRhs here
                {
                    newRhs = AH.MakeNameSegment($"nondet{i}", lowExprs[pi[i]].Type);
                }
                if (highStmt.Rhss.ElementAt(i) is HavocRhs) // If the high level is a havoc-rhs, then it needs to be given the values
                {
                    ps.Add(newRhs);
                }
            }

            string nextRoutineName = nextRoutine.NameSuffix;
            string hname           = nextRoutineMap[nextRoutine].NameSuffix;
            var    case_body       = AH.MakeApplyN($"H.Armada_TraceEntry_{hname}", ps, "H.Armada_TraceEntry");
            var    case0           = AH.MakeMatchCaseExpr($"Armada_TraceEntry_{nextRoutineName}", bvs, case_body);

            return(case0);
        }
Пример #13
0
        public virtual string GetOpenStepInvocation(NextRoutine nextRoutine)
        {
            return($@"
        lemma_OpenStep_{moduleName}_{nextRoutine.NameSuffix}({State}, {Step}, {Tid});
      ");

            /*
             * assert {moduleName}.Armada_ValidStep({State}, {Step}, {Tid}) <==>
             *         {Tid} in {State}.threads && {State}.stop_reason.Armada_NotStopped? && {ValidStepInvocation(nextRoutine)};
             * assert {moduleName}.Armada_ValidStep({State}, {Step}, {Tid}) ==>
             *         {GetNextStateInvocation(nextRoutine)} == {moduleName}.Armada_GetNextState({State}, {Step}, {Tid});
             */
        }
Пример #14
0
        protected MatchCaseExpr GetTraceEntryCaseForUpdateToSomehowNextRoutine_LH(NextRoutine nextRoutine)
        {
            var highNextRoutine = nextRoutineMap[nextRoutine];
            var lowStmt         = (UpdateStmt)nextRoutine.armadaStatement.Stmt;
            var lowExprs        = lowStmt.Lhss;

            var highStmt  = (SomehowStmt)highNextRoutine.armadaStatement.Stmt;
            var highExprs = highStmt.Mod.Expressions;

            var pi = GetMatchingLowLevelLhssForHighLevelLhss(lowExprs, highExprs);

            var bvs = new List <BoundVar> {
                AH.MakeBoundVar("tid", "Armada_ThreadHandle")
            };

            bvs.AddRange(nextRoutine.Formals.Select(f => AH.MakeBoundVar(f.LocalVarName, AddModuleNameToArmadaType(f.VarType, "L"))));

            var ps = new List <Expression> {
                AH.MakeNameSegment("tid", "Armada_ThreadHandle")
            };

            ps.AddRange(nextRoutine.Formals.Select(f => AH.MakeNameSegment(f.LocalVarName, f.VarType))); // Use the tid (and any other) parameters from the bound vars in the case statement

            for (int i = 0; i < highExprs.Count; i++)
            {
                var context = new NormalResolutionContext(nextRoutine, pgp.symbolsLow);
                // Add the pi[i]'th rhs from the low-level update statement
                var        rhs = lowStmt.Rhss.ElementAt(pi[i]);
                Expression newRhs;
                if (rhs is ExprRhs)
                {
                    var erhs         = (ExprRhs)rhs;
                    var newRhsRValue = context.ResolveAsRValue(erhs.Expr);
                    newRhs = newRhsRValue.Val;
                }
                else
                {
                    AH.PrintError(pgp.prog, "Havoc RHS not yet supported");
                    return(null);
                }

                ps.Add(newRhs);
            }

            string nextRoutineName = nextRoutine.NameSuffix;
            string hname           = nextRoutineMap[nextRoutine].NameSuffix;
            var    case_body       = AH.MakeApplyN($"H.Armada_TraceEntry_{hname}", ps, "H.Armada_TraceEntry");
            var    case0           = AH.MakeMatchCaseExpr($"Armada_TraceEntry_{nextRoutineName}", bvs, case_body);

            return(case0);
        }
Пример #15
0
        protected override string GetStepCaseForNextRoutine_LH(NextRoutine nextRoutine)
        {
            var hNextRoutine = LiftNextRoutine(nextRoutine);

            if (hNextRoutine == null)
            {
                return(GetStepCaseForSuppressedNextRoutine_LH(nextRoutine));
            }

            if (hNextRoutine.nextType == NextType.Update &&
                nextRoutine.nextType == NextType.Update)
            {
                // e.g.  low-level: v_1 := e_1;
                //      high-level: v_1 := *
                //
                // Also low-level: v_1 ::= e_1;
                //      high-level: v_1 ::= *
                return(GetStepCaseForUpdateToUpdateNextRoutine_LH(nextRoutine));
            }
            else if ((hNextRoutine.nextType == NextType.IfTrue || hNextRoutine.nextType == NextType.IfFalse) &&
                     (nextRoutine.nextType == NextType.IfTrue || nextRoutine.nextType == NextType.IfFalse))
            {
                // e.g.  low-level: if p {}
                //      high-level: if * {}
                return(GetStepCaseForIfToIfNextRoutine_LH(nextRoutine));
            }
            else if (hNextRoutine.nextType == NextType.Somehow &&
                     nextRoutine.nextType == NextType.Update)
            {
                // low-level: v_1, ..., v_n ::= e_1, ..., e_n;
                // high-level: for some permutation pi \in S_n,
                // somehow modifies v_{pi_1}
                //         ...
                //         modifies v_{pi_n}
                //
                // In order for star weakening to be possible, it is necessary for a permutation as above to exist.
                // This can be made part of CheckEquivalence
                //
                // Then, the low level step of NextStep()
                // newval{j} is the non-det variable that holds the new value of v_{pi_j}. So,
                // the j'th value in the list of hstep params given in the constructor called by
                // ConvertStep_LH should be e_{pi_j}.
                return(GetStepCaseForUpdateToSomehowNextRoutine_LH(nextRoutine));
            }
            else if (hNextRoutine.nextType == nextRoutine.nextType)
            {
                return(GetStepCaseForNormalNextRoutine_LH(nextRoutine));
            }
            AH.PrintError(pgp.prog, "Invalid statement for weakening.");
            return(null);
        }
Пример #16
0
        private void GenerateConvertImpliesValidStepLemma(NextRoutine nextRoutine)
        {
            NextRoutine hNextRoutine     = nextRoutineMap[nextRoutine];
            string      hNextRoutineName = hNextRoutine.NameSuffix;

            var hstep_params = String.Join("", hNextRoutine.Formals.Select(f => $", hentry.{f.GloballyUniqueVarName}"));

            var lpr = new ModuleStepPrinter("L");

            lpr.State     = "ls.s";
            lpr.NextState = "ls'.s";
            lpr.Step      = "lstep";
            var hpr = new ModuleStepPrinter("H");

            hpr.State     = "hs";
            hpr.NextState = "hs'";
            hpr.Step      = "hstep";

            var str = $@"
        lemma lemma_Step_{nextRoutine.NameSuffix}_ImpliesConvertedIsValidStep(
          ls: LPlusState,
          ls': LPlusState,
          lstep: L.Armada_Step,
          hstep: H.Armada_Step,
          tid: Armada_ThreadHandle
          )
          requires LPlus_ValidStep(ls, lstep, tid)
          requires ls' == LPlus_GetNextState(ls, lstep, tid)
          requires lstep.Armada_Step_{nextRoutine.NameSuffix}?
          requires InductiveInv(ls)
          requires hstep == ConvertStep_LH(ls, lstep, tid)
          ensures  H.Armada_ValidStep(ConvertTotalState_LPlusH(ls), hstep, tid)
        {{
          { lpr.GetOpenValidStepInvocation(nextRoutine) }
          var hs := ConvertTotalState_LPlusH(ls);
          var hs' := H.Armada_GetNextState(hs, hstep, tid);
          lemma_GetThreadLocalViewAlwaysCommutesWithConvert();
      ";

            foreach (var globalVarName in strategy.GlobalVars)
            {
                str += $"lemma_DoesNotAppearInStoreBufferImpliesThreadLocalViewOf_GlobalStaticVar_{globalVarName}_AlwaysMatchesGlobalView();\n";
            }
            str += hpr.GetOpenStepInvocation(hNextRoutine);
            str += "ProofCustomizationGoesHere(); }";
            pgp.AddLemma(str, "lift");
        }
Пример #17
0
        protected override void GenerateLiftStepLemmaForNormalNextRoutine(NextRoutine nextRoutine)
        {
            var nextRoutineName = nextRoutine.NameSuffix;

            var lstep_params = String.Join("", nextRoutine.Formals.Select(f => $", lstep.{f.GloballyUniqueVarName}"));
            var hstep_params = String.Join("", LiftNextRoutine(nextRoutine).Formals.Select(f => $", hstep.{f.GloballyUniqueVarName}"));

            var hNextRoutineName = LiftNextRoutine(nextRoutine).NameSuffix;

            var str = $@"
        lemma lemma_LiftNext_{nextRoutineName}(vr:VHRequest, ls:LPlusState, ls':LPlusState, lstep:L.Armada_TraceEntry)
            requires vr == GetVarHidingRequest()
            requires LPlus_NextOneStep(ls, ls', lstep)
            requires lstep.Armada_TraceEntry_{nextRoutineName}?
            ensures  !ShouldSuppressTraceEntry(ls.s, lstep)
            ensures  H.Armada_NextOneStep(vr.hider(ls), vr.hider(ls'), ConvertTraceEntry_LH(lstep))
        {{
            var hs := vr.hider(ls);
            var hs' := vr.hider(ls');
            var tid := lstep.tid;
            var hstep := ConvertTraceEntry_LH(lstep);

            lemma_GetThreadLocalViewAlwaysCommutesWithConvert();
            lemma_StoreBufferAppendAlwaysCommutesWithConvert();
            assert H.Armada_ValidStep_{hNextRoutineName}(hs, tid{hstep_params});
            if L.Armada_UndefinedBehaviorAvoidance_{nextRoutineName}(ls.s, tid{lstep_params}) {{
              assert H.Armada_UndefinedBehaviorAvoidance_{hNextRoutineName}(hs, tid{hstep_params});
              var alt_hs' := H.Armada_GetNextState_{hNextRoutineName}(hs, tid{hstep_params});
              assert hs'.stop_reason == alt_hs'.stop_reason;
              if tid in hs'.threads {{
                assert hs'.threads[tid] == alt_hs'.threads[tid];
              }}
              assert hs'.threads == alt_hs'.threads;
              assert hs'.mem == alt_hs'.mem;
              assert hs' == alt_hs';
              assert H.Armada_Next_{hNextRoutineName}(hs, hs', tid{hstep_params});
            }}
            else {{
              assert !H.Armada_UndefinedBehaviorAvoidance_{hNextRoutineName}(hs, tid{hstep_params});
            }}
        }}
      ";

            pgp.AddLemma(str);
        }
Пример #18
0
        public NextRoutineConstructor(Program i_prog, ArmadaSymbolTable i_symbols, NextType i_nextType, MethodInfo i_methodInfo,
                                      ArmadaStatement i_armadaStatement, Statement i_stmt, ArmadaPC i_startPC, ArmadaPC i_endPC)
        {
            prog     = i_prog;
            symbols  = i_symbols;
            nextType = i_nextType;
            validDefinedStepBuilder   = new PredicateBuilder(i_prog, true);
            validUndefinedStepBuilder = new PredicateBuilder(i_prog, false);
            getNextStateBuilder       = new ExpressionBuilder(i_prog);
            methodInfo      = i_methodInfo;
            method          = methodInfo == null ? null : methodInfo.method;
            armadaStatement = i_armadaStatement;
            stmt            = i_stmt;
            startPC         = i_startPC;
            endPC           = i_endPC;
            formals         = new List <NextFormal>();
            valid           = true;
            hasUndefinedBehaviorAvoidanceConstraint = false;
            definedBehaviorNextRoutine   = null;
            undefinedBehaviorNextRoutine = null;

            s     = ReserveVariableName("s");
            entry = ReserveVariableName("entry");
            tid   = ReserveVariableName("tid");
            t     = ReserveVariableName("t");
            locv  = ReserveVariableName("locv");

            if (startPC != null)
            {
                AddConjunct($"{t}.pc.{startPC}?");
                AddConjunct($"{t}.top.Armada_StackFrame_{startPC.methodName}?");

                if (methodInfo != null)
                {
                    var constraints = methodInfo.GetEnablingConstraintCollector(startPC);
                    if (constraints != null && !constraints.Empty)
                    {
                        AddConjunct($"Armada_EnablingConditions_{startPC}(s, tid)");
                    }
                }

                AddConjunct("Armada_UniversalStepConstraint(s, tid)");
            }
        }
Пример #19
0
        protected override void GenerateLiftStepLemmaForTauNextRoutine(NextRoutine nextRoutine)
        {
            var nextRoutineName = nextRoutine.NameSuffix;

            NextRoutine highNextRoutine     = LiftNextRoutine(nextRoutine);
            string      highNextRoutineName = highNextRoutine.NameSuffix;

            var lstep_params = String.Join("", nextRoutine.Formals.Select(f => $", lstep.{f.GloballyUniqueVarName}"));
            var hstep_params = String.Join("", highNextRoutine.Formals.Select(f => $", hstep.{f.GloballyUniqueVarName}"));

            var str = $@"
        lemma lemma_LiftNext_{nextRoutineName}(wr:WRequest, lps:LPlusState, lps':LPlusState, lstep:L.Armada_TraceEntry)
          requires wr == GetWeakeningRequest()
          requires lps in wr.inv
          requires LPlus_NextOneStep(lps, lps', lstep)
          requires lstep.Armada_TraceEntry_{nextRoutineName}?
          ensures H.Armada_NextOneStep(ConvertTotalState_LPlusH(lps), ConvertTotalState_LPlusH(lps'), ConvertTraceEntry_LH(lstep))
        {{
            var hs := wr.converter(lps);
            var hs' := wr.converter(lps');
            var tid := lstep.tid;
            var hstep := ConvertTraceEntry_LH(lstep);

            var lentry := lps.s.threads[tid].storeBuffer[0];
            assert H.Armada_ValidStep_{highNextRoutineName}(hs, tid{hstep_params});
            assert H.Armada_UndefinedBehaviorAvoidance_{highNextRoutineName}(hs, tid{hstep_params});
            var hentry := hs.threads[tid].storeBuffer[0];
            var lmem := lps.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' := H.Armada_GetNextState_{highNextRoutineName}(hs, tid{hstep_params});
            assert hmem1 == hmem2;
            assert hs'.threads[tid].storeBuffer == alt_hs'.threads[tid].storeBuffer;
            assert hs'.threads[tid] == alt_hs'.threads[tid];
            assert hs'.threads == alt_hs'.threads;
            assert hs' == alt_hs';
            assert H.Armada_Next_{highNextRoutineName}(hs, hs', tid{hstep_params});
        }}
      ";

            pgp.AddLemma(str);
        }
Пример #20
0
        protected override void GenerateLiftStepLemmaForTauNextRoutine(NextRoutine nextRoutine)
        {
            var nextRoutineName = nextRoutine.NameSuffix;

            var lstep_params = String.Join("", nextRoutine.Formals.Select(f => $", lstep.{f.GloballyUniqueVarName}"));
            var hstep_params = String.Join("", nextRoutine.Formals.Select(f => $", hstep.{f.GloballyUniqueVarName}"));

            var str = $@"
        lemma lemma_LiftNext_{nextRoutineName}(vr:VHRequest, ls:LPlusState, ls':LPlusState, lstep:L.Armada_TraceEntry)
            requires vr == GetVarHidingRequest()
            requires LPlus_NextOneStep(ls, ls', lstep)
            requires lstep.Armada_TraceEntry_{nextRoutineName}?
            ensures  if ShouldSuppressTraceEntry(ls.s, lstep) then
                       vr.hider(ls) == vr.hider(ls')
                     else
                       H.Armada_NextOneStep(vr.hider(ls), vr.hider(ls'), ConvertTraceEntry_LH(lstep))
        {{
            var hs := vr.hider(ls);
            var hs' := vr.hider(ls');
            var tid := lstep.tid;
            var hstep := ConvertTraceEntry_LH(lstep);

            var lentry := ls.s.threads[tid].storeBuffer[0];
            assert H.Armada_ValidStep_{nextRoutineName}(hs, tid{hstep_params});
            assert H.Armada_UndefinedBehaviorAvoidance_{nextRoutineName}(hs, tid{hstep_params});
            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' := H.Armada_GetNextState_{nextRoutineName}(hs, tid{hstep_params});
            assert hs'.threads[tid].storeBuffer == alt_hs'.threads[tid].storeBuffer;
            assert hs'.threads[tid] == alt_hs'.threads[tid];
            assert hs'.threads == alt_hs'.threads;
            assert hs' == alt_hs';
            assert H.Armada_Next_{nextRoutineName}(hs, hs', tid{hstep_params});
        }}
      ";

            pgp.AddLemma(str);
        }
Пример #21
0
        protected string GetStepCaseForUpdateToUpdateNextRoutine_LH(NextRoutine nextRoutine)
        {
            var hNextRoutine = nextRoutineMap[nextRoutine];
            var lowStmt      = (UpdateStmt)nextRoutine.armadaStatement.Stmt;
            var lowExprs     = lowStmt.Lhss;

            var hStmt  = (UpdateStmt)hNextRoutine.armadaStatement.Stmt;
            var hExprs = hStmt.Lhss;

            var pi  = GetMatchingLowLevelLhssForHighLevelLhss(lowExprs, hExprs);
            var bvs = nextRoutine.HasFormals ? $"params: L.Armada_StepParams_{nextRoutine.NameSuffix}" : "";
            var ps  = new List <string>();

            for (int i = 0; i < hExprs.Count; i++)
            {
                var failureReporter = new SimpleFailureReporter(pgp.prog);
                var context         = new NormalResolutionContext("L", nextRoutine.method.Name, pgp.symbolsLow, failureReporter);
                // Add the pi[i]'th rhs from the low-level update statement
                var    rhs = lowStmt.Rhss.ElementAt(pi[i]);
                string newRhs;
                if (rhs is ExprRhs)
                {
                    var erhs         = (ExprRhs)rhs;
                    var newRhsRValue = context.ResolveAsRValue(erhs.Expr);
                    newRhs = newRhsRValue.Val;
                }
                else // rhs must be HavocRhs here
                {
                    newRhs = $"params.nondet{i}";
                }
                if (hStmt.Rhss.ElementAt(i) is HavocRhs) // If the high level is a havoc-rhs, then it needs to be given the values
                {
                    ps.Add(newRhs);
                }
            }

            string hname    = hNextRoutine.NameSuffix;
            var    caseBody = hNextRoutine.HasFormals ? $"H.Armada_Step_{hname}(H.Armada_StepParams_{hname}({AH.CombineStringsWithCommas(ps)}))"
                                               : $"H.Armada_Step_{hname}";

            return($"case Armada_Step_{nextRoutine.NameSuffix}({bvs}) => {caseBody}\n");
        }
Пример #22
0
        protected MatchCaseExpr GetTraceEntryCaseForIfToIfNextRoutine_LH(NextRoutine nextRoutine)
        {
            var highNextRoutine = nextRoutineMap[nextRoutine];
            var lowStmt         = (IfStmt)nextRoutine.armadaStatement.Stmt;
            var highStmt        = (IfStmt)highNextRoutine.armadaStatement.Stmt;

            var bvs = new List <BoundVar> {
                AH.MakeBoundVar("tid", "Armada_ThreadHandle")
            };

            bvs.AddRange(nextRoutine.Formals.Select(f => AH.MakeBoundVar(f.LocalVarName, AddModuleNameToArmadaType(f.VarType, "L"))));

            var ps = new List <Expression> {
                AH.MakeNameSegment("tid", "Armada_ThreadHandle")
            };
            string nextRoutineName = nextRoutine.NameSuffix;
            string hname           = nextRoutineMap[nextRoutine].NameSuffix;
            var    case_body       = AH.MakeApplyN($"H.Armada_TraceEntry_{hname}", ps, "H.Armada_TraceEntry");
            var    case0           = AH.MakeMatchCaseExpr($"Armada_TraceEntry_{nextRoutineName}", bvs, case_body);

            return(case0);
        }
Пример #23
0
        protected override MatchCaseExpr GetTraceEntryCaseForNormalNextRoutine_LH(NextRoutine nextRoutine)
        {
            string nextRoutineName = nextRoutine.NameSuffix;

            var bvs = new List <BoundVar> {
                AH.MakeBoundVar("tid", "Armada_ThreadHandle")
            };

            bvs.AddRange(nextRoutine.Formals.Select(f => AH.MakeBoundVar(f.LocalVarName, AddModuleNameToArmadaType(f.VarType, "L"))));

            var ps = new List <Expression> {
                AH.MakeNameSegment("tid", "Armada_ThreadHandle")
            };

            ps.AddRange(nextRoutine.Formals.Select(f => AH.MakeNameSegment(f.LocalVarName, f.VarType)));

            if (nextRoutine.nextType == NextType.Call &&
                ((ArmadaCallStatement)nextRoutine.armadaStatement).CalleeName == strategy.MethodName ||
                nextRoutine.nextType == NextType.CreateThread &&
                ((nextRoutine.stmt as UpdateStmt).Rhss[0] as CreateThreadRhs).MethodName.val == strategy.MethodName)
            {
                var highRoutine = LiftNextRoutine(nextRoutine);
                var highFormals = new List <NextFormal>(highRoutine.Formals);
                for (var i = 0; i < highFormals.Count(); ++i)
                {
                    if (!nextRoutine.Formals.Any(f => f.LocalVarName == highFormals[i].LocalVarName))
                    {
                        ps.Insert(i + 1, AH.MakeNameSegment(strategy.InitializationExpression, highFormals[i].VarType));
                        break;
                    }
                }
            }

            string hname     = LiftNextRoutine(nextRoutine).NameSuffix;
            var    case_body = AH.MakeApplyN($"H.Armada_TraceEntry_{hname}", ps, "H.Armada_TraceEntry");
            var    case0     = AH.MakeMatchCaseExpr($"Armada_TraceEntry_{nextRoutineName}", bvs, case_body);

            return(case0);
        }
Пример #24
0
        protected string GetStepCaseForUpdateToSomehowNextRoutine_LH(NextRoutine nextRoutine)
        {
            var hNextRoutine = nextRoutineMap[nextRoutine];
            var lowStmt      = (UpdateStmt)nextRoutine.armadaStatement.Stmt;
            var lowExprs     = lowStmt.Lhss;

            var hStmt  = (SomehowStmt)hNextRoutine.armadaStatement.Stmt;
            var hExprs = hStmt.Mod.Expressions;

            var pi  = GetMatchingLowLevelLhssForHighLevelLhss(lowExprs, hExprs);
            var bvs = nextRoutine.HasFormals ? $"params: L.Armada_StepParams_{nextRoutine.NameSuffix}" : "";
            var ps  = nextRoutine.Formals.Select(f => $"params{f.LocalVarName}").ToList();

            for (int i = 0; i < hExprs.Count; i++)
            {
                var failureReporter = new SimpleFailureReporter(pgp.prog);
                var context         = new NormalResolutionContext("L", nextRoutine.method.Name, pgp.symbolsLow, failureReporter);
                // Add the pi[i]'th rhs from the low-level update statement
                var rhs = lowStmt.Rhss.ElementAt(pi[i]);
                if (rhs is ExprRhs)
                {
                    var erhs         = (ExprRhs)rhs;
                    var newRhsRValue = context.ResolveAsRValue(erhs.Expr);
                    ps.Add(newRhsRValue.Val);
                }
                else
                {
                    AH.PrintError(pgp.prog, "Havoc RHS not yet supported");
                    return(null);
                }
            }

            string hname    = hNextRoutine.NameSuffix;
            var    caseBody = hNextRoutine.HasFormals ? $"H.Armada_Step_{hname}(H.Armada_StepParams_{hname}({AH.CombineStringsWithCommas(ps)}))"
                                               : $"H.Armada_Step_{hname}";

            return($"case Armada_Step_{nextRoutine.NameSuffix}({bvs}) => {caseBody}\n");
        }
Пример #25
0
        protected override MatchCaseExpr GetTraceEntryCaseForNormalNextRoutine_LH(NextRoutine nextRoutine)
        {
            string nextRoutineName = nextRoutine.NameSuffix;

            var bvs = new List <BoundVar> {
                AH.MakeBoundVar("tid", "Armada_ThreadHandle")
            };

            bvs.AddRange(nextRoutine.Formals.Select(f => AH.MakeBoundVar(f.LocalVarName, AddModuleNameToArmadaType(f.VarType, "L"))));

            var ps = new List <Expression> {
                AH.MakeNameSegment("tid", "Armada_ThreadHandle")
            };
            var highRoutine = LiftNextRoutine(nextRoutine);

            ps.AddRange(highRoutine.Formals.Select(f => AH.MakeNameSegment(f.LocalVarName, f.VarType)));

            string hname     = LiftNextRoutine(nextRoutine).NameSuffix;
            var    case_body = AH.MakeApplyN($"H.Armada_TraceEntry_{hname}", ps, "H.Armada_TraceEntry");
            var    case0     = AH.MakeMatchCaseExpr($"Armada_TraceEntry_{nextRoutineName}", bvs, case_body);

            return(case0);
        }
Пример #26
0
        private void ExtractInternal(ArmadaSymbolTable symbols, DeclCollector declCollector, List <string> stepCtors, bool ub)
        {
            var nameSuffix = MakeNameSuffix();

            if (ub)
            {
                nameSuffix = "UB_" + nameSuffix;
            }

            if (formals.Any())
            {
                var paramsFormalsList = String.Join(", ", formals.Select(f => $"{f.LocalVarName}: {f.VarType}"));
                var paramsTypeDecl    = $"datatype Armada_StepParams_{nameSuffix} = Armada_StepParams_{nameSuffix}({paramsFormalsList})";
                declCollector.AddItem(paramsTypeDecl);
            }

            stepCtors.Add($"Armada_Step_{nameSuffix}("
                          + (formals.Any() ? $"params_{nameSuffix}: Armada_StepParams_{nameSuffix}" : "")
                          + ")");

            var extraParameterDecls = formals.Any() ? $", params: Armada_StepParams_{nameSuffix}" : "";
            var extraParameterArgs  = formals.Any() ? $", params" : "";
            var paramDecls          = String.Concat(formals.Select(f => $"var {f.LocalVarName} := params.{f.LocalVarName};\n"));
            var validState          = ub ? validUndefinedStepBuilder.Extract() : validDefinedStepBuilder.Extract();
            var nextState           = ub ? $"s.(stop_reason := Armada_StopReasonUndefinedBehavior)" : $"{paramDecls}{getNextStateBuilder.Extract()}";

            declCollector.AddItem($@"
        predicate Armada_ValidStep_{nameSuffix}(s: Armada_TotalState, tid: Armada_ThreadHandle{extraParameterDecls})
          requires tid in s.threads
        {{
          var t := s.threads[tid];
          var locv := Armada_GetThreadLocalView(s, tid);
          {paramDecls}
          {validState}
        }}
      ");

            declCollector.AddItem($@"
        function Armada_GetNextState_{nameSuffix}(s: Armada_TotalState, tid: Armada_ThreadHandle{extraParameterDecls})
          : Armada_TotalState
          requires tid in s.threads
          requires Armada_ValidStep_{nameSuffix}(s, tid{extraParameterArgs})
        {{
          var t := s.threads[tid];
          var locv := Armada_GetThreadLocalView(s, tid);
          {nextState}
        }}
      ");

            var stopping    = (nextType == NextType.TerminateProcess || nextType == NextType.AssertFalse || ub);
            var nextRoutine = new NextRoutine(prog, symbols, nextType, methodInfo, armadaStatement, stmt, startPC, endPC,
                                              formals, nameSuffix, ub, stopping);

            symbols.AddNextRoutine(nextRoutine);
            if (ub)
            {
                undefinedBehaviorNextRoutine = nextRoutine;
            }
            else
            {
                definedBehaviorNextRoutine = nextRoutine;
            }
        }
Пример #27
0
        protected override void GenerateLiftStepLemmaForNormalNextRoutine(NextRoutine nextRoutine)
        {
            var nextRoutineName = nextRoutine.NameSuffix;

            var lstep_params = String.Join("", nextRoutine.Formals.Select(f => $", lstep.{f.GloballyUniqueVarName}"));
            var hstep_params = String.Join("", nextRoutine.Formals.Select(f => $", hstep.{TranslateFormalNameUsingPcMap(f, nextRoutine.pc, pcMap)}"));

            var hNextRoutine = LiftNextRoutine(nextRoutine);

            hstep_params = String.Join("", hNextRoutine.Formals.Select(f => $", hstep.{f.GloballyUniqueVarName}"));
            string hNextRoutineName = hNextRoutine.NameSuffix;

            string optionalRequires = "";
            string optionalProof    = "";

            if (nextRoutine.nextType == NextType.Update && !((UpdateStmt)nextRoutine.stmt).BypassStoreBuffers)
            {
                optionalProof = "";
            }
            else if (nextRoutine.nextType == NextType.Call || nextRoutine.nextType == NextType.Return)
            {
                optionalProof = "assert ls'.threads[tid] == ConvertTotalState_HL(hs').threads[tid];";
            }
            else if (nextRoutine.nextType == NextType.Terminate)
            {
                optionalRequires = "requires !(hs.stop_reason.Armada_NotStopped? && lstep.tid in hs.threads && NewInstructionStoreBufferEntries_H(hs.threads[lstep.tid].storeBuffer))";
            }

            var str = $@"
        lemma lemma_LiftNext_{nextRoutineName}(
            ls:LState,
            ls':LState,
            lstep:L.Armada_TraceEntry,
            hs:HState,
            hs':HState,
            hstep:H.Armada_TraceEntry
            )
            {optionalRequires}
            requires !NewInstructionThread_H(hs, lstep.tid)
            requires L.Armada_NextOneStep(ls, ls', lstep)
            requires lstep.Armada_TraceEntry_{nextRoutineName}?
            requires hstep == ConvertTraceEntry_LH(lstep)
            requires hs' == H.Armada_GetNextStateAlways(hs, hstep)
            requires ls == ConvertTotalState_HL(hs)
            ensures  H.Armada_NextOneStep(hs, hs', hstep)
            ensures  ls' == ConvertTotalState_HL(hs')
        {{
            var tid := lstep.tid;

            lemma_GetThreadLocalViewAlwaysCommutesWithConvert();
            lemma_StoreBufferAppendAlwaysCommutesWithConvert();
            assert H.Armada_ValidStep_{hNextRoutineName}(hs, tid{hstep_params});
            if L.Armada_UndefinedBehaviorAvoidance_{nextRoutineName}(ls, tid{lstep_params}) {{
              {optionalProof}
              assert H.Armada_UndefinedBehaviorAvoidance_{hNextRoutineName}(hs, tid{hstep_params});
              var alt_hs' := H.Armada_GetNextState_{hNextRoutineName}(hs, tid{hstep_params});
              assert hs'.stop_reason == alt_hs'.stop_reason;
              if tid in hs'.threads {{
                assert hs'.threads[tid] == alt_hs'.threads[tid];
              }}
              assert hs'.threads == alt_hs'.threads;
              assert hs'.mem == alt_hs'.mem;
              assert hs' == alt_hs';
              assert H.Armada_Next_{hNextRoutineName}(hs, hs', tid{hstep_params});
            }}
            else {{
              assert !H.Armada_UndefinedBehaviorAvoidance_{hNextRoutineName}(hs, tid{hstep_params});
            }}
        }}
      ";

            pgp.AddLemma(str);
        }
Пример #28
0
 public StepDescriptor(StepDescriptorType i_stepType, NextRoutine i_nextRoutine)
 {
     stepType    = i_stepType;
     nextRoutine = i_nextRoutine;
 }
Пример #29
0
 public void AddNextRoutine(NextRoutine nextRoutine)
 {
     nextRoutines.Add(nextRoutine);
 }
Пример #30
0
 public NormalPCNode(ArmadaPC i_pc, NextRoutine i_nextRoutine, PCNode i_successor) : base(i_pc)
 {
     nextRoutine = i_nextRoutine;
     successor   = i_successor;
 }