//return first reachable blocks from block in afterPassificationCfg, which are non-empty and contained in finalCfg
        private static IEnumerable <Block> GetNonEmptyReachableSuccessors(
            Block afterPassiveBlock,
            CFGRepr afterPassificationCfg,
            CFGRepr finalCfg,
            IDictionary <Block, Block> afterPassiveToFinalBlock)
        {
            //block is unreachable after peephole
            var nonEmptySuccessors = new HashSet <Block>();

            if (afterPassificationCfg.NumOfSuccessors(afterPassiveBlock) > 0)
            {
                //find first reachable blocks that are not empty
                var toVisit = new Queue <Block>();
                toVisit.Enqueue(afterPassiveBlock);
                while (toVisit.Count > 0)
                {
                    var curBlock = toVisit.Dequeue();

                    if (curBlock.Cmds.Count != 0 && finalCfg.ContainsBlock(afterPassiveToFinalBlock[curBlock]))
                    {
                        nonEmptySuccessors.Add(curBlock);
                    }
                    else
                    {
                        foreach (var succ in afterPassificationCfg.GetSuccessorBlocks(curBlock))
                        {
                            toVisit.Enqueue(succ);
                        }
                    }
                }
            }

            return(nonEmptySuccessors);
        }
Exemple #2
0
        /// <summary>
        /// Provide source CFG for passification phase
        /// </summary>
        public static void BeforePassification(Implementation impl)
        {
            if (CommandLineOptions.Clo.GenerateIsaProgNoProofs)
            {
                return;
            }

            var config = new CFGReprConfigBuilder().SetIsAcyclic(true).SetBlockCopy(true).SetDesugarCalls(true)
                         .Build();

            beforePassificationCfg = CFGReprTransformer.GetCfgRepresentation(
                impl,
                config,
                out beforePassiveOrigBlock,
                out var newVarsFromDesugaring
                );
            cfgToDagHintManager.AfterDagToOrig = beforePassiveOrigBlock;
            beforePassiveData        = MethodDataFromImpl(impl, boogieGlobalData, newVarsFromDesugaring);
            passificationHintManager = new PassificationHintManager(beforePassiveOrigBlock);
            initialVarMapping        = new Dictionary <Block, IDictionary <Variable, Expr> >();

            // compute mapping between copied blocks (before dag -> after dag)
            var origToAfterDag = beforePassiveOrigBlock.InverseDict();

            beforeDagAfterDagBlock = DictionaryComposition(beforeDagOrigBlock, origToAfterDag);
        }
        public PassificationLemmaManager(
            CFGRepr cfg,
            IDictionary <Block, Block> origToPassiveBlock,
            IProgramAccessor programAccessor,
            IProgramAccessor passiveProgramAccessor,
            Tuple <string, string> varContextNonPassivePassive,
            StateRelationData oldStateRelationData,
            PassiveRelationGen relationGen,
            IVariableTranslationFactory varTranslationFactory,
            IVariableTranslationFactory passiveTranslationFactory)
        {
            this.cfg = cfg;
            this.origToPassiveBlock     = origToPassiveBlock;
            this.programAccessor        = programAccessor;
            this.passiveProgramAccessor = passiveProgramAccessor;
            _oldStateRelationData       = oldStateRelationData;
            _relationGen          = relationGen;
            initState             = IsaBoogieTerm.Normal(normalInitState);
            varTranslation        = varTranslationFactory.CreateTranslation().VarTranslation;
            passiveVarTranslation = passiveTranslationFactory.CreateTranslation().VarTranslation;
            //separate unique namer for function interpretations (since they already have a name in uniqueNamer): possible clashes

            boogieContext = new BoogieContextIsa(
                IsaCommonTerms.TermIdentFromName("A"),
                IsaCommonTerms.TermIdentFromName("M"),
                IsaCommonTerms.TermIdentFromName(varContextNonPassivePassive.Item1),
                IsaCommonTerms.TermIdentFromName("\\<Gamma>"),
                IsaCommonTerms.TermIdentFromName("\\<Omega>")
                );
            passiveVarContext = IsaCommonTerms.TermIdentFromName(varContextNonPassivePassive.Item2);
        }
 public static bool CheckVersionMap(
     IDictionary <Variable, int> versionMap,
     PassiveRelationGen relationGen,
     CFGRepr beforePassiveBlocks,
     IDictionary <Block, Block> beforeToPassiveBlocks
     )
 {
     return(GlobalVersion.CheckIsGlobal(beforeToPassiveBlocks.Values.ToList(), relationGen, versionMap,
                                        relationGen.LiveVarsBeforeBlock(beforePassiveBlocks.entry)));
 }
Exemple #5
0
        /// <summary>
        /// Provide source CFG for CFG-to-DAG phase
        /// </summary>
        public static void BeforeCFGToDAG(Implementation impl)
        {
            var config = new CFGReprConfigBuilder().SetIsAcyclic(false).SetBlockCopy(true).SetDesugarCalls(true)
                         .Build();

            beforeDagCfg = CFGReprTransformer.GetCfgRepresentation(impl,
                                                                   config,
                                                                   out beforeDagOrigBlock,
                                                                   out var newVarsFromDesugaring);
            beforeDagData       = MethodDataFromImpl(impl, boogieGlobalData, newVarsFromDesugaring);
            uniqueExitBlockOrig = null;
        }
Exemple #6
0
        /// <summary>
        /// Provide target CFG for passification phase, construct global version map.
        /// </summary>
        /// <param name="impl">source CFG after passification phase</param>
        /// <exception cref="ProofGenUnexpectedStateException">thrown if global version map is incorrect
        ///  (should never happen). </exception>
        public static void AfterPassificationCheckGlobalMap(Implementation impl)
        {
            afterPassificationImpl = impl;

            if (CommandLineOptions.Clo.GenerateIsaProgNoProofs)
            {
                return;
            }

            finalProgData = MethodDataFromImpl(impl, boogieGlobalData);
            var config = new CFGReprConfigBuilder().SetIsAcyclic(true).SetBlockCopy(true).SetDesugarCalls(false)
                         .SetDeepCopyPredCmd(TypeCheckBeforeVcMaybeRewritesCmd).Build();

            afterPassificationCfg =
                CFGReprTransformer.GetCfgRepresentation(impl, config, out afterPassificationToOrigBlock, out _);

            var passiveBlocks = new List <Block>(afterPassificationCfg.GetBlocksBackwards());

            var origToAfterPassificationBlock = afterPassificationToOrigBlock.InverseDict();

            beforePassiveToAfterPassiveBlock =
                DictionaryComposition(beforePassiveOrigBlock, origToAfterPassificationBlock);

            var globalVersion = new GlobalVersion();

            passiveRelationGen = new PassiveRelationGen(
                beforePassificationCfg,
                passificationHintManager,
                initialVarMapping,
                beforePassiveOrigBlock,
                beforePassiveToAfterPassiveBlock,
                ProofGenLiveVarAnalysis.ComputeLiveVariables(beforePassificationCfg, beforePassiveData)
                );

            //all variables before passification are the initial versions and already constrained
            globalVersionMap = globalVersion.GlobalVersionMap(
                passiveRelationGen,
                beforePassiveData.AllVariables(),
                afterPassificationCfg.entry,
                passiveBlocks);

            //Console.WriteLine("Version map: " + string.Join(Environment.NewLine, globalVersionMap));

            var versionMapCorrect =
                GlobalVersionChecker.CheckVersionMap(globalVersionMap, passiveRelationGen, beforePassificationCfg,
                                                     beforePassiveToAfterPassiveBlock);

            if (!versionMapCorrect)
            {
                throw new ProofGenUnexpectedStateException(typeof(ProofGenerationLayer), "Incorrect version map");
            }
        }
        private static IDictionary <Block, OuterDecl> GenerateCfgLemmas(
            CFGRepr afterPassificationCfg,
            CFGRepr finalCfg,
            IDictionary <Block, Block> afterPassiveToFinalBlock,
            HashSet <Block> reachableBlocks,
            IDictionary <Block, IList <OuterDecl> > lemmaDecls,
            VcPhaseLemmaManager vcPhaseLemmaManager,
            Term cfgTerm,
            IsaUniqueNamer lemmaNamer)
        {
            var blockToLemmaDecls = new Dictionary <Block, OuterDecl>();

            foreach (var bAfterPassive in afterPassificationCfg.GetBlocksBackwards())
            {
                IEnumerable <Block> finalCfgSuccessors;
                var isContainedInFinalCfg = afterPassiveToFinalBlock.TryGetValue(bAfterPassive, out var bFinal);
                if (!isContainedInFinalCfg)
                {
                    if (reachableBlocks.Contains(bAfterPassive))
                    {
                        finalCfgSuccessors =
                            GetNonEmptyReachableSuccessors(bAfterPassive, afterPassificationCfg, finalCfg,
                                                           afterPassiveToFinalBlock).Select(b => afterPassiveToFinalBlock[b]);
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    finalCfgSuccessors = finalCfg.GetSuccessorBlocks(bFinal);
                }

                var lemma = vcPhaseLemmaManager.GenerateCfgLemma(
                    bAfterPassive,
                    bFinal,
                    isContainedInFinalCfg,
                    afterPassificationCfg.GetSuccessorBlocks(bAfterPassive),
                    finalCfgSuccessors,
                    cfgTerm,
                    b => "cfg_" + lemmaNamer.GetName(b, b.Label),
                    (LemmaDecl)lemmaDecls[bAfterPassive].Last());
                blockToLemmaDecls.Add(bAfterPassive, lemma);
            }

            return(blockToLemmaDecls);
        }
 public PassiveRelationGen(
     CFGRepr beforePassiveCfg,
     PassificationHintManager hintManager,
     IDictionary <Block, IDictionary <Variable, Expr> > origToInitialVarMapping,
     IDictionary <Block, Block> nonPassiveToOrig,
     IDictionary <Block, Block> nonPassiveToPassive,
     IDictionary <Block, IEnumerable <Variable> > liveVarsBefore)
 {
     this.beforePassiveCfg    = beforePassiveCfg;
     this.hintManager         = hintManager;
     _origToInitialVarMapping = origToInitialVarMapping;
     this.nonPassiveToOrig    = nonPassiveToOrig;
     this.nonPassiveToPassive = nonPassiveToPassive;
     passiveToNonPassive      = nonPassiveToPassive.InverseDict();
     this.liveVarsBefore      = liveVarsBefore;
 }
        private ContextElem LemmaContext(
            CFGRepr cfg,
            Term vcAssm
            )
        {
            var multiRed = IsaBoogieTerm.RedCFGMulti(
                BoogieContextIsa.CreateWithNewVarContext(
                    boogieContext,
                    new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl())
                    ),
                programAccessor.CfgDecl(),
                IsaBoogieTerm.CFGConfigNode(new NatConst(cfg.GetUniqueIntLabel(cfg.entry)),
                                            IsaBoogieTerm.Normal(normalInitState)),
                IsaBoogieTerm.CFGConfig(finalNodeOrReturn, finalState)
                );
            var closedAssm        = EndToEndAssumptions.ClosednessAssumption(boogieContext.absValTyMap);
            var nonEmptyTypesAssm = EndToEndAssumptions.NonEmptyTypesAssumption(boogieContext.absValTyMap);
            var finterpAssm       = IsaBoogieTerm.FunInterpWf(boogieContext.absValTyMap, programAccessor.FunctionsDecl(),
                                                              boogieContext.funContext);
            var absValType = new VarType("a");
            //need to explicitly give type for normal state, otherwise Isabelle won't know that the abstract value type is the same as used in the VC
            var axiomAssm = EndToEndAssumptions.AxiomAssumption(boogieContext, programAccessor,
                                                                new TermWithExplicitType(normalInitState, IsaBoogieType.NormalStateType(absValType)));
            var presAssm =
                IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState, programAccessor.PreconditionsDecl());
            var localsAssm = EndToEndAssumptions.LocalStateAssumption(boogieContext,
                                                                      IsaCommonTerms.Snd(boogieContext.varContext), normalInitState);
            var globalsAssm = EndToEndAssumptions.GlobalStateAssumption(boogieContext,
                                                                        IsaCommonTerms.Fst(boogieContext.varContext), normalInitState);
            var oldGlobalStateAssm = EndToEndAssumptions.OldGlobalStateAssumption(normalInitState);
            var binderEmptyAssm    = EndToEndAssumptions.BinderStateEmpty(normalInitState);

            return
                (ContextElem.CreateWithAssumptions(
                     new List <Term>
            {
                multiRed, vcAssm, closedAssm, nonEmptyTypesAssm, finterpAssm, axiomAssm,
                presAssm, localsAssm, globalsAssm, oldGlobalStateAssm, binderEmptyAssm
            },
                     new List <string>
            {
                redAssmName, vcAssmName, closedAssmName, nonEmptyTypesAssmName, finterpAssmName, axiomAssmName,
                preconditionsAssmName, paramsLocalsAssmName, constsGlobalsAssmName, oldGlobalAssmName,
                binderEmptyAssmName
            }
                     ));
        }
Exemple #10
0
        /// <summary>
        /// Provide target CFG after unreachable blocks are pruned (after passification).
        /// </summary>
        public static void AfterUnreachablePruning(Implementation impl)
        {
            if (CommandLineOptions.Clo.GenerateIsaProgNoProofs)
            {
                return;
            }

            var config = new CFGReprConfigBuilder().SetIsAcyclic(true).SetBlockCopy(true).SetDesugarCalls(false)
                         .SetDeepCopyPredCmd(TypeCheckBeforeVcMaybeRewritesCmd).Build();

            afterUnreachablePruningCfg =
                CFGReprTransformer.GetCfgRepresentation(impl, config, out var afterUnreachableToOrigBlock, out _);

            var origToAfterUnreachableBlock = afterUnreachableToOrigBlock.InverseDict();

            afterPassificationToAfterUnreachableBlock =
                DictionaryComposition(afterPassificationToOrigBlock, origToAfterUnreachableBlock);
        }
        public IEnumerable <OuterDecl> EndToEndProof(
            string entryCfgLemma,
            string boogieToVcLemma,
            Term vcAssm,
            IProgramAccessor programAccessor,
            IProgramAccessor passiveProgramAccessor,
            Tuple <string, string> varContextNonPassivePassive,
            StateRelationData oldRelationData,
            CFGRepr cfg,
            IEnumerable <Variable> liveEntryVars,
            IVariableTranslation <Variable> varTranslation)
        {
            this.entryCfgLemma          = entryCfgLemma;
            this.boogieToVcLemma        = boogieToVcLemma;
            this.vcAssm                 = vcAssm;
            this.programAccessor        = programAccessor;
            this.passiveProgramAccessor = passiveProgramAccessor;
            boogieContext               = new BoogieContextIsa(
                IsaCommonTerms.TermIdentFromName("A"),
                IsaCommonTerms.TermIdentFromName("M"),
                IsaCommonTerms.TermIdentFromName(varContextNonPassivePassive.Item1),
                IsaCommonTerms.TermIdentFromName("\\<Gamma>"),
                IsaCommonTerms.EmptyList
                );
            passiveVarContext    = IsaCommonTerms.TermIdentFromName(varContextNonPassivePassive.Item2);
            this.oldRelationData = oldRelationData;
            this.cfg             = cfg;
            this.liveEntryVars   = liveEntryVars;
            this.varTranslation  = varTranslation;

            var locale = new LocaleDecl("glue_proof",
                                        Context(),
                                        GenerateLemma()
                                        );

            return(new List <OuterDecl>
            {
                locale
            });
        }
Exemple #12
0
        //if blockToNewVars is non-null, then the mapped variables are universally quantified for the corresponding block definition
        public IDictionary <Block, DefDecl> IsaDefsFromVC(IDictionary <Block, VCExpr> blockToVC,
                                                          IDictionary <Block, IList <VCExprVar> > blockToActiveVars,
                                                          CFGRepr cfg,
                                                          IDictionary <Block, IList <VCExprVar> > blockToNewVars = null)
        {
            Contract.Ensures(Contract.Result <IDictionary <Block, DefDecl> >().Count == cfg.NumOfBlocks());

            IDictionary <Block, DefDecl> blockToDefVC = new Dictionary <Block, DefDecl>();

            var vcExprIsaVisitor = new VCExprToIsaTranslator(uniqueNamer, blockToDefVC, blockToActiveVars);

            foreach (var block in cfg.GetBlocksBackwards())
            {
                // might be more efficient to hand over this:
                // IEnumerable<Tuple<Block, DefDecl>> successorDefs = cfg.outgoingBlocks[block].Select(b => new Tuple<Block, DefDecl>(b, blockToDefVC[b]));

                var term = vcExprIsaVisitor.Translate(blockToVC[block]);

                if (blockToNewVars != null && blockToNewVars.TryGetValue(block, out var newVars) && newVars != null &&
                    newVars.Any())
                {
                    IList <Identifier> boundVars = newVars
                                                   .Select(v => (Identifier) new SimpleIdentifier(uniqueNamer.GetName(v, v.Name))).ToList();
                    IList <TypeIsa> boundVarsTypes =
                        newVars.Select(v => pureTyIsaTransformer.Translate(v.Type)).ToList();

                    term = new TermQuantifier(TermQuantifier.QuantifierKind.ALL, boundVars, boundVarsTypes, term);
                }

                IList <Term> args = blockToActiveVars[block].Select(v => vcExprIsaVisitor.Translate(v)).ToList();

                var def = new DefDecl(GetVCDefName(block), new Tuple <IList <Term>, Term>(args, term));

                Contract.Assert(!blockToDefVC.ContainsKey(block));
                blockToDefVC.Add(block, def);
            }

            return(blockToDefVC);
        }
        private static HashSet <Block> ReachableBlocks(CFGRepr cfg)
        {
            var reachableBlocks = new HashSet <Block>();
            var queue           = new Queue <Block>();

            reachableBlocks.Add(cfg.entry);
            queue.Enqueue(cfg.entry);

            while (queue.TryDequeue(out var b))
            {
                if (!LemmaHelper.FinalStateIsMagic(b))
                {
                    //b's successors are not trivially unreachable
                    var successors = cfg.GetSuccessorBlocks(b);
                    foreach (var suc in successors)
                    {
                        reachableBlocks.Add(suc);
                        queue.Enqueue(suc);
                    }
                }
            }

            return(reachableBlocks);
        }
Exemple #14
0
        /// <summary>
        ///     Returns a mapping from blocks to corresponding verification conditions
        ///     Assumes that the expression defines a separate let binding for each block, where the name of the variable is given
        ///     by
        ///     "blockName_correct"
        /// </summary>
        public static IDictionary <Block, VCExpr> BlockToVCMapping(VCExprLet letExpr, CFGRepr cfg)
        {
            var blockToVC = new Dictionary <Block, VCExpr>();

            foreach (var binding in letExpr)
            {
                var predictionSuccess = PredictBlockName(binding.V.Name, out var predictedBlockName);
                if (predictionSuccess)
                {
                    try
                    {
                        var block = cfg.GetBlocksForwards().Single(b => b.Label.Equals(predictedBlockName));
                        blockToVC.Add(block, binding.E);
                    }
                    catch (Exception e)
                    {
                        throw new ProofGenUnexpectedStateException(typeof(VCBlockExtractor), e.Message);
                    }
                }
                else
                {
                    throw new ProofGenUnexpectedStateException(typeof(VCBlockExtractor),
                                                               "let binding does not correspond to block");
                }
            }

            if (blockToVC.Count != cfg.NumOfBlocks())
            {
                throw new ProofGenUnexpectedStateException(typeof(VCBlockExtractor),
                                                           "could not find let binding for all blocks");
            }

            return(blockToVC);
        }
        public IEnumerable <OuterDecl> EndToEndProof(
            string entryCfgLemma,
            string passificationEndToEndLemma,
            Term vcAssm,
            IProgramAccessor programAccessor,
            CFGRepr cfg)
        {
            this.programAccessor = programAccessor;
            boogieContext        = new BoogieContextIsa(
                IsaCommonTerms.TermIdentFromName("A"),
                IsaCommonTerms.TermIdentFromName("M"),
                IsaCommonTerms.TermIdentFromName(varContextName),
                IsaCommonTerms.TermIdentFromName("\\<Gamma>"),
                IsaCommonTerms.EmptyList
                );

            var abbrev = new AbbreviationDecl(
                varContextName,
                new Tuple <IList <Term>, Term>(new List <Term>(),
                                               new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl()))
                );
            var result = new List <OuterDecl> {
                abbrev
            };

            var kStepRed = IsaBoogieTerm.RedCFGKStep(
                BoogieContextIsa.CreateWithNewVarContext(
                    boogieContext,
                    new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl())
                    ),
                programAccessor.CfgDecl(),
                IsaBoogieTerm.CFGConfigNode(new NatConst(cfg.GetUniqueIntLabel(cfg.entry)),
                                            IsaBoogieTerm.Normal(normalInitState)),
                IsaCommonTerms.TermIdentFromName("j"),
                IsaBoogieTerm.CFGConfig(finalNodeOrReturn, finalState)
                );

            var proofSb = new StringBuilder();

            proofSb.AppendLine("proof -");
            proofSb.AppendLine("from " + redAssmName + " obtain j where Aux:" + "\"" + kStepRed + "\"");
            proofSb.AppendLine("by (meson rtranclp_imp_relpowp)");
            proofSb.AppendLine("show ?thesis");
            proofSb.AppendLine(ProofUtil.Apply("rule " + entryCfgLemma));
            //TODO: don't hardcode this
            proofSb.AppendLine("unfolding cfg_to_dag_lemmas_def");
            proofSb.AppendLine(ProofUtil.Apply("rule " + finterpAssmName));
            proofSb.AppendLine("apply (rule Aux)");
            proofSb.AppendLine("apply (rule dag_lemma_assms_same)");
            proofSb.AppendLine("unfolding state_well_typed_def");
            proofSb.AppendLine("apply (intro conjI)");
            proofSb.AppendLine("using " + paramsLocalsAssmName + " apply simp");
            proofSb.AppendLine("using " + constsGlobalsAssmName + " apply simp");
            proofSb.AppendLine("using " + constsGlobalsAssmName + " " + oldGlobalAssmName + " apply simp");
            proofSb.AppendLine("using " + binderEmptyAssmName + " apply simp");
            proofSb.AppendLine(ProofUtil.Apply("rule " + passificationEndToEndLemma));
            //TODO: don't hardcode this
            proofSb.AppendLine("unfolding glue_proof_def");
            proofSb.AppendLine("apply (intro conjI)");
            proofSb.AppendLine("apply assumption");
            proofSb.AppendLine("using " + vcAssmName + " apply simp");
            proofSb.AppendLine("using " + closedAssmName + " apply simp");
            proofSb.AppendLine("using " + nonEmptyTypesAssmName + " apply simp");
            proofSb.AppendLine(ProofUtil.Apply("rule " + finterpAssmName));
            proofSb.AppendLine("using " + axiomAssmName + " apply simp");
            proofSb.AppendLine("using " + paramsLocalsAssmName + " apply simp");
            proofSb.AppendLine("using " + constsGlobalsAssmName + " apply simp");
            proofSb.AppendLine("using " + binderEmptyAssmName + " apply simp");
            proofSb.AppendLine("using " + oldGlobalAssmName + " apply simp");
            proofSb.AppendLine("using " + preconditionsAssmName + " apply simp");
            proofSb.AppendLine("done");
            proofSb.AppendLine("qed");

            var helperLemmaName = "end_to_end_theorem_aux";

            var helperLemma =
                new LemmaDecl(
                    helperLemmaName,
                    LemmaContext(cfg, vcAssm),
                    CfgToDagLemmaManager.CfgLemmaConclusion(boogieContext, programAccessor.PostconditionsDecl(),
                                                            finalNodeOrReturn, finalState),
                    new Proof(new List <string> {
                proofSb.ToString()
            })
                    );

            result.Add(helperLemma);
            //transform end to end theorem to a compact representation

            var endToEndLemma =
                new LemmaDecl(
                    "end_to_end_theorem",
                    ContextElem.CreateWithAssumptions(new List <Term> {
                vcAssm
            }, new List <string> {
                "VC"
            }),
                    ProcedureIsCorrect(
                        programAccessor.FunctionsDecl(),
                        IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()),
                        IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()),
                        programAccessor.AxiomsDecl(),
                        programAccessor.ProcDecl()),
                    new Proof(
                        new List <string>
            {
                ProofUtil.Apply(ProofUtil.Rule(ProofUtil.OF("end_to_end_util", helperLemmaName))),
                "apply assumption " + "using VC apply simp " + " apply assumption+",
                ProofUtil.By("simp_all add: exprs_to_only_checked_spec_1 exprs_to_only_checked_spec_2 " +
                             programAccessor.ProcDeclName() + "_def " + programAccessor.CfgDeclName() + "_def")
            }
                        ));

            result.Add(endToEndLemma);
            return(result);
        }
Exemple #16
0
        public static Theory PassificationProof(
            string theoryName,
            string boogieToVcTheoryName,
            bool generateEndToEndLemma,
            LemmaDecl boogieToVcLemma,
            Term vcAssm,
            CFGRepr beforePassificationCfg,
            IDictionary <Block, Block> nonPassiveToPassiveBlock,
            PassiveRelationGen relationGen,
            IProgramAccessor beforePassiveProgAccess,
            IProgramAccessor passiveProgAccess,
            BoogieMethodData beforePassiveData,
            IVariableTranslationFactory beforePassiveFactory,
            IVariableTranslationFactory passiveFactory)
        {
            var varContextName              = "\\<Lambda>1";
            var passiveVarContextName       = "\\<Lambda>2";
            var varContextNonPassivePassive = Tuple.Create(varContextName, passiveVarContextName);

            var oldGlobalVars   = GetOldGlobalVariables(beforePassificationCfg);
            var oldRelationData =
                OldRelation(
                    oldGlobalVars,
                    beforePassiveFactory.CreateTranslation().VarTranslation,
                    out var oldRelListDecl);

            var passificationProofDecls = new List <OuterDecl>();

            passificationProofDecls.AddRange(oldRelListDecl);
            passificationProofDecls.AddRange(oldRelationData.VarToLookupLemma.Values);
            if (oldRelationData.VarToLookupLemma.Any())
            {
                passificationProofDecls.Add(new LemmasDecl(allOldLookupLemmasName,
                                                           oldRelationData.VarToLookupLemma.Values.Select(lemma => lemma.Name).ToList()));
            }

            var beforePassiveLemmaManager = new PassificationLemmaManager(
                beforePassificationCfg,
                nonPassiveToPassiveBlock,
                beforePassiveProgAccess,
                passiveProgAccess,
                varContextNonPassivePassive,
                oldRelationData,
                relationGen,
                beforePassiveFactory,
                passiveFactory
                );

            var lemmaNamer = new IsaUniqueNamer();

            var varContextAbbrev = new AbbreviationDecl(
                varContextName,
                new Tuple <IList <Term>, Term>(new List <Term>(), beforePassiveProgAccess.VarContext())
                );

            var passiveVarContextAbbrev = new AbbreviationDecl(
                passiveVarContextName,
                new Tuple <IList <Term>, Term>(new List <Term>(), passiveProgAccess.VarContext())
                );

            passificationProofDecls.Add(varContextAbbrev);
            passificationProofDecls.Add(passiveVarContextAbbrev);

            passificationProofDecls.AddRange(beforePassiveLemmaManager.Prelude());

            var cfgLemmas = new List <OuterDecl>();

            foreach (var block in beforePassificationCfg.GetBlocksBackwards())
            {
                var localAndCfgLemma =
                    beforePassiveLemmaManager.GenerateBlockLemma(
                        block,
                        GetLemmaName(block, lemmaNamer),
                        b => GetCfgLemmaName(b, lemmaNamer));
                passificationProofDecls.Add(localAndCfgLemma.Item1);
                cfgLemmas.Add(localAndCfgLemma.Item2);
            }

            //add cfg lemmas at the end
            passificationProofDecls.AddRange(cfgLemmas);

            if (generateEndToEndLemma)
            {
                var endToEnd = new PassificationEndToEnd();

                passificationProofDecls.AddRange(endToEnd.EndToEndProof(
                                                     GetCfgLemmaName(beforePassificationCfg.entry, lemmaNamer),
                                                     boogieToVcTheoryName + "." + boogieToVcLemma.Name,
                                                     vcAssm,
                                                     beforePassiveProgAccess,
                                                     passiveProgAccess,
                                                     varContextNonPassivePassive,
                                                     oldRelationData,
                                                     beforePassificationCfg,
                                                     relationGen.LiveVarsBeforeBlock(beforePassificationCfg.entry),
                                                     passiveFactory.CreateTranslation().VarTranslation
                                                     ));
            }

            var imports = new List <string>
            {
                "Boogie_Lang.Semantics", "Boogie_Lang.Util", beforePassiveProgAccess.TheoryName(),
                passiveProgAccess.TheoryName(), "Boogie_Lang.PassificationML",
                boogieToVcTheoryName
            };

            if (generateEndToEndLemma)
            {
                imports.Add("Boogie_Lang.PassificationEndToEnd");
            }

            return(new Theory(theoryName, imports, passificationProofDecls));
        }
        //return information at beginning of each block and store information at end of each block in out parameter
        //only store information if it is live
        public static IDictionary <Block, IDictionary <Variable, Expr> > ConstantVariableInformation(CFGRepr cfg,
                                                                                                     out IDictionary <Block, IDictionary <Variable, Expr> > constantExit)
        {
            var constantEntry = new Dictionary <Block, IDictionary <Variable, Expr> >();

            constantExit = new Dictionary <Block, IDictionary <Variable, Expr> >();
            foreach (var b in cfg.GetBlocksForwards())
            {
                var bEntry = constantEntry.ContainsKey(b) ? constantEntry[b] : null;
                var bExit  = ConstantExit(b, bEntry);
                constantExit.Add(b, bExit);
                foreach (var bSucc in cfg.GetSuccessorBlocks(b))
                {
                    //propagate constant information
                    if (constantEntry.TryGetValue(bSucc, out var succEntry))
                    {
                        //bSucc has multiple predecessors --> consolidate constant information
                        constantEntry[bSucc] = Consolidate(bExit, succEntry);
                    }
                    else
                    {
                        constantEntry.Add(bSucc, bExit);
                    }
                }
            }

            return(constantEntry);
        }
Exemple #18
0
        public IDictionary <Block, ISet <NamedDeclaration> > GetActiveDeclsPerBlock(IDictionary <Block, VCExpr> blockToVC,
                                                                                    IVCVarFunTranslator translator, CFGRepr cfg, out IDictionary <Block, ISet <Variable> > blockToNewVars)
        {
            var blockToDecls = new Dictionary <Block, ISet <NamedDeclaration> >();

            var declCollector = new VCExprDeclCollector();

            foreach (var b in cfg.GetBlocksBackwards())
            {
                var bDecls = declCollector.CollectNamedDeclarations(blockToVC[b], translator);
                foreach (var b_succ in cfg.GetSuccessorBlocks(b))
                {
                    //flattening
                    foreach (var sucDecl in blockToDecls[b_succ])
                    {
                        bDecls.Add(sucDecl);
                    }
                }

                blockToDecls[b] = bDecls;
            }

            blockToNewVars = null;

            return(blockToDecls);
        }
        public static Theory ProgramToVcProof(
            string theoryName,
            bool generateEndToEndProof,
            CFGRepr finalCfg,
            CFGRepr afterPassificationCfg,
            IDictionary <Block, Block> afterPassiveToFinalBlock,
            IDictionary <Block, Block> afterPassiveToOrigBlock,
            IProgramAccessor passiveProgAccess,
            IProgramAccessor beforePassiveProgAccess,
            BoogieMethodData methodData,
            ProgramVcProofData vcProofData,
            IVariableTranslationFactory varFactory,
            TypePremiseEraserFactory eraserFactory,
            VCExpressionGenerator gen,
            out Term vcAssm,
            out LemmaDecl endToEndLemma)
        {
            var lemmaNamer          = new IsaUniqueNamer();
            var passiveLemmaManager = new VcPhaseLemmaManager(
                vcProofData.VcBoogieInfo.VcInst,
                methodData,
                vcProofData.VcFunctions,
                passiveProgAccess.BlockInfo(),
                varFactory);

            var afterPassiveReachableBlocks = ReachableBlocks(afterPassificationCfg);

            var finalProgramLemmas =
                GenerateVCLemmas(afterPassificationCfg, finalCfg, afterPassiveToFinalBlock, afterPassiveToOrigBlock,
                                 afterPassiveReachableBlocks, passiveLemmaManager, vcProofData.VcHintManager, lemmaNamer);
            var cfgProgramLemmas =
                GenerateCfgLemmas(afterPassificationCfg, finalCfg, afterPassiveToFinalBlock,
                                  afterPassiveReachableBlocks, finalProgramLemmas, passiveLemmaManager, passiveProgAccess.CfgDecl(),
                                  lemmaNamer);

            var afterPassificationDecls = new List <OuterDecl>();

            foreach (var v in finalProgramLemmas.Values)
            {
                afterPassificationDecls.AddRange(v);
            }
            afterPassificationDecls.AddRange(cfgProgramLemmas.Values);

            var afterPassificationLocale =
                GenerateLocale("passification", passiveLemmaManager, afterPassificationDecls);

            var passiveOuterDecls = new List <OuterDecl> {
                vcProofData.VcLocale
            };

            passiveOuterDecls.Add(afterPassificationLocale);

            //generate axiom
            var axiomUniqueNamer  = new IsaUniqueNamer();
            var axId              = 0;
            var axiomToLemma      = new Dictionary <Axiom, OuterDecl>();
            var vcRewriteLemmaGen =
                new VcRewriteLemmaGen(eraserFactory, VCExprToIsaTranslator.CreateNameBasedTranslator(new IsaUniqueNamer()));

            var vcAxiomLemmaManager = new VcAxiomLemmaManager(
                vcProofData.VcBoogieInfo.VcInstAxiom,
                methodData,
                vcProofData.VcFunctions,
                vcRewriteLemmaGen, varFactory);

            var axiomLocaleRequiredDecls = new List <OuterDecl>();

            foreach (var axiom in vcProofData.VcBoogieInfo.VcAxiomsInfo)
            {
                if (axiom is VcBoogieAxiomInfo vcBoogieAxiom)
                {
                    var axiomVcLemma =
                        vcAxiomLemmaManager.AxiomVcLemma(
                            axiomUniqueNamer.GetName(axiom, "axiom_vc_" + axId),
                            vcBoogieAxiom.Axiom,
                            vcBoogieAxiom.Expr,
                            out var requiredDecls);
                    axiomToLemma.Add(vcBoogieAxiom.Axiom, axiomVcLemma);
                    axiomLocaleRequiredDecls.AddRange(requiredDecls);
                }
            }

            /* we add the required declarations for the axiom locale to the outer theory, since the axiom locale fixes variables that could clash
             * with the declarations */
            passiveOuterDecls.AddRange(axiomLocaleRequiredDecls);
            var axiomLocale = GenerateLocale("axioms", vcAxiomLemmaManager, axiomToLemma.Values.ToList());

            passiveOuterDecls.Add(axiomLocale);

            if (generateEndToEndProof)
            {
                var endToEnd = new EndToEndVCProof(
                    methodData,
                    passiveProgAccess,
                    vcProofData.VcFunctions,
                    vcProofData.VcBoogieInfo,
                    afterPassificationCfg,
                    finalCfg,
                    afterPassificationLocale.Name + "." + cfgProgramLemmas[afterPassificationCfg.entry].Name,
                    axiomLocale.Name,
                    ax => axiomLocale.Name + "." + axiomToLemma[ax].Name,
                    varFactory,
                    vcProofData.VcTranslator,
                    eraserFactory,
                    gen);
                passiveOuterDecls.AddRange(endToEnd.GenerateProof(out vcAssm, out endToEndLemma));
            }
            else
            {
                vcAssm        = null;
                endToEndLemma = null;
            }

            return
                (new Theory(theoryName,
                            new List <string>
            {
                "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.VCHints", "Boogie_Lang.VCPhaseML",
                passiveProgAccess.TheoryName(), beforePassiveProgAccess.TheoryName()
            },
                            passiveOuterDecls));
        }
        /**
         * cases:
         * 1) is loop head block
         * 2) is back edge block
         * 3) successor is loop head block
         *
         * any combination is possible
         */
        public static Theory CfgToDagProof(
            PhasesTheories phasesTheories,
            bool generateEndToEndLemma,
            Term vcAssm,
            CFGRepr beforeDagCfg,
            CFGRepr afterDagCfg,
            Block afterUniqueExit,
            BoogieMethodData beforeDagData,
            CfgToDagHintManager hintManager,
            IDictionary <Block, Block> beforeToAfter,
            IProgramAccessor beforeDagProgAccess,
            IProgramAccessor afterDagProgAccess,
            IVariableTranslationFactory varFactory)
        {
            var afterToBefore = beforeToAfter.InverseDict();

            //track mapping from blocks to loops that the block is contained in and for which it is not the loop head
            IDictionary <Block, IList <Block> > blocksToLoops = new Dictionary <Block, IList <Block> >();

            foreach (var afterBlock in afterDagCfg.GetBlocksBackwards())
            {
                if (afterToBefore.TryGetValue(afterBlock, out var beforeBlock))
                {
                    var loops = new HashSet <Block>();
                    foreach (var bSuc in beforeDagCfg.GetSuccessorBlocks(beforeBlock))
                    {
                        if (blocksToLoops.TryGetValue(bSuc, out var loopsSuc))
                        {
                            //if successor inside of a loop L and the block is not the loop head of L, then the block is also inside L
                            foreach (var loopSuc in loopsSuc)
                            {
                                if (!loopSuc.Equals(beforeBlock))
                                {
                                    loops.Add(loopSuc);
                                }
                            }
                        }
                    }

                    /* a node is inside all loops for which it has an out-going backedge
                     * if a node has a backedge to itself (i.e., it is also a loop head), then we do not add this loop
                     */
                    if (hintManager.TryIsBackedgeNode(beforeBlock, out var backedgeLoops))
                    {
                        foreach (var backedgeLoop in backedgeLoops)
                        {
                            if (beforeBlock != backedgeLoop)
                            {
                                loops.Add(backedgeLoop);
                            }
                        }
                    }

                    var loopsList = loops.ToList();
                    blocksToLoops.Add(beforeBlock, loopsList);
                }
            }

            var varContextName   = "\\<Lambda>1";
            var varContextAbbrev = new AbbreviationDecl(
                varContextName,
                new Tuple <IList <Term>, Term>(new List <Term>(), beforeDagProgAccess.VarContext())
                );

            var funContextWfName = "Wf_Fun";
            var boogieContext    = new BoogieContextIsa(
                IsaCommonTerms.TermIdentFromName("A"),
                IsaCommonTerms.TermIdentFromName("M"),
                IsaCommonTerms.TermIdentFromName(varContextName),
                IsaCommonTerms.TermIdentFromName("\\<Gamma>"),
                IsaCommonTerms.EmptyList);
            var lemmaManager = new CfgToDagLemmaManager(
                beforeDagProgAccess,
                afterDagProgAccess,
                boogieContext,
                afterDagCfg,
                funContextWfName,
                hintManager,
                blocksToLoops,
                beforeToAfter,
                beforeDagData,
                afterUniqueExit,
                varFactory);

            var lemmaNamer = new IsaUniqueNamer();
            var outerDecls = new List <OuterDecl>();

            outerDecls.Add(varContextAbbrev);
            outerDecls.Add(new DeclareDecl("Nat.One_nat_def[simp del]"));
            if (afterUniqueExit != null)
            {
                outerDecls.AddRange(lemmaManager.UnifiedExitLemma(GetCfgLemmaName(afterUniqueExit, lemmaNamer)));
            }

            foreach (var afterBlock in afterDagCfg.GetBlocksBackwards())
            {
                if (afterToBefore.TryGetValue(afterBlock, out var beforeBlock))
                {
                    //if the node's only edge is a backedge, then an "assume false" will be added
                    var singleCutEdge = hintManager.TryIsBackedgeNode(beforeBlock, out var _) &&
                                        beforeDagCfg.NumOfSuccessors(beforeBlock) == 1;

                    var(localLemmas, cfgLemma) =
                        lemmaManager.BlockLemma(
                            beforeBlock,
                            afterBlock,
                            beforeDagCfg.GetSuccessorBlocks(beforeBlock),
                            block => GetLemmaName(block, lemmaNamer),
                            block => GetCfgLemmaName(block, lemmaNamer),
                            singleCutEdge
                            );

                    outerDecls.AddRange(localLemmas);
                    outerDecls.Add(cfgLemma);
                }
                else
                {
                    //block was added as part of transformation
                    if (afterBlock == afterDagCfg.entry)
                    {
                        //entry lemma handled elsewhere
                        continue;
                    }

                    var afterBlockSuccessors     = afterDagCfg.GetSuccessorBlocks(afterBlock);
                    var afterBlockSuccessorsList = afterBlockSuccessors.ToList();
                    if (!afterBlockSuccessorsList.Any())
                    {
                        //this must be the unique node
                        if (afterUniqueExit == null)
                        {
                            throw new ProofGenUnexpectedStateException(
                                      "unique exit block added, but only exit block existed before cfg-to-dag");
                        }

                        continue;
                    }

                    if (afterBlockSuccessorsList.Count != 1)
                    {
                        throw new ProofGenUnexpectedStateException(
                                  "Block added in CFG-to-DAG phase does not have a unique successor");
                    }

                    var afterUniqueSuc = afterBlockSuccessorsList.First();
                    if (afterToBefore.TryGetValue(afterUniqueSuc, out var beforeUniqueSuc))
                    {
                        hintManager.IsLoopHead(beforeUniqueSuc, out var hint);
                        var lemma = lemmaManager.NewBlockLemma(
                            GetCfgLemmaName(afterBlock, lemmaNamer),
                            afterBlock,
                            afterUniqueSuc,
                            hint
                            );
                        outerDecls.Add(lemma);
                    }
                    else if (hintManager.IsNewBackedgeBlock(afterBlock, out var loopHeadHint))
                    {
                        if (afterDagCfg.GetSuccessorBlocks(afterUniqueSuc).Any())
                        {
                            throw new ProofGenUnexpectedStateException(
                                      "New backedge node has successor that is not the exit node.");
                        }

                        //afterUniqueSuc is a successor to a backedge node for which all edges were eliminated
                        var lemma = lemmaManager.NewBlockLemma(
                            GetCfgLemmaName(afterBlock, lemmaNamer),
                            afterBlock,
                            null,
                            loopHeadHint
                            );
                        outerDecls.Add(lemma);
                    }
                    else
                    {
                        throw new ProofGenUnexpectedStateException(
                                  "CFG-to-DAG: Unique successor of added block cannot be mapped to original block");
                    }
                }
            }

            var entryLemma = lemmaManager.EntryLemma("entry_lemma", beforeDagCfg.entry, afterDagCfg.entry,
                                                     b => GetCfgLemmaName(b, lemmaNamer));

            outerDecls.Add(entryLemma);

            var absValType           = new VarType("a");
            var cfgToDagLemmasLocale = new LocaleDecl(
                "cfg_to_dag_lemmas",
                new ContextElem(
                    new List <Tuple <TermIdent, TypeIsa> >
            {
                Tuple.Create((TermIdent)boogieContext.absValTyMap,
                             IsaBoogieType.AbstractValueTyFunType(absValType)),
                Tuple.Create((TermIdent)boogieContext.funContext, IsaBoogieType.FunInterpType(absValType))
            },
                    new List <Term>
            {
                IsaBoogieTerm.FunInterpWf(boogieContext.absValTyMap, beforeDagProgAccess.FunctionsDecl(),
                                          boogieContext.funContext)
            },
                    new List <string> {
                funContextWfName
            }
                    ),
                outerDecls
                );

            var theoryOuterDecls = new List <OuterDecl>();

            theoryOuterDecls.Add(cfgToDagLemmasLocale);

            if (generateEndToEndLemma)
            {
                var endToEndManager = new CfgToDagEndToEnd();
                var endToEndDecls   = endToEndManager.EndToEndProof(
                    cfgToDagLemmasLocale.Name + "." + entryLemma.Name,
                    phasesTheories.EndToEndLemmaName(PhasesTheories.Phase.Passification, true),
                    vcAssm,
                    beforeDagProgAccess,
                    beforeDagCfg
                    );
                theoryOuterDecls.AddRange(endToEndDecls);
            }

            return(new Theory(
                       phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag),
                       new List <string>
            {
                "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.BackedgeElim", "Boogie_Lang.TypingML",
                beforeDagProgAccess.TheoryName(),
                afterDagProgAccess.TheoryName(), phasesTheories.TheoryName(PhasesTheories.Phase.Passification),
                phasesTheories.TheoryName(PhasesTheories.Phase.Vc)
            },
                       theoryOuterDecls
                       ));
        }
        //assume that block identities in the two CFGs are the same (only edges may be different)
        private static IDictionary <Block, IList <OuterDecl> > GenerateVCLemmas(
            CFGRepr afterPassificationCfg,
            CFGRepr finalCfg,
            IDictionary <Block, Block> afterPassiveToFinalBlock,
            IDictionary <Block, Block> afterPassiveToOrigBlock,
            HashSet <Block> reachableBlocks,
            VcPhaseLemmaManager vcPhaseLemmaManager,
            VCHintManager vcHintManager,
            IsaUniqueNamer lemmaNamer)
        {
            var blockToLemmaDecls = new Dictionary <Block, IList <OuterDecl> >();

            foreach (var bAfterPassive in afterPassificationCfg.GetBlocksBackwards())
            {
                var result = new List <OuterDecl>();

                if (afterPassiveToFinalBlock.TryGetValue(bAfterPassive, out var bFinal))
                {
                    string vcHintsName = null;
                    if (vcHintManager.TryGetHints(afterPassiveToOrigBlock[bAfterPassive], out var hints,
                                                  out var requiredDecls))
                    {
                        //FIXME potential val name clash
                        vcHintsName = GetLemmaName(bAfterPassive, lemmaNamer) + "_hints";
                        var code = MLUtil.DefineVal(vcHintsName, MLUtil.MLList(hints));
                        //required declarations must be added first
                        result.AddRange(requiredDecls);
                        result.Add(new MLDecl(code));
                    }

                    result.Add(vcPhaseLemmaManager.GenerateBlockLemma(
                                   bAfterPassive, bFinal, finalCfg.GetSuccessorBlocks(bFinal), GetLemmaName(bFinal, lemmaNamer),
                                   vcHintsName));
                    //do not use identity of final CFG block to be consistent with other branches
                    blockToLemmaDecls.Add(bAfterPassive, result);
                }
                else if (reachableBlocks.Contains(bAfterPassive))
                {
                    //block was removed after peephole but is reachable before peephole
                    if (bAfterPassive.Cmds.Count == 0)
                    {
                        //find the successors of b in the final cfg (i.e., the first non-empty reachable blocks)
                        var nonEmptyReachableSuccessors =
                            GetNonEmptyReachableSuccessors(bAfterPassive, afterPassificationCfg, finalCfg,
                                                           afterPassiveToFinalBlock);
                        //add lemma
                        var decls = new List <OuterDecl>
                        {
                            vcPhaseLemmaManager.GenerateEmptyBlockLemma(
                                bAfterPassive,
                                nonEmptyReachableSuccessors.Select(b => afterPassiveToFinalBlock[b]),
                                GetLemmaName(bAfterPassive, lemmaNamer))
                        };
                        blockToLemmaDecls.Add(bAfterPassive, decls);
                    }
                    else
                    {
                        throw new ProofGenUnexpectedStateException(
                                  "Non-empty reachable block removed during peep-hole");
                    }
                }
            }

            return(blockToLemmaDecls);
        }
        public IProgramAccessor GetIsaProgram(
            string theoryName,
            string procName,
            BoogieMethodData methodData,
            IsaProgramGeneratorConfig config,
            IVariableTranslationFactory varTranslationFactory,
            CFGRepr cfg,
            out IList <OuterDecl> decls,
            bool generateMembershipLemmas = true,
            bool onlyGlobalData           = false
            )
        {
            this.varTranslationFactory = varTranslationFactory;
            varTranslation             = varTranslationFactory.CreateTranslation();
            cmdIsaVisitor = new MultiCmdIsaVisitor(varTranslationFactory);

            /*
             * Term program = IsaBoogieTerm.Program(IsaCommonTerms.TermIdentFromName(funcs.name),
             *  new TermList(new List<Term>()),
             *  new TermList(new List<Term>()),
             *  IsaCommonTerms.TermIdentFromName(axiomsDecl.name),
             *  new List<Term>() { method });
             *
             * var list = new List<Tuple<IList<Term>, Term>>
             * {
             *  new Tuple<IList<Term>, Term>(new List<Term>(), program)
             * };
             */

            //OuterDecl programDefinition = new DefDecl("ProgramM", new Tuple<IList<Term>, Term>(new List<Term>(), program));

            decls = new List <OuterDecl>();
            var isaGlobalProgramRepr = new IsaGlobalProgramRepr(
                FunctionDeclarationsName(),
                AxiomDeclarationsName(),
                VariableDeclarationsName("globals"),
                VariableDeclarationsName("constants")
                );
            var globalsMax = methodData.Constants.Count() + methodData.GlobalVars.Count() - 1;
            // assume single versioning and order on constants, globals, params, locals
            var localsMin = globalsMax + 1;

            if (globalsMax < 0)
            {
                globalsMax = 0;
            }

            MembershipLemmaManager membershipLemmaManager;

            if (onlyGlobalData)
            {
                membershipLemmaManager = new MembershipLemmaManager(
                    isaGlobalProgramRepr, globalsMax, varTranslationFactory, theoryName);
            }
            else
            {
                var outEdges       = GetOutEdgesIsa(procName, cfg, out var edgeLemmas);
                var blockInfo      = BlockToInfo(theoryName, procName, cfg, edgeLemmas);
                var isaProgramRepr = new IsaProgramRepr(
                    isaGlobalProgramRepr,
                    PreconditionDeclarationName(),
                    PostconditionDeclarationName(),
                    VariableDeclarationsName("params"),
                    VariableDeclarationsName("locals"),
                    cfgName,
                    procDefName);
                membershipLemmaManager = new MembershipLemmaManager(config, isaProgramRepr, blockInfo,
                                                                    Tuple.Create(globalsMax, localsMin), varTranslationFactory, theoryName);

                var nodesToBlocks = GetNodeToBlocksIsa(cfg, blockInfo.BlockCmdsDefs);

                decls.AddRange(blockInfo.BlockCmdsDefs.Values);

                Term entry         = new IntConst(BigNum.FromInt(cfg.GetUniqueIntLabel(cfg.entry)));
                var  methodBodyCFG =
                    IsaBoogieTerm.MethodCFGBody(
                        entry, IsaCommonTerms.TermIdentFromName(outEdges.Name),
                        IsaCommonTerms.TermIdentFromName(nodesToBlocks.Name)
                        );

                var methodBodyDecl = GetMethodBodyCFGDecl(procName, methodBodyCFG);
                decls.AddRange(
                    new List <OuterDecl>
                {
                    outEdges, nodesToBlocks, methodBodyDecl
                });

                decls.AddRange(blockInfo.BlockCmdsLemmas.Values);
                decls.AddRange(blockInfo.BlockOutEdgesLemmas.Values);

                if (config.specsConfig != SpecsConfig.None)
                {
                    OuterDecl preconditions;
                    OuterDecl postconditions;

                    if (config.specsConfig == SpecsConfig.AllPreCheckedPost)
                    {
                        preconditions  = GetExprListIsa(PreconditionDeclarationName(), methodData.Preconditions.Select(pre => pre.Item1));
                        postconditions = GetExprListIsa(PostconditionDeclarationName(), methodData.Postconditions.Where(post => !post.Item2).Select(post => post.Item1));
                    }
                    else
                    {
                        preconditions  = GetExprListIsa(PreconditionDeclarationName(), methodData.Preconditions);
                        postconditions = GetExprListIsa(PostconditionDeclarationName(), methodData.Postconditions);
                    }

                    decls.Add(preconditions);
                    decls.Add(postconditions);
                }

                if (config.generateParamsAndLocals)
                {
                    decls.Add(GetVariableDeclarationsIsa("params", methodData.InParams));
                    decls.Add(GetVariableDeclarationsIsa("locals", methodData.Locals));
                }

                /* membership lemmas might still be added even if the parameter and local variable definitions are not generated
                 * at this point (since the variable context may still be different, which requires other lookup lemmas)
                 */
                if (generateMembershipLemmas)
                {
                    membershipLemmaManager.AddVariableMembershipLemmas(methodData.InParams, VarKind.ParamOrLocal);
                    membershipLemmaManager.AddVariableMembershipLemmas(methodData.Locals, VarKind.ParamOrLocal);
                }
            }

            if (config.generateAxioms)
            {
                decls.Add(GetAxioms(methodData.Axioms));
                if (generateMembershipLemmas)
                {
                    membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms);
                }
            }

            if (config.generateFunctions)
            {
                decls.Add(GetFunctionDeclarationsIsa(methodData.Functions));
                if (generateMembershipLemmas)
                {
                    membershipLemmaManager.AddFunctionMembershipLemmas(methodData.Functions);
                }
            }

            if (config.generateGlobalsAndConstants)
            {
                decls.Add(GetVariableDeclarationsIsa("globals", methodData.GlobalVars));
                decls.Add(GetVariableDeclarationsIsa("constants", methodData.Constants));
            }

            if (generateMembershipLemmas)
            {
                membershipLemmaManager.AddVariableMembershipLemmas(methodData.GlobalVars, VarKind.Global);
                membershipLemmaManager.AddVariableMembershipLemmas(methodData.Constants, VarKind.Constant);
                decls.AddRange(membershipLemmaManager.OuterDecls());
            }

            if (config.specsConfig != SpecsConfig.None)
            {
                DefDecl methodDef = MethodDefinition(membershipLemmaManager, methodData, config.specsConfig);
                decls.Add(methodDef);
            }

            return(membershipLemmaManager);
        }
        //cfg must be acyclic
        public static IDictionary <Block, IEnumerable <Variable> > ComputeLiveVariables(CFGRepr cfg,
                                                                                        BoogieMethodData methodData)
        {
            var liveVarsBefore = new Dictionary <Block, IEnumerable <Variable> >();

            var allVarsSet = new HashSet <Variable>(methodData.AllVariables());

            foreach (var b in cfg.GetBlocksBackwards())
            {
                var bCurLiveVars = new HashSet <Variable>();
                foreach (var bSuc in cfg.GetSuccessorBlocks(b))
                {
                    bCurLiveVars.UnionWith(liveVarsBefore[bSuc]);
                }

                for (var idx = b.cmds.Count - 1; idx >= 0; idx--)
                {
                    UpdateLiveSet(b.cmds[idx], bCurLiveVars);
                }

                //due to the VariableCollector's implementation bound variables may also have been included
                bCurLiveVars.RemoveWhere(v => !allVarsSet.Contains(v));
                liveVarsBefore.Add(b, bCurLiveVars);
            }

            return(liveVarsBefore);
        }
        public static LocaleDecl ConvertVC(
            string localeName,
            VCExpr vc,
            IEnumerable <VCExpr> vcAxioms,
            IActiveDeclGenerator activeDeclGenerator,
            Boogie2VCExprTranslator translator,
            TypeAxiomBuilderPremisses axiomBuilder,
            BoogieMethodData methodData,
            CFGRepr cfg,
            out VCInstantiation <Block> vcinst,
            out VCInstantiation <VCExpr> vcinstAxiom,
            out IVCVarFunTranslator vcTranslator,
            out IEnumerable <Function> vcTypeFunctions)
        {
            var vcLet = vc as VCExprLet;

            Contract.Assert(vcLet != null);

            var uniqueNamer = new IsaUniqueNamer();
            var blockToVC   = VCBlockExtractor.BlockToVCMapping(vcLet, cfg);

            var declCollector = new VCFunDeclCollector();
            var funToVCfun    =
                declCollector.CollectFunDeclarations(new List <VCExpr> {
                vc
            }.Concat(vcAxioms), methodData.Functions);
            IVCVarFunTranslator varTranslator =
                new VCVarFunTranslator(methodData.AllVariables(), funToVCfun, translator, axiomBuilder);

            var activeDeclsPerBlock =
                activeDeclGenerator.GetActiveDeclsPerBlock(blockToVC, varTranslator, cfg, out var blockToNewVars);

            #region temporary: extend vc instantiation to support vc functions

            IList <Function> otherFunctions    = new List <Function>();
            ISet <Function>  otherFunctionsSet = new HashSet <Function>();

            foreach (var decl in activeDeclsPerBlock[cfg.entry])
            {
                if (decl is Function fun && !varTranslator.TranslateBoogieFunction(fun, out _))
                {
                    otherFunctions.Add(fun);
                    otherFunctionsSet.Add(fun);
                }
            }

            //also record functions that are used elswhere (type axiom related functions)
            var collector = new VCExprDeclCollector();
            var vcExprs   = vcAxioms.ToList();
            foreach (var ax in vcExprs)
            {
                var decls = collector.CollectNamedDeclarations(ax, varTranslator);
                foreach (var d in decls)
                {
                    if (d is Function fun && !varTranslator.TranslateBoogieFunction(fun, out _) &&
                        !otherFunctions.Contains(d))
                    {
                        otherFunctions.Add(fun);
                    }
                }
            }

            #endregion

            IDictionary <Block, IList <NamedDeclaration> > activeDeclsPerBlockSorted =
                SortActiveDecls(activeDeclsPerBlock, methodData.Functions.Union(otherFunctions), varTranslator,
                                out var activeVarsPerBlock);

            var blockToNewVCVars = ConvertVariableToVCExpr(blockToNewVars, varTranslator);

            var blockToIsaTranslator = new VCBlockToIsaTranslator(uniqueNamer);
            var blockToVCExpr        =
                blockToIsaTranslator.IsaDefsFromVC(blockToVC, activeVarsPerBlock, cfg, blockToNewVCVars);

            //add vc definitions of blocks in correct order
            IList <OuterDecl> vcOuterDecls = new List <OuterDecl>();

            foreach (var block in cfg.GetBlocksBackwards())
            {
                vcOuterDecls.Add(blockToVCExpr[block]);
            }

            vcinst = new VCInstantiation <Block>(blockToVCExpr, activeDeclsPerBlockSorted, localeName);

            /*
             *
             * //reason for using second reference: cannot use out parameters in lambda expressions
             * var vcinstInternal = vcinst;
             *
             * LemmaDecl vcCorrectLemma = new LemmaDecl("vc_correct",
             *  new TermApp(vcinstInternal.GetVCObjRef(cfg.entry, false),
             *             activeVarsPerBlock[cfg.entry].Select(v => (Term) IsaCommonTerms.TermIdentFromName(uniqueNamer.GetName(v, v.Name))).ToList()),
             *  new Proof(
             *    new List<string>() {
             *        "apply (simp only: " +
             *        cfg.GetBlocksForwards().Select(b => vcinstInternal.GetVCObjNameRef(b, false) + "_def").Concat(" ")
             + ")",
             +        "oops"
             +    }
             +  ));
             +
             + vcOuterDecls.Add(vcCorrectLemma);
             */

            //axioms
            var activeDeclsPerAxiom = VCInstAxioms(vcExprs, varTranslator);
            IDictionary <VCExpr, IList <NamedDeclaration> > activeDeclsPerAxiomSorted =
                SortActiveDecls(activeDeclsPerAxiom, methodData.Functions.Union(otherFunctions), varTranslator,
                                out var activeVarsPerAxiom);
            var axiomToDef          = new Dictionary <VCExpr, DefDecl>();
            var vcExprIsaTranslator = new VCExprToIsaTranslator(uniqueNamer);

            if (activeDeclsPerAxiomSorted.Count != vcExprs.Count())
            {
                throw new ProofGenUnexpectedStateException(typeof(VCToIsaInterface), "count not in-sync");
            }

            var axId = 0;
            foreach (var vcAx in activeDeclsPerAxiomSorted.Keys)
            {
                IList <Term> args = activeVarsPerAxiom[vcAx].Select(v => vcExprIsaTranslator.Translate(v)).ToList();
                var          rhs  = vcExprIsaTranslator.Translate(vcAx);

                var def = new DefDecl("vcax_" + axId, new Tuple <IList <Term>, Term>(args, rhs));
                axiomToDef.Add(vcAx, def);
                axId++;
            }

            vcinstAxiom = new VCInstantiation <VCExpr>(axiomToDef, activeDeclsPerAxiomSorted, localeName);

            vcOuterDecls.AddRange(axiomToDef.Values);

            var vcFunctions = methodData.Functions.Where(f => varTranslator.TranslateBoogieFunction(f, out var result))
                              .Select(f =>
            {
                if (varTranslator.TranslateBoogieFunction(f, out var result))
                {
                    return(result);
                }
                throw new InvalidOperationException();
            }).Union(otherFunctions);

            vcTranslator    = varTranslator;
            vcTypeFunctions = otherFunctions;

            return(new LocaleDecl(localeName, ContextElem.CreateWithFixedVars(GetVarsInVC(vcFunctions, uniqueNamer)),
                                  vcOuterDecls));
        }
        public IDictionary <Block, ISet <NamedDeclaration> > GetActiveDeclsPerBlock(IDictionary <Block, VCExpr> blockToVC,
                                                                                    IVCVarFunTranslator translator, CFGRepr cfg, out IDictionary <Block, ISet <Variable> > blockToNewVars)
        {
            var blockToDefinedDecls = new Dictionary <Block, ISet <NamedDeclaration> >();

            foreach (var b in cfg.GetBlocksForwards())
            {
                blockToDefinedDecls.Add(b, new HashSet <NamedDeclaration>());
            }

            var declCollector = new VCExprDeclCollector();

            var blockToNamedDecls = new Dictionary <Block, ISet <NamedDeclaration> >();

            //compute all named declarations in the VC for each block b which have been used before b is reached
            foreach (var b in cfg.GetBlocksForwards())
            {
                var bDecls = declCollector.CollectNamedDeclarations(blockToVC[b], translator);
                blockToNamedDecls.Add(b, bDecls);

                foreach (var bSucc in cfg.GetSuccessorBlocks(b))
                {
                    blockToDefinedDecls[bSucc].UnionWith(bDecls);
                    blockToDefinedDecls[bSucc].UnionWith(blockToDefinedDecls[b]);
                }
            }

            //compute all named declarations in the VC for each block b that are in any path reached from b and which were defined in any path reaching b
            //named declarations which are not variables are trivially defined at the beginning of the CFG
            var blockToActiveDecls = new Dictionary <Block, ISet <NamedDeclaration> >();

            blockToNewVars = new Dictionary <Block, ISet <Variable> >();
            foreach (var b in cfg.GetBlocksBackwards())
            {
                var bDecls = blockToNamedDecls[b];

                ISet <NamedDeclaration> oldActiveDecls = new HashSet <NamedDeclaration>();
                ISet <Variable>         newDecls       = new HashSet <Variable>();

                foreach (var d in bDecls)
                {
                    if (d is Variable v && !blockToDefinedDecls[b].Contains(d))
                    {
                        newDecls.Add(v);
                    }