Example #1
0
        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);
            }
        }
Example #2
0
 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;
 }
Example #3
0
        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);
        }
Example #4
0
        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);
            }
        }
Example #5
0
        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);
        }
Example #6
0
        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);
        }
Example #7
0
 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;
 }
Example #8
0
        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));
        }
Example #9
0
        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);
            }
        }
Example #10
0
 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;
 }
Example #11
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)");
            }
        }
Example #12
0
        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();
            }
        }
Example #13
0
        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);
                        }
                    }
                }
            }
        }
Example #14
0
 public ArmadaPC()
 {
     symbols          = null;
     methodName       = null;
     instructionCount = 0;
 }
Example #15
0
 public virtual Type GetFlattenedType(ArmadaSymbolTable symbols, string moduleName = null)
 {
     return(symbols.FlattenType(ty, moduleName));
 }
Example #16
0
 public ArmadaPC CloneWithNewSymbolTable(ArmadaSymbolTable newSymbols)
 {
     return(new ArmadaPC(newSymbols, methodName, instructionCount));
 }
Example #17
0
 public NextFormal(string globallyUniqueVarName, string localVarName, Type varType, ArmadaSymbolTable symbols)
 {
     GloballyUniqueVarName = globallyUniqueVarName;
     LocalVarName          = localVarName;
     VarType = symbols.FlattenType(varType).ToString();
 }
Example #18
0
        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);
                    }
                }
            }
        }
Example #19
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;
            }
        }
Example #20
0
 public override Type GetFlattenedType(ArmadaSymbolTable symbols, string moduleName = null)
 {
     return(AH.ReferToType("Armada_Pointer"));
 }
Example #21
0
 public ArmadaPC(ArmadaSymbolTable i_symbols, string i_methodName, int i_instructionCount)
 {
     symbols          = i_symbols;
     methodName       = i_methodName;
     instructionCount = i_instructionCount;
 }
Example #22
0
        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));
        }