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"); }
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>(); }
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); }
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); }
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); }
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; }
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}); "); }
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)}; */ }
//////////////////////////////////////////////////////////////////////// /// 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)); } }
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"); }
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); }
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); }
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}); */ }
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); }
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); }
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"); }
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); }
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)"); } }
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); }
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); }
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"); }
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); }
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); }
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"); }
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); }
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; } }
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); }
public StepDescriptor(StepDescriptorType i_stepType, NextRoutine i_nextRoutine) { stepType = i_stepType; nextRoutine = i_nextRoutine; }
public void AddNextRoutine(NextRoutine nextRoutine) { nextRoutines.Add(nextRoutine); }
public NormalPCNode(ArmadaPC i_pc, NextRoutine i_nextRoutine, PCNode i_successor) : base(i_pc) { nextRoutine = i_nextRoutine; successor = i_successor; }