private void ExtractOldVariablesForBodylessMethod(Program prog, ArmadaSymbolTable symbols, Method meth, ArmadaSingleMethodSymbolTable smst) { if (meth.Ens == null) { return; } if (!meth.Ens.Any()) { return; } var s = AH.MakeNameSegment("s", "Armada_TotalState"); var tid = AH.MakeNameSegment("tid", "Armada_ThreadHandle"); var failureCollector = new SimpleFailureReporter(prog); var ensContext = new BodylessMethodSnapshotResolutionContext(s, tid, meth.Name, symbols, failureCollector); foreach (var ens in meth.Ens) { var ensResolvedJustToGetOldValues = ensContext.ResolveAsRValue(ens.E); } int whichOldValue = 0; foreach (var oldValue in ensContext.OldValues) { var varName = $"Armada_Old{whichOldValue}"; var v = new MethodStackFrameUnaddressableLocalArmadaVariable(varName, oldValue.Type, oldValue, ArmadaVarType.ExternOld, meth.Name); ++whichOldValue; smst.AddVariable(prog, v); } }
public MethodInfo(Program i_prog, ArmadaSymbolTable i_symbols, Method i_method) { prog = i_prog; symbols = i_symbols; method = i_method; numPCs = 0; constraints = new Dictionary <ArmadaPC, EnablingConstraintCollector>(); returnPCs = new List <ArmadaPC>(); nonyieldingPCs = new HashSet <ArmadaPC>(); parsedBody = null; atomicCallsAndReturns = false; }
public MethodInfo AddMethod(ArmadaSymbolTable symbols, Method method) { if (methodPCInfo.ContainsKey(method.Name)) { AH.PrintError(prog, Token.NoToken, $"Attempt to add method {method.Name} twice to AllMethodsInfo"); return(methodPCInfo[method.Name]); } var info = new MethodInfo(prog, symbols, method); methodPCInfo[method.Name] = info; return(info); }
public void Extract(ArmadaSymbolTable symbols, DeclCollector declCollector, List <string> stepCtors) { if (!valid) { return; } ExtractInternal(symbols, declCollector, stepCtors, false); if (hasUndefinedBehaviorAvoidanceConstraint) { ExtractInternal(symbols, declCollector, stepCtors, true); } }
public static void Visit(ArmadaSymbolTable symbols, MethodInfo methodInfo, IPCNodeVisitor visitor) { var states = new List <PCNode>(); var steps = new List <StepDescriptor>(); var loopHeads = new HashSet <ArmadaPC>(); var branches = new List <bool>(); var rootNode = methodInfo.method.Body == null?GeneratePCStructureForMethodWithNoBody(symbols, methodInfo, loopHeads) : GeneratePCStructureForMethodWithBody(methodInfo, loopHeads); var visitedLoops = loopHeads.ToDictionary(h => h, h => - 1); rootNode.Visit(visitor, methodInfo.method.Name, states, steps, visitedLoops, branches); }
private bool GetLevelsAndStrategy() { foreach (var d in mProof.TopLevelDecls) { if (d is RefinementParametersDecl) { var refinement = (RefinementParametersDecl)d; if (mLow != null || mHigh != null) { AH.PrintError(prog, $"More than one 'refinement' declaration found in proof module {mProof.Name}"); return(false); } if (!LookupLevel(refinement.LowLevel, "low-level", out mLow)) { return(false); } if (!LookupLevel(refinement.HighLevel, "high-level", out mHigh)) { return(false); } } else if (d is StrategyDecl) { if (strategy != null) { AH.PrintError(prog, $"More than one strategy found in proof module {mProof.Name}"); return(false); } strategy = (StrategyDecl)d; } } if (mLow == null || mHigh == null) { AH.PrintError(prog, $"No 'refinement' declaration found in proof module {mProof.Name}"); return(false); } if (strategy == null) { AH.PrintError(prog, $"No strategy given in proof module {mProof.Name}"); return(false); } symbolsLow = mLow.ModuleDef.ArmadaSymbols; symbolsHigh = mHigh.ModuleDef.ArmadaSymbols; return(true); }
public AtomicSpec(ProofGenerationParams i_pgp, ArmadaSymbolTable i_symbols, string i_auxName, string i_prefix, bool i_low, string i_moduleName, string i_typeState, string i_specFunctions, string i_spec, string i_validStep, string i_getNextState) { pgp = i_pgp; symbols = i_symbols; auxName = i_auxName; prefix = i_prefix; low = i_low; moduleName = i_moduleName; typeState = i_typeState; specFunctions = i_specFunctions; spec = i_spec; validStep = i_validStep; getNextState = i_getNextState; }
private static PCNode GeneratePCStructureForMethodWithNoBody(ArmadaSymbolTable symbols, MethodInfo methodInfo, HashSet <ArmadaPC> loopHeads) { Method method = methodInfo.method; var startPC = new ArmadaPC(symbols, method.Name, 0); var midPC = new ArmadaPC(symbols, method.Name, 1); var endPC = new ArmadaPC(symbols, method.Name, 2); PCNode endNode = new ReturningPCNode(endPC); PCNode loopRestartNode = new LoopRestartPCNode(midPC); PCNode midNode = new WhilePCNode(midPC, method.externContinueNextRoutine, method.externEndNextRoutine, loopRestartNode, endNode); PCNode startNode = new NormalPCNode(startPC, method.externStartNextRoutine, midNode); loopHeads.Add(midPC); return(new StartingPCNode(startPC, startNode)); }
public void AddMethodInfo(Program prog, ClassDecl c, ArmadaSymbolTable symbols, Method meth, bool fromStructsModule, ArmadaStructs structs) { bool isExternal = (meth.Body is null || Attributes.Contains(meth.Attributes, "extern")); var smst = new ArmadaSingleMethodSymbolTable(meth, isExternal, fromStructsModule); foreach (var formal in meth.Ins) { var v = new MethodStackFrameUnaddressableLocalArmadaVariable(formal.Name, formal.Type, null, ArmadaVarType.Input, meth.Name); smst.AddVariable(prog, v); } foreach (var formal in meth.Outs) { var v = new MethodStackFrameUnaddressableLocalArmadaVariable(formal.Name, formal.Type, null, ArmadaVarType.Output, meth.Name); smst.AddVariable(prog, v); } ExtractLocalVariables(prog, meth.Body, meth.Name, smst, structs); if (isExternal && meth.Reads.Expressions != null) { var reads = meth.Reads.Expressions; for (int i = 0; i < reads.Count; ++i) { Expression read_expr = reads.ElementAt(i); var varName = $"Armada_Extern{i}"; var v = new MethodStackFrameUnaddressableLocalArmadaVariable(varName, read_expr.Type, null, ArmadaVarType.ExternRead, meth.Name); smst.AddVariable(prog, v); } } if (methodTable.ContainsKey(meth.Name)) { AH.PrintError(prog, $"Method {meth.Name} already defined"); } else { methodTable[meth.Name] = smst; } if (isExternal && meth.Body == null) { ExtractOldVariablesForBodylessMethod(prog, symbols, meth, smst); } }
public NextRoutine(Program i_prog, ArmadaSymbolTable i_symbols, NextType i_nextType, MethodInfo i_methodInfo, ArmadaStatement i_armadaStatement, Statement i_stmt, ArmadaPC i_startPC, ArmadaPC i_endPC, List <NextFormal> i_formals, string i_nameSuffix, bool i_undefinedBehavior, bool i_stopping) { prog = i_prog; symbols = i_symbols; nextType = i_nextType; methodInfo = i_methodInfo; armadaStatement = i_armadaStatement; stmt = i_stmt; startPC = i_startPC; endPC = i_endPC; formals = new List <NextFormal>(i_formals); nameSuffix = i_nameSuffix; undefinedBehavior = i_undefinedBehavior; stopping = i_stopping; }
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)"); } }
public void ParseMethodBody(ArmadaSymbolTable symbols) { var parse = new ParseInfo(prog, symbols, this); parsedBody = ArmadaStatement.ParseStatement(parse, method.Body); var startPC = GenerateOnePC(); returnPC = parsedBody.AssignPCs(startPC); ArmadaStatement.ComputeNonyieldingPCs(parsedBody, nonyieldingPCs); symbols.AssociateLabelWithPC("Start", startPC); symbols.AssociateLabelWithPC("End", returnPC); foreach (var statement in parsedBody) { statement.AssociateLabelsWithPCs(); statement.GenerateEnablingConstraints(); } }
public void ParseMethodBody(ArmadaSymbolTable symbols) { var context = new ParseContext(prog, symbols, this); parsedBody = ArmadaStatement.ParseStatement(context, method.Body); var startPC = GenerateOnePC(); var endPC = parsedBody.AssignPCs(prog, symbols, this, startPC); ArmadaStatement.CollectReturnPCs(parsedBody, returnPCs); ArmadaStatement.ComputeNonyieldingPCs(parsedBody, nonyieldingPCs); foreach (var statement in parsedBody) { if (statement is ArmadaAssumeStatement) { var s = (ArmadaAssumeStatement)statement; var assumePC = s.StartPC; if (!constraints.ContainsKey(assumePC)) { constraints[assumePC] = new EnablingConstraintCollector(prog); } s.AddEnablingConstraint(symbols, this, constraints[assumePC]); } } symbols.AssociateLabelWithPC("Start", startPC); symbols.AssociateLabelWithPC("End", endPC); foreach (var statement in parsedBody) { var stmt = statement.Stmt; if (stmt != null) { for (var lbl = stmt.Labels; lbl != null; lbl = lbl.Next) { if (lbl.Data != null && lbl.Data.Name != null) { symbols.AssociateLabelWithPC(lbl.Data.Name, statement.StartPC); } } } } }
public ArmadaPC() { symbols = null; methodName = null; instructionCount = 0; }
public virtual Type GetFlattenedType(ArmadaSymbolTable symbols, string moduleName = null) { return(symbols.FlattenType(ty, moduleName)); }
public ArmadaPC CloneWithNewSymbolTable(ArmadaSymbolTable newSymbols) { return(new ArmadaPC(newSymbols, methodName, instructionCount)); }
public NextFormal(string globallyUniqueVarName, string localVarName, Type varType, ArmadaSymbolTable symbols) { GloballyUniqueVarName = globallyUniqueVarName; LocalVarName = localVarName; VarType = symbols.FlattenType(varType).ToString(); }
public NextRoutine(Program i_prog, ArmadaSymbolTable i_symbols, NextType i_nextType, MethodInfo methodInfo, ArmadaStatement i_armadaStatement, Statement i_stmt, ArmadaPC i_pc, ArmadaPC i_endPC) { prog = i_prog; symbols = i_symbols; nextType = i_nextType; validStepBuilder = new PredicateBuilder(i_prog); crashAvoidanceBuilder = new PredicateBuilder(i_prog); getNextStateBuilder = new ExpressionBuilder(i_prog); method = methodInfo != null ? methodInfo.method : null; armadaStatement = i_armadaStatement; stmt = i_stmt; pc = i_pc; endPC = i_endPC; formals = new List <NextFormal>(); valid = true; s = ReserveVariableName("s", "Armada_TotalState"); tid = ReserveVariableName("tid", "Armada_ThreadHandle"); locv = null; // s.stop_reason.Armada_NotStopped? var stop_reason = AH.MakeExprDotName(s, "stop_reason", "Armada_StopReason"); var not_stopped = AH.MakeExprDotName(stop_reason, "Armada_NotStopped?", new BoolType()); AddConjunct(not_stopped); // tid in s.threads var threads = AH.MakeExprDotName(s, "threads", AH.MakeThreadsType()); var tid_in_threads = AH.MakeInExpr(tid, threads); AddConjunct(tid_in_threads); // var t := s.threads[tid]; t = AddVariableDeclaration("t", AH.MakeSeqSelectExpr(threads, tid, "Armada_Thread")); // var locv := Armada_GetThreadLocalView(s, tid); locv = AH.MakeApply2("Armada_GetThreadLocalView", s, tid, "Armada_SharedMemory"); locv = AddVariableDeclaration("locv", locv); if (pc != null) { var current_pc = AH.MakeExprDotName(t, "pc", "Armada_PC"); var pc_correct = AH.MakeEqExpr(current_pc, AH.MakeNameSegment(pc.ToString(), "Armada_PC")); AddConjunct(pc_correct); // t.top.Armada_StackFrame_{methodName}? var top = AH.MakeExprDotName(t, "top", "Armada_StackFrame"); var top_frame_correct = AH.MakeExprDotName(top, $"Armada_StackFrame_{pc.methodName}?", new BoolType()); AddConjunct(top_frame_correct); if (methodInfo != null) { var constraints = methodInfo.GetEnablingConstraintCollector(pc); if (constraints != null && !constraints.Empty) { var enabling_condition = AH.MakeApply2($"Armada_EnablingConditions_{pc}", s, tid, new BoolType()); AddConjunct(enabling_condition); } } } }
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; } }
public override Type GetFlattenedType(ArmadaSymbolTable symbols, string moduleName = null) { return(AH.ReferToType("Armada_Pointer")); }
public ArmadaPC(ArmadaSymbolTable i_symbols, string i_methodName, int i_instructionCount) { symbols = i_symbols; methodName = i_methodName; instructionCount = i_instructionCount; }
public void Extract(ModuleDefinition m, ArmadaSymbolTable symbols, List <MemberDecl> newDefaultClassDecls, List <DatatypeCtor> entryCtors, List <MatchCaseExpr> overallNextCases, List <MatchCaseExpr> validStepCases, List <MatchCaseExpr> crashAvoidanceCases, List <MatchCaseExpr> getNextStateCases) { if (!valid) { return; } var entryFormals = new List <Formal> { AH.MakeFormal("tid", "Armada_ThreadHandle") }; var commonFormals = new List <Formal> { AH.MakeFormal("s", "Armada_TotalState"), AH.MakeFormal("tid", "Armada_ThreadHandle") }; var overallNextFormals = new List <Formal> { AH.MakeFormal("s", "Armada_TotalState"), AH.MakeFormal("s'", "Armada_TotalState"), AH.MakeFormal("tid", "Armada_ThreadHandle") }; var caseArguments = new List <BoundVar> { AH.MakeBoundVar("tid", "Armada_ThreadHandle") }; var commonMatchBodyArguments = new List <Expression>() { AH.MakeNameSegment("s", "Armada_TotalState"), AH.MakeNameSegment("tid", "Armada_ThreadHandle") }; var overallNextMatchBodyArguments = new List <Expression>() { AH.MakeNameSegment("s", "Armada_TotalState"), AH.MakeNameSegment("s'", "Armada_TotalState"), AH.MakeNameSegment("tid", "Armada_ThreadHandle") }; foreach (var f in formals) { var flattened_type = symbols.FlattenType(f.VarType); commonFormals.Add(AH.MakeFormal(f.LocalVarName, flattened_type)); overallNextFormals.Add(AH.MakeFormal(f.LocalVarName, flattened_type)); entryFormals.Add(AH.MakeFormal(f.GloballyUniqueVarName, flattened_type)); caseArguments.Add(AH.MakeBoundVar(f.LocalVarName, flattened_type)); commonMatchBodyArguments.Add(AH.MakeNameSegment(f.LocalVarName, flattened_type)); overallNextMatchBodyArguments.Add(AH.MakeNameSegment(f.LocalVarName, flattened_type)); } var nameSuffix = NameSuffix; var entryName = $"Armada_TraceEntry_{nameSuffix}"; entryCtors.Add(AH.MakeDatatypeCtor(entryName, entryFormals)); var validStepFn = AH.MakeNameSegment($"Armada_ValidStep_{nameSuffix}", (Type)null); var validStepMatchBody = AH.SetExprType(new ApplySuffix(Token.NoToken, validStepFn, commonMatchBodyArguments), new BoolType()); validStepCases.Add(AH.MakeMatchCaseExpr(entryName, caseArguments, validStepMatchBody)); var validStepPredBody = validStepBuilder.Extract(); var validStepName = $"Armada_ValidStep_{nameSuffix}"; var validStepPred = AH.MakePredicate(validStepName, commonFormals, validStepPredBody); newDefaultClassDecls.Add(validStepPred); var crashAvoidanceFn = AH.MakeNameSegment($"Armada_UndefinedBehaviorAvoidance_{nameSuffix}", (Type)null); var crashAvoidanceMatchBody = AH.SetExprType(new ApplySuffix(Token.NoToken, crashAvoidanceFn, commonMatchBodyArguments), new BoolType()); crashAvoidanceCases.Add(AH.MakeMatchCaseExpr(entryName, caseArguments, crashAvoidanceMatchBody)); var crashAvoidanceName = $"Armada_UndefinedBehaviorAvoidance_{nameSuffix}"; var crashAvoidancePredBody = crashAvoidanceBuilder.Extract(); var crashAvoidancePred = AH.MakePredicateWithReq(crashAvoidanceName, commonFormals, validStepMatchBody, crashAvoidancePredBody); newDefaultClassDecls.Add(crashAvoidancePred); var getNextStateFn = AH.MakeNameSegment($"Armada_GetNextState_{nameSuffix}", (Type)null); var getNextStateMatchBody = AH.SetExprType(new ApplySuffix(Token.NoToken, getNextStateFn, commonMatchBodyArguments), "Armada_TotalState"); getNextStateCases.Add(AH.MakeMatchCaseExpr(entryName, caseArguments, getNextStateMatchBody)); var getNextStateName = $"Armada_GetNextState_{nameSuffix}"; var getNextStateFnBody = getNextStateBuilder.Extract(); var getNextStateReq = AH.MakeAndExpr(validStepMatchBody, crashAvoidanceMatchBody); var getNextStateFunc = AH.MakeFunctionWithReq(getNextStateName, commonFormals, getNextStateReq, getNextStateFnBody); newDefaultClassDecls.Add(getNextStateFunc); // predicate Armada_Next_{nameSuffix}(s:Armada_TotalState, s':Armada_TotalState, ...) { // && Armada_ValidStep_{nameSuffix}(s, ...) // && s' == if Armada_UndefinedBehaviorAvoidance(s, ...) then Armada_GetNextState(s, ...) // else s.(stop_reason := Armada_StopReasonUndefinedBehavior) // } var s_with_undefined_behavior = AH.MakeDatatypeUpdateExpr(s, "stop_reason", AH.MakeNameSegment("Armada_StopReasonUndefinedBehavior", "Armada_StopReason")); var target_s_prime = AH.MakeIfExpr(crashAvoidanceMatchBody, getNextStateMatchBody, s_with_undefined_behavior); var s_prime = AH.MakeNameSegment("s'", "Armada_TotalState"); var s_prime_correct = AH.MakeEqExpr(s_prime, target_s_prime); var overallNextBody = AH.MakeAndExpr(validStepMatchBody, s_prime_correct); var overallNextName = $"Armada_Next_{nameSuffix}"; var overallNextPred = AH.MakePredicate(overallNextName, overallNextFormals, overallNextBody); newDefaultClassDecls.Add(overallNextPred); var overallNextFn = AH.MakeNameSegment(overallNextName, (Type)null); var overallNextMatchBody = AH.SetExprType(new ApplySuffix(Token.NoToken, overallNextFn, overallNextMatchBodyArguments), new BoolType()); overallNextCases.Add(AH.MakeMatchCaseExpr(entryName, caseArguments, overallNextMatchBody)); }