From e59ce5362d2f077710d10b092efa8166b6284f35 Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Wed, 10 Aug 2022 17:28:08 +0200 Subject: [PATCH 001/123] ast_to_cfg certification in progress copying of unoptimized blocks to be done --- Source/Boogie.sln | 29 +- Source/Core/Absy.cs | 7 + Source/Core/AbsyCmd.cs | 173 +- Source/Core/ObjectExtensions.cs | 159 ++ Source/Core/Parser.cs | 5 +- Source/Core/ProofGenInfo.cs | 592 ++++++ Source/Core/ProofGenInfoManager.cs | 39 + Source/ExecutionEngine/ExecutionEngine.cs | 16 +- Source/ProofGenUtil/ObjectExtensions.cs | 158 ++ Source/ProofGenUtil/ProofGenUtil.csproj | 9 + Source/ProofGeneration/ASTRepr/ASTRepr.cs | 84 + .../AstToCfg/AstToCfgEndToEnd.cs | 323 +++ .../AstToCfg/AstToCfgLemmaManager.cs | 1728 +++++++++++++++++ .../AstToCfg/AstToCfgManager.cs | 212 ++ .../BoogieIsaInterface/IProgramAccessor.cs | 2 + .../BoogieIsaInterface/IsaBlockInfo.cs | 37 + .../BoogieIsaInterface/IsaBoogieTerm.cs | 143 ++ .../BoogieIsaInterface/IsaBoogieType.cs | 9 +- .../IsaProgramGenerator_forAst.cs | 425 ++++ .../MembershipLemmaManager.cs | 52 + .../BoogieIsaInterface/MultiCmdIsaVisitor.cs | 2 +- .../ProgramGeneratorHelper_forAst.cs | 283 +++ .../DeBruijnFixedVarTranslation.cs | 8 + .../CFGRepr/CFGReprTransformer.cs | 4 +- .../CfgToDag/CfgToDagEndToEnd.cs | 39 +- .../CfgToDag/CfgToDagLemmaManager.cs | 59 +- .../CfgToDag/CfgToDagManager.cs | 14 +- .../Passification/PassificationEndToEnd.cs | 17 +- .../PassificationLemmaManager.cs | 5 +- .../Passification/PassificationManager.cs | 8 +- Source/ProofGeneration/PhasesTheories.cs | 7 +- Source/ProofGeneration/ProofGenConfig.cs | 5 +- .../ProofGeneration/ProofGenerationLayer.cs | 305 ++- Source/VCGeneration/VCGen.cs | 2 +- 34 files changed, 4876 insertions(+), 84 deletions(-) create mode 100644 Source/Core/ObjectExtensions.cs create mode 100644 Source/Core/ProofGenInfo.cs create mode 100644 Source/Core/ProofGenInfoManager.cs create mode 100644 Source/ProofGenUtil/ObjectExtensions.cs create mode 100644 Source/ProofGenUtil/ProofGenUtil.csproj create mode 100644 Source/ProofGeneration/ASTRepr/ASTRepr.cs create mode 100644 Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs create mode 100644 Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs create mode 100644 Source/ProofGeneration/AstToCfg/AstToCfgManager.cs create mode 100644 Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator_forAst.cs create mode 100644 Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelper_forAst.cs diff --git a/Source/Boogie.sln b/Source/Boogie.sln index 865070aca..b6465d89a 100644 --- a/Source/Boogie.sln +++ b/Source/Boogie.sln @@ -42,10 +42,13 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CoreTests", "UnitTests\CoreTests\CoreTests.csproj", "{D2D77420-CFDB-4DA1-B7E7-844C8E8CC686}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProofGeneration", "ProofGeneration\ProofGeneration.csproj", "{3059B8EB-DCE0-4468-9801-5D0A2A226472}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExecutionEngineTests", "UnitTests\ExecutionEngineTests\ExecutionEngineTests.csproj", "{473CF455-4306-46E3-9A44-FB7DBA42CA38}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Isabelle", "Isabelle\Isabelle.csproj", "{89B2CE6C-5BE5-49F2-9C88-8EADFDA9C549}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProofGenUtil", "ProofGenUtil\ProofGenUtil.csproj", "{729804D8-E3CE-4C06-AE15-F1D833AC3E06}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -203,18 +206,6 @@ Global {7A4B3721-D902-4265-94DB-CA8B0BB295B7}.Release|x64.Build.0 = Release|Any CPU {7A4B3721-D902-4265-94DB-CA8B0BB295B7}.Release|x86.ActiveCfg = Release|Any CPU {7A4B3721-D902-4265-94DB-CA8B0BB295B7}.Release|x86.Build.0 = Release|Any CPU - {CE190976-D727-4038-8D8A-8C5579E48CCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CE190976-D727-4038-8D8A-8C5579E48CCF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CE190976-D727-4038-8D8A-8C5579E48CCF}.Debug|x64.ActiveCfg = Debug|Any CPU - {CE190976-D727-4038-8D8A-8C5579E48CCF}.Debug|x64.Build.0 = Debug|Any CPU - {CE190976-D727-4038-8D8A-8C5579E48CCF}.Debug|x86.ActiveCfg = Debug|Any CPU - {CE190976-D727-4038-8D8A-8C5579E48CCF}.Debug|x86.Build.0 = Debug|Any CPU - {CE190976-D727-4038-8D8A-8C5579E48CCF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CE190976-D727-4038-8D8A-8C5579E48CCF}.Release|Any CPU.Build.0 = Release|Any CPU - {CE190976-D727-4038-8D8A-8C5579E48CCF}.Release|x64.ActiveCfg = Release|Any CPU - {CE190976-D727-4038-8D8A-8C5579E48CCF}.Release|x64.Build.0 = Release|Any CPU - {CE190976-D727-4038-8D8A-8C5579E48CCF}.Release|x86.ActiveCfg = Release|Any CPU - {CE190976-D727-4038-8D8A-8C5579E48CCF}.Release|x86.Build.0 = Release|Any CPU {51768B2E-FFF9-49F0-96D7-022250A4BEB4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {51768B2E-FFF9-49F0-96D7-022250A4BEB4}.Debug|Any CPU.Build.0 = Debug|Any CPU {51768B2E-FFF9-49F0-96D7-022250A4BEB4}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -299,6 +290,20 @@ Global {89B2CE6C-5BE5-49F2-9C88-8EADFDA9C549}.Release|x64.Build.0 = Release|Any CPU {89B2CE6C-5BE5-49F2-9C88-8EADFDA9C549}.Release|x86.ActiveCfg = Release|Any CPU {89B2CE6C-5BE5-49F2-9C88-8EADFDA9C549}.Release|x86.Build.0 = Release|Any CPU + {3059B8EB-DCE0-4468-9801-5D0A2A226472}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3059B8EB-DCE0-4468-9801-5D0A2A226472}.Debug|Any CPU.Build.0 = Debug|Any CPU + {729804D8-E3CE-4C06-AE15-F1D833AC3E06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {729804D8-E3CE-4C06-AE15-F1D833AC3E06}.Debug|Any CPU.Build.0 = Debug|Any CPU + {729804D8-E3CE-4C06-AE15-F1D833AC3E06}.Debug|x64.ActiveCfg = Debug|Any CPU + {729804D8-E3CE-4C06-AE15-F1D833AC3E06}.Debug|x64.Build.0 = Debug|Any CPU + {729804D8-E3CE-4C06-AE15-F1D833AC3E06}.Debug|x86.ActiveCfg = Debug|Any CPU + {729804D8-E3CE-4C06-AE15-F1D833AC3E06}.Debug|x86.Build.0 = Debug|Any CPU + {729804D8-E3CE-4C06-AE15-F1D833AC3E06}.Release|Any CPU.ActiveCfg = Release|Any CPU + {729804D8-E3CE-4C06-AE15-F1D833AC3E06}.Release|Any CPU.Build.0 = Release|Any CPU + {729804D8-E3CE-4C06-AE15-F1D833AC3E06}.Release|x64.ActiveCfg = Release|Any CPU + {729804D8-E3CE-4C06-AE15-F1D833AC3E06}.Release|x64.Build.0 = Release|Any CPU + {729804D8-E3CE-4C06-AE15-F1D833AC3E06}.Release|x86.ActiveCfg = Release|Any CPU + {729804D8-E3CE-4C06-AE15-F1D833AC3E06}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {FDF25D38-01A2-4EAA-8A3E-6F8F7CD254D2} = {EC2B5ECD-B97D-43D6-86F8-28163710B717} diff --git a/Source/Core/Absy.cs b/Source/Core/Absy.cs index 539a145b3..f28d5d859 100644 --- a/Source/Core/Absy.cs +++ b/Source/Core/Absy.cs @@ -4469,6 +4469,13 @@ public Implementation(IToken /*!*/ tok, StructuredStmts = structuredStmts; BigBlocksResolutionContext ctx = new BigBlocksResolutionContext(structuredStmts, errorHandler); Blocks = ctx.Blocks; + + #region proofgen + IDictionary mapFromImplementationToProofGenInfo = ProofGenInfoManager.GetMapFromImplementationToProofGenInfo(); + ProofGenInfo correspondingProofGenInfo = ProofGenInfoManager.GetCurrentProofGenInfo(); + mapFromImplementationToProofGenInfo.Add(this, correspondingProofGenInfo); + #endregion + BlockPredecessorsComputed = false; scc = null; Attributes = kv; diff --git a/Source/Core/AbsyCmd.cs b/Source/Core/AbsyCmd.cs index 14534af60..e58afb08d 100644 --- a/Source/Core/AbsyCmd.cs +++ b/Source/Core/AbsyCmd.cs @@ -436,6 +436,12 @@ public List /*!*/ Blocks { get { + #region proofgen + ProofGenInfo proofGenInfo = new ProofGenInfo(); + proofGenInfo.SetStmtList(stmtList); + ProofGenInfoManager.SetCurrentProofGenInfo(proofGenInfo); + #endregion + Contract.Ensures(cce.NonNullElements(Contract.Result>())); if (blocks == null) { @@ -446,6 +452,16 @@ public List /*!*/ Blocks // Also, determine a good value for "prefix". CheckLegalLabels(stmtList, null, null); + #region proofgen + proofGenInfo.InstantiateVars(); + + foreach (BigBlock bb in stmtList.BigBlocks) + { + proofGenInfo.AddBigBlockBeforeNamingAnonymous(bb, true, null, null, BranchIndicator.NoGuard); + } + proofGenInfo.MakeOriginalAst(stmtList); + #endregion + // fill in names of anonymous blocks NameAnonymousBlocks(stmtList); @@ -455,7 +471,7 @@ public List /*!*/ Blocks if (this.errorHandler.count == startErrorCount) { // generate blocks from the big blocks - CreateBlocks(stmtList, null); + CreateBlocks(stmtList, null, proofGenInfo); } } @@ -694,7 +710,7 @@ void RecordSuccessors(StmtList stmtList, BigBlock successor) // If the enclosing context is a loop, then "runOffTheEndLabel" is the loop head label; // otherwise, it is null. - void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) + void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, ProofGenInfo proofGenInfo) { Contract.Requires(stmtList != null); Contract.Requires(blocks != null); @@ -723,6 +739,19 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) // this BigBlock has the very same components as a Block Contract.Assert(b.ec == null); Block block = new Block(b.tok, b.LabelName, theSimpleCmds, b.tc); + + #region proofgen + if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(b)) + { + proofGenInfo.AddBigBlockToBlockPair(b, block); + + if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(b)) + { + proofGenInfo.AddBigBlockToHintsPair(b, (null, BranchIndicator.NoGuard)); + } + } + #endregion + blocks.Add(block); } else if (b.ec == null) @@ -740,6 +769,17 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) Block block = new Block(b.tok, b.LabelName, theSimpleCmds, trCmd); blocks.Add(block); + + #region proofgen + if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(b)) + { + proofGenInfo.AddBigBlockToBlockPair(b, block); + if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(b)) + { + proofGenInfo.AddBigBlockToHintsPair(b, (null, BranchIndicator.NoGuard)); + } + } + #endregion } else if (b.ec is BreakCmd) { @@ -747,6 +787,17 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) Contract.Assert(bcmd.BreakEnclosure != null); Block block = new Block(b.tok, b.LabelName, theSimpleCmds, GotoSuccessor(b.ec.tok, bcmd.BreakEnclosure)); blocks.Add(block); + + #region proofgen + if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(b)) + { + proofGenInfo.AddBigBlockToBlockPair(b, block); + if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(b)) + { + proofGenInfo.AddBigBlockToHintsPair(b, (null, BranchIndicator.NoGuard)); + } + } + #endregion } else if (b.ec is WhileCmd) { @@ -777,6 +828,17 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) Block block = new Block(b.tok, b.LabelName, theSimpleCmds, new GotoCmd(wcmd.tok, new List {loopHeadLabel})); blocks.Add(block); + + #region proofgen + if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(b)) + { + proofGenInfo.AddBigBlockToBlockPair(b, block); + if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(b)) + { + proofGenInfo.AddBigBlockToHintsPair(b, (null, BranchIndicator.NoGuard)); + } + } + #endregion // LoopHead: assert/assume loop_invariant; goto LoopDone, LoopBody; List ssHead = new List(); @@ -789,16 +851,49 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) new GotoCmd(wcmd.tok, new List {loopDoneLabel, loopBodyLabel})); blocks.Add(block); + #region proofgen + foreach (var tuple in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().Values) + { + if (tuple.Item2 == b) + { + BigBlock simpleCmdsRemoved = tuple.Item1; + proofGenInfo.AddBigBlockToBlockPair(simpleCmdsRemoved, block); + proofGenInfo.AddBigBlockToHintsPair(simpleCmdsRemoved, (null, BranchIndicator.NoGuard)); + break; + } + } + #endregion + if (!bodyGuardTakenCareOf) { // LoopBody: assume guard; goto firstLoopBlock; block = new Block(wcmd.tok, loopBodyLabel, ssBody, new GotoCmd(wcmd.tok, new List {wcmd.Body.BigBlocks[0].LabelName})); blocks.Add(block); + + #region proofgen + BigBlock loopBodyBeginning = wcmd.Body.BigBlocks[0]; + if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(loopBodyBeginning)) + { + proofGenInfo.AddBigBlockToBlockPair(loopBodyBeginning, block); + if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(loopBodyBeginning)) + { + proofGenInfo.AddBigBlockToHintsPair(loopBodyBeginning, (wcmd.Guard, BranchIndicator.GuardHolds)); + } + } + #endregion } + #region proofgen + foreach (BigBlock bb in wcmd.Body.BigBlocks) + { + proofGenInfo.AddBigBlockToLoopPair(bb, b); + } + proofGenInfo.AddBigBlockToHintsPair(wcmd.Body.BigBlocks.First(), (wcmd.Guard, BranchIndicator.GuardHolds)); + #endregion + // recurse to create the blocks for the loop body - CreateBlocks(wcmd.Body, loopHeadLabel); + CreateBlocks(wcmd.Body, loopHeadLabel, proofGenInfo); // LoopDone: assume !guard; goto loopSuccessor; TransferCmd trCmd; @@ -814,6 +909,33 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) block = new Block(wcmd.tok, loopDoneLabel, ssDone, trCmd); blocks.Add(block); + + #region proofgen + BigBlock loopDone = b.successorBigBlock; + BigBlock parent = stmtList.ParentBigBlock; + BigBlock parentCopy = null; + if (parent != null) + { + parentCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[parent]; + } + if (loopDone == null) + { + loopDone = new BigBlock(Token.NoToken, null, new List(), null, null);; + b.successorBigBlock = loopDone; + + proofGenInfo.RecordLoopDoneBlock(loopDone); + proofGenInfo.AddBigBlockBeforeNamingAnonymous(loopDone, true, parent, parentCopy, BranchIndicator.NoGuard); + proofGenInfo.AddBigBlockToBlockPair(loopDone, block); + + if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(loopDone)) + { + proofGenInfo.AddBigBlockToHintsPair(loopDone, (wcmd.Guard, BranchIndicator.GuardFails)); + } + + BigBlock loopDoneCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[loopDone]; + proofGenInfo.AddToOriginalAst(loopDoneCopy); + } + #endregion } else { @@ -854,6 +976,24 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) Block block = new Block(b.tok, predLabel, predCmds, new GotoCmd(ifcmd.tok, new List {thenLabel, elseLabel})); blocks.Add(block); + + #region proofgen + if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(b)) + { + proofGenInfo.AddBigBlockToBlockPair(b, block); + if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(b)) + { + proofGenInfo.AddBigBlockToHintsPair(b, (null, BranchIndicator.NoGuard)); + } + } + + proofGenInfo.AddBigBlockToHintsPair(ifcmd.thn.BigBlocks.First(), (ifcmd.Guard, BranchIndicator.GuardHolds)); + + if (ifcmd.elseBlock != null) + { + proofGenInfo.AddBigBlockToHintsPair(ifcmd.elseBlock.BigBlocks.First(), (ifcmd.Guard, BranchIndicator.GuardFails)); + } + #endregion if (!thenGuardTakenCareOf) { @@ -861,10 +1001,22 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) block = new Block(ifcmd.tok, thenLabel, ssThen, new GotoCmd(ifcmd.tok, new List {ifcmd.thn.BigBlocks[0].LabelName})); blocks.Add(block); + + #region proofgen + BigBlock thnBranchBeginning = ifcmd.thn.BigBlocks[0]; + if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(thnBranchBeginning)) + { + proofGenInfo.AddBigBlockToBlockPair(thnBranchBeginning, block); + if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(thnBranchBeginning)) + { + proofGenInfo.AddBigBlockToHintsPair(thnBranchBeginning, (ifcmd.Guard, BranchIndicator.GuardHolds)); + } + } + #endregion } // recurse to create the blocks for the then branch - CreateBlocks(ifcmd.thn, n == 0 ? runOffTheEndLabel : null); + CreateBlocks(ifcmd.thn, n == 0 ? runOffTheEndLabel : null, proofGenInfo); if (ifcmd.elseBlock != null) { @@ -875,10 +1027,21 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel) block = new Block(ifcmd.tok, elseLabel, ssElse, new GotoCmd(ifcmd.tok, new List {ifcmd.elseBlock.BigBlocks[0].LabelName})); blocks.Add(block); + #region proofgen + BigBlock elseBranchBeginning = ifcmd.elseBlock.BigBlocks[0]; + if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(elseBranchBeginning)) + { + proofGenInfo.AddBigBlockToBlockPair(elseBranchBeginning, block); + if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(elseBranchBeginning)) + { + proofGenInfo.AddBigBlockToHintsPair(elseBranchBeginning, (ifcmd.Guard, BranchIndicator.GuardFails)); + } + } + #endregion } // recurse to create the blocks for the else branch - CreateBlocks(ifcmd.elseBlock, n == 0 ? runOffTheEndLabel : null); + CreateBlocks(ifcmd.elseBlock, n == 0 ? runOffTheEndLabel : null, proofGenInfo); } else if (ifcmd.elseIf != null) { diff --git a/Source/Core/ObjectExtensions.cs b/Source/Core/ObjectExtensions.cs new file mode 100644 index 000000000..c1ed7ef1d --- /dev/null +++ b/Source/Core/ObjectExtensions.cs @@ -0,0 +1,159 @@ +/** + * +Deep copy utility method taken from https://github.com/Burtsev-Alexey/net-object-deep-copy and adjusted + +Source code is released under the MIT license. + +The MIT License (MIT) +Copyright (c) 2014 Burtsev Alexey + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; + +using Core.ArrayExtensions; + +namespace Core +{ + public static class ObjectExtensions + { + private static readonly MethodInfo CloneMethod = + typeof(object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance); + + public static bool IsPrimitive(this System.Type type) + { + if (type == typeof(string)) return true; + return type.IsValueType & type.IsPrimitive; + } + + /// + /// Do not deeply copy objects for which evaluates to false + /// + public static object Copy(this object originalObject, Predicate deepCopyPred) + { + return InternalCopy(originalObject, new Dictionary(new ReferenceEqualityComparer()), + deepCopyPred); + } + + private static object InternalCopy(object originalObject, IDictionary visited, + Predicate deepCopyPred) + { + if (originalObject == null) return null; + var typeToReflect = originalObject.GetType(); + if (IsPrimitive(typeToReflect) || !deepCopyPred(typeToReflect)) return originalObject; + if (visited.ContainsKey(originalObject)) return visited[originalObject]; + if (typeof(Delegate).IsAssignableFrom(typeToReflect)) return null; + var cloneObject = CloneMethod.Invoke(originalObject, null); + if (typeToReflect.IsArray) + { + var arrayType = typeToReflect.GetElementType(); + if (IsPrimitive(arrayType) == false && deepCopyPred(arrayType)) + { + var clonedArray = (Array) cloneObject; + clonedArray.ForEach((array, indices) => + array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited, deepCopyPred), indices)); + } + } + + visited.Add(originalObject, cloneObject); + CopyFields(originalObject, visited, cloneObject, typeToReflect, deepCopyPred); + RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect, deepCopyPred); + return cloneObject; + } + + private static void RecursiveCopyBaseTypePrivateFields(object originalObject, + IDictionary visited, object cloneObject, Type typeToReflect, Predicate deepCopyPred) + { + if (typeToReflect.BaseType != null) + { + RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType, + deepCopyPred); + CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType, deepCopyPred, + BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate); + } + } + + private static void CopyFields(object originalObject, IDictionary visited, object cloneObject, + Type typeToReflect, Predicate deepCopyPred, + BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | + BindingFlags.FlattenHierarchy, Func filter = null) + { + foreach (var fieldInfo in typeToReflect.GetFields(bindingFlags)) + { + if (filter != null && filter(fieldInfo) == false) continue; + if (IsPrimitive(fieldInfo.FieldType) || !deepCopyPred(fieldInfo.FieldType)) continue; + var originalFieldValue = fieldInfo.GetValue(originalObject); + var clonedFieldValue = InternalCopy(originalFieldValue, visited, deepCopyPred); + fieldInfo.SetValue(cloneObject, clonedFieldValue); + } + } + + public static T Copy(this T original, Predicate deepCopyPred) + { + return (T) Copy((object) original, deepCopyPred); + } + } + + public class ReferenceEqualityComparer : EqualityComparer + { + public override bool Equals(object x, object y) + { + return ReferenceEquals(x, y); + } + + public override int GetHashCode(object obj) + { + if (obj == null) return 0; + return obj.GetHashCode(); + } + } + + namespace ArrayExtensions + { + public static class ArrayExtensions + { + public static void ForEach(this Array array, Action action) + { + if (array.LongLength == 0) return; + var walker = new ArrayTraverse(array); + do + { + action(array, walker.Position); + } while (walker.Step()); + } + } + + internal class ArrayTraverse + { + private readonly int[] maxLengths; + public int[] Position; + + public ArrayTraverse(Array array) + { + maxLengths = new int[array.Rank]; + for (var i = 0; i < array.Rank; ++i) maxLengths[i] = array.GetLength(i) - 1; + Position = new int[array.Rank]; + } + + public bool Step() + { + for (var i = 0; i < Position.Length; ++i) + if (Position[i] < maxLengths[i]) + { + Position[i]++; + for (var j = 0; j < i; j++) Position[j] = 0; + return true; + } + + return false; + } + } + } +} \ No newline at end of file diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs index 335f4c868..6d2d60bb7 100644 --- a/Source/Core/Parser.cs +++ b/Source/Core/Parser.cs @@ -20,6 +20,7 @@ using System; using System.Diagnostics.Contracts; +using System.Linq; using System.Reflection; namespace Microsoft.Boogie { @@ -563,7 +564,7 @@ void Procedure(out Procedure/*!*/ proc, out /*maybe null*/ Implementation impl) Spec(pre, mods, post); } ImplBody(out locals, out stmtList); - impl = new Implementation(x, x.val, typeParams.ConvertAll(tp => new TypeVariable(tp.tok, tp.Name)), + impl = new Implementation(x, x.val, typeParams.ConvertAll(tp => new TypeVariable(tp.tok, tp.Name)), Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, kv == null ? null : (QKeyValue)kv.Clone(), this.errors); } else SynErr(112); @@ -581,7 +582,7 @@ void Implementation(out Implementation/*!*/ impl) { Expect(35); ProcSignature(false, out x, out typeParams, out ins, out outs, out kv); ImplBody(out locals, out stmtList); - impl = new Implementation(x, x.val, typeParams, ins, outs, locals, stmtList, kv, this.errors); + impl = new Implementation(x, x.val, typeParams, ins, outs, locals, stmtList, kv, this.errors); } void Attribute(ref QKeyValue kv) { diff --git a/Source/Core/ProofGenInfo.cs b/Source/Core/ProofGenInfo.cs new file mode 100644 index 000000000..ca0f164ef --- /dev/null +++ b/Source/Core/ProofGenInfo.cs @@ -0,0 +1,592 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Linq; +using System.Reflection; + +using Core; + +namespace Microsoft.Boogie +{ + public enum BranchIndicator + { + NoGuard, + GuardHolds, + GuardFails, + LoopBody + } + + /// + /// A class used to collect information needed for the generation of the AST-to-CFG part of the validation certificate for a Boogie procedure. + /// + public class ProofGenInfo + { + /// The original object, which contains the original list of objects, which is Boogie's internal AST representation. + private StmtList stmtList; + + private IList unoptimizedBlocks; + private List newVarsAfterDesugaringinCFGBlocks; + + /// A list of copies of the objects in . + private IList originalAst; + + /// A list containing the same objects, which are in with all nested BigBlocks explicitly added. + private IList bigblocksBeforeNamingAnonymous; + + // Dictionaries used to keep track of relations between different kinds of blocks. + private IDictionary mappingOrigBigBlockToOrigBlock; + private IDictionary mappingCopyBigblockToOrigBigblock; + private IDictionary mappingOrigBigblockToCopyBigblock; + + //TODO: Fix this. + /** A dictionary mapping a 'LoopHead' BigBlock to a tuple of two BigBlocks. + * A LoopHead is a special BigBlock that is a second copy (copy of a copy) has an empty list of simpleCmds and a as a . + * The first BigBlock in the tuple is the copied BigBlock, from which the LoopHead was created. + * The second BigBlock in the tuple is the original BigBlock the copy corresponds to. */ + private IDictionary mappingCopyBigblockToOrigBigblockWithTupleValue; + + //TODO: Consider changing to a set. + // A marker set to false indicates that a BigBlock is nested in another BigBlock. + private IDictionary mappingCopyBigBlockToMarker; + + //TODO: This mapping uses Original BigBlocks, not copies. Fix. + /** The first hint is a guard (possibly null) that needs to be taken care of in the global lemma that's to be generated. + * The second hint is a BranchIndicator that indicates how that needs to be done. */ + private IDictionary mappingCopyBigBlockToHints; + + // Map a BigBlock (copy) to the unique integer label (index) of its corresponding Term object (in InnerAst.cs). + private IDictionary mappingCopyBigBlockToIndex; + + // Map a BigBlock (original) to the Loop BigBlock (original) it's nested into. + private IDictionary mappingBigBlockToOrigLoopBigBlock; + + // TODO: This doesn't need to be a list. + // List of BigBlocks added after a loop if that loop is the end of the procedure. + private IList loopEndingBlocks; + + private List newVarsFromDesugaring; + + public void InstantiateVars() + { + originalAst = new List(); + bigblocksBeforeNamingAnonymous = new List(); + + mappingCopyBigBlockToMarker = new Dictionary(); + + mappingOrigBigBlockToOrigBlock = new Dictionary(); + mappingCopyBigblockToOrigBigblock = new Dictionary(); + mappingOrigBigblockToCopyBigblock = new Dictionary(); + mappingCopyBigblockToOrigBigblockWithTupleValue = new Dictionary(); + + mappingCopyBigBlockToHints = new Dictionary(); + mappingCopyBigBlockToIndex = new Dictionary(); + + mappingBigBlockToOrigLoopBigBlock = new Dictionary(); + newVarsFromDesugaring = new List(); + + loopEndingBlocks = new List(); + } + + public void SetStmtList(StmtList stmtList) + { + this.stmtList = stmtList; + } + + public StmtList GetStmtList() + { + return stmtList; + } + + public void SetUnoptimizedBlocks(IList blocks) + { + unoptimizedBlocks = blocks; + } + + public IList GetUnpotimizedBlocks() + { + return unoptimizedBlocks; + } + + public void SetNewVarsCFG(List newVars) + { + newVarsAfterDesugaringinCFGBlocks = newVars; + } + + public List GetNewVarsCFG() + { + return newVarsAfterDesugaringinCFGBlocks; + } + + public IList GetBigBlocks() + { + return bigblocksBeforeNamingAnonymous; + } + + public IList GetOriginalAst() + { + return originalAst; + } + + public IDictionary GetMappingCopyBigBlockToMarker() + { + return mappingCopyBigBlockToMarker; + } + + public IDictionary GetMappingOrigBigBlockToOrigBlock() + { + return mappingOrigBigBlockToOrigBlock; + } + + public IDictionary GetMappingCopyBigblockToOrigBigblock() + { + return mappingCopyBigblockToOrigBigblock; + } + + public IDictionary GetMappingOrigBigblockToCopyBigblock() + { + return mappingOrigBigblockToCopyBigblock; + } + + public IDictionary GetMappingCopyBigblockToOrigBigblockWithTupleValue() + { + return mappingCopyBigblockToOrigBigblockWithTupleValue; + } + + public IDictionary GetMappingCopyBigBlockToHints() + { + return mappingCopyBigBlockToHints; + } + + public IDictionary GetMappingBigBlockToLoopBigBlock() + { + return mappingBigBlockToOrigLoopBigBlock; + } + + public IDictionary GetMappingCopyBigBlockToIndex() + { + return mappingCopyBigBlockToIndex; + } + + public IList GetloopEndingBlocks() + { + return loopEndingBlocks; + } + + public List GetNewVarsFromDesugaring() + { + return newVarsFromDesugaring; + } + + public void MakeOriginalAst(StmtList stmtList) + { + foreach (var bb in stmtList.BigBlocks) + { + BigBlock copy = mappingOrigBigblockToCopyBigblock[bb]; + originalAst.Add(copy); + } + } + + public void AddToOriginalAst(BigBlock b) + { + originalAst.Add(b); + } + + /// + /// Add a BigBlock to the list and recursively add its nested BigBlocks. + /// + public void AddBigBlockBeforeNamingAnonymous(BigBlock b, bool marker, BigBlock parentBigBlockOrig, + BigBlock parentBigBlockCopy, BranchIndicator branchIndicator) + { + BigBlock copy = null; + switch (branchIndicator) + { + case BranchIndicator.NoGuard: + FillEmptyElseBranches(b); + //injectEmptyBlockAtTheEndOfBranches(b); + + copy = CopyBigBlock(b); + mappingCopyBigblockToOrigBigblock.Add(copy, b); + mappingOrigBigblockToCopyBigblock.Add(b, copy); + mappingCopyBigBlockToMarker.Add(copy, marker); + bigblocksBeforeNamingAnonymous.Add(copy); + break; + + case BranchIndicator.GuardHolds: + { + IfCmd ifcmd = (IfCmd) parentBigBlockOrig.ec; + int position = ifcmd.thn.BigBlocks.IndexOf(b); + + IfCmd ifcmdCopy = (IfCmd) parentBigBlockCopy.ec; + BigBlock currentBigBlockCopy = ifcmdCopy.thn.BigBlocks[position]; + + mappingCopyBigblockToOrigBigblock.Add(currentBigBlockCopy, b); + mappingOrigBigblockToCopyBigblock.Add(b, currentBigBlockCopy); + mappingCopyBigBlockToMarker.Add(currentBigBlockCopy, marker); + bigblocksBeforeNamingAnonymous.Add(currentBigBlockCopy); + + copy = currentBigBlockCopy; + break; + } + case BranchIndicator.GuardFails: + { + IfCmd ifcmd = (IfCmd) parentBigBlockOrig.ec; + int position = ifcmd.elseBlock.BigBlocks.IndexOf(b); + + IfCmd ifcmdCopy = (IfCmd) parentBigBlockCopy.ec; + BigBlock currentBigBlockCopy = ifcmdCopy.elseBlock.BigBlocks[position]; + + mappingCopyBigblockToOrigBigblock.Add(currentBigBlockCopy, b); + mappingOrigBigblockToCopyBigblock.Add(b, currentBigBlockCopy); + mappingCopyBigBlockToMarker.Add(currentBigBlockCopy, marker); + bigblocksBeforeNamingAnonymous.Add(currentBigBlockCopy); + + copy = currentBigBlockCopy; + break; + } + case BranchIndicator.LoopBody: + { + WhileCmd wcmd = (WhileCmd) parentBigBlockOrig.ec; + int position = wcmd.Body.BigBlocks.IndexOf(b); + + WhileCmd wcmdCopy = (WhileCmd) parentBigBlockCopy.ec; + BigBlock currentBigBlockCopy = wcmdCopy.Body.BigBlocks[position]; + + mappingCopyBigblockToOrigBigblock.Add(currentBigBlockCopy, b); + mappingOrigBigblockToCopyBigblock.Add(b, currentBigBlockCopy); + mappingCopyBigBlockToMarker.Add(currentBigBlockCopy, marker); + bigblocksBeforeNamingAnonymous.Add(currentBigBlockCopy); + + copy = currentBigBlockCopy; + break; + } + default: + throw new ArgumentOutOfRangeException(nameof(branchIndicator), branchIndicator, + "Unknown or Uninitialized Branch Indicator"); + } + + if (b.ec is IfCmd) + { + IfCmd ifcmd = (IfCmd) b.ec; + foreach (BigBlock bb in ifcmd.thn.BigBlocks) + { + AddBigBlockBeforeNamingAnonymous(bb, false, b, copy, BranchIndicator.GuardHolds); + } + + if (ifcmd.elseBlock != null) + { + foreach (BigBlock bb in ifcmd.elseBlock.BigBlocks) + { + AddBigBlockBeforeNamingAnonymous(bb, false, b, copy, BranchIndicator.GuardFails); + } + } + } + else if (b.ec is WhileCmd) + { + BigBlock simpleCmdsRemoved = new BigBlock(copy.tok, copy.LabelName, new List(), copy.ec, copy.tc); + //simpleCmdsRemoved.successorBigBlock = b.successorBigBlock; + BigBlock copy1 = simpleCmdsRemoved; + mappingCopyBigblockToOrigBigblock.Add(copy1, simpleCmdsRemoved); + mappingCopyBigblockToOrigBigblockWithTupleValue.Add(copy1, (simpleCmdsRemoved, b)); + mappingOrigBigblockToCopyBigblock.Add(simpleCmdsRemoved, copy1); + bigblocksBeforeNamingAnonymous.Add(copy1); + mappingCopyBigBlockToMarker.Add(copy1, false); + + WhileCmd whilecmd = (WhileCmd) b.ec; + foreach (BigBlock bb in whilecmd.Body.BigBlocks) + { + AddBigBlockBeforeNamingAnonymous(bb, false, b, copy, BranchIndicator.LoopBody); + } + } + } + + public void AddBigBlockToLoopPair(BigBlock b0, BigBlock b1) + { + mappingBigBlockToOrigLoopBigBlock.Add(b0, b1); + + if (b0.ec is IfCmd ifcmd) + { + foreach (var thenBb in ifcmd.thn.BigBlocks) + { + AddBigBlockToLoopPair(thenBb, b1); + } + + if (ifcmd.elseBlock != null) + { + foreach (var elseBb in ifcmd.elseBlock.BigBlocks) + { + AddBigBlockToLoopPair(elseBb, b1); + } + } + } + } + + public void AddBigBlockToBlockPair(BigBlock b0, Block b1) + { + mappingOrigBigBlockToOrigBlock.Add(b0, b1); + } + + public void AddBigBlockToHintsPair(BigBlock b, (Expr, BranchIndicator) tuple) + { + mappingCopyBigBlockToHints.Add(b, (tuple.Item1, tuple.Item2)); + } + + public void AddBigBlockToIndexPair(BigBlock b, int index) + { + mappingCopyBigBlockToIndex.Add(b, index); + } + + /// + /// Make a copy of a BigBlock. The objects in its simpleCmds field and in the simpleCmds fields of its nested BigBlocks are not copied. + /// + public BigBlock CopyBigBlock(BigBlock b) + { + StructuredCmd ecCopy = null; + if (b.ec is IfCmd) + { + IfCmd @if = (IfCmd) b.ec; + + IList thenCopy = new List(); + foreach (BigBlock bb in @if.thn.BigBlocks) + { + thenCopy.Add(CopyBigBlock(bb)); + } + + StmtList thenCopyStmts = new StmtList(thenCopy, @if.thn.EndCurly); + + IList elseCopy = new List(); + StmtList elseCopyStmts; + if (@if.elseBlock == null) + { + elseCopyStmts = new StmtList(elseCopy, new Token()); + } + else + { + foreach (BigBlock bb in @if.elseBlock.BigBlocks) + { + elseCopy.Add(CopyBigBlock(bb)); + } + + elseCopyStmts = new StmtList(elseCopy, @if.elseBlock.EndCurly); + } + + ecCopy = new IfCmd(@if.tok, @if.Guard, thenCopyStmts, @if.elseIf, elseCopyStmts); + } + else if (b.ec is WhileCmd) + { + WhileCmd @while = (WhileCmd) b.ec; + + IList bodyCopy = new List(); + foreach (BigBlock bb in @while.Body.BigBlocks) + { + bodyCopy.Add(CopyBigBlock(bb)); + } + + StmtList bodyCopyStmts = new StmtList(bodyCopy, @while.Body.EndCurly); + ecCopy = new WhileCmd(@while.tok, @while.Guard, @while.Invariants, bodyCopyStmts); + } + else + { + ecCopy = b.ec; + } + + var copyCmds = new List(); + var newVarsFromDesugaring = new List(); + foreach (var cmd in b.simpleCmds) + { + copyCmds.Add(cmd); + } + + GetNewVarsFromDesugaring().AddRange(newVarsFromDesugaring); + String nameCopy = b.LabelName != null ? "''" + b.LabelName + "''" : null; + return new BigBlock(b.tok, nameCopy, copyCmds, ecCopy, b.tc); + } + + /// + /// If the elseBlock field of an is null, initialize it to a with one 'empty' BigBlock. + /// This is done, so that the AST-to-CFG part of the proof generation can properly generate a proof. + /// + private void FillEmptyElseBranches(BigBlock b) + { + if (b.ec is IfCmd ifcmd) + { + foreach (var thenBb in ifcmd.thn.BigBlocks) + { + FillEmptyElseBranches(thenBb); + } + + if (ifcmd.elseBlock == null) + { + IList emptyElseBranch = new List(); + BigBlock emptyElseBranchBigBlock = new BigBlock(Token.NoToken, null, new List(), null, null); + emptyElseBranch.Add(emptyElseBranchBigBlock); + + emptyElseBranchBigBlock.successorBigBlock = b.successorBigBlock; + + ifcmd.elseBlock = new StmtList(emptyElseBranch, Token.NoToken); + } + + foreach (var elseBb in ifcmd.elseBlock.BigBlocks) + { + FillEmptyElseBranches(elseBb); + } + } + else if (b.ec is WhileCmd wcmd) + { + foreach (var bodyBb in wcmd.Body.BigBlocks) + { + FillEmptyElseBranches(bodyBb); + } + } + } + + public void RecordLoopDoneBlock(BigBlock loopDoneBigBlock) + { + loopEndingBlocks.Add(loopDoneBigBlock); + } + + private bool InBigBlock(BigBlock bigBlockToBeChecked, BigBlock possibleContainerBigBlock) + { + if (possibleContainerBigBlock.ec is WhileCmd wcmd) + { + if (wcmd.Body.BigBlocks.Contains(bigBlockToBeChecked)) + { + return true; + } + + foreach (var bodyBb in wcmd.Body.BigBlocks) + { + if (InBigBlock(bigBlockToBeChecked, bodyBb)) + { + return true; + } + } + } + else if (possibleContainerBigBlock.ec is IfCmd ifcmd) + { + if (ifcmd.thn.BigBlocks.Contains(bigBlockToBeChecked) || + ifcmd.elseBlock.BigBlocks.Contains(bigBlockToBeChecked)) + { + return true; + } + + foreach (var thenBb in ifcmd.thn.BigBlocks) + { + if (InBigBlock(bigBlockToBeChecked, thenBb)) + { + return true; + } + } + + if (ifcmd.elseBlock != null) + { + foreach (var elseBb in ifcmd.elseBlock.BigBlocks) + { + if (InBigBlock(bigBlockToBeChecked, elseBb)) + { + return true; + } + } + } + } + + return false; + } + + private static readonly MethodInfo CloneMethod = + typeof(object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance); + + public IList CopyBlocks( + IList blocks, + Dictionary> predecessorMap, + bool desugarCalls, + Predicate deepCopyCmdPred, + out List newVarsFromDesugaring) + { + //shallow copy of each block + update edges to copied blocks + deep copy of cmds if specified + //TODO: need to make sure this is sufficient + IDictionary oldToNewBlock = new Dictionary(); + + IList copyBlocks = new List(); + + newVarsFromDesugaring = new List(); + + //don't copy variables, since proof generation assumes sharing of variable identities + Func copyCmd = cmd => + deepCopyCmdPred(cmd) + ? cmd.Copy(t => t != typeof(IdentifierExpr) && t != typeof(TypeVariable) && t != typeof(QKeyValue)) + : (Cmd) CloneMethod.Invoke(cmd, null); + + foreach (var b in blocks) + { + var copyCmds = new List(); + foreach (var cmd in b.Cmds) + if (cmd is SugaredCmd sugaredCmd && desugarCalls) + { + var stateCmd = sugaredCmd.Desugaring as StateCmd; + newVarsFromDesugaring.AddRange(stateCmd.Locals); + foreach (var desugaredCmd in stateCmd.Cmds) copyCmds.Add(copyCmd(desugaredCmd)); + } + else + { + copyCmds.Add(copyCmd(cmd)); + } + + var copyBlock = (Block) CloneMethod.Invoke(b, null); + copyBlock.Cmds = copyCmds; + copyBlock.Predecessors = predecessorMap[b]; + + copyBlocks.Add(copyBlock); + oldToNewBlock.Add(b, copyBlock); + } + + //make sure block references are updated accordingly + foreach (var copyBlock in copyBlocks) + { + if (copyBlock.TransferCmd is GotoCmd gtc) + { + var newSuccessors = gtc.labelTargets.Select(succ => oldToNewBlock[succ]).ToList(); + var gotoCmdCopy = (GotoCmd) CloneMethod.Invoke(gtc, null); + gotoCmdCopy.labelTargets = newSuccessors; + copyBlock.TransferCmd = gotoCmdCopy; + } + else + { + copyBlock.TransferCmd = (TransferCmd) CloneMethod.Invoke(copyBlock.TransferCmd, null); + } + + if (copyBlock.Predecessors != null) + copyBlock.Predecessors = copyBlock.Predecessors.Select(succ => oldToNewBlock[succ]).ToList(); + } + + return copyBlocks; + } + + /// + /// Copy from . We compute predecessors ourselves, since at certain points the + /// predecessors property for blocks is not in-sync with the CFG (and we do not want to adjust the Boogie + /// objects). + /// + public Dictionary> ComputePredecessors(IEnumerable blocks) + { + var predecessors = new Dictionary>(); + foreach (var b in blocks) predecessors.Add(b, new List()); + + foreach (var b in blocks) + { + var gtc = b.TransferCmd as GotoCmd; + if (gtc != null) + { + Contract.Assert(gtc.labelTargets != null); + foreach (var /*!*/ dest in gtc.labelTargets) + { + Contract.Assert(dest != null); + predecessors[dest].Add(b); + } + } + } + + return predecessors; + } + + } +} \ No newline at end of file diff --git a/Source/Core/ProofGenInfoManager.cs b/Source/Core/ProofGenInfoManager.cs new file mode 100644 index 000000000..e14f8122a --- /dev/null +++ b/Source/Core/ProofGenInfoManager.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; + +namespace Microsoft.Boogie +{ + public static class ProofGenInfoManager + { + private static IDictionary mapFromImplementationToProofGenInfo; + private static ProofGenInfo currentProofGenInfo; + + public static IDictionary GetMapFromImplementationToProofGenInfo() + { + /* + if (mapFromImplementationToProofGenInfo == null) + { + mapFromImplementationToProofGenInfo = new Dictionary(); + } + + return mapFromImplementationToProofGenInfo; + */ + + return mapFromImplementationToProofGenInfo ??= new Dictionary(); + } + + public static ProofGenInfo GetCurrentProofGenInfo() + { + return currentProofGenInfo ??= new ProofGenInfo(); + } + + public static void SetCurrentProofGenInfo(ProofGenInfo proofGenInfo) + { + currentProofGenInfo = proofGenInfo; + } + } +} \ No newline at end of file diff --git a/Source/ExecutionEngine/ExecutionEngine.cs b/Source/ExecutionEngine/ExecutionEngine.cs index 0a0362ec6..005a233ba 100644 --- a/Source/ExecutionEngine/ExecutionEngine.cs +++ b/Source/ExecutionEngine/ExecutionEngine.cs @@ -501,10 +501,24 @@ public static bool ProcessProgram(Program program, string bplFileName, string pr CommandLineOptions.Clo.PrettyPrint); CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured; } + + #region proofgen + + foreach (var tuple in ProofGenInfoManager.GetMapFromImplementationToProofGenInfo()) + { + Implementation impl = tuple.Key; + ProofGenInfo proofGenInfo = tuple.Value; + + var predecessorMap = proofGenInfo.ComputePredecessors(impl.Blocks); + var unoptimizedBlockCopies = proofGenInfo.CopyBlocks(impl.Blocks , predecessorMap, true, cmd => false, out var newVarsAfterDesugaring); + proofGenInfo.SetUnoptimizedBlocks(unoptimizedBlockCopies); + proofGenInfo.SetNewVarsCFG(newVarsAfterDesugaring); + } + #endregion EliminateDeadVariables(program); - CoalesceBlocks(program); + //CoalesceBlocks(program); Inline(program); diff --git a/Source/ProofGenUtil/ObjectExtensions.cs b/Source/ProofGenUtil/ObjectExtensions.cs new file mode 100644 index 000000000..84281091f --- /dev/null +++ b/Source/ProofGenUtil/ObjectExtensions.cs @@ -0,0 +1,158 @@ +/** + * +Deep copy utility method taken from https://github.com/Burtsev-Alexey/net-object-deep-copy and adjusted + +Source code is released under the MIT license. + +The MIT License (MIT) +Copyright (c) 2014 Burtsev Alexey + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using ProofGenUtil.ArrayExtensions; + +namespace ProofGenUtil +{ + public static class ObjectExtensions + { + private static readonly MethodInfo CloneMethod = + typeof(object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance); + + public static bool IsPrimitive(this Type type) + { + if (type == typeof(string)) return true; + return type.IsValueType & type.IsPrimitive; + } + + /// + /// Do not deeply copy objects for which evaluates to false + /// + public static object Copy(this object originalObject, Predicate deepCopyPred) + { + return InternalCopy(originalObject, new Dictionary(new ReferenceEqualityComparer()), + deepCopyPred); + } + + private static object InternalCopy(object originalObject, IDictionary visited, + Predicate deepCopyPred) + { + if (originalObject == null) return null; + var typeToReflect = originalObject.GetType(); + if (IsPrimitive(typeToReflect) || !deepCopyPred(typeToReflect)) return originalObject; + if (visited.ContainsKey(originalObject)) return visited[originalObject]; + if (typeof(Delegate).IsAssignableFrom(typeToReflect)) return null; + var cloneObject = CloneMethod.Invoke(originalObject, null); + if (typeToReflect.IsArray) + { + var arrayType = typeToReflect.GetElementType(); + if (IsPrimitive(arrayType) == false && deepCopyPred(arrayType)) + { + var clonedArray = (Array) cloneObject; + clonedArray.ForEach((array, indices) => + array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited, deepCopyPred), indices)); + } + } + + visited.Add(originalObject, cloneObject); + CopyFields(originalObject, visited, cloneObject, typeToReflect, deepCopyPred); + RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect, deepCopyPred); + return cloneObject; + } + + private static void RecursiveCopyBaseTypePrivateFields(object originalObject, + IDictionary visited, object cloneObject, Type typeToReflect, Predicate deepCopyPred) + { + if (typeToReflect.BaseType != null) + { + RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType, + deepCopyPred); + CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType, deepCopyPred, + BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate); + } + } + + private static void CopyFields(object originalObject, IDictionary visited, object cloneObject, + Type typeToReflect, Predicate deepCopyPred, + BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | + BindingFlags.FlattenHierarchy, Func filter = null) + { + foreach (var fieldInfo in typeToReflect.GetFields(bindingFlags)) + { + if (filter != null && filter(fieldInfo) == false) continue; + if (IsPrimitive(fieldInfo.FieldType) || !deepCopyPred(fieldInfo.FieldType)) continue; + var originalFieldValue = fieldInfo.GetValue(originalObject); + var clonedFieldValue = InternalCopy(originalFieldValue, visited, deepCopyPred); + fieldInfo.SetValue(cloneObject, clonedFieldValue); + } + } + + public static T Copy(this T original, Predicate deepCopyPred) + { + return (T) Copy((object) original, deepCopyPred); + } + } + + public class ReferenceEqualityComparer : EqualityComparer + { + public override bool Equals(object x, object y) + { + return ReferenceEquals(x, y); + } + + public override int GetHashCode(object obj) + { + if (obj == null) return 0; + return obj.GetHashCode(); + } + } + + namespace ArrayExtensions + { + public static class ArrayExtensions + { + public static void ForEach(this Array array, Action action) + { + if (array.LongLength == 0) return; + var walker = new ArrayTraverse(array); + do + { + action(array, walker.Position); + } while (walker.Step()); + } + } + + internal class ArrayTraverse + { + private readonly int[] maxLengths; + public int[] Position; + + public ArrayTraverse(Array array) + { + maxLengths = new int[array.Rank]; + for (var i = 0; i < array.Rank; ++i) maxLengths[i] = array.GetLength(i) - 1; + Position = new int[array.Rank]; + } + + public bool Step() + { + for (var i = 0; i < Position.Length; ++i) + if (Position[i] < maxLengths[i]) + { + Position[i]++; + for (var j = 0; j < i; j++) Position[j] = 0; + return true; + } + + return false; + } + } + } +} \ No newline at end of file diff --git a/Source/ProofGenUtil/ProofGenUtil.csproj b/Source/ProofGenUtil/ProofGenUtil.csproj new file mode 100644 index 000000000..eb2460e91 --- /dev/null +++ b/Source/ProofGenUtil/ProofGenUtil.csproj @@ -0,0 +1,9 @@ + + + + net6.0 + enable + enable + + + diff --git a/Source/ProofGeneration/ASTRepr/ASTRepr.cs b/Source/ProofGeneration/ASTRepr/ASTRepr.cs new file mode 100644 index 000000000..58db5bc5f --- /dev/null +++ b/Source/ProofGeneration/ASTRepr/ASTRepr.cs @@ -0,0 +1,84 @@ +using System.Collections.Generic; +using System.Diagnostics.Contracts; +using System.Linq; +using Isabelle.Ast; +using Isabelle.Util; +using Microsoft.Boogie; + +namespace ProofGeneration.ASTRepresentation +{ + public class ASTRepr + { + private readonly IList bigblocks; + + public ASTRepr(IList bigblocks) + { + this.bigblocks = bigblocks; + } + + public int NumOfBlocks() + { + return bigblocks.Count; + } + + public bool ContainsBlock(BigBlock b) + { + return bigblocks.Contains(b); + } + + public int GetUniqueIntLabel(BigBlock b) + { + for (var i = 0; i < bigblocks.Count; i++) + { + if (bigblocks[i] == b) + { + return i; + } + } + + return -1; + } + + public TermList GetAstAsTermList(ProofGenInfo proofGenInfo) + { + IList terms = new List(); + for (var i = 0; i < bigblocks.Count; i++) + { + if (proofGenInfo.GetMappingCopyBigBlockToMarker()[bigblocks[i]]) + { + Term bb = IsaCommonTerms.TermIdentFromName("bigblock_" + i); + terms.Add(bb); + } + } + + return new TermList(terms); + } + + public List GetMainContinuations(ProofGenInfo proofGenInfo) + { + List strings = new List(); + for (var i = 0; i < bigblocks.Count; i++) + { + if (proofGenInfo.GetMappingCopyBigBlockToMarker()[bigblocks[i]]) + { + string cont = "cont_" + i + "_def"; + strings.Add(cont); + } + } + + return strings; + } + + public IEnumerable GetBlocksForwards() + { + for (var i = 0; i < bigblocks.Count; i++) + yield return bigblocks[i]; + } + + public IEnumerable GetBlocksBackwards() + { + for (var i = bigblocks.Count - 1; i >= 0; i--) + yield return bigblocks[i]; + } + } +} \ No newline at end of file diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs b/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs new file mode 100644 index 000000000..7233acc65 --- /dev/null +++ b/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs @@ -0,0 +1,323 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Isabelle.Ast; +using Isabelle.Util; +using Microsoft.Boogie; +using ProofGeneration.BoogieIsaInterface; +using ProofGeneration.CFGRepresentation; +using ProofGeneration.ASTRepresentation; +using ProofGeneration.PhasesUtil; +using ProofGeneration.Util; +using ProofGeneration.ASTRepresentation; + +namespace ProofGeneration.AstToCfg +{ + public class AstToCfgEndToEnd + { + private readonly string axiomAssmName = "Axioms"; + private readonly string binderEmptyAssmName = "BinderNs"; + private readonly string closedAssmName = "Closed"; + private readonly string constsGlobalsAssmName = "ConstsGlobal"; + //private readonly TermIdent finalNodeOrReturn = IsaCommonTerms.TermIdentFromName("m'"); + //private readonly TermIdent finalState = IsaCommonTerms.TermIdentFromName("s'"); + private readonly string finterpAssmName = "FInterp"; + private readonly string nonEmptyTypesAssmName = "NonEmptyTypes"; + + private readonly TermIdent normalInitState = IsaCommonTerms.TermIdentFromName("ns"); + private readonly string oldGlobalAssmName = "OldGlobal"; + private readonly string paramsLocalsAssmName = "ParamsLocal"; + private readonly string preconditionsAssmName = "Precondition"; + + private readonly string redAssmName = "Red"; + private readonly string vcAssmName = "VC"; + private BoogieContextIsa boogieContext; + + private IProgramAccessor beforeCfgProgramAccessor; + //private IProgramAccessor afterCfgProgramAccessor; + + private readonly string varContextName = "\\0"; + + //private readonly LemmaDecl entryLemma; + + public IEnumerable EndToEndProof( + string entryBlockAstLemma, + string cfgToDagEndToEndLemma, + Term vcAssm, + IProgramAccessor beforeCfgProgramAccessor, + IProgramAccessor afterCfgProgramAccessor, + ASTRepr ast, + ProofGenInfo proofGenInfo) + { + this.beforeCfgProgramAccessor = beforeCfgProgramAccessor; + //this.afterCfgProgramAccessor = afterCfgProgramAccessor; + + boogieContext = new BoogieContextIsa( + IsaCommonTerms.TermIdentFromName("A"), + IsaCommonTerms.TermIdentFromName("M"), + IsaCommonTerms.TermIdentFromName(varContextName), + IsaCommonTerms.TermIdentFromName("\\"), + IsaCommonTerms.EmptyList + ); + + var abbrev = new AbbreviationDecl( + varContextName, + new Tuple, Term>(new List(), + new TermTuple(beforeCfgProgramAccessor.ConstsAndGlobalsDecl(), beforeCfgProgramAccessor.ParamsAndLocalsDecl())) + ); + var result = new List {abbrev}; + + BigBlock bigblock0 = ast.GetBlocksForwards().First(); + string cont0 = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[bigblock0]; + Term cont0Id = IsaCommonTerms.TermIdentFromName(cont0); + Term stateName = IsaCommonTerms.TermIdentFromName("ns"); + Term initState1 = IsaBoogieTerm.Normal(stateName); + + var kStepBigBlockRed = IsaBoogieTerm.RedBigBlockKStep( + BoogieContextIsa.CreateWithNewVarContext( + boogieContext, + new TermTuple(beforeCfgProgramAccessor.ConstsAndGlobalsDecl(), beforeCfgProgramAccessor.ParamsAndLocalsDecl()) + ), + IsaBoogieTerm.StartConfigTerm(bigblock0, cont0Id, beforeCfgProgramAccessor, initState1), + IsaBoogieTerm.EndConfigTerm(), + IsaBoogieTerm.astId(), + IsaCommonTerms.TermIdentFromName("j") + ); + + var proofSb = new StringBuilder(); + proofSb.AppendLine("proof -"); + proofSb.AppendLine("from " + redAssmName + " obtain j where Aux:" + "\"" + kStepBigBlockRed + "\""); + proofSb.AppendLine("by (meson rtranclp_imp_relpowp)"); + proofSb.AppendLine("show ?thesis"); + proofSb.AppendLine(ProofUtil.Apply("rule ast_to_cfg_lemmas." + entryBlockAstLemma)); + proofSb.AppendLine("unfolding ast_to_cfg_lemmas_def"); + proofSb.AppendLine("apply (rule FInterp)"); + proofSb.AppendLine("apply (rule Aux)"); + proofSb.AppendLine("apply (rule valid_config_implies_not_failure)"); + proofSb.AppendLine(ProofUtil.Apply("rule " + cfgToDagEndToEndLemma)); + proofSb.AppendLine("apply (simp add: " + + beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def " + + afterCfgProgramAccessor.ParamsDecl() + "_def " + afterCfgProgramAccessor.LocalsDecl() + "_def)"); + 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 " + preconditionsAssmName + " apply (simp add: " + + beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def " + + afterCfgProgramAccessor.ParamsDecl() + "_def " + afterCfgProgramAccessor.LocalsDecl() + "_def " + + beforeCfgProgramAccessor.PreconditionsDecl() + "_def " + afterCfgProgramAccessor.PreconditionsDecl() + "_def)"); + proofSb.AppendLine("using " + paramsLocalsAssmName + " apply (simp add: " + + beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def " + + afterCfgProgramAccessor.ParamsDecl() + "_def " + afterCfgProgramAccessor.LocalsDecl() + "_def)"); + proofSb.AppendLine("using " + constsGlobalsAssmName + " apply (simp add: " + + beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def " + + afterCfgProgramAccessor.ParamsDecl() + "_def " + afterCfgProgramAccessor.LocalsDecl() + "_def)"); + + proofSb.AppendLine("using " + oldGlobalAssmName + " apply simp"); + proofSb.AppendLine("using " + binderEmptyAssmName + " apply simp"); + + proofSb.AppendLine("apply (rule valid_config_implies_satisfied_posts)"); + proofSb.AppendLine(ProofUtil.Apply("rule " + cfgToDagEndToEndLemma)); + proofSb.AppendLine("apply (simp add: " + + beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def " + + afterCfgProgramAccessor.ParamsDecl() + "_def " + afterCfgProgramAccessor.LocalsDecl() + "_def)"); + //TODO: don't hardcode this + 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 " + preconditionsAssmName + " apply (simp add: " + + beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def " + + afterCfgProgramAccessor.ParamsDecl() + "_def " + afterCfgProgramAccessor.LocalsDecl() + "_def " + + beforeCfgProgramAccessor.PreconditionsDecl() + "_def " + afterCfgProgramAccessor.PreconditionsDecl() + "_def)"); + proofSb.AppendLine("using " + paramsLocalsAssmName + " apply (simp add: " + + beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def " + + afterCfgProgramAccessor.ParamsDecl() + "_def " + afterCfgProgramAccessor.LocalsDecl() + "_def)"); + proofSb.AppendLine("using " + constsGlobalsAssmName + " apply (simp add: " + + beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def " + + afterCfgProgramAccessor.ParamsDecl() + "_def " + afterCfgProgramAccessor.LocalsDecl() + "_def)"); + + proofSb.AppendLine("using " + oldGlobalAssmName + " apply simp"); + proofSb.AppendLine("using " + binderEmptyAssmName + " apply simp+"); + + proofSb.AppendLine("done"); + proofSb.AppendLine("qed"); + + var helperLemmaName = "end_to_end_theorem_aux_ast"; + + var helperLemma = + new LemmaDecl( + helperLemmaName, + LemmaContext(ast, vcAssm, proofGenInfo), + IsaBoogieTerm.AstValidConfiguration(boogieContext, beforeCfgProgramAccessor.PostconditionsDecl()), + new Proof(new List {proofSb.ToString()}) + ); + result.Add(helperLemma); + + var assumptions = new List(); + + string contName = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[bigblock0]; + Term contId = IsaCommonTerms.TermIdentFromName(contName); + Term initStateId = IsaBoogieTerm.Normal(IsaCommonTerms.TermIdentFromName("ns")); + + Term astDecl = ast.GetAstAsTermList(proofGenInfo); + List continuations = ast.GetMainContinuations(proofGenInfo); + string continuationsAsString = null; + foreach (var str in continuations) + { + continuationsAsString += str + " "; + } + + var initAstTerm = new TermApp + ( + IsaCommonTerms.TermIdentFromName("init_ast"), + astDecl, + IsaCommonTerms.TermIdentFromName("ns") + ); + + BoogieContextIsa dummyBoogieContext = new BoogieContextIsa( + IsaCommonTerms.TermIdentFromName("A"), + IsaCommonTerms.TermIdentFromName("M"), + IsaCommonTerms.TermIdentFromName("\\"), + IsaCommonTerms.TermIdentFromName("\\"), + IsaCommonTerms.TermIdentFromName("\\") + ); + + var bigBlockMultiRedInitAst = IsaBoogieTerm.RedBigBlockMulti( + dummyBoogieContext, + initAstTerm, + IsaBoogieTerm.EndConfigTerm(), + IsaBoogieTerm.astId() + ); + + assumptions.Add(bigBlockMultiRedInitAst); + + var bigBlockMultiRed = IsaBoogieTerm.RedBigBlockMulti( + dummyBoogieContext, + IsaBoogieTerm.StartConfigTerm(bigblock0, contId, beforeCfgProgramAccessor, initStateId), + IsaBoogieTerm.EndConfigTerm(), + IsaBoogieTerm.astId() + ); + + var proofMethods = new List + { + "using assms", + "by (simp add: " + continuationsAsString + ")" + }; + + var initializationLemmaName = "initialization"; + var initializationLemma = + new LemmaDecl( + initializationLemmaName, + ContextElem.CreateWithAssumptions(assumptions), + bigBlockMultiRed, + new Proof(proofMethods) + ); + result.Add(initializationLemma); + + //transform end to end theorem to a compact representation + var endToEndLemma = + new LemmaDecl( + "end_to_end_theorem_ast", + ContextElem.CreateWithAssumptions(new List {vcAssm}, new List {"VC"}), + ProcedureIsCorrect( + beforeCfgProgramAccessor.FunctionsDecl(), + IsaCommonTerms.TermIdentFromName(beforeCfgProgramAccessor.ConstsDecl()), + IsaCommonTerms.TermIdentFromName(beforeCfgProgramAccessor.GlobalsDecl()), + beforeCfgProgramAccessor.AxiomsDecl(), + beforeCfgProgramAccessor.ProcDecl()), + new Proof( + new List + { + ProofUtil.Apply(ProofUtil.Rule(ProofUtil.OF("end_to_end_util2",helperLemmaName))), + "apply (rule initialization)", + "unfolding " + beforeCfgProgramAccessor.ProcDeclName() + "_def", + "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 " + + beforeCfgProgramAccessor.ProcDeclName() + "_def " + beforeCfgProgramAccessor.CfgDeclName() + "_def") + } + ) ); + + result.Add(endToEndLemma); + return result; + } + + private ContextElem LemmaContext( + ASTRepr ast, + Term vcAssm, + ProofGenInfo proofGenInfo + ) + { + BigBlock bigblock0 = ast.GetBlocksForwards().First(); + string contName = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[bigblock0]; + Term contId = IsaCommonTerms.TermIdentFromName(contName); + Term initStateId = IsaBoogieTerm.Normal(IsaCommonTerms.TermIdentFromName("ns")); + + var bigBlockMultiRed = IsaBoogieTerm.RedBigBlockMulti( + BoogieContextIsa.CreateWithNewVarContext( + boogieContext, + new TermTuple(beforeCfgProgramAccessor.ConstsAndGlobalsDecl(), beforeCfgProgramAccessor.ParamsAndLocalsDecl()) + ), + IsaBoogieTerm.StartConfigTerm(bigblock0, contId, beforeCfgProgramAccessor, initStateId), + IsaBoogieTerm.EndConfigTerm(), + IsaBoogieTerm.astId() + ); + var closedAssm = EndToEndAssumptions.ClosednessAssumption(boogieContext.absValTyMap); + var nonEmptyTypesAssm = EndToEndAssumptions.NonEmptyTypesAssumption(boogieContext.absValTyMap); + var finterpAssm = IsaBoogieTerm.FunInterpWf(boogieContext.absValTyMap, beforeCfgProgramAccessor.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, beforeCfgProgramAccessor, + new TermWithExplicitType(normalInitState, IsaBoogieType.NormalStateType(absValType))); + var presAssm = + IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState, beforeCfgProgramAccessor.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 + { + bigBlockMultiRed, vcAssm, closedAssm, nonEmptyTypesAssm, finterpAssm, axiomAssm, + presAssm, localsAssm, globalsAssm, oldGlobalStateAssm, binderEmptyAssm + }, + new List + { + redAssmName, vcAssmName, closedAssmName, nonEmptyTypesAssmName, finterpAssmName, axiomAssmName, + preconditionsAssmName, paramsLocalsAssmName, constsGlobalsAssmName, oldGlobalAssmName, + binderEmptyAssmName + } + ); + } + + private static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term globalDecls, Term axioms, + Term procedure) + { + var typeInterpId = new SimpleIdentifier("A"); + return + TermQuantifier.MetaAll( + new List{typeInterpId}, + null, + new TermApp( + IsaCommonTerms.TermIdentFromName("proc_is_correct"), + new TermWithExplicitType(new TermIdent(typeInterpId), IsaBoogieType.AbstractValueTyFunType(new VarType("a"))), + funDecls, + constantDecls, + globalDecls, + axioms, + procedure, + //TODO: define this elsewhere + IsaCommonTerms.TermIdentFromName("Ast.proc_body_satisfies_spec"))); + } + } +} \ No newline at end of file diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs new file mode 100644 index 000000000..5ef81267b --- /dev/null +++ b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs @@ -0,0 +1,1728 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using Isabelle.Ast; +using Isabelle.Util; +using Microsoft.Boogie; +using ProofGeneration.BoogieIsaInterface; +using ProofGeneration.BoogieIsaInterface.VariableTranslation; +using ProofGeneration.CFGRepresentation; +using ProofGeneration.Util; + +namespace ProofGeneration.AstToCfg +{ + public class AstToCfgLemmaManager + { + private readonly CFGRepr afterCfg; + private readonly IProgramAccessor afterCfgProgAccess; + + private readonly BasicCmdIsaVisitor basicCmdIsaVisitor; + + private readonly IProgramAccessor beforeCfgProgAccess; + private readonly IDictionary beforeToAfterBlock; + + private readonly BoogieContextIsa astBoogieContext; + private readonly BoogieContextIsa cfgBoogieContext; + + private readonly TermIdent finalNode = IsaCommonTerms.TermIdentFromName("m'"); + private readonly Term finalState = IsaCommonTerms.TermIdentFromName("s'"); + private readonly string funContextWfName; + + private readonly IDictionary mappingBigBlockToGlobalLemmaDecl; + private readonly IDictionary mappingBigBlockToLocalLemmaDecl; + + //private readonly CfgToDagHintManager hintManager; + + private readonly IsaUniqueNamer namer = new IsaUniqueNamer(); + + private readonly Term initState1; + private readonly Term normalInitState1 = IsaCommonTerms.TermIdentFromName("ns1"); + + private readonly string redCfgName = "Red"; + + //private readonly TypingTacticGenerator typingTacticGenerator; + private readonly IVariableTranslation variableTranslation; + + private readonly BoogieMethodData beforeCfgData; + + private readonly IDictionary beforeDagOrigBlock; + + public AstToCfgLemmaManager( + IProgramAccessor beforeCfgProgAccess, + IProgramAccessor afterCfgProgAccess, + BoogieContextIsa astBoogieContext, + BoogieContextIsa cfgBoogieContext, + CFGRepr afterCfg, + string funContextWfName, + // CfgToDagHintManager hintManager, + // IDictionary> blocksToLoops, + IDictionary beforeDagOrigBlock, + IDictionary beforeToAfterBlock, + BoogieMethodData beforeCfgData, + IVariableTranslationFactory varFactory + ) + { + this.beforeCfgProgAccess = beforeCfgProgAccess; + this.afterCfgProgAccess = afterCfgProgAccess; + this.afterCfg = afterCfg; + this.funContextWfName = funContextWfName; + variableTranslation = varFactory.CreateTranslation().VarTranslation; + // this.hintManager = hintManager; + // this.blocksToLoops = blocksToLoops; + this.beforeToAfterBlock = beforeToAfterBlock; + this.beforeCfgData = beforeCfgData; + + this.astBoogieContext = astBoogieContext; + this.cfgBoogieContext = cfgBoogieContext; + + initState1 = IsaBoogieTerm.Normal(normalInitState1); + basicCmdIsaVisitor = new BasicCmdIsaVisitor(varFactory); + mappingBigBlockToGlobalLemmaDecl = new Dictionary(); + mappingBigBlockToLocalLemmaDecl = new Dictionary(); + //typingTacticGenerator = new TypingTacticGenerator(beforeCfgProgAccess, varFactory); + + this.beforeDagOrigBlock = beforeDagOrigBlock; + } + + private TermList HavocedVarsTerm(IEnumerable vars) + { + return new TermList( + vars.Select(x => + { + if (variableTranslation.TryTranslateVariableId(x, out var varId, out _)) + { + return varId; + } + + throw new ProofGenUnexpectedStateException("Could not extract variable id"); + }).ToList()); + } + private Term InvariantsTerm(IEnumerable invs) + { + return new TermList(invs.Select(e => basicCmdIsaVisitor.Translate(e)).ToList()); + } + private Term ExprTerm(Expr expr) + { + return basicCmdIsaVisitor.Translate(expr); + } + + public LemmaDecl LocalLemma( + BigBlock beforeBlock, + Block afterBlock, + Expr guardHint, + Func blockLemmaName, + BranchIndicator indicator) + { + var beforeBigblockDefName = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(beforeBlock).First(); + Term startConfig = IsaBoogieTerm.StartConfigTerm(beforeBlock, IsaCommonTerms.TermIdentFromName("cont0"), beforeCfgProgAccess, initState1); + Term endConfig = IsaBoogieTerm.EndConfigTerm(); + + var afterCmdsDefName = afterCfgProgAccess.BlockInfo().CmdsQualifiedName(afterBlock); + Term afterCmds = IsaCommonTerms.TermIdentFromName(afterCmdsDefName); + + var quatifiedstateId = new SimpleIdentifier("ns1'"); + + var finalStateId2 = new SimpleIdentifier("s2'"); + Term finalState2 = new TermIdent(finalStateId2); + Term astId = IsaBoogieTerm.astId(); + + var localLemmas = new List(); + + #region local block lemma + + //TODO: write the proofs using ProofUtil + var assumptions = new List + { + IsaBoogieTerm.RedBigBlock(astBoogieContext, startConfig, endConfig, astId) + }; + + Term cfgVerifiesAssm = + TermQuantifier.MetaAll( + new List {finalStateId2}, + null, + TermBinary.MetaImplies( + IsaBoogieTerm.RedCmdList(cfgBoogieContext, afterCmds, initState1, finalState2), + TermBinary.Neq(finalState2, IsaBoogieTerm.Failure())) + ); + assumptions.Add(cfgVerifiesAssm); + + bool hasGuardHint = false; + if (indicator == BranchIndicator.GuardHolds && guardHint != null) + { + Term traceIsPossible = IsaBoogieTerm.RedExpr(astBoogieContext, + ExprTerm(guardHint), + normalInitState1, + new TermApp(IsaBoogieTerm.BoolValConstr(), IsaCommonTerms.TermIdentFromName("True"))); + hasGuardHint = true; + assumptions.Add(traceIsPossible); + } + else if (indicator == BranchIndicator.GuardFails && guardHint != null) + { + Term traceIsPossible = IsaBoogieTerm.RedExpr(astBoogieContext, + ExprTerm(guardHint), + normalInitState1, + new TermApp(IsaBoogieTerm.BoolValConstr(), IsaCommonTerms.TermIdentFromName("False"))); + hasGuardHint = true; + assumptions.Add(traceIsPossible); + } + + Term conclusion = + TermBinary.And( + TermBinary.Neq(IsaCommonTerms.TermIdentFromName("reached_state"), IsaBoogieTerm.Failure()), + TermQuantifier.ForAll( + new List {quatifiedstateId}, + null, + TermBinary.Implies( + TermBinary.Eq(IsaCommonTerms.TermIdentFromName("reached_state"), IsaBoogieTerm.Normal(new TermIdent(quatifiedstateId))), + IsaBoogieTerm.RedCmdList(cfgBoogieContext, afterCmds, initState1, IsaBoogieTerm.Normal(new TermIdent(quatifiedstateId))) ) + )); + + var proofMethods = new List(); + var proofSb = new StringBuilder(); + + if (indicator == 0 || guardHint == null) + { + proofSb.AppendLine(ProofUtil.Apply("rule block_local_rel_generic")); + proofSb.AppendLine(ProofUtil.Apply("rule Rel_Main_test[of " + beforeBigblockDefName + "]")); + proofSb.AppendLine(ProofUtil.Apply("simp add: " + beforeBigblockDefName + "_def " + afterCmdsDefName + "_def")); + proofSb.AppendLine(ProofUtil.Apply(ProofUtil.Repeat("simp add: " + afterCmdsDefName + "_def"))); + proofSb.AppendLine(ProofUtil.Apply("rule astStep")); + proofSb.AppendLine(ProofUtil.Apply("rule cfgBlockDoesntFail")); + proofSb.AppendLine(ProofUtil.Apply( ProofUtil.Repeat("simp add: " + afterCmdsDefName + "_def " + beforeBigblockDefName + "_def"))); + proofSb.AppendLine("done"); + + // proofMethods = new List + // { + // ProofUtil.Apply("rule block_local_rel_generic"), + // ProofUtil.Apply("rule Rel_Main_test[of " + beforeBigblockDefName + "]"), + // ProofUtil.Apply("simp add: " + beforeBigblockDefName + "_def " + afterCmdsDefName + "_def"), + // ProofUtil.Apply("simp add: " + afterCmdsDefName + "_def)+", + // ProofUtil.Apply("rule astStep"), + // ProofUtil.Apply("rule cfgBlockDoesntFail"), + // ProofUtil.Apply("simp add: " + afterCmdsDefName + "_def " + beforeBigblockDefName + "_def)+", + // "done" + // }; + } + else if (indicator == BranchIndicator.GuardHolds) + { + proofSb.AppendLine("unfolding " + afterCmdsDefName + "_def"); + proofSb.AppendLine(ProofUtil.Apply("rule guard_holds_push_through_assumption")); + proofSb.AppendLine(ProofUtil.Apply("rule block_local_rel_generic")); + proofSb.AppendLine(ProofUtil.Apply("rule Rel_Main_test[of " + beforeBigblockDefName + "]")); + proofSb.AppendLine(ProofUtil.Apply("simp add: " + beforeBigblockDefName + "_def")); + proofSb.AppendLine(ProofUtil.Apply("simp+")); + proofSb.AppendLine(ProofUtil.Apply("rule astStep")); + proofSb.AppendLine(ProofUtil.Apply("rule push_through_assumption_test1, rule cfgBlockDoesntFail")); + proofSb.AppendLine(ProofUtil.Apply("simp add: " + afterCmdsDefName + "_def")); + proofSb.AppendLine(ProofUtil.Apply(ProofUtil.Repeat("simp add: assms(3) " + beforeBigblockDefName + "_def"))); + proofSb.AppendLine("done"); + + // proofMethods = new List + // { + // "unfolding " + afterCmdsDefName + "_def", + // ProofUtil.Apply("rule guard_holds_push_through_assumption"), + // ProofUtil.Apply("rule block_local_rel_generic"), + // ProofUtil.Apply("rule Rel_Main_test[of " + beforeBigblockDefName + "]"), + // ProofUtil.Apply("simp add: " + beforeBigblockDefName + "_def"), + // ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + // ProofUtil.Apply("rule astStep"), + // ProofUtil.Apply("rule push_through_assumption_test1, rule cfgBlockDoesntFail"), + // ProofUtil.Apply("simp add: " + afterCmdsDefName + "_def"), + // ProofUtil.Apply("simp add: assms(3) " + beforeBigblockDefName + "_def)+", + // "done" + // }; + } + else if (indicator == BranchIndicator.GuardFails) + { + proofSb.AppendLine("unfolding " + afterCmdsDefName + "_def"); + proofSb.AppendLine(ProofUtil.Apply("rule guard_fails_push_through_assumption")); + proofSb.AppendLine(ProofUtil.Apply("rule block_local_rel_generic")); + proofSb.AppendLine(ProofUtil.Apply("rule Rel_Main_test[of " + beforeBigblockDefName + "]")); + proofSb.AppendLine(ProofUtil.Apply("simp add: " + beforeBigblockDefName + "_def")); + proofSb.AppendLine(ProofUtil.Apply("simp+")); + proofSb.AppendLine(ProofUtil.Apply("rule astStep")); + proofSb.AppendLine(ProofUtil.Apply("rule cfgBlockDoesntFail")); + proofSb.AppendLine(ProofUtil.Apply("simp add: " + afterCmdsDefName + "_def")); + proofSb.AppendLine(ProofUtil.Apply("rule push_through_assumption1")); + proofSb.AppendLine(ProofUtil.Apply("simp")); + proofSb.AppendLine(ProofUtil.Apply(NegationRule(guardHint))); + proofSb.AppendLine(ProofUtil.Apply("rule guardHint")); + proofSb.AppendLine(ProofUtil.Apply( ProofUtil.Repeat("simp add: " + beforeBigblockDefName + "_def"))); + proofSb.AppendLine(ProofUtil.Apply(NegationRule(guardHint))); + proofSb.AppendLine(ProofUtil.Apply("rule guardHint")); + proofSb.AppendLine("done"); + + // proofMethods = new List + // { + // "unfolding " + afterCmdsDefName + "_def", + // ProofUtil.Apply("rule guard_fails_push_through_assumption"), + // ProofUtil.Apply("rule block_local_rel_generic"), + // ProofUtil.Apply("rule Rel_Main_test[of " + beforeBigblockDefName + "]"), + // ProofUtil.Apply("simp add: " + beforeBigblockDefName + "_def"), + // ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + // ProofUtil.Apply("rule astStep"), + // ProofUtil.Apply("rule cfgBlockDoesntFail"), + // ProofUtil.Apply("simp add: " + afterCmdsDefName + "_def"), + // ProofUtil.Apply("rule push_through_assumption1"), + // ProofUtil.Apply(ProofUtil.Simp()), + // ProofUtil.Apply("" + NegationRule(guardHint) + ""), + // ProofUtil.Apply("rule guardHint"), + // ProofUtil.Apply("simp add: " + beforeBigblockDefName + "_def)+", + // ProofUtil.Apply("" + NegationRule(guardHint) + ""), + // ProofUtil.Apply("rule guardHint"), + // "done" + // }; + } + + List assmsLabels = new List {"astStep", "cfgBlockDoesntFail"}; + if (hasGuardHint) + { + assmsLabels.Add("guardHint"); + } + var localLemma = new LemmaDecl( + blockLemmaName(beforeBlock), + ContextElem.CreateWithAssumptions(assumptions, assmsLabels), + conclusion, + new Proof(new List {proofSb.ToString()}) + ); + + #endregion + + mappingBigBlockToLocalLemmaDecl.Add(beforeBlock, localLemma); + localLemmas.Add(localLemma); + + return localLemma; + } + + #region generate global lemma + public LemmaDecl GenerateGlobalLemma( + BigBlock startingBigBlock, + Term continuation, + Block relatedBlock, + Term posts, + (Expr, BranchIndicator) hints, + Func globalBlockLemmaName, + ProofGenInfo proofGenInfo) + { + var assumptions = new List(); + + #region assumption 1: trace through the ast + Term startConfig = IsaBoogieTerm.StartConfigTerm(startingBigBlock, continuation, beforeCfgProgAccess, initState1); + Term endConfig = IsaBoogieTerm.EndConfigTerm(); + Term astId = IsaBoogieTerm.astId(); + Term numStepsId = IsaCommonTerms.TermIdentFromName("j"); + + Term astTrace = IsaBoogieTerm.RedBigBlockKStep(astBoogieContext, startConfig, endConfig, astId, numStepsId); + assumptions.Add(astTrace); + #endregion + + var finalCfgNodeId = new SimpleIdentifier("m'"); + var finalStateId = new SimpleIdentifier("s'"); + Term initialStateNode = new NatConst(afterCfg.GetUniqueIntLabel(relatedBlock)); + var boundStateId = new SimpleIdentifier("ns_end"); + + #region assumption 2: all cfg traces end in a non-failing state + + Term cfgVerifiesAssm = + TermQuantifier.MetaAll( + new List {finalCfgNodeId, finalStateId}, + null, + TermBinary.MetaImplies( + IsaBoogieTerm.RedCFGMulti(cfgBoogieContext, + afterCfgProgAccess.CfgDecl(), + IsaBoogieTerm.CFGConfigNode( + initialStateNode, IsaBoogieTerm.Normal(normalInitState1) + ), + IsaBoogieTerm.CFGConfig(finalNode, finalState)), + TermBinary.Neq(finalState, IsaBoogieTerm.Failure())) + ); + assumptions.Add(cfgVerifiesAssm); + + #endregion + + #region assumption 3: all cfg traces end in a state that satisfies the post-conditions + Term cfgSatisfiesPostsAssm = + TermQuantifier.MetaAll( + new List {finalCfgNodeId, finalStateId}, + null, + TermBinary.MetaImplies( + IsaBoogieTerm.RedCFGMulti(cfgBoogieContext, + afterCfgProgAccess.CfgDecl(), + IsaBoogieTerm.CFGConfigNode( + initialStateNode, IsaBoogieTerm.Normal(normalInitState1) + ), + IsaBoogieTerm.CFGConfig(finalNode, finalState)), + TermBinary.MetaImplies( + new TermApp(IsaCommonTerms.TermIdentFromName("is_final_config"), IsaBoogieTerm.CFGConfig(finalNode, finalState)), + TermQuantifier.ForAll( + new List {boundStateId}, + null, + TermBinary.Implies( + TermBinary.Eq(finalState, IsaBoogieTerm.Normal(new TermIdent(boundStateId))), + IsaBoogieTerm.ExprAllSat(astBoogieContext, new TermIdent(boundStateId), posts)) + ) + )) + ); + assumptions.Add(cfgSatisfiesPostsAssm); + + #endregion + + #region conditional assumption 4: the given trace through the ast is actually possible + + bool guardSemantics = false; + BigBlock correspondingOrigBigBlock = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; + if (hints.Item2 == BranchIndicator.GuardHolds && hints.Item1 != null) + { + Term traceIsPossible = IsaBoogieTerm.RedExpr(astBoogieContext, + ExprTerm(hints.Item1), + normalInitState1, + new TermApp(IsaBoogieTerm.BoolValConstr(), IsaCommonTerms.TermIdentFromName("True"))); + guardSemantics = true; + assumptions.Add(traceIsPossible); + } + else if (hints.Item2 == BranchIndicator.GuardFails && hints.Item1 != null) + { + Term traceIsPossible = IsaBoogieTerm.RedExpr(astBoogieContext, + ExprTerm(hints.Item1), + normalInitState1, + new TermApp(IsaBoogieTerm.BoolValConstr(), IsaCommonTerms.TermIdentFromName("False"))); + guardSemantics = true; + assumptions.Add(traceIsPossible); + } + else if (proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().ContainsKey(startingBigBlock)) + { + WhileCmd wcmd = (WhileCmd) startingBigBlock.ec; + if (wcmd.Guard == null) + { + Term personalGuard = Isabelle.Util.IsaCommonTerms.TermIdentFromName("personal_guard"); + Term equalitySign = Isabelle.Util.IsaCommonTerms.TermIdentFromName("="); + + Term personalGuardIsNone = + new TermApp(personalGuard, equalitySign, IsaCommonTerms.NoneOption()); + guardSemantics = true; + assumptions.Add(personalGuardIsNone); + } + } + else if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingOrigBigBlock)) + { + BigBlock loopBigBlockOrig = proofGenInfo.GetMappingBigBlockToLoopBigBlock()[correspondingOrigBigBlock]; + BigBlock loopBigBlockCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[loopBigBlockOrig]; + + WhileCmd wcmd = (WhileCmd) loopBigBlockCopy.ec; + if (wcmd.Guard == null) + { + Term enclosingLoopGuard = Isabelle.Util.IsaCommonTerms.TermIdentFromName("guard_of_enclosing_loop"); + Term equalitySign = Isabelle.Util.IsaCommonTerms.TermIdentFromName("="); + + Term enclosingLoopGuardIsNone = + new TermApp(enclosingLoopGuard, equalitySign, IsaCommonTerms.NoneOption()); + guardSemantics = true; + assumptions.Add(enclosingLoopGuardIsNone); + } + } + + #endregion + + BigBlock correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; + if (proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().ContainsKey(startingBigBlock)) + { + correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()[startingBigBlock].Item2; + } + BigBlock successorBigBlockOrig = correspondingBigBlockOrig.successorBigBlock; + + #region conditional assumption 5: loop induction hypothesis + + bool hasLoopIH = false; + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + BigBlock enclosingLoop = proofGenInfo.GetMappingBigBlockToLoopBigBlock()[correspondingBigBlockOrig]; + BigBlock enclosingLoopCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[enclosingLoop]; + + IDictionary origBlockBeforeDag = beforeDagOrigBlock.InverseDict(); + Block enclosingLoopCfgBlock = proofGenInfo.GetMappingOrigBigBlockToOrigBlock()[enclosingLoop]; + Block enclosingLoopCfgBlockCopy = origBlockBeforeDag[enclosingLoopCfgBlock]; + + Term blockIndex; + if (true /* enclosingLoopCfgBlockCopy.cmds.Any() */ ) + { + Block successorCfgBlock = afterCfg.GetSuccessorBlocks(enclosingLoopCfgBlockCopy).First(); + //Block successorCfgBlockCopy = origBlockBeforeDag[successorCfgBlock]; + + blockIndex = new NatConst(afterCfg.GetUniqueIntLabel(successorCfgBlock)); + } + else + { + blockIndex = new NatConst(afterCfg.GetUniqueIntLabel(enclosingLoopCfgBlockCopy)); + } + + int unwrappedEnclosingLoopBigBlockIndex = proofGenInfo.GetMappingCopyBigBlockToIndex()[enclosingLoopCopy] + 1; + + Term succBigBlockTermId = IsaCommonTerms.TermIdentFromName(beforeCfgProgAccess.BigBlockInfo().TheoryName + ".bigblock_" + unwrappedEnclosingLoopBigBlockIndex); + Term succContId = IsaCommonTerms.TermIdentFromName("cont_" + unwrappedEnclosingLoopBigBlockIndex); + Term cfgBodyId = IsaCommonTerms.TermIdentFromName(afterCfgProgAccess.BlockInfo().getTheoryName() + ".proc_body"); + //Term blockIndex = new NatConst(unwrappedEnclosingLoopBigBlockIndex); + + Term loop_ih_assm = IsaBoogieTerm.LoopIH(astBoogieContext, cfgBoogieContext, astId, succBigBlockTermId, succContId, cfgBodyId, blockIndex, posts); + hasLoopIH = true; + assumptions.Add(loop_ih_assm); + } + + #endregion + + Term conclusion = IsaBoogieTerm.AstValidConfiguration(astBoogieContext, posts); + + //TODO: Document the cases for the proofs + #region proof + var proofMethods = new List(); + + //A BigBlock is final if it EITHER has no successor and it has no structure to branch into OR it contains a return command. + if (successorBigBlockOrig == null && startingBigBlock.ec == null || startingBigBlock.tc is ReturnCmd) + { + proofMethods = GenerateFinalBlockProof(startingBigBlock, relatedBlock, hints.Item1, hints.Item2, proofGenInfo); + } + //TODO: Fix this. + //A BigBlock is a LoopHead if it is a key in this dictionary. + else if (proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().ContainsKey(startingBigBlock)) + { + WhileCmd wcmd = (WhileCmd) startingBigBlock.ec; + Expr guard = wcmd.Guard; + proofMethods = GenerateLoopHeadProof(startingBigBlock, relatedBlock, guard, proofGenInfo); + } + //A BigBlock is generic if it has no structure to branch into and it doesn't contain a return command. + else if (startingBigBlock.ec == null) + { + proofMethods = GenerateProofGeneric(startingBigBlock, relatedBlock, hints.Item1, hints.Item2, proofGenInfo); + } + //A 'WhileSuccessor' proof is generated for a BigBlock that contains a non-null WhileCmd object and a non-empty simpleCmds list. + //A BigBlock that contains a non-null WhileCmd object and an empty simpleCmds list is treated as a special case. + else if (startingBigBlock.ec is WhileCmd && mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock)) + { + WhileCmd wcmd = (WhileCmd) startingBigBlock.ec; + Expr personalGuard = wcmd.Guard; + proofMethods = GenerateWhileSuccessorProof(startingBigBlock, relatedBlock, hints.Item1, personalGuard, hints.Item2, proofGenInfo); + } + //An 'IfSuccessor' proof is generated for a BigBlock that contains a non-null IfCmd object. + else if (startingBigBlock.ec is IfCmd) + { + IfCmd ifcmd = (IfCmd) startingBigBlock.ec; + Expr guard = ifcmd.Guard; + proofMethods = GenerateIfSuccessorProof(startingBigBlock, relatedBlock, guard, hints.Item1, hints.Item2, proofGenInfo); + } + //TODO: Test consecutive loops in a loop. + /* TODO: All BigBlocks in a loop body except the very first one are assigned a NoGuard BranchIndicator. + TODO: This works for ProofGen only if Block Coalescing is turned off. */ + //These last three checks all address the special case of a BigBlock that contains a non-null WhileCmd object and an empty simpleCmds. + //1. The BigBlock contains a non-null WhileCmd object and an empty simpleCmds and is right in the beginning of an Else Branch. + else if (hints.Item2 == BranchIndicator.GuardFails && + correspondingBigBlockOrig.ec is WhileCmd && + !startingBigBlock.simpleCmds.Any()) + { + proofMethods = GenerateEndingAfterUnwrappingProof(startingBigBlock, relatedBlock, hints.Item1, BranchIndicator.GuardFails, proofGenInfo); + } + //2. The BigBlock contains a non-null WhileCmd object and an empty simpleCmds and is in another loop. + else if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + proofMethods = GenerateEndingAfterUnwrappingProof(startingBigBlock, relatedBlock, hints.Item1, hints.Item2, proofGenInfo); + } + //3. The BigBlock contains a non-null WhileCmd object and an empty simpleCmds. + else if (!startingBigBlock.simpleCmds.Any() && startingBigBlock.ec is WhileCmd) + { + proofMethods = GenerateEndingAfterUnwrappingProof(startingBigBlock, relatedBlock, hints.Item1, BranchIndicator.NoGuard, proofGenInfo); + } + #endregion + + List assmsLabels = new List {"astTrace", "cfgDoesntFail", "cfgSatisfiesPosts"}; + if (guardSemantics) + { + assmsLabels.Add("guardHint"); + } + + if (hasLoopIH) + { + assmsLabels.Add("inductionHypothesis"); + } + + var globalLemma = new LemmaDecl( + globalBlockLemmaName(startingBigBlock), + ContextElem.CreateWithAssumptions(assumptions, assmsLabels), + conclusion, + new Proof(proofMethods) + ); + + mappingBigBlockToGlobalLemmaDecl.Add(startingBigBlock, globalLemma); + return globalLemma; + } + #endregion + + private string NegationRule(Expr guard) + { + NAryExpr nary = guard as NAryExpr; + + if (ReferenceEquals(guard, Expr.Literal(true))) + { + return ProofUtil.Rule("neg_equiv1"); + } + if (ReferenceEquals(guard, Expr.Literal(false))) + { + return ProofUtil.Rule("neg_equiv2"); + } + if (nary != null) + { + if (nary.Fun is UnaryOperator unOp) + { + if (unOp.Op == UnaryOperator.Opcode.Not) + { + return ProofUtil.Rule("double_neg"); + } + } + else if (nary.Fun is BinaryOperator binOp) + { + if (binOp.Op == BinaryOperator.Opcode.Eq) + { + return ProofUtil.Rule("neg_eq"); + } + if (binOp.Op == BinaryOperator.Opcode.Neq) + { + return ProofUtil.Rule("neg_neq"); + } + if (binOp.Op == BinaryOperator.Opcode.Lt) + { + return ProofUtil.Rule("neg_lt"); + } + if (binOp.Op == BinaryOperator.Opcode.Le) + { + return ProofUtil.Rule("neg_le"); + } + if (binOp.Op == BinaryOperator.Opcode.Ge) + { + return ProofUtil.Rule("neg_ge"); + } + if (binOp.Op == BinaryOperator.Opcode.Gt) + { + return ProofUtil.Rule("neg_gt"); + } + } + } + + return ProofUtil.Rule("neg_refl"); + } + + private string ExpandDefinitions(string contId, BigBlock startingBigBlock, ProofGenInfo proofGenInfo, BranchIndicator branchIndicator) + { + //BigBlock correspondingBigBlockOrig = proofGenInfo.getMappingCopyBigblockToOrigBigblock()[startingBigBlock]; + //IfCmd _if = (IfCmd) correspondingBigBlockOrig.ec; + + IfCmd @if = (IfCmd) startingBigBlock.ec; + + string expansion = "apply (simp add: " + contId + "_def "; + if (branchIndicator == BranchIndicator.GuardHolds) + { + foreach (var thenBb in @if.thn.BigBlocks) + { + BigBlock thenBranchCopy = thenBb; //proofGenInfo.getMappingOrigBigblockToCopyBigblock()[then_bb]; + string thenBranchId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(thenBranchCopy).First(); + string thenBranchContId = "cont_" + (proofGenInfo.GetMappingCopyBigBlockToIndex()[thenBranchCopy]); + expansion += thenBranchId + "_def " + thenBranchContId + "_def "; + } + } + else if (@if.elseBlock != null) + { + foreach (var elseBb in @if.elseBlock.BigBlocks) + { + BigBlock elseBranchCopy = elseBb; //proofGenInfo.getMappingOrigBigblockToCopyBigblock()[else_bb]; + string elseBranchId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(elseBranchCopy).First(); + string elseBranchContId = "cont_" + (proofGenInfo.GetMappingCopyBigBlockToIndex()[elseBranchCopy]); + expansion += elseBranchId + "_def " + elseBranchContId + "_def "; + } + } + + expansion += ")"; + return expansion; + } + + private List GenerateFinalBlockProof( + BigBlock startingBigBlock, + Block relatedBlock, + Expr entryGuard, + BranchIndicator indicator, + ProofGenInfo proofGenInfo) + { + string bigblockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(startingBigBlock).First(); + string blockId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".block_" + afterCfg.GetUniqueIntLabel(relatedBlock); + string nodeId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".node_" + afterCfg.GetUniqueIntLabel(relatedBlock); + string outEdgesId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".outEdges_" + afterCfg.GetUniqueIntLabel(relatedBlock); + string contId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[startingBigBlock]; + + string syntacticRel; + string traceIsPossible = ProofUtil.Apply("rule guardHint"); + List finalPartofProof; + List middlePartofProof; + List beginningOfProof; + + if (mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock)) + { + string nameLemmaLocal = "placeholder"; + if (mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock)) + { + nameLemmaLocal = mappingBigBlockToLocalLemmaDecl[startingBigBlock].Name; + } + + syntacticRel = ProofUtil.Apply("rule Rel_Main_test[of " + bigblockId + "]"); + finalPartofProof = new List + { + ProofUtil.Apply("rule " + nameLemmaLocal), + "apply assumption+", + (indicator != 0 && entryGuard != null) ? traceIsPossible : "", + "done", + "qed" + }; + } + else if (startingBigBlock.tc is ReturnCmd) + { + syntacticRel = ProofUtil.Apply("rule Rel_Invs[of " + bigblockId + "]"); + finalPartofProof = new List + { + ProofUtil.Apply("simp add: " + bigblockId + "_def"), + ProofUtil.Apply("simp add: " + blockId + "_def"), + ProofUtil.Apply("simp add: end_return"), + "done", + "qed" + }; + } + else + { + syntacticRel = ProofUtil.Apply("rule Rel_Invs[of " + bigblockId + "]"); + finalPartofProof = new List + { + ProofUtil.Apply("simp add: " + bigblockId + "_def"), + ProofUtil.Apply("simp add: end_static"), + "done", + "qed" + }; + } + + if (indicator == 0 || entryGuard == null) + { + middlePartofProof = new List + { + ProofUtil.Apply("rule disjI1"), + ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("rule " + outEdgesId), + ProofUtil.Apply("rule cfgDoesntFail"), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("rule cfgSatisfiesPosts"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("simp add: " + nodeId) + }; + } + else if (indicator == BranchIndicator.GuardFails) + { + middlePartofProof = new List + { + ProofUtil.Apply("rule disjI2"), + ProofUtil.Apply("rule disjI2"), + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply(" " + NegationRule(entryGuard)), + ProofUtil.Apply("rule guardHint"), + ProofUtil.Apply("rule " + outEdgesId), + ProofUtil.Apply("rule cfgDoesntFail"), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("rule cfgSatisfiesPosts"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("simp add: " + nodeId) + }; + } + else if (indicator == BranchIndicator.GuardHolds) + { + middlePartofProof = new List + { + ProofUtil.Apply("rule disjI2"), + ProofUtil.Apply("rule disjI1"), + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("rule guardHint"), + ProofUtil.Apply("rule " + outEdgesId), + ProofUtil.Apply("rule cfgDoesntFail"), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("rule cfgSatisfiesPosts"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("simp add: " + nodeId) + }; + } + else + { + middlePartofProof = new List + { + ProofUtil.Apply("rule disjI1"), + ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("rule " + outEdgesId), + ProofUtil.Apply("rule cfgDoesntFail"), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("rule cfgSatisfiesPosts"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("simp add: " + nodeId), + }; + } + + beginningOfProof = new List + { + "proof -", + "show ?thesis", + ProofUtil.Apply("rule generic_ending_block_global_rel"), + syntacticRel, + ProofUtil.Apply("simp add: " + bigblockId + "_def"), + mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply(ProofUtil.Simp()) : "", + ProofUtil.Apply("rule astTrace"), + ProofUtil.Apply("simp add: " + bigblockId + "_def"), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply(ProofUtil.Simp()), + startingBigBlock.tc is ReturnCmd ? "" : ProofUtil.Apply("rule " + contId + "_def"), + ProofUtil.Apply("rule " + nodeId) + }; + + List proofMethods = new List(); + proofMethods.AddRange(beginningOfProof); + proofMethods.AddRange(middlePartofProof); + proofMethods.AddRange(finalPartofProof); + + return proofMethods; + } + + private List GenerateLoopHeadProof( + BigBlock startingBigBlock, + Block relatedBlock, + Expr personalGuard, + ProofGenInfo proofGenInfo) + { + List proofMethods = new List(); + + BigBlock correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; + if (proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().Keys.Contains(startingBigBlock)) + { + correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()[startingBigBlock].Item2; + } + + //Get the BigBlock that comes after the loop. + BigBlock afterLoopBigBlockOrig = correspondingBigBlockOrig.successorBigBlock; + BigBlock afterLoopBigBlockCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[afterLoopBigBlockOrig]; + + BigBlock unwrappedAfterLoopBigBlockCopy = null; + foreach (var tuple in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) + { + if (tuple.Value.Item2 == afterLoopBigBlockOrig) + { + unwrappedAfterLoopBigBlockCopy = tuple.Key; + break; + } + } + + //Get the BigBlock that's the first one in the loop body. + WhileCmd wcmd = (WhileCmd) correspondingBigBlockOrig.ec; + BigBlock bodyBigBlockOrig = wcmd.Body.BigBlocks.First(); + BigBlock bodyBigBlockCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[bodyBigBlockOrig]; + + //Get the successor CFG blocks to the CFG block that's related to the starting BigBlock. + IEnumerable successors = afterCfg.GetSuccessorBlocks(relatedBlock); + if (successors != null && successors.Any()) + { + Block succ1 = successors.First(); + int succ1UniqueIntLabel = afterCfg.GetUniqueIntLabel(succ1); + Block succ2 = successors.Last(); + int succ2UniqueIntLabel = afterCfg.GetUniqueIntLabel(succ2); + + //Get the names of all of the terms that are to be used in the proof. + string bigblockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(startingBigBlock).First(); + string blockId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".block_" + afterCfg.GetUniqueIntLabel(relatedBlock); + string nodeId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".node_" + afterCfg.GetUniqueIntLabel(relatedBlock); + string outEdgesId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".outEdges_" + afterCfg.GetUniqueIntLabel(relatedBlock); + + //string bigblockBodyId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(bodyBigBlockCopy).First(); + string contId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[startingBigBlock]; + string bodyBigBlockContId = "cont_" + (proofGenInfo.GetMappingCopyBigBlockToIndex()[bodyBigBlockCopy]); + + #region loop body definitions in simplifier + + string unfoldedLoopBodyDefinitions = "apply (simp add: " + contId + "_def "; + WhileCmd _while = (WhileCmd) correspondingBigBlockOrig.ec; + foreach (BigBlock bodyBb in _while.Body.BigBlocks) + { + BigBlock bodyBbCopy = null; + if (proofGenInfo.GetMappingOrigBigblockToCopyBigblock().ContainsKey(bodyBb)) + { + bodyBbCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[bodyBb]; + } + else + { + foreach (var tuple in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) + { + if (tuple.Value.Item2 == bodyBb) + { + bodyBbCopy = tuple.Key; + break; + } + } + } + + if (bodyBbCopy != null) + { + string currBigBlockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(bodyBbCopy).First(); + string currContId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[bodyBbCopy]; + + unfoldedLoopBodyDefinitions = + unfoldedLoopBodyDefinitions + currBigBlockId + "_def " + currContId + "_def "; + } + } + + unfoldedLoopBodyDefinitions += ")"; + #endregion + + string afterLoopBigBlockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(afterLoopBigBlockCopy).First(); + + string succBlockId1 = afterCfgProgAccess.BlockInfo().getTheoryName() + ".block_" + afterCfg.GetUniqueIntLabel(succ1); + string succNodeId1 = afterCfgProgAccess.BlockInfo().getTheoryName() + ".node_" + afterCfg.GetUniqueIntLabel(succ1); + string succOutEdgesId1 = afterCfgProgAccess.BlockInfo().getTheoryName() + ".outEdges_" + afterCfg.GetUniqueIntLabel(succ1); + + string afterLoopContId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[afterLoopBigBlockCopy]; + + string nameLemmaSucc1 = mappingBigBlockToGlobalLemmaDecl[bodyBigBlockCopy].Name; + string nameLemmaSucc2 = mappingBigBlockToGlobalLemmaDecl[afterLoopBigBlockCopy].Name; + + string unwrappedAfterLoopBigBlockId = ""; + string unwrappedAfterLoopContId = ""; + string nameLemmaSucc3 = ""; + if (unwrappedAfterLoopBigBlockCopy != null) + { + unwrappedAfterLoopBigBlockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(unwrappedAfterLoopBigBlockCopy).First(); + unwrappedAfterLoopContId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[unwrappedAfterLoopBigBlockCopy]; + nameLemmaSucc3 = mappingBigBlockToGlobalLemmaDecl[unwrappedAfterLoopBigBlockCopy].Name; + } + + #region construct proof + + var beginningOfProof = new List + { + "using assms", + "proof (induction j arbitrary: ns1 rule: less_induct)", + "case (less j)", + "then show ?case", + "proof (cases j)", + "case 0", + "then show ?thesis", + "using valid_configuration_def less.prems(1) is_final.elims(2) " + contId + "_def" + " by fastforce", + "next", + "case (Suc j')", + "show ?thesis", + ProofUtil.Apply("rule block_global_rel_loop_head "), + ProofUtil.Apply("rule Rel_Invs[of " + bigblockId + " _ _ _ " + blockId + "]"), + ProofUtil.Apply("simp add:" + bigblockId + "_def " + blockId + "_def"), + ProofUtil.Apply("rule less(2)"), + ProofUtil.Apply("rule less(3), simp"), + ProofUtil.Apply("rule less(4), simp"), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("simp add:" + bigblockId + "_def"), + "apply simp ", + ProofUtil.Apply("rule block_local_rel_loop_head"), + ProofUtil.Apply("rule Rel_Invs[of " + bigblockId + "]"), + ProofUtil.Apply(ProofUtil.Repeat("simp add:" + bigblockId + "_def")), + ProofUtil.Apply(ProofUtil.Repeat("simp add:" + blockId + "_def " + nodeId)), + ProofUtil.Apply("rule " + contId + "_def"), + ProofUtil.Apply("erule disjE"), + + personalGuard == null ? ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) : null, + personalGuard == null ? "apply (erule disjE)" : null, + //TODO: get rid of this + personalGuard == null ? "defer" : null, + + ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succ2UniqueIntLabel + "]")), + ProofUtil.Apply(ProofUtil.Repeat("simp add:" + outEdgesId)), + ProofUtil.Apply("simp add:member_rec(1)"), + personalGuard != null ? ProofUtil.Apply("erule conjE") : null, + ProofUtil.Apply("rule " + nameLemmaSucc1 + ""), + unfoldedLoopBodyDefinitions, + ProofUtil.Apply(ProofUtil.Repeat("blast")), + ProofUtil.Apply("rule loop_IH_prove"), + ProofUtil.Apply("rule less.IH"), + ProofUtil.Apply("erule strictly_smaller_helper2"), + ProofUtil.Apply(ProofUtil.Simp()), + "unfolding " + contId + "_def " + bodyBigBlockContId + "_def", + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("blast"), + ProofUtil.Apply("blast"), + + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) && + personalGuard == null + ? ProofUtil.Apply("rule guardHint") + : null, + }; + + var insideOfLoopAddition1 = new List + { + ProofUtil.Apply("rule loop_IH_prove"), + ProofUtil.Apply("rule loop_IH_apply"), + + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) && + personalGuard == null + ? ProofUtil.Apply("rule less(6)") + : ProofUtil.Apply("rule less(5)"), + + ProofUtil.Apply("rule strictly_smaller_helper3"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + }; + + var insideOfLoopAddition2 = new List + { + ProofUtil.Apply("rule loop_IH_prove"), + ProofUtil.Apply("rule loop_IH_apply"), + + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) && + personalGuard == null + ? ProofUtil.Apply("rule less(6)") + : ProofUtil.Apply("rule less(5)"), + + ProofUtil.Apply("rule strictly_smaller_helper4"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + }; + + var whileTrueEndingAfterSkippingEndBlock = new List + { + personalGuard == null && !proofGenInfo.GetMappingBigBlockToLoopBigBlock() + .ContainsKey(correspondingBigBlockOrig) + ? ProofUtil.Apply("rule guardHint") + : null, + ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succ1UniqueIntLabel + "]")), + ProofUtil.Apply(ProofUtil.Repeat("simp add:" + outEdgesId)), + ProofUtil.Apply("simp add:member_rec(1)"), + personalGuard != null ? ProofUtil.Apply("erule conjE") : null, + ProofUtil.Apply("rule ending_after_skipping_endblock2"), + + //TODO: repeat is possibly redundant here! + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("blast"), + personalGuard != null ? ProofUtil.Apply("blast") : ProofUtil.Apply(ProofUtil.Repeat("blast")), + personalGuard != null ? ProofUtil.Apply(ProofUtil.Simp()) : null, + + personalGuard != null && !personalGuard.Equals(Expr.True) ? ProofUtil.Apply(ProofUtil.Simp()) : null, + personalGuard != null && !personalGuard.Equals(Expr.True) + ? ProofUtil.Apply("rule " + nameLemmaSucc2 + "") + : null, + + //TODO: repeat is redundant here! + personalGuard != null && !personalGuard.Equals(Expr.True) ? ProofUtil.Apply("blast") : null, + + //afterLoopBigBlockOrig.successorBigBlock != null ? "apply blast" : null, + personalGuard == null ? ProofUtil.Apply("rule " + nameLemmaSucc2) : null, + personalGuard == null ? ProofUtil.Apply(ProofUtil.Simp()) : null, + + ProofUtil.Apply("blast") + }; + + var endingAfterSkippingEndblock = new List + { + personalGuard == null && !proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule guardHint") : null, + ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succ1UniqueIntLabel + "]")), + ProofUtil.Apply(ProofUtil.Repeat("simp add:" + outEdgesId)), + ProofUtil.Apply("simp add:member_rec(1)"), + personalGuard != null ? ProofUtil.Apply("erule conjE") : null, + ProofUtil.Apply("rule ending_after_skipping_endblock2"), + + //TODO: repeat is possibly redundant here! + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("blast"), + personalGuard != null ? ProofUtil.Apply("blast") : ProofUtil.Apply(ProofUtil.Repeat("blast")), + personalGuard != null ? ProofUtil.Apply(ProofUtil.Simp()) : null, + + personalGuard != null && !personalGuard.Equals(Expr.True) ? ProofUtil.Apply(ProofUtil.Simp()) : null, + personalGuard != null && !personalGuard.Equals(Expr.True) ? ProofUtil.Apply("rule " + nameLemmaSucc2 + "") : null, + + //TODO: repeat is redundant here! + personalGuard != null && !personalGuard.Equals(Expr.True) ? ProofUtil.Apply("blast") : null, + + //afterLoopBigBlockOrig.successorBigBlock != null ? "apply blast" : null, + personalGuard == null ? ProofUtil.Apply("rule " + nameLemmaSucc2) : null, + personalGuard == null ? ProofUtil.Apply(ProofUtil.Simp()) : null, + + proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Repeat("blast")) : null, + + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) + ? (personalGuard != null + ? ProofUtil.Apply("rule correctness_propagates_through_assumption") + : ProofUtil.Apply("rule correctness_propagates_through_empty")) + : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? "apply blast" : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply("simp add: " + succNodeId1 + "") : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply("simp add: " + succBlockId1 + "_def") : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) + ? (personalGuard != null + ? ProofUtil.Apply(NegationRule(personalGuard)) + : null) + : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Simp()) : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply("simp add: " + succOutEdgesId1 + "") : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Repeat("simp add: member_rec")) : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) + ? (personalGuard != null + ? ProofUtil.Apply("rule correctness_propagates_through_assumption3") + : ProofUtil.Apply("rule correctness_propagates_through_empty2")) + : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? "apply blast" : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply("simp add: " + succNodeId1 + "") : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply("simp add: " + succBlockId1 + "_def") : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) + ? (personalGuard != null + ? ProofUtil.Apply(NegationRule(personalGuard)) + : null) + : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Simp()) : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply("simp add: " + succOutEdgesId1 + "") : null, + !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Repeat("simp add: member_rec")) : null + }; + + var endingAfterSkippingEndBlockAndUnwrapping = new List + { + ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succ1UniqueIntLabel + "]")), + ProofUtil.Apply(ProofUtil.Repeat("simp add:" + outEdgesId)), + ProofUtil.Apply("simp add:member_rec(1)"), + ProofUtil.Apply("erule conjE"), + + ProofUtil.Apply("rule ending_after_skipping_endblock_and_unwrapping"), + "apply assumption", + ProofUtil.Apply("simp add: " + afterLoopBigBlockId + "_def"), + ProofUtil.Apply(ProofUtil.Simp()), + "apply assumption", + "apply blast", + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("simp add:" + succNodeId1 + ""), + ProofUtil.Apply("simp add:" + succBlockId1 + "_def"), + ProofUtil.Apply(NegationRule(personalGuard)), + ProofUtil.Apply("simp add:" + succOutEdgesId1), + ProofUtil.Apply("simp add: member_rec"), + ProofUtil.Apply("simp add:" + succNodeId1), + ProofUtil.Apply("simp add:" + succOutEdgesId1), + ProofUtil.Apply("simp add: member_rec"), + ProofUtil.Apply("rule " + nameLemmaSucc3), + ProofUtil.Apply("simp add: " + unwrappedAfterLoopBigBlockId + "_def " + afterLoopContId + "_def " + unwrappedAfterLoopContId + "_def"), + ProofUtil.Apply("rule correctness_propagates_through_assumption"), + "apply blast", + ProofUtil.Apply("simp add:" + succNodeId1 + ""), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("simp add:" + succOutEdgesId1 + ""), + ProofUtil.Apply("simp add: member_rec"), + "apply blast", + ProofUtil.Apply("rule correctness_propagates_through_assumption3"), + ProofUtil.Apply(ProofUtil.Repeat("simp add:" + succNodeId1)), + ProofUtil.Apply("simp add:" + succOutEdgesId1), + ProofUtil.Apply(ProofUtil.Repeat("simp add: member_rec")) + }; + + proofMethods.AddRange(beginningOfProof); + + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + proofMethods.AddRange(insideOfLoopAddition1); + } + + //TODO: do the second check if BlockCoalescing is activated, otherwise keep as is + if (personalGuard != null && personalGuard.Equals(Expr.True)) + { + proofMethods.AddRange(whileTrueEndingAfterSkippingEndBlock); + } + else + { + proofMethods.AddRange(endingAfterSkippingEndblock); + } + // if (afterLoopBigBlockOrig.ec is WhileCmd && !afterLoopBigBlockCopy.simpleCmds.Any()) + // { + // proofMethods.AddRange(endingAfterSkippingEndBlockAndUnwrapping); + // } + // else + // { + // proofMethods.AddRange(endingAfterSkippingEndblock); + // } + + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + proofMethods.AddRange(insideOfLoopAddition2); + } + + proofMethods.AddRange( + new List + { + "done", + "qed", + "qed" + }); + + #endregion + + } + return proofMethods; + } + + private List GenerateProofGeneric( + BigBlock startingBigBlock, + Block relatedBlock, + Expr entryGuard, + BranchIndicator indicator, + ProofGenInfo proofGenInfo) + { + string bigblockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(startingBigBlock).First(); + string blockId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".block_" + afterCfg.GetUniqueIntLabel(relatedBlock); + string nodeId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".node_" + afterCfg.GetUniqueIntLabel(relatedBlock); + string outEdgesId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".outEdges_" + afterCfg.GetUniqueIntLabel(relatedBlock); + string contId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[startingBigBlock]; + + BigBlock correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; + BigBlock successorBigBlockOrig = correspondingBigBlockOrig.successorBigBlock; + BigBlock successorBigBlockCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[successorBigBlockOrig]; + + foreach (var kvPair in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) + { + if (kvPair.Value.Item2 == successorBigBlockOrig) + { + successorBigBlockCopy = kvPair.Key; + break; + } + } + + int succUniqueLoopLabel = -1; + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + BigBlock loop = proofGenInfo.GetMappingBigBlockToLoopBigBlock()[correspondingBigBlockOrig]; + BigBlock loopCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[loop]; + + IDictionary origBlockBeforeDag = beforeDagOrigBlock.InverseDict(); + + Block enclosingLoopCfgBlock = proofGenInfo.GetMappingOrigBigBlockToOrigBlock()[loop]; + Block enclosingLoopCfgBlockCopy = origBlockBeforeDag[enclosingLoopCfgBlock]; + + if (true /* enclosingLoopCfgBlockCopy.cmds.Any() */) + { + Block successorCfgBlock = afterCfg.GetSuccessorBlocks(enclosingLoopCfgBlockCopy).First(); + //Block successorCfgBlockCopy = origBlockBeforeDag[successorCfgBlock]; + + succUniqueLoopLabel = afterCfg.GetUniqueIntLabel(successorCfgBlock); + } + else + { + succUniqueLoopLabel = afterCfg.GetUniqueIntLabel(enclosingLoopCfgBlockCopy); + } + + //succUniqueLoopLabel = proofGenInfo.getMappingCopyBigBlockToIndex()[loopCopy]; + //succUniqueLoopLabel += 1; + } + + var proofMethods = new List(); + IEnumerable successors = afterCfg.GetSuccessorBlocks(relatedBlock); + if (successors != null && successors.Any()) + { + Block succ1 = successors.First(); + int succUniqueIntLabel = afterCfg.GetUniqueIntLabel(succ1); + + string nameLemmaLocal = "prelimNameTest"; + if (mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock)) + { + nameLemmaLocal = mappingBigBlockToLocalLemmaDecl[startingBigBlock].Name; + } + + string nameLemmaSucc = "nameLemmaSuccTest"; + if (!proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) || + correspondingBigBlockOrig.successorBigBlock != proofGenInfo.GetMappingBigBlockToLoopBigBlock()[correspondingBigBlockOrig]) + { + nameLemmaSucc = mappingBigBlockToGlobalLemmaDecl[successorBigBlockCopy].Name; + } + + var beginningOfProof = new List + { + "proof -", + "show ?thesis ", + ProofUtil.Apply("rule block_global_rel_generic"), + startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply("rule Rel_Main_test[of " + bigblockId + "]") : ProofUtil.Apply("rule Rel_Invs[of " + bigblockId + "]") , + ProofUtil.Apply("simp add: " + bigblockId + "_def"), + startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, + ProofUtil.Apply("rule astTrace"), + ProofUtil.Apply("simp add: " + bigblockId + "_def"), + ProofUtil.Apply("rule " + nodeId + "") + }; + + var middlePartOfProof = new List(); + if (indicator == 0 || entryGuard == null) + { + middlePartOfProof = new List + { + ProofUtil.Apply("rule disjI1"), + ProofUtil.Apply("rule " + blockId + "_def"), + // indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails ? ProofUtil.Apply("rule conjI") : null, + // indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails ? ProofUtil.Apply(ProofUtil.Simp()) : null, + ProofUtil.Apply("rule cfgDoesntFail"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("rule " + contId + "_def"), + ProofUtil.Apply("simp add: " + nodeId + ""), + // !startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, + startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply("rule " + nameLemmaLocal + "") : null, + startingBigBlock.simpleCmds.Any() ? "apply assumption" : null, + startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, + }; + } + else if (indicator == BranchIndicator.GuardFails) + { + middlePartOfProof = new List + { + ProofUtil.Apply("rule disjI2"), + ProofUtil.Apply("rule disjI2"), + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply("" + NegationRule(entryGuard) + ""), + ProofUtil.Apply("rule guardHint"), + ProofUtil.Apply("rule cfgDoesntFail"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("rule " + contId + "_def"), + ProofUtil.Apply("simp add: " + nodeId + ""), + //!startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, + startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply("rule " + nameLemmaLocal + "") : null, + startingBigBlock.simpleCmds.Any() ? "apply assumption" : null, + startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, + startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply("rule guardHint") : null, + }; + } + //TODO: this check isn't correct! Why? + else if (indicator == BranchIndicator.GuardHolds || proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + middlePartOfProof = new List + { + ProofUtil.Apply("rule disjI2"), + ProofUtil.Apply("rule disjI1"), + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("rule guardHint"), + ProofUtil.Apply("rule cfgDoesntFail"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("rule " + contId + "_def"), + ProofUtil.Apply("simp add: " + nodeId + ""), + //!startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, + startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply("rule " + nameLemmaLocal + "") : null, + startingBigBlock.simpleCmds.Any() ? "apply assumption" : null, + startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, + startingBigBlock.simpleCmds.Any() && indicator == BranchIndicator.GuardHolds ? ProofUtil.Apply("rule guardHint") : null, + }; + } + + var proofEnd = new List(); + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) && + correspondingBigBlockOrig.successorBigBlock.ec is WhileCmd) + { + proofEnd = new List + { + ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x=" + succUniqueLoopLabel + "]")), + ProofUtil.Apply("simp add: " + outEdgesId + ""), + ProofUtil.Apply("simp add: member_rec(1)"), + ProofUtil.Apply("rule loop_IH_apply"), + ProofUtil.Apply("rule inductionHypothesis"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) + }; + } + else + { + proofEnd = new List + { + ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succUniqueIntLabel + "]")), + ProofUtil.Apply(ProofUtil.Repeat("simp add: " + outEdgesId)), + ProofUtil.Apply("simp add: member_rec(1)"), + ProofUtil.Apply("rule " + nameLemmaSucc + ""), + !proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Simp()) : null, + "apply blast+", + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_prove") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_apply") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule inductionHypothesis") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule less_trans_inv") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? "apply blast+" : null, + }; + } + + //TODO: name the assumptions + proofMethods.AddRange(beginningOfProof); + proofMethods.AddRange(middlePartOfProof); + proofMethods.AddRange(proofEnd); + proofMethods.AddRange( + new List + { + "done", + "qed" + }); + } + return proofMethods; + } + + + private List GenerateEndingAfterUnwrappingProof( + BigBlock startingBigBlock, + Block relatedBlock, + Expr entryGuard, + BranchIndicator indicator, + ProofGenInfo proofGenInfo) + { + BigBlock correspondingOrigBigBlock = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; + List loopExtension = new List(); + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingOrigBigBlock)) + { + loopExtension = new List + { + ProofUtil.Apply("rule loop_IH_prove"), + ProofUtil.Apply("rule loop_IH_apply"), + ProofUtil.Apply("rule inductionHypothesis"), + ProofUtil.Apply("rule strictly_smaller_helper2"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + }; + } + + string bigblockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(startingBigBlock).First(); + string blockId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".block_" + afterCfg.GetUniqueIntLabel(relatedBlock); + string nodeId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".node_" + afterCfg.GetUniqueIntLabel(relatedBlock); + string outEdgesId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".outEdges_" + afterCfg.GetUniqueIntLabel(relatedBlock); + + BigBlock correspondingOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; + BigBlock unwrappedBigBlockCopy = null; + foreach (var tuple in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) + { + if (tuple.Value.Item2 == correspondingOrig) + { + unwrappedBigBlockCopy = tuple.Key; + break; + } + } + + string succBigBlockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(unwrappedBigBlockCopy).First(); + + string contId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[startingBigBlock]; + string succContId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[unwrappedBigBlockCopy]; + + //string nameLemmaLocal = mappingBigBlockToLocalLemmaDecl[startingBigBlock].Name; + string nameLemmaSuccGlobal = mappingBigBlockToGlobalLemmaDecl[unwrappedBigBlockCopy].Name; + + string correctnessPropagates = null; + string correctnessPropagatesPosts = null; + if (entryGuard == null) + { correctnessPropagates = ProofUtil.Apply("rule correctness_propagates_through_empty"); + correctnessPropagatesPosts = ProofUtil.Apply("rule correctness_propagates_through_empty2"); } + else if (indicator == BranchIndicator.GuardFails) + { correctnessPropagates = ProofUtil.Apply("rule correctness_propagates_through_assumption"); + correctnessPropagatesPosts = ProofUtil.Apply("rule correctness_propagates_through_assumption3"); } + else if (indicator == BranchIndicator.GuardHolds) + { correctnessPropagates = ProofUtil.Apply("rule correctness_propagates_through_assumption2"); + correctnessPropagatesPosts = ProofUtil.Apply("rule correctness_propagates_through_assumption4"); } + else if (indicator == BranchIndicator.NoGuard) + { correctnessPropagates = ProofUtil.Apply("rule correctness_propagates_through_empty"); + correctnessPropagatesPosts = ProofUtil.Apply("rule correctness_propagates_through_empty2"); } + + string rule = "apply( " + NegationRule(entryGuard) + ")"; + if (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.NoGuard || entryGuard == null) + { + rule = ""; + } + + List proofMethods = new List + { + ProofUtil.Apply("rule ending_after_unwrapping"), + ProofUtil.Apply("rule astTrace"), + ProofUtil.Apply("simp add: " + bigblockId + "_def"), + ProofUtil.Apply("rule cfgDoesntFail, simp"), + ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("rule " + nameLemmaSuccGlobal + ""), + ProofUtil.Apply("simp add: " + succBigBlockId + "_def " + contId + "_def " + succContId + "_def"), + correctnessPropagates, + "using assms(2)", + "apply blast", + ProofUtil.Apply("simp add: " + nodeId + ""), + ProofUtil.Apply("simp add: " + blockId + "_def"), + indicator != BranchIndicator.NoGuard ? rule : null, + (indicator != BranchIndicator.NoGuard && entryGuard != null) ? ProofUtil.Apply("rule guardHint") : null, + ProofUtil.Apply("simp add: " + outEdgesId + ""), + ProofUtil.Apply("simp add: member_rec"), + ProofUtil.Apply(ProofUtil.Simp()), + correctnessPropagatesPosts, + "using assms(3)", + "apply blast", + ProofUtil.Apply("simp add: " + nodeId + ""), + ProofUtil.Apply("simp add: " + blockId + "_def"), + indicator != BranchIndicator.NoGuard ? rule : null, + (indicator != BranchIndicator.NoGuard && entryGuard != null) ? ProofUtil.Apply("rule guardHint") : null, + ProofUtil.Apply("simp add: " + outEdgesId + ""), + ProofUtil.Apply("simp add: member_rec"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) + }; + + proofMethods.AddRange(loopExtension); + proofMethods.Add("done"); + + return proofMethods; + } + + private List GenerateWhileSuccessorProof( + BigBlock startingBigBlock, + Block relatedBlock, + Expr entryGuard, + Expr personalGuard, + BranchIndicator indicator, + ProofGenInfo proofGenInfo) + { + string bigblockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(startingBigBlock).First(); + string blockId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".block_" + afterCfg.GetUniqueIntLabel(relatedBlock); + string nodeId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".node_" + afterCfg.GetUniqueIntLabel(relatedBlock); + string outEdgesId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".outEdges_" + afterCfg.GetUniqueIntLabel(relatedBlock); + + BigBlock correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; + BigBlock successorBigBlockCopy = null; + foreach (var tuple in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) + { + if (correspondingBigBlockOrig == tuple.Value.Item2) + { + successorBigBlockCopy = tuple.Key; + break; + } + } + + string succBigBlockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(successorBigBlockCopy).First(); + + WhileCmd wcmd = (WhileCmd) correspondingBigBlockOrig.ec; + BigBlock bodyBigBlockOrig = wcmd.Body.BigBlocks.First(); + BigBlock bodyBigBlockCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[bodyBigBlockOrig]; + + var proofMethods = new List(); + IEnumerable successors = afterCfg.GetSuccessorBlocks(relatedBlock); + if (successors != null && successors.Any()) + { + Block succ = successors.First(); + int succUniqueIntLabel = afterCfg.GetUniqueIntLabel(succ); + + string contId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[startingBigBlock]; + string successorContId = "cont_" + (proofGenInfo.GetMappingCopyBigBlockToIndex()[successorBigBlockCopy]); + + string nameLemmaSucc = mappingBigBlockToGlobalLemmaDecl[successorBigBlockCopy].Name; + string nameLemmaLocal = null; + + if (mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock)) + { + nameLemmaLocal = mappingBigBlockToLocalLemmaDecl[startingBigBlock].Name; + } + + proofMethods = new List + { + "proof -", + "show ?thesis", + ProofUtil.Apply("rule block_global_rel_while_successor"), + ProofUtil.Apply("rule astTrace"), + indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails ? + ProofUtil.Apply("rule Rel_Main_test[of " + bigblockId + "]") : ProofUtil.Apply("rule Rel_Main_test[of " + bigblockId + " _ " + blockId + "]"), + ProofUtil.Apply("simp add: " + bigblockId + "_def " + blockId + "_def"), + ProofUtil.Apply("simp add: " + bigblockId + "_def " + blockId + "_def"), + ProofUtil.Apply("simp add: " + bigblockId + "_def " + blockId + "_def"), + ProofUtil.Apply("simp add: " + blockId + "_def"), + ProofUtil.Apply("rule " + nodeId + ""), + + entryGuard == null ? ProofUtil.Apply("rule disjI1") : null, + + entryGuard != null ? (indicator == BranchIndicator.NoGuard ? ProofUtil.Apply("rule disjI1") : ProofUtil.Apply("rule disjI2")) : null, + entryGuard != null && indicator == BranchIndicator.GuardHolds ? ProofUtil.Apply("rule disjI1") : null, + entryGuard != null && indicator == BranchIndicator.GuardFails ? ProofUtil.Apply("rule disjI2") : null, + + ProofUtil.Apply("simp add: " + blockId + "_def"), + entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule conjI") : null, + entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply(ProofUtil.Simp()) : null, + entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule conjI") : null, + entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply(ProofUtil.Simp()) : null, + entryGuard != null && (indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule conjI") : null, + entryGuard != null && (indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("" + NegationRule(entryGuard) + "") : null, + entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule guardHint") : null, + ProofUtil.Apply("rule cfgDoesntFail, simp"), + ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply("simp add: " + nodeId + "") : null, + mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply("rule " + nameLemmaLocal + "") : null, + mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply("simp add: " + bigblockId + "_def") : null, + mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) : null, + entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule guardHint") : null, + //personalGuard != null ? ProofUtil.Apply("erule disjE") : null, + //personalGuard == null ? ProofUtil.Apply("erule disjE, simp") : null, + //personalGuard == null ? ProofUtil.Apply("erule disjE, simp") : null, + //personalGuard == null ? ProofUtil.Apply("rule disjE, simp") : null, + + ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succUniqueIntLabel + "]")), + ProofUtil.Apply(ProofUtil.Repeat("simp add: " + outEdgesId)), + ProofUtil.Apply("simp add: member_rec(1)"), + ProofUtil.Apply("rule " + nameLemmaSucc + ""), + ProofUtil.Apply("simp add: " + succBigBlockId + "_def " + contId + "_def "+ successorContId + "_def"), + "apply blast+", + + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_prove") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_apply") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule inductionHypothesis") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule less_trans_inv") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) : null, + + "done", + "qed", + }; + } + return proofMethods; + } + + private List GenerateIfSuccessorProof( + BigBlock startingBigBlock, + Block relatedBlock, + Expr personalGuard, + Expr entryGuard, + BranchIndicator indicator, + ProofGenInfo proofGenInfo) + { + string bigblockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(startingBigBlock).First(); + string blockId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".block_" + + afterCfg.GetUniqueIntLabel(relatedBlock); + string nodeId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".node_" + + afterCfg.GetUniqueIntLabel(relatedBlock); + string outEdgesId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".outEdges_" + + afterCfg.GetUniqueIntLabel(relatedBlock); + + BigBlock correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; + + IfCmd _if = (IfCmd) correspondingBigBlockOrig.ec; + BigBlock thenBranchOrig = _if.thn.BigBlocks.First(); + BigBlock thenBranchCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[thenBranchOrig]; + string thenBranchId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(thenBranchCopy).First(); + string thenBranchContId = "cont_" + (proofGenInfo.GetMappingCopyBigBlockToIndex()[thenBranchCopy]); + string nameLemmaThen = mappingBigBlockToGlobalLemmaDecl[thenBranchCopy].Name; + + string nameLemmaElse = "noLemmaElse"; + if (_if.elseBlock != null) + { + BigBlock elseBranchOrig = _if.elseBlock.BigBlocks.First(); + BigBlock elseBranchCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[elseBranchOrig]; + string elseBranchId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(elseBranchCopy).First(); + string elseBranchContId = "cont_" + (proofGenInfo.GetMappingCopyBigBlockToIndex()[elseBranchCopy]); + nameLemmaElse = mappingBigBlockToGlobalLemmaDecl[elseBranchCopy].Name; + } + + var proofMethods = new List(); + IEnumerable successors = afterCfg.GetSuccessorBlocks(relatedBlock); + if (successors != null && successors.Any()) + { + Block succ = successors.First(); + Block succ2 = successors.Last(); + int succUniqueIntLabel = afterCfg.GetUniqueIntLabel(succ); + int succUniqueIntLabel2 = afterCfg.GetUniqueIntLabel(succ2); + + string contId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[startingBigBlock]; + string nameLemmaLocal = null; + + if (mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock)) + { + nameLemmaLocal = mappingBigBlockToLocalLemmaDecl[startingBigBlock].Name; + } + + var beginningOfProof = new List + { + "proof -", + "show ?thesis", + ProofUtil.Apply("rule block_global_rel_if_successor"), + startingBigBlock.simpleCmds.Any() ? + (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails ? + ProofUtil.Apply("rule Rel_Main_test[of " + bigblockId + "]") : ProofUtil.Apply("rule Rel_Main_test[of " + bigblockId + " _ " + blockId + "]")) : + ProofUtil.Apply("rule Rel_Invs[of " + bigblockId + "]"), + ProofUtil.Apply("simp add: " + blockId + "_def " + bigblockId + "_def"), + startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply("simp add: " + blockId + "_def") : null, + ProofUtil.Apply("rule astTrace"), + ProofUtil.Apply("simp add: " + bigblockId + "_def"), + ProofUtil.Apply("rule " + nodeId + "") + }; + + var middlePartOfProof = new List + { + entryGuard == null ? ProofUtil.Apply("rule disjI1") : null, + + entryGuard != null ? (indicator == BranchIndicator.NoGuard ? ProofUtil.Apply("rule disjI1") : ProofUtil.Apply("rule disjI2")) : null, + entryGuard != null && indicator == BranchIndicator.GuardHolds ? ProofUtil.Apply("rule disjI1") : null, + entryGuard != null && indicator == BranchIndicator.GuardFails ? ProofUtil.Apply("rule disjI2") : null, + ProofUtil.Apply("simp add: " + blockId + "_def"), + entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule conjI") : null, + entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply(ProofUtil.Simp()) : null, + entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule conjI") : null, + entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply(ProofUtil.Simp()) : null, + entryGuard != null && (indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule conjI") : null, + entryGuard != null && (indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("" + NegationRule(entryGuard) + "") : null, + entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule guardHint") : null, + ProofUtil.Apply("rule cfgDoesntFail, simp"), + ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply("simp add: " + nodeId + "") : null, + mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply("rule " + nameLemmaLocal + "") : null, + mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply("simp add: " + bigblockId + "_def") : null, + mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) : null, + entryGuard != null && startingBigBlock.simpleCmds.Any() && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule guardHint") : null, + personalGuard != null ? ProofUtil.Apply("erule disjE") : null, + //personalGuard == null ? ProofUtil.Apply("erule disjE, simp") : null, + //personalGuard == null ? ProofUtil.Apply("erule disjE, simp") : null, + personalGuard == null ? ProofUtil.Apply("rule disjE, simp") : null + }; + + var finalPartOfProof = new List + { + ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succUniqueIntLabel + "]")), + ProofUtil.Apply(ProofUtil.Repeat("simp add: " + outEdgesId)), + ProofUtil.Apply("simp add: member_rec(1)"), + ProofUtil.Apply("rule conjE"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("rule " + nameLemmaThen + ""), + ExpandDefinitions(contId, startingBigBlock, proofGenInfo, BranchIndicator.GuardHolds), + "apply blast+", + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_prove") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_apply") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule inductionHypothesis") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule less_trans_inv") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) : null, + personalGuard != null && !proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? + ProofUtil.Apply(ProofUtil.Simp()) : null, + + ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succUniqueIntLabel2 + "]")), + ProofUtil.Apply(ProofUtil.Repeat("simp add: " + outEdgesId)), + ProofUtil.Apply("simp add: member_rec(1)"), + ProofUtil.Apply("rule conjE"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + ProofUtil.Apply("rule " + nameLemmaElse + ""), + ExpandDefinitions(contId, startingBigBlock, proofGenInfo, BranchIndicator.GuardFails), + "apply blast+", + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_prove") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_apply") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule inductionHypothesis") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule less_trans_inv") : null, + proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) : null, + + "done", + "qed" + }; + + proofMethods.AddRange(beginningOfProof); + proofMethods.AddRange(middlePartOfProof); + proofMethods.AddRange(finalPartOfProof); + } + return proofMethods; + } + } +} \ No newline at end of file diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs new file mode 100644 index 000000000..d8ecb831c --- /dev/null +++ b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs @@ -0,0 +1,212 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Isabelle.Ast; +using Isabelle.Util; +using Microsoft.Boogie; +using ProofGeneration.ASTRepresentation; +using ProofGeneration.BoogieIsaInterface; +using ProofGeneration.BoogieIsaInterface.VariableTranslation; +using ProofGeneration.CFGRepresentation; +using ProofGeneration.Util; + +namespace ProofGeneration.AstToCfg +{ + internal class AstToCfgManager + { + public static Theory AstToCfgProof( + PhasesTheories phasesTheories, + //bool generateEndToEndLemma, + Term vcAssm, + ProofGenInfo proofGenInfo, + ASTRepr beforeCfgAst, + CFGRepr afterCfg, + BoogieMethodData beforeCfgData, + IDictionary beforeDagOrigBlock, + IDictionary mappingWithHints, + IDictionary beforeToAfter, + IProgramAccessor beforeCfgProgAccess, + IProgramAccessor afterCfgProgAccess, + IVariableTranslationFactory varFactory, + MultiCmdIsaVisitor multiCmdIsaVisitor) + { + LemmaDecl entryLemma = null; + //var afterToBefore = beforeToAfter.InverseDict(); + + var varContextName = "\\1"; + var varContextAbbrev = new AbbreviationDecl( + varContextName, + new Tuple, Term>(new List(), beforeCfgProgAccess.VarContext()) + ); + + var funContextWfName = "Wf_Fun"; + var astBoogieContext = new BoogieContextIsa( + IsaCommonTerms.TermIdentFromName("A"), + IsaCommonTerms.TermIdentFromName("M"), + IsaCommonTerms.TermIdentFromName(varContextName), + IsaCommonTerms.TermIdentFromName("\\"), + IsaCommonTerms.EmptyList); + var cfgBoogieContext = new BoogieContextIsa( + IsaCommonTerms.TermIdentFromName("A"), + IsaCommonTerms.TermIdentFromName("M'"), + IsaCommonTerms.TermIdentFromName(varContextName), + IsaCommonTerms.TermIdentFromName("\\"), + IsaCommonTerms.EmptyList); + + var lemmaManager = new AstToCfgLemmaManager( + beforeCfgProgAccess, + afterCfgProgAccess, + astBoogieContext, + cfgBoogieContext, + afterCfg, + funContextWfName, + beforeDagOrigBlock, + beforeToAfter, + beforeCfgData, + varFactory); + + var lemmaNamer = new IsaUniqueNamer(); + IList outerDecls = new List(); + + outerDecls.Add(varContextAbbrev); + outerDecls.Add(new DeclareDecl("Nat.One_nat_def[simp del]")); + + foreach (BigBlock beforeBlock in beforeCfgAst.GetBlocksBackwards()) + { + //BigBlock beforeBlockOrig = proofGenInfo.getMappingCopyBigblockToOrigBigblock()[beforeBlock]; + Block afterBlock = beforeToAfter[beforeBlock]; + + int bigblockIndex = proofGenInfo.GetMappingCopyBigBlockToIndex()[beforeBlock]; + //int blockIndex = afterCfg.GetUniqueIntLabel(afterBlock); + + BigBlock successorBigBlockOrig; + BigBlock successorBigBlockCopy; + int succBigBlockIndex = -1; + Block successorBlock; + int succBlockIndex = -1; + if (proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[beforeBlock].successorBigBlock != null) + { + successorBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[beforeBlock].successorBigBlock; + successorBigBlockCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[successorBigBlockOrig]; + succBigBlockIndex = proofGenInfo.GetMappingCopyBigBlockToIndex()[successorBigBlockCopy]; + successorBlock = beforeToAfter[successorBigBlockCopy]; + succBlockIndex = afterCfg.GetUniqueIntLabel(successorBlock); + } + + (Block, Expr, BranchIndicator) hints = mappingWithHints[beforeBlock]; + + if (beforeBlock.simpleCmds.Any() && multiCmdIsaVisitor.Translate(beforeBlock.simpleCmds).Any()) + { + LemmaDecl localLemmaDecl = lemmaManager.LocalLemma( + beforeBlock, + afterBlock, + hints.Item2, + bigblock => GetLemmaName(bigblock, lemmaNamer, beforeCfgProgAccess.BigBlockInfo()), + hints.Item3 + ); + outerDecls.Add(localLemmaDecl); + } + + LemmaDecl globalLemmaDecl = + lemmaManager.GenerateGlobalLemma( + beforeBlock, + IsaCommonTerms.TermIdentFromName("cont_" + bigblockIndex), + afterBlock, + IsaCommonTerms.TermIdentFromName(beforeCfgProgAccess.BigBlockInfo().TheoryName + ".post"), + (hints.Item2, hints.Item3), + bigblock => GetGlobalLemmaName(bigblock, lemmaNamer, beforeCfgProgAccess.BigBlockInfo()), + proofGenInfo + ); + outerDecls.Add(globalLemmaDecl); + + if (proofGenInfo.GetMappingCopyBigBlockToIndex()[beforeBlock] == 0) + { + entryLemma = globalLemmaDecl; + } + } + + var absValType = new VarType("a"); + var cfgToDagLemmasLocale = new LocaleDecl( + "ast_to_cfg_lemmas", + new ContextElem( + new List> + { + Tuple.Create((TermIdent) astBoogieContext.absValTyMap, + IsaBoogieType.AbstractValueTyFunType(absValType)), + Tuple.Create((TermIdent) astBoogieContext.funContext, IsaBoogieType.FunInterpType(absValType)) + }, + new List + { + IsaBoogieTerm.FunInterpWf(astBoogieContext.absValTyMap, beforeCfgProgAccess.FunctionsDecl(), + astBoogieContext.funContext) + }, + new List {funContextWfName} + ), + outerDecls + ); + + var theoryOuterDecls = new List(); + theoryOuterDecls.Add(cfgToDagLemmasLocale); + + var endToEndManager = new AstToCfgEndToEnd(); + var endToEndDecls = endToEndManager.EndToEndProof( + entryLemma.Name, + phasesTheories.EndToEndLemmaName(PhasesTheories.Phase.CfgToDag, false) + "_theorem_aux", + vcAssm, + beforeCfgProgAccess, + afterCfgProgAccess, + beforeCfgAst, + proofGenInfo + ); + theoryOuterDecls.AddRange(endToEndDecls); + + return new Theory( + phasesTheories.TheoryName(PhasesTheories.Phase.AstToCfg), + new List + { + "Boogie_Lang.Ast", "Boogie_Lang.Ast_Cfg_Transformation", "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.BackedgeElim", "Boogie_Lang.TypingML", + beforeCfgProgAccess.TheoryName(), + afterCfgProgAccess.TheoryName(), phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag), + phasesTheories.TheoryName(PhasesTheories.Phase.Passification), + phasesTheories.TheoryName(PhasesTheories.Phase.Vc) + }, + theoryOuterDecls + ); + } + + public static bool PredHasLoop(BigBlock b, ASTRepr ast, out BigBlock predecessor) + { + IEnumerable bbs = ast.GetBlocksForwards(); + BigBlock[] bbsArray = bbs.ToArray(); + + for (var i = 0; i < bbsArray.Length; i++) + { + // String test = bbsArray[i].simpleCmds.First().ToString(); + // String test2 = b.simpleCmds.First().ToString(); + // StructuredCmd ec1 = bbsArray[i].ec; + // StructuredCmd ec2 = b.ec; + // String name1 = bbsArray[i].LabelName; + // String name2 = b.LabelName; + + if (bbsArray[i] == b && i != 0 && bbsArray[i - 1].ec is WhileCmd) + { + predecessor = bbsArray[i - 1]; + return true; + } + } + + predecessor = null; + return false; + } + + private static string GetLemmaName(BigBlock b, IsaUniqueNamer namer, IsaBigBlockInfo bbInfo) + { + return namer.GetName(b, "rel_" + bbInfo.CmdsQualifiedName(b).First()); + } + + private static string GetGlobalLemmaName(BigBlock b, IsaUniqueNamer namer, IsaBigBlockInfo bbInfo) + { + return "global_" + namer.GetName(b, "rel_" + bbInfo.CmdsQualifiedName(b).First()); + } + } +} \ No newline at end of file diff --git a/Source/ProofGeneration/BoogieIsaInterface/IProgramAccessor.cs b/Source/ProofGeneration/BoogieIsaInterface/IProgramAccessor.cs index 3d540ab25..1a363607c 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IProgramAccessor.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IProgramAccessor.cs @@ -43,6 +43,8 @@ public interface IProgramAccessor : IGlobalProgramAccessor public Term VarContext(); public IsaBlockInfo BlockInfo(); + + public IsaBigBlockInfo BigBlockInfo(); public string MembershipLemma(Declaration d); diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBlockInfo.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBlockInfo.cs index 7edf5bb75..16f5cf628 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaBlockInfo.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBlockInfo.cs @@ -29,6 +29,7 @@ IDictionary blockCmdsLemmas public IDictionary BlockOutEdgesLemmas { get; } public IDictionary BlockCmdsLemmas { get; } + public string getTheoryName() { return theoryName; } public string CmdsQualifiedName(Block b) { @@ -50,4 +51,40 @@ private string QualifiedName(OuterDecl decl) return theoryName + "." + decl.Name; } } + + public class IsaBigBlockInfo + { + //private readonly string theoryName; + + public IsaBigBlockInfo( + string theoryName, + IDictionary bigblockIds, + IDictionary> bigblockDefs + ) + { + TheoryName = theoryName; + BigBlockIds = bigblockIds; + BigBlockDefs = bigblockDefs; + } + + public IDictionary BigBlockIds { get; } + public IDictionary> BigBlockDefs { get; } + public string TheoryName { get; } + + public IList CmdsQualifiedName(BigBlock b) + { + return QualifiedName(BigBlockDefs[b]); + } + + private IList QualifiedName(IList decls) + { + IList names = new List(); + foreach (var decl in decls) + { + names.Add(TheoryName + "." + decl.Name); + } + + return names; + } + } } \ No newline at end of file diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs index 25986d8fe..a99aeb5e7 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs @@ -36,6 +36,10 @@ public static class IsaBoogieTerm private static readonly TermIdent redCfgMultiId = IsaCommonTerms.TermIdentFromName("red_cfg_multi"); private static readonly TermIdent redCfgKStepId = IsaCommonTerms.TermIdentFromName("red_cfg_k_step"); private static readonly TermIdent redCmdListId = IsaCommonTerms.TermIdentFromName("red_cmd_list"); + private static readonly TermIdent redBigBlockId = IsaCommonTerms.TermIdentFromName("red_bigblock"); + private static readonly TermIdent redBigBlockKStepId = IsaCommonTerms.TermIdentFromName("red_bigblock_k_step"); + private static readonly TermIdent redBigBlockMultiId = IsaCommonTerms.TermIdentFromName("rtranclp"); + private static readonly TermIdent astValidConfigId = IsaCommonTerms.TermIdentFromName("Ast.valid_configuration"); private static readonly TermIdent redExprId = IsaCommonTerms.TermIdentFromName("red_expr"); private static readonly TermIdent normalStateId = IsaCommonTerms.TermIdentFromName("Normal"); private static readonly TermIdent magicStateId = IsaCommonTerms.TermIdentFromName("Magic"); @@ -44,6 +48,8 @@ public static class IsaBoogieTerm private static readonly TermIdent outEdgesId = IsaCommonTerms.TermIdentFromName("out_edges"); private static readonly TermIdent nodeToBlockId = IsaCommonTerms.TermIdentFromName("node_to_block"); private static readonly TermIdent funInterpWfId = IsaCommonTerms.TermIdentFromName("fun_interp_wf"); + + private static readonly TermIdent astLoopIhId = IsaCommonTerms.TermIdentFromName("loop_IH"); private static readonly TermIdent funInterpSingleWfId = IsaCommonTerms.TermIdentFromName("fun_interp_single_wf"); @@ -357,6 +363,11 @@ public static Term ProcCall(string procname, IList args, IList retur { return new TermApp(procCallId, new StringConst(procname), new TermList(args), new TermList(returnVars)); } + + public static Term MethodASTBody(IList bigblocks) + { + return new TermList(bigblocks); + } public static Term MethodCFGBody(Term entryNode, Term outEdges, Term nodeToBlock) { @@ -446,6 +457,113 @@ public static Term RedCmdList(BoogieContextIsa boogieContext, Term cmdList, Term } ); } + + public static Term RedBigBlock(BoogieContextIsa boogieContext, Term startConfig, Term endConfig, Term ast) + { + return + new TermApp(redBigBlockId, + new List + { + boogieContext.absValTyMap, + boogieContext.methodContext, + boogieContext.varContext, + boogieContext.funContext, + boogieContext.rtypeEnv, + ast, + startConfig, + endConfig + } + ); + } + + public static Term RedBigBlockKStep(BoogieContextIsa boogieContext, Term startConfig, Term endConfig, Term ast, Term numSteps) + { + return + new TermApp(redBigBlockKStepId, + new List + { + boogieContext.absValTyMap, + boogieContext.methodContext, + boogieContext.varContext, + boogieContext.funContext, + boogieContext.rtypeEnv, + ast, + startConfig, + numSteps, + endConfig + } + ); + } + + public static Term RedBigBlockMulti(BoogieContextIsa boogieContext, Term startConfig, Term endConfig, Term ast) + { + IList bigblockContextList = new List + { + boogieContext.absValTyMap, + boogieContext.methodContext, + boogieContext.varContext, + boogieContext.funContext, + boogieContext.rtypeEnv, + ast + }; + Term redbigBlockTerm = new TermApp(redBigBlockId, bigblockContextList); + + return + new TermApp(redBigBlockMultiId, + new List + { + redbigBlockTerm, + startConfig, + endConfig + } + ); + } + + public static Term StartConfigTerm(BigBlock b, Term cont0, IProgramAccessor beforeCfgProgAccess, Term initState1) + { + var beforeBigblockDefName = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(b).First(); + Term beforeBigblock = IsaCommonTerms.TermIdentFromName(beforeBigblockDefName); + //Term cont0 = IsaCommonTerms.TermIdentFromName("cont0"); + + IList startConfigArgs = new List(); + startConfigArgs.Add(beforeBigblock); + startConfigArgs.Add(cont0); + startConfigArgs.Add(initState1); + + return new TermTuple(startConfigArgs); + } + + public static Term EndConfigTerm() + { + IList endConfigArgs = new List(); + endConfigArgs.Add(IsaCommonTerms.TermIdentFromName("reached_bb")); + endConfigArgs.Add(IsaCommonTerms.TermIdentFromName("reached_cont")); + endConfigArgs.Add(IsaCommonTerms.TermIdentFromName("reached_state")); + + return new TermTuple(endConfigArgs); + } + public static Term astId() + { + return IsaCommonTerms.TermIdentFromName("T"); + } + + public static Term AstValidConfiguration(BoogieContextIsa boogieContext, Term posts) + { + return + new TermApp(astValidConfigId, + new List + { + boogieContext.absValTyMap, + boogieContext.varContext, + boogieContext.funContext, + boogieContext.rtypeEnv, + posts, + IsaCommonTerms.TermIdentFromName("reached_bb"), + IsaCommonTerms.TermIdentFromName("reached_cont"), + IsaCommonTerms.TermIdentFromName("reached_state") + } + ); + } public static Term RedCFGMulti(BoogieContextIsa boogieContext, Term cfg, Term initCFGConfig, Term finalCFGConfig) @@ -484,6 +602,31 @@ public static Term RedCFGKStep(BoogieContextIsa boogieContext, Term cfg, Term in finalCFGConfig }); } + + public static Term LoopIH(BoogieContextIsa astBoogieContext, BoogieContextIsa cfgBoogieContext, Term ast, Term bigblock, Term cont, Term cfgBody, Term blockIndex, Term posts) + { + return + new TermApp(astLoopIhId, + new List + { + IsaCommonTerms.TermIdentFromName("j"), + astBoogieContext.absValTyMap, + astBoogieContext.methodContext, + cfgBoogieContext.methodContext, + astBoogieContext.varContext, + astBoogieContext.funContext, + astBoogieContext.rtypeEnv, + ast, + bigblock, + cont, + cfgBody, + blockIndex, + posts, + IsaCommonTerms.TermIdentFromName("reached_bb"), + IsaCommonTerms.TermIdentFromName("reached_cont"), + IsaCommonTerms.TermIdentFromName("reached_state") + }); + } public static Term CFGConfigNode(Term node, Term state) { diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieType.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieType.cs index 00c22b838..4be20a7d1 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieType.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieType.cs @@ -86,7 +86,12 @@ public static TypeIsa CFGNodeOrReturnType() public static TypeIsa ProcedureType() { - return new DataType("procedure"); + return new DataType("mbodyCFG procedure"); + } + + public static TypeIsa AstProcedureType() + { + return new DataType("ast procedure"); } public static TypeIsa GetBlockType() @@ -119,7 +124,7 @@ public static TypeIsa VarContextType() public static TypeIsa ProcContextType() { - return new DataType("proc_context", new List()); + return new DataType("mbodyCFG proc_context", new List()); } public static TypeIsa FunInterpType(TypeIsa absValType) diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator_forAst.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator_forAst.cs new file mode 100644 index 000000000..98daf0168 --- /dev/null +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator_forAst.cs @@ -0,0 +1,425 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using Isabelle.Ast; +using Isabelle.Util; +using Microsoft.BaseTypes; +using Microsoft.Boogie; +using ProofGeneration.BoogieIsaInterface; +using ProofGeneration.BoogieIsaInterface.VariableTranslation; +using ProofGeneration.CFGRepresentation; +using ProofGeneration.ASTRepresentation; +using ProofGeneration.Util; + +namespace ProofGeneration +{ + internal class IsaProgramGenerator_forAst + { + private MultiCmdIsaVisitor cmdIsaVisitor; + private BoogieVariableTranslation varTranslation; + private IVariableTranslationFactory varTranslationFactory; + + private readonly string astName = "proc_body"; + private readonly string procDefName = "ast_proc"; + + public IProgramAccessor GetIsaProgram( + string theoryName, + string procName, + BoogieMethodData methodData, + IsaProgramGeneratorConfig config, + IVariableTranslationFactory varTranslationFactory, + ASTRepr ast, + ASTRepr originalAst, + ProofGenInfo proofGenInfo, + out IList decls, + bool generateMembershipLemmas = true, + bool onlyGlobalData = false + ) + { + this.varTranslationFactory = varTranslationFactory; + varTranslation = varTranslationFactory.CreateTranslation(); + cmdIsaVisitor = new MultiCmdIsaVisitor(varTranslationFactory); + + decls = new List(); + 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 bigblockInfo = BigBlockToInfo(theoryName, ast, proofGenInfo); + var isaProgramRepr = new IsaProgramRepr( + isaGlobalProgramRepr, + PreconditionDeclarationName(), + PostconditionDeclarationName(), + VariableDeclarationsName("params"), + VariableDeclarationsName("locals"), + astName, + procDefName); + membershipLemmaManager = new MembershipLemmaManager(config, isaProgramRepr, bigblockInfo, + Tuple.Create(globalsMax, localsMin), varTranslationFactory, theoryName); + + foreach (var decl_list in bigblockInfo.BigBlockDefs.Values) + { + decls.AddRange(decl_list); + } + + IList continuations = getContinuations(originalAst, proofGenInfo); + decls.AddRange(continuations); + + IList bigblock_terms = new List(); + IEnumerable bigblocks = ast.GetBlocksBackwards(); + foreach (BigBlock b in bigblocks) + { + Term b_term = IsaCommonTerms.TermIdentFromName("bigblock_" + ast.GetUniqueIntLabel(b)); + if (proofGenInfo.GetMappingCopyBigBlockToMarker()[b]) + { + bigblock_terms.Add(b_term); + } + } + + bigblock_terms = Enumerable.Reverse(bigblock_terms).ToList(); + var methodBodyAST = IsaBoogieTerm.MethodASTBody(bigblock_terms); + + var methodBodyDecl = GetMethodBodyASTDecl(procName, methodBodyAST); + decls.AddRange( + new List + { + methodBodyDecl + }); + + 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; + } + + private DefDecl GetAxioms(IEnumerable axioms) + { + var axiomsExpr = new List(); + foreach (var ax in axioms) + { + var axTerms = cmdIsaVisitor.Translate(ax.Expr); + if (axTerms.Count != 1) + throw new ProofGenUnexpectedStateException(GetType(), "axiom not translated into single term"); + axiomsExpr.Add(axTerms.First()); + } + + var equation = new Tuple, Term>(new List(), new TermList(axiomsExpr)); + + return new DefDecl(AxiomDeclarationsName(), equation); + } + + private string AxiomDeclarationsName() + { + return "axioms"; + } + + private DefDecl MethodDefinition(IProgramAccessor programAccessor, BoogieMethodData methodData, SpecsConfig specConfig) + { + var modifiedVarsTerm = new TermList( + methodData.ModifiedVars.Select(id => + { + if (varTranslation.VarTranslation.TryTranslateVariableId(id.Decl, out Term idTerm, out _)) + { + return idTerm; + } + else + { + throw new ProofGenUnexpectedStateException("Could not get variable id"); + } + }).ToList()); + + var mapping = + new List> + { + Tuple.Create("proc_ty_args", (Term) new NatConst(methodData.TypeParams.Count())), + Tuple.Create("proc_args", (Term) IsaCommonTerms.TermIdentFromName(programAccessor.ParamsDecl())), + //TODO: incorporate return values and modified variables + Tuple.Create("proc_rets", (Term) IsaCommonTerms.EmptyList), + Tuple.Create("proc_modifs", (Term) modifiedVarsTerm), + Tuple.Create("proc_pres", specConfig == SpecsConfig.All ? programAccessor.PreconditionsDecl() : IsaBoogieTerm.LiftExprsToCheckedSpecs(programAccessor.PreconditionsDecl())), + Tuple.Create("proc_posts", specConfig == SpecsConfig.All ? programAccessor.PostconditionsDecl() : IsaBoogieTerm.LiftExprsToCheckedSpecs(programAccessor.PostconditionsDecl())), + //TODO: support abstract procedures + Tuple.Create("proc_body", + IsaCommonTerms.SomeOption(new TermTuple(IsaCommonTerms.TermIdentFromName(programAccessor.LocalsDecl()), programAccessor.CfgDecl()))) + }; + + Term method = new TermRecord(mapping); + + DefDecl methodDef = DefDecl.CreateWithoutArg(procDefName, IsaBoogieType.AstProcedureType(), method); + return methodDef; + } + + private IsaBigBlockInfo BigBlockToInfo(string theoryName, ASTRepr ast, ProofGenInfo proofGenInfo) + { + var blockToDecl = new Dictionary>(); + var blockToCounter = new Dictionary(); + + //var astTerm = IsaCommonTerms.TermIdentFromName(astName); + //var astDef = astName + "_def"; + + foreach (BigBlock b in ast.GetBlocksForwards()) + { + int flag = 0; + if (proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().Keys.Contains(b)) + { + flag = 1; + } + BigBlockTermBuilder builder = new BigBlockTermBuilder(); + int uniqueIntLabel = ast.GetUniqueIntLabel(b); + string nameToUse = "bigblock_" + uniqueIntLabel; + var translatedBigBlock = builder.makeBigBlockTerm(b, cmdIsaVisitor, flag, 0, nameToUse, out int updatedNestedBlockTracker); + + proofGenInfo.AddBigBlockToIndexPair(b, uniqueIntLabel); + + //var blockDecl = DefDecl.CreateWithoutArg("bigblock_" + ast.GetUniqueIntLabel(b), translatedBigBlock); + + IDictionary> bb_defs = builder.getBigblockDefDecls(); + foreach(KeyValuePair> bb_def in bb_defs) + { + if (!blockToDecl.ContainsKey(bb_def.Key)) + { + blockToDecl.Add(bb_def.Key, bb_def.Value); + } + } + + blockToCounter[b] = uniqueIntLabel; + } + + return new IsaBigBlockInfo(theoryName, blockToCounter, blockToDecl); + } + + private IList getContinuations(ASTRepr originalAst, ProofGenInfo proofGenInfo) + { + IList declsToReturn = new List(); + BigBlockTermBuilder builder = new BigBlockTermBuilder(); + + //TODO: document this properly + foreach (BigBlock b in originalAst.GetBlocksBackwards()) + { + BigBlock correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[b]; + BigBlock successorBigBlockOrig = correspondingBigBlockOrig.successorBigBlock; + + int successorIndex = -1; + if (successorBigBlockOrig != null) + { + BigBlock successorBigBlockCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[successorBigBlockOrig]; + successorIndex = proofGenInfo.GetMappingCopyBigBlockToIndex()[successorBigBlockCopy]; + } + + BigBlock correspondingBigBlockCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[correspondingBigBlockOrig]; + + Term continuation = builder.makeContinuationTerm(correspondingBigBlockCopy, proofGenInfo, successorIndex); + int bigblockIndex = proofGenInfo.GetMappingCopyBigBlockToIndex()[correspondingBigBlockCopy]; + DefDecl continuationDecl = DefDecl.CreateWithoutArg("cont_" + bigblockIndex, continuation); + declsToReturn.Add(continuationDecl); + + DefDecl continuationDeclForUnwrappedBigBlock = null; + + if (b.ec is WhileCmd) + { + foreach (var pair in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) + { + if (pair.Value.Item2 == correspondingBigBlockOrig) + { + BigBlock unwrapped = pair.Key; + + Term continuationUnwrapped = builder.makeContinuationTerm(unwrapped, proofGenInfo, successorIndex); + int bigblockIndexUnwrapped = proofGenInfo.GetMappingCopyBigBlockToIndex()[unwrapped]; + continuationDeclForUnwrappedBigBlock = DefDecl.CreateWithoutArg("cont_" + bigblockIndexUnwrapped, continuationUnwrapped); + } + } + + if (continuationDeclForUnwrappedBigBlock != null) + { + declsToReturn.Add(continuationDeclForUnwrappedBigBlock); + } + + WhileCmd wcmd = (WhileCmd) b.ec; + ASTRepr body = new ASTRepr(wcmd.Body.BigBlocks); + + IList bodyConts = getContinuations(body, proofGenInfo); + declsToReturn.AddRange(bodyConts); + } + else if (b.ec is IfCmd) + { + IfCmd ifcmd = (IfCmd) b.ec; + ASTRepr thn = new ASTRepr(ifcmd.thn.BigBlocks); + declsToReturn.AddRange(getContinuations(thn, proofGenInfo)); + + if (ifcmd.elseBlock != null) + { + ASTRepr elseBlock = new ASTRepr(ifcmd.elseBlock.BigBlocks); + declsToReturn.AddRange(getContinuations(elseBlock, proofGenInfo)); + } + } + } + + return declsToReturn; + } + + private DefDecl GetFunctionDeclarationsIsa(IEnumerable functions) + { + //var equations = new List, Term>>(); + var fdecls = new List(); + + + foreach (var f in functions) fdecls.Add(IsaBoogieTerm.FunDecl(f, varTranslationFactory)); + + return DefDecl.CreateWithoutArg(FunctionDeclarationsName(), new TermList(fdecls)); + } + + private string FunctionDeclarationsName() + { + return "fdecls"; + } + + private string PreconditionDeclarationName() + { + return "pres"; + } + + private string PostconditionDeclarationName() + { + return "post"; + } + + private DefDecl GetVariableDeclarationsIsa(string varKind, IEnumerable variables) + { + var typeIsaVisitor = new TypeIsaVisitor(varTranslation.TypeVarTranslation); + + var vdecls = new List(); + + foreach (var v in variables) + { + if (varTranslation.VarTranslation.TryTranslateVariableId(v, out var resId, out _)) + { + vdecls.Add(IsaBoogieTerm.VarDecl(v, resId, typeIsaVisitor, cmdIsaVisitor.TranslateSingle)); + } + else + { + throw new ProofGenUnexpectedStateException(GetType(), "Cannot translate variable " + v.Name); + } + } + + var equation = new Tuple, Term>(new List(), new TermList(vdecls)); + return new DefDecl(VariableDeclarationsName(varKind), IsaBoogieType.VariableDeclsType, + equation); + } + + private string VariableDeclarationsName(string varKind) + { + return varKind + "_vdecls"; + } + + private DefDecl GetExprListIsa(string declName, IEnumerable exprs) + { + var result = new List(); + foreach (var expr in exprs) + { + var termTuple = cmdIsaVisitor.TranslateSingle(expr); + result.Add(termTuple); + } + + return DefDecl.CreateWithoutArg(declName, new TermList(result)); + } + + private DefDecl GetExprListIsa(string declName, IEnumerable> exprs) + { + var result = new List(); + foreach (var expr in exprs) + { + var termTuple = new TermTuple(cmdIsaVisitor.TranslateSingle(expr.Item1), new BoolConst(expr.Item2)); + result.Add(termTuple); + } + + return DefDecl.CreateWithoutArg(declName, new TermList(result)); + } + + private DefDecl GetMethodBodyASTDecl(string methodName, Term methodBodyAST) + { + return DefDecl.CreateWithoutArg(astName, methodBodyAST); + } + + } +} \ No newline at end of file diff --git a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs index 807f5f253..e01bdb261 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs @@ -41,6 +41,7 @@ public class MembershipLemmaManager : IProgramAccessor private readonly string globalsWfName = "globals_wf"; private readonly List helperLemmas = new List(); private readonly IsaBlockInfo isaBlockInfo; + private readonly IsaBigBlockInfo isaBigBlockInfo; private readonly IsaProgramRepr isaProgramRepr; private readonly string locals; @@ -148,6 +149,52 @@ string theoryName AddDisjointnessLemmas(GlobalsMaxLocalsMin.Item1, GlobalsMaxLocalsMin.Item2); AddWellFormednessLemmas(); } + + public MembershipLemmaManager( + IsaProgramGeneratorConfig config, + IsaProgramRepr isaProgramRepr, + IsaBigBlockInfo isaBigBlockInfo, + Tuple GlobalsMaxLocalsMin, + IVariableTranslationFactory factory, + string theoryName + ) + { + parent = config.parentAccessor; + this.isaProgramRepr = isaProgramRepr; + this.factory = factory; + this.theoryName = theoryName; + this.config = config; + this.isaBigBlockInfo = isaBigBlockInfo; + typeIsaVisitor = new TypeIsaVisitor(factory.CreateTranslation().TypeVarTranslation); + basicCmdIsaVisitor = new BasicCmdIsaVisitor(factory); + paramsAndLocalsDefs = + new[] {isaProgramRepr.paramsDeclDef + "_def", isaProgramRepr.localVarsDeclDef + "_def"}; + + parameters = config.generateParamsAndLocals + ? QualifyAccessName(isaProgramRepr.paramsDeclDef) + : parent.ParamsDecl(); + locals = config.generateParamsAndLocals + ? QualifyAccessName(isaProgramRepr.localVarsDeclDef) + : parent.LocalsDecl(); + paramsAndLocalsList = + IsaCommonTerms.AppendList(IsaCommonTerms.TermIdentFromName(parameters), + IsaCommonTerms.TermIdentFromName(locals)); + + consts = config.generateGlobalsAndConstants + ? QualifyAccessName(isaProgramRepr.GlobalProgramRepr.constantsDeclDef) + : parent.ConstsDecl(); + globals = config.generateGlobalsAndConstants + ? QualifyAccessName(isaProgramRepr.GlobalProgramRepr.globalsDeclDef) + : parent.GlobalsDecl(); + + constsAndGlobalsDefs = + new[] {consts + "_def", globals + "_def"}; + constsAndGlobalsList = + IsaCommonTerms.AppendList(IsaCommonTerms.TermIdentFromName(consts), + IsaCommonTerms.TermIdentFromName(globals)); + AddDisjointnessLemmas(GlobalsMaxLocalsMin.Item1, GlobalsMaxLocalsMin.Item2); + AddWellFormednessLemmas(); + } public string TheoryName() { @@ -283,6 +330,11 @@ public IsaBlockInfo BlockInfo() { return isaBlockInfo; } + + public IsaBigBlockInfo BigBlockInfo() + { + return isaBigBlockInfo; + } public string LookupVarDeclLemma(Variable v) { diff --git a/Source/ProofGeneration/BoogieIsaInterface/MultiCmdIsaVisitor.cs b/Source/ProofGeneration/BoogieIsaInterface/MultiCmdIsaVisitor.cs index deb266f99..81823426f 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/MultiCmdIsaVisitor.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/MultiCmdIsaVisitor.cs @@ -50,7 +50,7 @@ public IList Translate(IList cmds) { if (!(cmd is CommentCmd)) { - cmdsIsa.AddRange(Translate(cmd)); + cmdsIsa.AddRange(Translate(cmd)); } } diff --git a/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelper_forAst.cs b/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelper_forAst.cs new file mode 100644 index 000000000..c54bd6a0b --- /dev/null +++ b/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelper_forAst.cs @@ -0,0 +1,283 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; +using System.Xml; +using Isabelle.Ast; +using Isabelle.Util; +using Microsoft.BaseTypes; +using Microsoft.Boogie; +using ProofGeneration.BoogieIsaInterface; + +namespace ProofGeneration +{ + internal class BigBlockTermBuilder + { + private IDictionary> bigBlocksDefDecls; + + public BigBlockTermBuilder() + { + bigBlocksDefDecls = new Dictionary>(); + } + + public IDictionary> getBigblockDefDecls() + { + return bigBlocksDefDecls; + } + + public Term makeBigBlockTerm(BigBlock b, MultiCmdIsaVisitor cmdIsaVisitor, int flag, int nestedBlockTracker, string nameToUse, + out int updatedNestedBlockTracker) + { + var bigblock_term = IsaCommonTerms.TermIdentFromName("BigBlock"); + IList bigblock_args = new List(); + IList bigblock_args_no_cmds = new List(); + + Term name_option; + if (b.LabelName == null) + { + name_option = IsaCommonTerms.NoneOption(); + } + else + { + name_option = IsaCommonTerms.SomeOption(IsaCommonTerms.TermIdentFromName(b.LabelName)); + } + + bigblock_args.Add(name_option); + + var translatedCmds = cmdIsaVisitor.Translate(b.simpleCmds); + TermList cmdsList = new TermList(translatedCmds); + + bigblock_args.Add(cmdsList); + + Term structure_option = makeStructuredCmdTerm(b, cmdIsaVisitor, nestedBlockTracker + 1, flag, nameToUse, + out int updatedTrackerAfterStr); + bigblock_args.Add(structure_option); + + Term transfer_option = null; + if (b.tc is null) + { + transfer_option = IsaCommonTerms.NoneOption(); + } + else if (b.tc is GotoCmd) + { + GotoCmd _goto = (GotoCmd) b.tc; + List target_names = _goto.labelNames; + IList goto_arg_terms = new List(); + foreach (String target in target_names) + { + TermIdent target_term = IsaCommonTerms.TermIdentFromName(target); + goto_arg_terms.Add(target_term); + } + TermIdent goto_ident = IsaCommonTerms.TermIdentFromName("Goto"); + Term arg_for_option = new TermApp(goto_ident, goto_arg_terms); + transfer_option = IsaCommonTerms.SomeOption(arg_for_option); + } + else if (b.tc is ReturnCmd) + { + Term arg_for_option = IsaCommonTerms.TermIdentFromName("Return"); + transfer_option = IsaCommonTerms.SomeOption(arg_for_option); + } + bigblock_args.Add(transfer_option); + + IList bb_decls = new List(); + Term bigblock = new TermApp(bigblock_term, bigblock_args); + + if (nestedBlockTracker == 0) + { + OuterDecl bigblock_def = DefDecl.CreateWithoutArg(nameToUse, bigblock); + bb_decls.Add(bigblock_def); + bigBlocksDefDecls.Add(b, bb_decls); + } + + //bigBlocksDefDecls.Add(b, bb_decls); + + updatedNestedBlockTracker = updatedTrackerAfterStr; + return bigblock; + } + + public Term makeStructuredCmdTerm(BigBlock b, MultiCmdIsaVisitor cmdIsaVisitor, int nestedBlockTracker, int flag, string nameToUse, + out int updatedNestedBlockTracker) + { + Term strCmdTermOption = null; + if (b.ec == null) + { + strCmdTermOption = IsaCommonTerms.NoneOption(); + } + else if (b.ec is IfCmd) + { + IfCmd _if = (IfCmd) b.ec; + Term if_term = IsaCommonTerms.TermIdentFromName("ParsedIf"); + + Expr guard = _if.Guard; + Term guard_term = null; + if (guard is null) + { + guard_term = IsaCommonTerms.NoneOption(); + } + else + { + guard_term = IsaCommonTerms.SomeOption(cmdIsaVisitor.TranslateSingle(guard)); + } + + IList then_branch = _if.thn.BigBlocks; + IList then_branch_bigblock_terms = new List(); + foreach (BigBlock bb in then_branch) + { + Term translated_bb = makeBigBlockTerm(bb, cmdIsaVisitor, 0, nestedBlockTracker, nameToUse, + out int updatedTrackerAfterBlock); + then_branch_bigblock_terms.Add(translated_bb); + nestedBlockTracker = updatedTrackerAfterBlock + 1; + } + Term then_branch_term = new TermList(then_branch_bigblock_terms); + + IList else_branch = _if.elseBlock.BigBlocks; + IList else_branch_bigblock_terms = new List(); + foreach (BigBlock bb in else_branch) + { + Term translated_bb = makeBigBlockTerm(bb, cmdIsaVisitor, 0, nestedBlockTracker, nameToUse, + out int updatedTrackerAfterBlock); + else_branch_bigblock_terms.Add(translated_bb); + nestedBlockTracker = updatedTrackerAfterBlock + 1; + } + Term else_branch_term = new TermList(else_branch_bigblock_terms); + + IList if_args_list = new List(); + if_args_list.Add(guard_term); + if_args_list.Add(then_branch_term); + if_args_list.Add(else_branch_term); + + strCmdTermOption = IsaCommonTerms.SomeOption(new TermApp(if_term, if_args_list)); + } + else if (b.ec is WhileCmd) + { + WhileCmd _while = (WhileCmd) b.ec; + Term wrapper = IsaCommonTerms.TermIdentFromName("WhileWrapper"); + Term while_term = IsaCommonTerms.TermIdentFromName("ParsedWhile"); + + Expr guard = _while.Guard; + Term guard_term = null; + if (guard is null) + { + guard_term = IsaCommonTerms.NoneOption(); + } + else + { + guard_term = IsaCommonTerms.SomeOption(cmdIsaVisitor.TranslateSingle(guard)); + } + + IList invariants = _while.Invariants; + IList inv_terms = new List(); + foreach (PredicateCmd inv in invariants) + { + Term translated_inv = cmdIsaVisitor.TranslateSingle(inv.Expr); + inv_terms.Add(translated_inv); + } + Term invs_as_term = new TermList(inv_terms); + + IList bodyBigBlocks = _while.Body.BigBlocks; + IList body_bigblock_terms = new List(); + foreach (BigBlock bb in bodyBigBlocks) + { + Term translated_bb = makeBigBlockTerm(bb, cmdIsaVisitor, 0, nestedBlockTracker, nameToUse, + out int updatedTrackerAfterBlock); + body_bigblock_terms.Add(translated_bb); + nestedBlockTracker = updatedTrackerAfterBlock + 1; + } + Term body_term = new TermList(body_bigblock_terms); + + IList while_args_list = new List(); + while_args_list.Add(guard_term); + while_args_list.Add(invs_as_term); + while_args_list.Add(body_term); + + Term unwrapped_str_loc = new TermApp(while_term, while_args_list); + strCmdTermOption = IsaCommonTerms.SomeOption(flag == 1 ? unwrapped_str_loc : new TermApp(wrapper, unwrapped_str_loc)); + } + else if (b.ec is BreakCmd) + { + BreakCmd _break = (BreakCmd) b.ec; + Term label = IsaCommonTerms.TermIdentFromName(_break.Label); + Term break_term = IsaCommonTerms.TermIdentFromName("ParsedBreak"); + Term strCmdTerm = new TermApp(break_term, label); + + strCmdTermOption = IsaCommonTerms.SomeOption(strCmdTerm); + } + + updatedNestedBlockTracker = nestedBlockTracker; + return strCmdTermOption; + } + + public Term makeContinuationTerm(BigBlock b, ProofGenInfo proofGenInfo, int successorIndex) + { + Term continuationTerm; + Term continuationStart; + Term continuationEnd; + + BigBlock correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[b]; + if (proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().Keys.Contains(b)) + { + correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()[b].Item2; + } + + BigBlock successorBigBlockOrig = correspondingBigBlockOrig.successorBigBlock; + + if (successorBigBlockOrig == null) + { + continuationTerm = IsaCommonTerms.TermIdentFromName("KStop"); + return continuationTerm; + } + + if (successorBigBlockOrig.ec is WhileCmd) + { + WhileCmd wcmd = (WhileCmd) successorBigBlockOrig.ec; + if (InLoop(correspondingBigBlockOrig, wcmd.Body.BigBlocks)) + { + successorIndex++; + + continuationStart = + IsaCommonTerms.TermIdentFromName("KSeq bigblock_" + successorIndex); + continuationTerm = new TermApp(continuationStart, IsaCommonTerms.TermIdentFromName("cont_" + successorIndex)); + return continuationTerm; + } + } + + if (b.ec is WhileCmd && proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().Keys.Contains(b)) + { + continuationStart = IsaCommonTerms.TermIdentFromName("KEndBlock (KSeq bigblock_" + successorIndex); + continuationEnd = IsaCommonTerms.TermIdentFromName(")"); + continuationTerm = new TermApp(continuationStart, IsaCommonTerms.TermIdentFromName("cont_" + successorIndex), continuationEnd); + return continuationTerm; + } + + continuationStart = IsaCommonTerms.TermIdentFromName("KSeq bigblock_" + successorIndex); + continuationTerm = new TermApp(continuationStart, IsaCommonTerms.TermIdentFromName("cont_" + successorIndex)); + + return continuationTerm; + } + + private bool InLoop(BigBlock b, IList bbs) + { + foreach (var curr in bbs) + { + if (curr == b) + { + return true; + } + + if (curr.ec is IfCmd ifcmd) + { + if (InLoop(b, ifcmd.thn.BigBlocks) || (ifcmd.elseBlock != null) && InLoop(b, ifcmd.elseBlock.BigBlocks)) + { + return true; + } + } + } + + return false; + } + + + } +} \ No newline at end of file diff --git a/Source/ProofGeneration/BoogieIsaInterface/VariableTranslation/DeBruijnFixedVarTranslation.cs b/Source/ProofGeneration/BoogieIsaInterface/VariableTranslation/DeBruijnFixedVarTranslation.cs index d0489bd66..bad0971ef 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/VariableTranslation/DeBruijnFixedVarTranslation.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/VariableTranslation/DeBruijnFixedVarTranslation.cs @@ -46,6 +46,14 @@ void AddVarsToMapping(IEnumerable vars, IDictionary dic public int VariableId(Variable variable) { + foreach (var id in paramsAndLocalMapping.Keys) + { + if (variable.ToString() == id.ToString()) + { + variable = id; + } + } + if (paramsAndLocalMapping.TryGetValue(variable, out var localResult)) return localResult; if (globalsMapping.TryGetValue(variable, out var globalResult)) return globalResult; diff --git a/Source/ProofGeneration/CFGRepr/CFGReprTransformer.cs b/Source/ProofGeneration/CFGRepr/CFGReprTransformer.cs index ee5f5204c..8519ec57d 100644 --- a/Source/ProofGeneration/CFGRepr/CFGReprTransformer.cs +++ b/Source/ProofGeneration/CFGRepr/CFGReprTransformer.cs @@ -46,7 +46,7 @@ public static CFGRepr GetCfgRepresentation( if (config.GenerateBlockCopy) { - blocksToConvert = CopyBlocks(impl.Blocks, predecessorMap, config.GenerateBlockCopy, + blocksToConvert = CopyBlocks(impl.Blocks, predecessorMap, config.DesugarCalls, config.DeepCopyCmdPred, out newVarsFromDesugaring); var newToOldInternal = new Dictionary(); @@ -139,7 +139,7 @@ private static Dictionary> ComputePredecessors(IEnumerable GetTopologicalLabeling(IList blocks) + public static IDictionary GetTopologicalLabeling(IList blocks) { Contract.Requires(blocks != null); Contract.Ensures(blocks.Count == Contract.Result>().Count); diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs index 668842cc0..be4b0b7fb 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs @@ -29,7 +29,9 @@ public class CfgToDagEndToEnd private readonly string redAssmName = "Red"; private readonly string vcAssmName = "VC"; private BoogieContextIsa boogieContext; + private IProgramAccessor programAccessor; + private IProgramAccessor beforeCfgProgramAccessor; private readonly string varContextName = "\\0"; @@ -38,9 +40,12 @@ public IEnumerable EndToEndProof( string passificationEndToEndLemma, Term vcAssm, IProgramAccessor programAccessor, + IProgramAccessor beforeCfgProgramAccessor, CFGRepr cfg) { this.programAccessor = programAccessor; + this.beforeCfgProgramAccessor = beforeCfgProgramAccessor; + boogieContext = new BoogieContextIsa( IsaCommonTerms.TermIdentFromName("A"), IsaCommonTerms.TermIdentFromName("M"), @@ -52,14 +57,14 @@ public IEnumerable EndToEndProof( var abbrev = new AbbreviationDecl( varContextName, new Tuple, Term>(new List(), - new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl())) + new TermTuple(beforeCfgProgramAccessor.ConstsAndGlobalsDecl(), beforeCfgProgramAccessor.ParamsAndLocalsDecl())) ); var result = new List {abbrev}; var kStepRed = IsaBoogieTerm.RedCFGKStep( BoogieContextIsa.CreateWithNewVarContext( boogieContext, - new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl()) + new TermTuple(beforeCfgProgramAccessor.ConstsAndGlobalsDecl(), beforeCfgProgramAccessor.ParamsAndLocalsDecl()) ), programAccessor.CfgDecl(), IsaBoogieTerm.CFGConfigNode(new NatConst(cfg.GetUniqueIntLabel(cfg.entry)), @@ -109,7 +114,7 @@ public IEnumerable EndToEndProof( new LemmaDecl( helperLemmaName, LemmaContext(cfg, vcAssm), - CfgToDagLemmaManager.CfgLemmaConclusion(boogieContext, programAccessor.PostconditionsDecl(), + CfgToDagLemmaManager.CfgLemmaConclusion(boogieContext, beforeCfgProgramAccessor.PostconditionsDecl(), finalNodeOrReturn, finalState), new Proof(new List {proofSb.ToString()}) ); @@ -132,12 +137,20 @@ public IEnumerable EndToEndProof( 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") + programAccessor.ProcDeclName() + "_def " + programAccessor.CfgDeclName() + "_def " + + programAccessor.PreconditionsDeclName() + "_def " + programAccessor.PostconditionsDeclName() + "_def " + + programAccessor.ParamsDecl() + "_def " + programAccessor.LocalsDecl() + "_def " + + beforeCfgProgramAccessor.PreconditionsDeclName() + "_def " + beforeCfgProgramAccessor.PostconditionsDeclName() + "_def " + + beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def") } ) ); + + if (!ProofGenerationLayer.GenerateASTToCFGProof()) + { + result.Add(endToEndLemma); + } - result.Add(endToEndLemma); - return result; + return result; } private ContextElem LemmaContext( @@ -148,7 +161,7 @@ Term vcAssm var multiRed = IsaBoogieTerm.RedCFGMulti( BoogieContextIsa.CreateWithNewVarContext( boogieContext, - new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl()) + new TermTuple(beforeCfgProgramAccessor.ConstsAndGlobalsDecl(), beforeCfgProgramAccessor.ParamsAndLocalsDecl()) ), programAccessor.CfgDecl(), IsaBoogieTerm.CFGConfigNode(new NatConst(cfg.GetUniqueIntLabel(cfg.entry)), @@ -157,14 +170,14 @@ Term vcAssm ); var closedAssm = EndToEndAssumptions.ClosednessAssumption(boogieContext.absValTyMap); var nonEmptyTypesAssm = EndToEndAssumptions.NonEmptyTypesAssumption(boogieContext.absValTyMap); - var finterpAssm = IsaBoogieTerm.FunInterpWf(boogieContext.absValTyMap, programAccessor.FunctionsDecl(), + var finterpAssm = IsaBoogieTerm.FunInterpWf(boogieContext.absValTyMap, beforeCfgProgramAccessor.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, + var axiomAssm = EndToEndAssumptions.AxiomAssumption(boogieContext, beforeCfgProgramAccessor, new TermWithExplicitType(normalInitState, IsaBoogieType.NormalStateType(absValType))); var presAssm = - IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState, programAccessor.PreconditionsDecl()); + IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState, beforeCfgProgramAccessor.PreconditionsDecl()); var localsAssm = EndToEndAssumptions.LocalStateAssumption(boogieContext, IsaCommonTerms.Snd(boogieContext.varContext), normalInitState); var globalsAssm = EndToEndAssumptions.GlobalStateAssumption(boogieContext, @@ -197,14 +210,16 @@ public static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term gl new List{ typeInterpId}, null, new TermApp( - IsaCommonTerms.TermIdentFromName("proc_is_correct"), + IsaCommonTerms.TermIdentFromName("Semantics.proc_is_correct"), //TODO: here assuming that we use "'a" for the abstract value type carrier t --> make t a parameter somewhere new TermWithExplicitType(new TermIdent(typeInterpId), IsaBoogieType.AbstractValueTyFunType(new VarType("a"))), funDecls, constantDecls, globalDecls, axioms, - procedure)); + procedure, + //TODO: define this elsewhere. + IsaCommonTerms.TermIdentFromName("Semantics.proc_body_satisfies_spec"))); } } } \ No newline at end of file diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagLemmaManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagLemmaManager.cs index ba46fdfdb..814bd4490 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagLemmaManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagLemmaManager.cs @@ -18,6 +18,8 @@ public class CfgToDagLemmaManager private readonly IProgramAccessor afterDagProgAccess; private readonly Block afterExitBlock; + private readonly IProgramAccessor beforeCfgProgAccess; + private readonly BasicCmdIsaVisitor basicCmdIsaVisitor; private readonly IProgramAccessor beforeDagProgAccess; @@ -51,6 +53,7 @@ public class CfgToDagLemmaManager //afterExitBlock is non-null iff afterExitBlock is a newly generated unique exit block after the CFG-to-DAG transformation public CfgToDagLemmaManager( + IProgramAccessor beforeCfgProgAccess, IProgramAccessor beforeDagProgAccess, IProgramAccessor afterDagProgAccess, BoogieContextIsa boogieContext, @@ -64,6 +67,7 @@ public CfgToDagLemmaManager( IVariableTranslationFactory varFactory ) { + this.beforeCfgProgAccess = beforeCfgProgAccess; this.beforeDagProgAccess = beforeDagProgAccess; this.afterDagProgAccess = afterDagProgAccess; this.afterDagCfg = afterDagCfg; @@ -78,7 +82,7 @@ IVariableTranslationFactory varFactory initState1 = IsaBoogieTerm.Normal(normalInitState1); initState2 = IsaBoogieTerm.Normal(normalInitState2); basicCmdIsaVisitor = new BasicCmdIsaVisitor(varFactory); - typingTacticGenerator = new TypingTacticGenerator(beforeDagProgAccess, varFactory); + typingTacticGenerator = new TypingTacticGenerator(beforeCfgProgAccess, varFactory); } private TermList HavocedVarsTerm(IEnumerable vars) @@ -281,7 +285,7 @@ public LemmaDecl EntryLemma(string lemmaName, Block beforeEntryBlock, Block afte assumptions.Add(dagVerifiesCfgAssm); var preAssm = - IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState2, beforeDagProgAccess.PreconditionsDecl()); + IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState2, beforeCfgProgAccess.PreconditionsDecl()); assumptions.Add(preAssm); var afterEntrySuccessors = afterDagCfg.GetSuccessorBlocks(afterEntryBlock); @@ -301,10 +305,10 @@ public LemmaDecl EntryLemma(string lemmaName, Block beforeEntryBlock, Block afte ProofUtil.Apply("erule assms(3)"), ProofUtil.Apply("rule assms(2)"), "unfolding " + afterDagProgAccess.BlockInfo().CmdsQualifiedName(afterEntryBlock) + "_def", - ProofUtil.Apply("rule assume_pres_normal[where ?es=" + beforeDagProgAccess.PreconditionsDeclName() + + ProofUtil.Apply("rule assume_pres_normal[where ?es=" + beforeCfgProgAccess.PreconditionsDeclName() + "]"), ProofUtil.Apply("rule assms(4)"), - "unfolding " + beforeDagProgAccess.PreconditionsDeclName() + "_def", + "unfolding " + beforeCfgProgAccess.PreconditionsDeclName() + "_def", "apply simp", ProofUtil.Apply("rule " + afterDagProgAccess.BlockInfo().OutEdgesMembershipLemma(afterEntryBlock)), ProofUtil.Apply(ProofUtil.Simp( @@ -341,7 +345,7 @@ public IList UnifiedExitLemma(string lemmaName) }; var conclusion = IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState2, - beforeDagProgAccess.PostconditionsDecl()); + beforeCfgProgAccess.PostconditionsDecl()); var typingTactics = new List(); var lemmas = new List(); @@ -363,7 +367,7 @@ public IList UnifiedExitLemma(string lemmaName) conclusion, new Proof(new List { - "unfolding expr_all_sat_def " + beforeDagProgAccess.PostconditionsDeclName() + "_def ", + "unfolding expr_all_sat_def " + beforeCfgProgAccess.PostconditionsDeclName() + "_def ", ProofUtil.Apply("rule cfg_dag_rel_post_invs_3"), "apply (erule assms(1))", ProofUtil.Apply("rule " + @@ -522,7 +526,7 @@ public Tuple, LemmaDecl> BlockLemma( if (blockHeadHint != null) foreach (var x in blockHeadHint.ModifiedVars) - proofMethods.Add(ProofUtil.Apply(ProofUtil.Simp(beforeDagProgAccess.LookupVarDeclLemma(x)))); + proofMethods.Add(ProofUtil.Apply(ProofUtil.Simp(beforeCfgProgAccess.LookupVarDeclLemma(x)))); //TODO proof that post invariants reduce to booleans proofMethods.Add(TypingTactics(typingTactics, null)); @@ -626,7 +630,7 @@ public Tuple, LemmaDecl> BlockLemma( private Term CfgLemmaConclusion(Term finalNode, Term finalState) { - return CfgLemmaConclusion(boogieContext, beforeDagProgAccess.PostconditionsDecl(), + return CfgLemmaConclusion(boogieContext, beforeCfgProgAccess.PostconditionsDecl(), finalNode, finalState); } @@ -634,7 +638,7 @@ public static Term CfgLemmaConclusion(BoogieContextIsa boogieContext, Term post, Term finalState) { return new TermApp( - IsaCommonTerms.TermIdentFromName("valid_configuration"), + IsaCommonTerms.TermIdentFromName("Semantics.valid_configuration"), boogieContext.absValTyMap, boogieContext.varContext, boogieContext.funContext, @@ -729,22 +733,24 @@ private void GenerateProofBody( If so, then we need to get the invariant satisfiability from that block. */ foreach (var afterSuc in afterDagCfg.GetSuccessorBlocks(afterBlock)) + { if (hintManager.IsNewBackedgeBlock(afterSuc, out var loopHead, out var _) && loopHead == bSuc) { - //TODO separate function for this and share code with case below - var afterSucId = afterDagProgAccess.BlockInfo().BlockIds[afterSuc]; - sb.AppendLine("(* proof strategy for new backedge block *)"); - sb.AppendLine("apply (erule allE[where x=" + afterSucId + "])"); - sb.AppendLine(ProofUtil.Apply( - ProofUtil.Simp(afterDagProgAccess.BlockInfo() - .OutEdgesMembershipLemma(afterBlock)))); - sb.AppendLine(ProofUtil.Apply(ProofUtil.Simp("member_rec(1)"))); - sb.AppendLine(ProofUtil.Apply("erule " + cfgLemmaName(afterSuc))); - sb.AppendLine(ProofUtil.Apply("assumption, assumption, simp")); - sb.AppendLine("(* finish proof strategy for new backedge block *)"); - break; + //TODO separate function for this and share code with case below + var afterSucId = afterDagProgAccess.BlockInfo().BlockIds[afterSuc]; + sb.AppendLine("(* proof strategy for new backedge block *)"); + sb.AppendLine("apply (erule allE[where x=" + afterSucId + "])"); + sb.AppendLine(ProofUtil.Apply( + ProofUtil.Simp(afterDagProgAccess.BlockInfo() + .OutEdgesMembershipLemma(afterBlock)))); + sb.AppendLine(ProofUtil.Apply(ProofUtil.Simp("member_rec(1)"))); + sb.AppendLine(ProofUtil.Apply("erule " + cfgLemmaName(afterSuc))); + sb.AppendLine(ProofUtil.Apply("assumption, assumption, simp")); + sb.AppendLine("(* finish proof strategy for new backedge block *)"); + break; } + } if (beforeBlock.Equals(bSuc)) { @@ -907,8 +913,8 @@ private string TypingTactics(IEnumerable typingTactics, string stateWtTh ProofUtil.OF("" + "type_safety_top_level_inv", funContextWfName, - beforeDagProgAccess.FuncsWfTyLemma(), - beforeDagProgAccess + beforeCfgProgAccess.FuncsWfTyLemma(), + beforeCfgProgAccess .VarContextWfTyLemma()))); if (stateWtThm != null) sb.AppendLine(ProofUtil.Apply("rule " + stateWtThm)); @@ -975,8 +981,7 @@ Func cfgLemmaName .BlockCmdsMembershipLemma(afterBlock))); sb.AppendLine(ProofUtil.Apply("erule " + dagVerifiesName)); sb.AppendLine(ProofUtil.Apply("rule " + dagAssmsName)); - sb.AppendLine("unfolding " + beforeDagProgAccess.PostconditionsDeclName() + - "_def"); + sb.AppendLine("unfolding " + beforeCfgProgAccess.PostconditionsDeclName() + "_def"); sb.AppendLine(ProofUtil.Apply("rule " + blockLemmaName(beforeBlock))); sb.AppendLine("apply assumption+"); sb.AppendLine( @@ -1030,7 +1035,7 @@ private Proof GenerateProofLoopHead( sb.AppendLine("show ?case"); sb.AppendLine("proof (cases j)"); sb.AppendLine( - "case 0 with less.prems(1) show ?thesis unfolding valid_configuration_def by auto"); + "case 0 with less.prems(1) show ?thesis unfolding Semantics.valid_configuration_def by auto"); sb.AppendLine("next"); sb.AppendLine("case (Suc j')"); sb.Append("from less(3) have " + stateRelLoopHeadName + ":"); @@ -1152,7 +1157,7 @@ Term numSteps cfg, modVars, invs, - beforeDagProgAccess.PostconditionsDecl(), + beforeCfgProgAccess.PostconditionsDecl(), normalState, finalState, loopHeadNode, diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs index f99fff19a..c631ea59d 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs @@ -24,6 +24,7 @@ public class CfgToDagManager public static Theory CfgToDagProof( PhasesTheories phasesTheories, bool generateEndToEndLemma, + bool generatedAstToCfgProof, Term vcAssm, CFGRepr beforeDagCfg, CFGRepr afterDagCfg, @@ -31,10 +32,16 @@ public static Theory CfgToDagProof( BoogieMethodData beforeDagData, CfgToDagHintManager hintManager, IDictionary beforeToAfter, + IProgramAccessor beforeCfgProgAccess, IProgramAccessor beforeDagProgAccess, IProgramAccessor afterDagProgAccess, IVariableTranslationFactory varFactory) { + if (!generatedAstToCfgProof) + { + beforeCfgProgAccess = beforeDagProgAccess; + } + 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 @@ -65,7 +72,7 @@ public static Theory CfgToDagProof( var varContextName = "\\1"; var varContextAbbrev = new AbbreviationDecl( varContextName, - new Tuple, Term>(new List(), beforeDagProgAccess.VarContext()) + new Tuple, Term>(new List(), beforeCfgProgAccess.VarContext()) ); var funContextWfName = "Wf_Fun"; @@ -76,6 +83,7 @@ public static Theory CfgToDagProof( IsaCommonTerms.TermIdentFromName("\\"), IsaCommonTerms.EmptyList); var lemmaManager = new CfgToDagLemmaManager( + beforeCfgProgAccess, beforeDagProgAccess, afterDagProgAccess, boogieContext, @@ -189,7 +197,7 @@ public static Theory CfgToDagProof( }, new List { - IsaBoogieTerm.FunInterpWf(boogieContext.absValTyMap, beforeDagProgAccess.FunctionsDecl(), + IsaBoogieTerm.FunInterpWf(boogieContext.absValTyMap, beforeCfgProgAccess.FunctionsDecl(), boogieContext.funContext) }, new List {funContextWfName} @@ -208,6 +216,7 @@ public static Theory CfgToDagProof( phasesTheories.EndToEndLemmaName(PhasesTheories.Phase.Passification, true), vcAssm, beforeDagProgAccess, + beforeCfgProgAccess, beforeDagCfg ); theoryOuterDecls.AddRange(endToEndDecls); @@ -218,6 +227,7 @@ public static Theory CfgToDagProof( new List { "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.BackedgeElim", "Boogie_Lang.TypingML", + generatedAstToCfgProof ? beforeCfgProgAccess.TheoryName() : null, beforeDagProgAccess.TheoryName(), afterDagProgAccess.TheoryName(), phasesTheories.TheoryName(PhasesTheories.Phase.Passification), phasesTheories.TheoryName(PhasesTheories.Phase.Vc) diff --git a/Source/ProofGeneration/Passification/PassificationEndToEnd.cs b/Source/ProofGeneration/Passification/PassificationEndToEnd.cs index 05e940b63..505b954bb 100644 --- a/Source/ProofGeneration/Passification/PassificationEndToEnd.cs +++ b/Source/ProofGeneration/Passification/PassificationEndToEnd.cs @@ -43,11 +43,13 @@ public class PassificationEndToEnd private StateRelationData oldRelationData; private IProgramAccessor passiveProgramAccessor; + private IProgramAccessor beforePhaseProgramAccessor; + private TermIdent passiveVarContext; private IProgramAccessor programAccessor; private IVariableTranslation varTranslation; private Term vcAssm; - + public PassificationEndToEnd() { stateRelList = IsaCommonTerms.TermIdentFromName(stateRelListDefName); @@ -58,6 +60,7 @@ public IEnumerable EndToEndProof( string entryCfgLemma, string boogieToVcLemma, Term vcAssm, + IProgramAccessor beforePhaseProgramAccessor, IProgramAccessor programAccessor, IProgramAccessor passiveProgramAccessor, Tuple varContextNonPassivePassive, @@ -69,6 +72,7 @@ public IEnumerable EndToEndProof( this.entryCfgLemma = entryCfgLemma; this.boogieToVcLemma = boogieToVcLemma; this.vcAssm = vcAssm; + this.beforePhaseProgramAccessor = beforePhaseProgramAccessor; this.programAccessor = programAccessor; this.passiveProgramAccessor = passiveProgramAccessor; boogieContext = new BoogieContextIsa( @@ -167,7 +171,7 @@ private List GenerateLemma() foreach (var idVar in varIds) relWfProofMethods.Add( - ProofUtil.Apply(ProofUtil.Simp(programAccessor.LookupVarTyLemma(idVar.Item2), + ProofUtil.Apply(ProofUtil.Simp(beforePhaseProgramAccessor.LookupVarTyLemma(idVar.Item2), passiveProgramAccessor.LookupVarTyLemma(idVar.Item2))) ); @@ -249,7 +253,12 @@ private List GenerateLemma() { ProofUtil.Apply("rule " + ProofUtil.OF("nstate_old_rel_states_helper", constsGlobalsAssmName, oldGlobalEqualAssmName)), - ProofUtil.Apply("simp only: fst_conv snd_conv " + programAccessor.GlobalsLocalsDisjointLemma()) + ProofUtil.Apply("simp only: fst_conv snd_conv " + programAccessor.GlobalsLocalsDisjointLemma()), + + // generatedAstToCfgProof ? + // "unfolding " + beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def " + + // beforeCfgProgramAccessor.GlobalsDecl() + "_def " + beforeCfgProgramAccessor.ConstsDecl() + "_def" : null, + // generatedAstToCfgProof ? "apply simp" : null }; void ConvertRelPropertyToListElems() @@ -440,7 +449,7 @@ private ContextElem Context() var multiRed = IsaBoogieTerm.RedCFGMulti( BoogieContextIsa.CreateWithNewVarContext( boogieContext, - new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl()) + new TermTuple(beforePhaseProgramAccessor.ConstsAndGlobalsDecl(), beforePhaseProgramAccessor.ParamsAndLocalsDecl()) ), programAccessor.CfgDecl(), IsaBoogieTerm.CFGConfigNode(new NatConst(cfg.GetUniqueIntLabel(cfg.entry)), diff --git a/Source/ProofGeneration/Passification/PassificationLemmaManager.cs b/Source/ProofGeneration/Passification/PassificationLemmaManager.cs index ee9c0ae80..c5d7021ce 100644 --- a/Source/ProofGeneration/Passification/PassificationLemmaManager.cs +++ b/Source/ProofGeneration/Passification/PassificationLemmaManager.cs @@ -38,6 +38,7 @@ internal class PassificationLemmaManager private readonly IVariableTranslation passiveVarTranslation; private readonly IProgramAccessor programAccessor; + private readonly IProgramAccessor beforePhaseProgramAccessor; private readonly Dictionary smallestRequiredVersionDict = new Dictionary(); private readonly TermIdent stateRel = IsaCommonTerms.TermIdentFromName("R"); @@ -49,6 +50,7 @@ internal class PassificationLemmaManager public PassificationLemmaManager( CFGRepr cfg, IDictionary origToPassiveBlock, + IProgramAccessor beforePhaseProgramAccessor, IProgramAccessor programAccessor, IProgramAccessor passiveProgramAccessor, Tuple varContextNonPassivePassive, @@ -59,6 +61,7 @@ public PassificationLemmaManager( { this.cfg = cfg; this.origToPassiveBlock = origToPassiveBlock; + this.beforePhaseProgramAccessor = beforePhaseProgramAccessor; this.programAccessor = programAccessor; this.passiveProgramAccessor = passiveProgramAccessor; _oldStateRelationData = oldStateRelationData; @@ -113,7 +116,7 @@ public Tuple GenerateBlockLemma(Block block, string localL * in which case the variable is not newly constrained */ if (!tuple.Item3) constrainedPassiveVars.Add(passiveVarTerm); lookupTyUpdatesLemmas.Add( - Tuple.Create(programAccessor.LookupVarTyLemma(origVar), + Tuple.Create(beforePhaseProgramAccessor.LookupVarTyLemma(origVar), passiveProgramAccessor.LookupVarTyLemma(passiveVar)) ); } diff --git a/Source/ProofGeneration/Passification/PassificationManager.cs b/Source/ProofGeneration/Passification/PassificationManager.cs index 0a56329b7..d1c9d7b08 100644 --- a/Source/ProofGeneration/Passification/PassificationManager.cs +++ b/Source/ProofGeneration/Passification/PassificationManager.cs @@ -34,12 +34,14 @@ public static Theory PassificationProof( CFGRepr beforePassificationCfg, IDictionary nonPassiveToPassiveBlock, PassiveRelationGen relationGen, + IProgramAccessor beforePhaseProgramAccess, IProgramAccessor beforePassiveProgAccess, IProgramAccessor passiveProgAccess, BoogieMethodData beforePassiveData, IVariableTranslationFactory beforePassiveFactory, IVariableTranslationFactory passiveFactory) { + var varContextName = "\\1"; var passiveVarContextName = "\\2"; var varContextNonPassivePassive = Tuple.Create(varContextName, passiveVarContextName); @@ -61,6 +63,7 @@ public static Theory PassificationProof( var beforePassiveLemmaManager = new PassificationLemmaManager( beforePassificationCfg, nonPassiveToPassiveBlock, + beforePhaseProgramAccess, beforePassiveProgAccess, passiveProgAccess, varContextNonPassivePassive, @@ -74,7 +77,7 @@ public static Theory PassificationProof( var varContextAbbrev = new AbbreviationDecl( varContextName, - new Tuple, Term>(new List(), beforePassiveProgAccess.VarContext()) + new Tuple, Term>(new List(), beforePhaseProgramAccess.VarContext()) ); var passiveVarContextAbbrev = new AbbreviationDecl( @@ -111,6 +114,7 @@ public static Theory PassificationProof( GetCfgLemmaName(beforePassificationCfg.entry, lemmaNamer), boogieToVcTheoryName + "." + boogieToVcLemma.Name, vcAssm, + beforePhaseProgramAccess, beforePassiveProgAccess, passiveProgAccess, varContextNonPassivePassive, @@ -123,7 +127,7 @@ public static Theory PassificationProof( var imports = new List { - "Boogie_Lang.Semantics", "Boogie_Lang.Util", beforePassiveProgAccess.TheoryName(), + "Boogie_Lang.Semantics", "Boogie_Lang.Util", beforePhaseProgramAccess.TheoryName(), passiveProgAccess.TheoryName(), "Boogie_Lang.PassificationML", boogieToVcTheoryName }; diff --git a/Source/ProofGeneration/PhasesTheories.cs b/Source/ProofGeneration/PhasesTheories.cs index d35f810bd..793b7dc07 100644 --- a/Source/ProofGeneration/PhasesTheories.cs +++ b/Source/ProofGeneration/PhasesTheories.cs @@ -6,9 +6,11 @@ public enum Phase { Vc, Passification, - CfgToDag + CfgToDag, + AstToCfg } + private readonly string astToCfgTheoryName; private readonly string cfgToDagTheoryName; private readonly string passificationTheoryName; @@ -20,6 +22,7 @@ public PhasesTheories(string prefix) vcPhaseTheoryName = prefix + "_vcphase_proof"; passificationTheoryName = prefix + "_passification_proof"; cfgToDagTheoryName = prefix + "_cfgtodag_proof"; + astToCfgTheoryName = prefix + "_asttocfg_proof"; } public string TheoryName(Phase phase) @@ -32,6 +35,8 @@ public string TheoryName(Phase phase) return passificationTheoryName; case Phase.CfgToDag: return cfgToDagTheoryName; + case Phase.AstToCfg: + return astToCfgTheoryName; default: throw new ProofGenUnexpectedStateException("unknown phase"); } diff --git a/Source/ProofGeneration/ProofGenConfig.cs b/Source/ProofGeneration/ProofGenConfig.cs index af7ae0003..1389601f1 100644 --- a/Source/ProofGeneration/ProofGenConfig.cs +++ b/Source/ProofGeneration/ProofGenConfig.cs @@ -6,16 +6,19 @@ public class ProofGenConfig { public ProofGenConfig( + bool generateAstToCfg, bool generateCfgDagE2E, bool generatePassifE2E, bool generateVcE2E ) { + GenerateAstToCfg = generateAstToCfg; GenerateCfgDagE2E = generateCfgDagE2E; GeneratePassifE2E = generatePassifE2E; GenerateVcE2E = generateVcE2E; } - + + public bool GenerateAstToCfg { get; } public bool GenerateCfgDagE2E { get; } public bool GeneratePassifE2E { get; } public bool GenerateVcE2E { get; } diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 8af9a9883..5cbd76e43 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -8,6 +8,8 @@ using Microsoft.Boogie.ProofGen; using Microsoft.Boogie.TypeErasure; using Microsoft.Boogie.VCExprAST; +using ProofGeneration.ASTRepresentation; +using ProofGeneration.AstToCfg; using ProofGeneration.BoogieIsaInterface; using ProofGeneration.BoogieIsaInterface.VariableTranslation; using ProofGeneration.CFGRepresentation; @@ -22,11 +24,26 @@ namespace ProofGeneration public class ProofGenerationLayer { private static Implementation afterPassificationImpl; + private static Implementation beforeCFGtoDagImpl; + //private static Implementation beforeDagImpl; + private static ProofGenInfo proofGenInfo; + + private static MultiCmdIsaVisitor cmdIsaVisitor; + + private static ASTRepr beforeCfgAst; + private static IDictionary beforeCfgAfterCfgBlock; + //private static BoogieMethodData beforeCfgData; + + private static IDictionary beforeOptimizationsOrigBlock; private static IDictionary beforeDagOrigBlock; private static IDictionary beforeDagAfterDagBlock; + + private static CFGRepr beforeOptimizationsCFG; + private static CFGRepr beforeDagCfg; + private static BoogieMethodData beforeOptimizationsData; private static BoogieMethodData beforeDagData; private static IDictionary beforePassiveToAfterPassiveBlock; @@ -60,10 +77,11 @@ public class ProofGenerationLayer private static CfgToDagHintManager cfgToDagHintManager; + //private static Block uniqueExitBlockOrigBeforeOptimizations; private static Block uniqueExitBlockOrig; private static readonly ProofGenConfig _proofGenConfig = - new ProofGenConfig(true, true, true); + new ProofGenConfig(true, true, true, true); private static IProgramAccessor globalDataProgAccess; @@ -102,17 +120,49 @@ public static void Program(Program p) } } + public static bool GenerateASTToCFGProof() + { + return _proofGenConfig.GenerateAstToCfg; + } + + public static void BeforeOptimizations(Implementation impl) + { + var config = new CFGReprConfigBuilder().SetIsAcyclic(false).SetBlockCopy(true).SetDesugarCalls(true) + .Build(); + beforeOptimizationsCFG = CFGReprTransformer.GetCfgRepresentation(impl, + config, + out beforeOptimizationsOrigBlock, + out var newVarsFromDesugaring); + beforeOptimizationsData = MethodDataFromImpl(impl, boogieGlobalData, newVarsFromDesugaring); + //uniqueExitBlockOrigBeforeOptimizations = null; + } + /// /// Provide source CFG for CFG-to-DAG phase /// public static void BeforeCFGToDAG(Implementation impl) { + beforeCFGtoDagImpl = impl; + var config = new CFGReprConfigBuilder().SetIsAcyclic(false).SetBlockCopy(true).SetDesugarCalls(true) .Build(); beforeDagCfg = CFGReprTransformer.GetCfgRepresentation(impl, config, out beforeDagOrigBlock, out var newVarsFromDesugaring); + + foreach (var block in impl.Blocks) + { + if (beforeDagOrigBlock.Values.Contains(block)) + { + continue; + } + else + { + throw new Exception(); + } + } + beforeDagData = MethodDataFromImpl(impl, boogieGlobalData, newVarsFromDesugaring); uniqueExitBlockOrig = null; } @@ -128,7 +178,7 @@ public static void GraphCfgToDag(Graph g) /// /// Provide the generated unified exit block. If no unified exit block is created (for example, when there is only /// one exit block), then invoke this method with null. - /// + /// Impl public static void CreateUnifiedExitBlock(Block generatedExitBlock) { uniqueExitBlockOrig = generatedExitBlock; @@ -242,7 +292,6 @@ private static bool TypeCheckBeforeVcMaybeRewritesCmd(Cmd cmd) public static void AfterPassificationCheckGlobalMap(Implementation impl) { afterPassificationImpl = impl; - if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) return; @@ -408,6 +457,55 @@ public static void SetTypeEraserFactory(TypePremiseEraserFactory factory) vcHintManager = new VCHintManager(new VcRewriteLemmaGen(factory, translator)); } + private static void DesugarCmdsInBigBlock(BigBlock b) + { + List copyCmds = new List(); + List newVarsFromDesugaring = new List(); + foreach (Cmd cmd in b.simpleCmds) + { + + if (cmd is SugaredCmd sugaredCmd) + { + var stateCmd = sugaredCmd.Desugaring as StateCmd; + if (stateCmd != null) + { + newVarsFromDesugaring.AddRange(stateCmd.Locals); + foreach (var desugaredCmd in stateCmd.Cmds) + { + copyCmds.Add(desugaredCmd); + } + } + } + else + { + copyCmds.Add(cmd); + } + } + + proofGenInfo.GetNewVarsFromDesugaring().AddRange(newVarsFromDesugaring); + b.simpleCmds = copyCmds; + + if (b.ec is IfCmd ifCmd) + { + foreach (var then_bb in ifCmd.thn.BigBlocks) + { + DesugarCmdsInBigBlock(then_bb); + } + + foreach (var else_bb in ifCmd.elseBlock.BigBlocks) + { + DesugarCmdsInBigBlock(else_bb); + } + } + else if (b.ec is WhileCmd wcmd) + { + foreach (var body_bb in wcmd.Body.BigBlocks) + { + DesugarCmdsInBigBlock(body_bb); + } + } + } + /// /// Generate all proofs for the current procedure. /// @@ -431,13 +529,72 @@ public static void VCGenerateAllProofs( Boogie2VCExprTranslator translator, TypeAxiomBuilderPremisses axiomBuilder) { + var map = ProofGenInfoManager.GetMapFromImplementationToProofGenInfo(); + proofGenInfo = map[afterPassificationImpl]; + + IList bigBlocks = proofGenInfo.GetBigBlocks(); + foreach (BigBlock b in bigBlocks) + { + DesugarCmdsInBigBlock(b); + } + + //TODO: test + + IList unoptimizedCFGBlocks = proofGenInfo.GetUnpotimizedBlocks(); + var newToOldInternal = new Dictionary(); + unoptimizedCFGBlocks.ZipDo(afterPassificationImpl.Blocks, (bNew, bOld) => newToOldInternal.Add(bNew, bOld)); + beforeOptimizationsOrigBlock = newToOldInternal; + + beforeOptimizationsData = MethodDataFromImpl(afterPassificationImpl, boogieGlobalData, proofGenInfo.GetNewVarsCFG()); + var config = new CFGReprConfigBuilder().SetIsAcyclic(false).SetBlockCopy(true).SetDesugarCalls(true) + .Build(); + + IDictionary labeling; + if (config.IsAcyclic) + { + labeling = CFGReprTransformer.GetTopologicalLabeling(unoptimizedCFGBlocks); + } + else + { + labeling = new Dictionary(); + var idx = 0; + foreach (var b in unoptimizedCFGBlocks) + { + labeling.Add(b, idx); + idx++; + } + } + + IDictionary> outgoingBlocks = new Dictionary>(); + foreach (var block in unoptimizedCFGBlocks) + { + var curOutgoing = new List(); + if (block.TransferCmd is GotoCmd gotoCmd) curOutgoing.AddRange(gotoCmd.labelTargets); + outgoingBlocks.Add(block, curOutgoing); + } + + Block entryBlock = null; + foreach (var block in unoptimizedCFGBlocks) + { + if (block.Predecessors.Count == 0) + { + if (entryBlock != null) + throw new ProofGenUnexpectedStateException(typeof(CFGReprTransformer), "no unique CFG entry"); + entryBlock = block; + } + } + + beforeOptimizationsCFG = new CFGRepr(outgoingBlocks, labeling, entryBlock); + + // + var uniqueNamer = new IsaUniqueNamer(); var theories = new List(); if (axiomBuilder == null && typeAxioms != null) throw new ArgumentException("type axioms can only be null if axiom builder is null"); /* Since in the proofs calls are desugared, there can be more variables in "beforePassiveData". If only - the progam should be generaed, then these variables should be ignored. */ + the program should be generated, then these variables should be ignored. */ var mainData = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? beforeDagData : beforePassiveData; var fixedVarTranslation2 = new DeBruijnFixedVarTranslation(mainData); @@ -445,11 +602,73 @@ public static void VCGenerateAllProofs( var varTranslationFactory2 = new DeBruijnVarFactory(fixedVarTranslation2, fixedTyVarTranslation2, boogieGlobalData); + cmdIsaVisitor = new MultiCmdIsaVisitor(varTranslationFactory2); + + IProgramAccessor beforeAstToCfgProgAccess = null; + if (_proofGenConfig.GenerateAstToCfg) + { + #region before ast to cfg program + + beforeCfgAst = new ASTRepr(proofGenInfo.GetBigBlocks()); + ASTRepr originalAst = new ASTRepr(proofGenInfo.GetOriginalAst()); + + var beforeAstToCfgTheoryName = + uniqueNamer.GetName(afterPassificationImpl.Name + "_before_ast_to_cfg_prog"); + //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) + var specsConfig_ast = CommandLineOptions.Clo.GenerateIsaProgNoProofs + ? SpecsConfig.All + : SpecsConfig.AllPreCheckedPost; + var beforeAstToCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, + true, specsConfig_ast, true); + + beforeAstToCfgProgAccess = new IsaProgramGenerator_forAst().GetIsaProgram( + beforeAstToCfgTheoryName, + afterPassificationImpl.Name, + mainData, beforeAstToCfgConfig, varTranslationFactory2, + beforeCfgAst, + originalAst, + proofGenInfo, + out var programDeclsBeforeAstToCfg, + !CommandLineOptions.Clo.GenerateIsaProgNoProofs); + procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "ast", beforeAstToCfgProgAccess); + + var beforeAstToCfgProgTheory = new Theory(beforeAstToCfgTheoryName, + new List + { + "Boogie_Lang.Ast", "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", + "\"../" + globalDataProgAccess.TheoryName() + "\"" + }, + programDeclsBeforeAstToCfg); + theories.Add(beforeAstToCfgProgTheory); + + #endregion + } + + #region unoptimized cfg program + var unoptimizedCfgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_unoptimized_cfg_prog"); + //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) + var _specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; + var unoptimizedCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, true, _specsConfig, true); + var unoptimizedCfgProgAccess = new IsaProgramGenerator().GetIsaProgram( + unoptimizedCfgTheoryName, + afterPassificationImpl.Name, + mainData, unoptimizedCfgConfig, varTranslationFactory2, + beforeOptimizationsCFG, + out var programDeclsUnoptimizedCfg, + !CommandLineOptions.Clo.GenerateIsaProgNoProofs); + procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "unoptimized", unoptimizedCfgProgAccess); + + var unoptimizedCfgProgTheory = new Theory(unoptimizedCfgTheoryName, + new List {"Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", "\"../"+ globalDataProgAccess.TheoryName() + "\""}, + programDeclsUnoptimizedCfg); + theories.Add(unoptimizedCfgProgTheory); + #endregion + #region before cfg to dag program var beforeCfgToDagTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_cfg_to_dag_prog"); //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) var specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; - var beforeCfgToDagConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, false, false, false, true, specsConfig, true); + var beforeCfgToDagConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, true, specsConfig, true); var beforeCfgToDagProgAccess = new IsaProgramGenerator().GetIsaProgram( beforeCfgToDagTheoryName, afterPassificationImpl.Name, @@ -473,9 +692,12 @@ public static void VCGenerateAllProofs( #region before passive program + IProgramAccessor parentProgramAccessorForPassification; + parentProgramAccessorForPassification = _proofGenConfig.GenerateAstToCfg ? beforeAstToCfgProgAccess : beforeCfgToDagProgAccess; + var beforePassiveProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_passive_prog"); var beforePassiveConfig = - new IsaProgramGeneratorConfig(beforeCfgToDagProgAccess, false, false, false, false, SpecsConfig.None, false); + new IsaProgramGeneratorConfig(parentProgramAccessorForPassification, false, false, false, false, SpecsConfig.None, false); var beforePassiveProgAccess = new IsaProgramGenerator().GetIsaProgram(beforePassiveProgTheoryName, afterPassificationImpl.Name, mainData, beforePassiveConfig, varTranslationFactory2, @@ -524,10 +746,12 @@ public static void VCGenerateAllProofs( out var programDecls, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); + var theoryNameForParentImport = _proofGenConfig.GenerateAstToCfg ? beforeAstToCfgProgAccess.TheoryName() : beforePassiveProgAccess.TheoryName(); + var finalProgTheory = new Theory(finalProgTheoryName, new List - {"Boogie_Lang.Semantics", "Boogie_Lang.Util", beforePassiveProgAccess.TheoryName()}, + {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, programDecls); theories.Add(finalProgTheory); @@ -565,7 +789,7 @@ out var endToEndLemma #region before passive var passificationProgTheory = new Theory(beforePassiveProgTheoryName, - new List {"Boogie_Lang.Semantics", "Boogie_Lang.Util", beforeCfgToDagTheoryName}, + new List {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, programDeclsBeforePassive); theories.Add(passificationProgTheory); @@ -574,6 +798,9 @@ out var endToEndLemma Console.WriteLine("Before passive prog mapping: " + fixedVarTranslation2.OutputMapping()); */ + IProgramAccessor beforePhaseProgramAccess; + beforePhaseProgramAccess = !_proofGenConfig.GenerateAstToCfg ? beforePassiveProgAccess : beforeAstToCfgProgAccess; + var passificationProofTheory = PassificationManager.PassificationProof( phasesTheories.TheoryName(PhasesTheories.Phase.Passification), theoryPassive.TheoryName, @@ -583,6 +810,7 @@ out var endToEndLemma beforePassificationCfg, beforePassiveToAfterPassiveBlock, passiveRelationGen, + beforePhaseProgramAccess, beforePassiveProgAccess, passiveProgAccess, mainData, @@ -593,6 +821,65 @@ out var endToEndLemma #endregion + if (_proofGenConfig.GenerateAstToCfg) + { + #region ast to cfg + + beforeCfgAfterCfgBlock = new Dictionary(); + IDictionary mappingWithHints = + new Dictionary(); + + IDictionary mappingCopyBigblockToOrigBigblock = + proofGenInfo.GetMappingCopyBigblockToOrigBigblock(); + IDictionary mappingOrigBigBlockToOrigBlock = + proofGenInfo.GetMappingOrigBigBlockToOrigBlock(); + + IDictionary mappingOrigBlockToCopyBlock = beforeDagOrigBlock.InverseDict(); + + IDictionary mappingBigBlockToHints = + proofGenInfo.GetMappingCopyBigBlockToHints(); + foreach (var pair in mappingOrigBigBlockToOrigBlock) + { + var origBigBlock = pair.Key; + var copyBigBlock = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[origBigBlock]; + var origBlock = pair.Value; + + if (!mappingOrigBlockToCopyBlock.ContainsKey(origBlock)) + { + int debug = 5; + } + var copyBlock = mappingOrigBlockToCopyBlock[origBlock]; + var hints = mappingBigBlockToHints[origBigBlock]; + + beforeCfgAfterCfgBlock.Add(copyBigBlock, copyBlock); + mappingWithHints.Add(copyBigBlock, (copyBlock, hints.Item1, hints.Item2)); + } + + var astToCfgProofTheory = AstToCfgManager.AstToCfgProof( + phasesTheories, + //_proofGenConfig.GenerateCfgDagE2E, + vcAssm, + proofGenInfo, + beforeCfgAst, + //beforeOptimizationsCFG, + beforeDagCfg, + //uniqueExitBlock, + //beforeOptimizationsData, + beforeDagData, + //beforeOptimizationsOrigBlock, + beforeDagOrigBlock, + mappingWithHints, + //cfgToDagHintManager, + beforeCfgAfterCfgBlock, + beforeAstToCfgProgAccess, + beforeCfgToDagProgAccess, + varTranslationFactory2, + cmdIsaVisitor); + theories.Add(astToCfgProofTheory); + + #endregion + } + #region cfg to dag var uniqueExitBlock = @@ -604,6 +891,7 @@ out var endToEndLemma var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( phasesTheories, _proofGenConfig.GenerateCfgDagE2E, + _proofGenConfig.GenerateAstToCfg, vcAssm, beforeDagCfg, beforePassificationCfg, @@ -611,6 +899,7 @@ out var endToEndLemma beforeDagData, cfgToDagHintManager, beforeDagAfterDagBlock, + beforeAstToCfgProgAccess, beforeCfgToDagProgAccess, beforePassiveProgAccess, varTranslationFactory2); diff --git a/Source/VCGeneration/VCGen.cs b/Source/VCGeneration/VCGen.cs index aaf80527e..435bf626f 100644 --- a/Source/VCGeneration/VCGen.cs +++ b/Source/VCGeneration/VCGen.cs @@ -1064,7 +1064,7 @@ private void RecordCutEdge(Dictionary> edgesCut, Block from, public void ConvertCFG2DAG(Implementation impl, Dictionary> edgesCut = null, int taskID = -1) { - Contract.Requires(impl != null); + Contract.Requires(impl != null); impl.PruneUnreachableBlocks(); // This is needed for VCVariety.BlockNested, and is otherwise just an optimization #region proofgen From fa6423830bc2d1d6beb66362023f2f8ec17be5e1 Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Wed, 17 Aug 2022 17:07:46 +0200 Subject: [PATCH 002/123] for procedures with breaks or gotos, certificate for AST-to-CFG not generated --- Source/ProofGeneration/ProofGenConfig.cs | 2 +- .../ProofGeneration/ProofGenerationLayer.cs | 86 ++++++++++++------- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/Source/ProofGeneration/ProofGenConfig.cs b/Source/ProofGeneration/ProofGenConfig.cs index 1389601f1..faa200902 100644 --- a/Source/ProofGeneration/ProofGenConfig.cs +++ b/Source/ProofGeneration/ProofGenConfig.cs @@ -18,7 +18,7 @@ bool generateVcE2E GenerateVcE2E = generateVcE2E; } - public bool GenerateAstToCfg { get; } + public bool GenerateAstToCfg { get; set; } public bool GenerateCfgDagE2E { get; } public bool GeneratePassifE2E { get; } public bool GenerateVcE2E { get; } diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 5cbd76e43..84aaa5328 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -80,8 +80,8 @@ public class ProofGenerationLayer //private static Block uniqueExitBlockOrigBeforeOptimizations; private static Block uniqueExitBlockOrig; - private static readonly ProofGenConfig _proofGenConfig = - new ProofGenConfig(true, true, true, true); + private static ProofGenConfig _proofGenConfig = + new ProofGenConfig(false, true, true, true); private static IProgramAccessor globalDataProgAccess; @@ -124,6 +124,20 @@ public static bool GenerateASTToCFGProof() { return _proofGenConfig.GenerateAstToCfg; } + + private static bool AstContainsGotoOrBreak(ProofGenInfo proofGenInfo) + { + IList ast = proofGenInfo.GetBigBlocks(); + foreach (var b in ast) + { + if (b.ec is BreakCmd || b.tc is GotoCmd) + { + return true; + } + } + + return false; + } public static void BeforeOptimizations(Implementation impl) { @@ -532,6 +546,11 @@ public static void VCGenerateAllProofs( var map = ProofGenInfoManager.GetMapFromImplementationToProofGenInfo(); proofGenInfo = map[afterPassificationImpl]; + if (AstContainsGotoOrBreak(proofGenInfo)) + { + _proofGenConfig.GenerateAstToCfg = false; + } + IList bigBlocks = proofGenInfo.GetBigBlocks(); foreach (BigBlock b in bigBlocks) { @@ -618,9 +637,9 @@ public static void VCGenerateAllProofs( var specsConfig_ast = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; - var beforeAstToCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, + var beforeAstToCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, true, specsConfig_ast, true); - + beforeAstToCfgProgAccess = new IsaProgramGenerator_forAst().GetIsaProgram( beforeAstToCfgTheoryName, afterPassificationImpl.Name, @@ -642,27 +661,38 @@ public static void VCGenerateAllProofs( theories.Add(beforeAstToCfgProgTheory); #endregion + + + #region unoptimized cfg program + + var unoptimizedCfgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_unoptimized_cfg_prog"); + //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) + var _specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs + ? SpecsConfig.All + : SpecsConfig.AllPreCheckedPost; + var unoptimizedCfgConfig = + new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, true, _specsConfig, true); + var unoptimizedCfgProgAccess = new IsaProgramGenerator().GetIsaProgram( + unoptimizedCfgTheoryName, + afterPassificationImpl.Name, + mainData, unoptimizedCfgConfig, varTranslationFactory2, + beforeOptimizationsCFG, + out var programDeclsUnoptimizedCfg, + !CommandLineOptions.Clo.GenerateIsaProgNoProofs); + procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "unoptimized", + unoptimizedCfgProgAccess); + + var unoptimizedCfgProgTheory = new Theory(unoptimizedCfgTheoryName, + new List + { + "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", + "\"../" + globalDataProgAccess.TheoryName() + "\"" + }, + programDeclsUnoptimizedCfg); + theories.Add(unoptimizedCfgProgTheory); + + #endregion } - - #region unoptimized cfg program - var unoptimizedCfgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_unoptimized_cfg_prog"); - //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) - var _specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; - var unoptimizedCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, true, _specsConfig, true); - var unoptimizedCfgProgAccess = new IsaProgramGenerator().GetIsaProgram( - unoptimizedCfgTheoryName, - afterPassificationImpl.Name, - mainData, unoptimizedCfgConfig, varTranslationFactory2, - beforeOptimizationsCFG, - out var programDeclsUnoptimizedCfg, - !CommandLineOptions.Clo.GenerateIsaProgNoProofs); - procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "unoptimized", unoptimizedCfgProgAccess); - - var unoptimizedCfgProgTheory = new Theory(unoptimizedCfgTheoryName, - new List {"Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", "\"../"+ globalDataProgAccess.TheoryName() + "\""}, - programDeclsUnoptimizedCfg); - theories.Add(unoptimizedCfgProgTheory); - #endregion #region before cfg to dag program var beforeCfgToDagTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_cfg_to_dag_prog"); @@ -692,8 +722,7 @@ public static void VCGenerateAllProofs( #region before passive program - IProgramAccessor parentProgramAccessorForPassification; - parentProgramAccessorForPassification = _proofGenConfig.GenerateAstToCfg ? beforeAstToCfgProgAccess : beforeCfgToDagProgAccess; + IProgramAccessor parentProgramAccessorForPassification = _proofGenConfig.GenerateAstToCfg ? beforeAstToCfgProgAccess : beforeCfgToDagProgAccess; var beforePassiveProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_passive_prog"); var beforePassiveConfig = @@ -746,7 +775,7 @@ public static void VCGenerateAllProofs( out var programDecls, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); - var theoryNameForParentImport = _proofGenConfig.GenerateAstToCfg ? beforeAstToCfgProgAccess.TheoryName() : beforePassiveProgAccess.TheoryName(); + var theoryNameForParentImport = _proofGenConfig.GenerateAstToCfg ? beforeAstToCfgProgAccess.TheoryName() : beforeCfgToDagProgAccess.TheoryName(); var finalProgTheory = new Theory(finalProgTheoryName, @@ -798,8 +827,7 @@ out var endToEndLemma Console.WriteLine("Before passive prog mapping: " + fixedVarTranslation2.OutputMapping()); */ - IProgramAccessor beforePhaseProgramAccess; - beforePhaseProgramAccess = !_proofGenConfig.GenerateAstToCfg ? beforePassiveProgAccess : beforeAstToCfgProgAccess; + IProgramAccessor beforePhaseProgramAccess = !_proofGenConfig.GenerateAstToCfg ? beforePassiveProgAccess : beforeAstToCfgProgAccess; var passificationProofTheory = PassificationManager.PassificationProof( phasesTheories.TheoryName(PhasesTheories.Phase.Passification), From f9db316d4b325435a93ddf6315d4d4061d84a281 Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Wed, 5 Oct 2022 08:07:33 +0200 Subject: [PATCH 003/123] some pull request comments resolved --- Source/Core/Absy.cs | 4 +- Source/Core/AbsyCmd.cs | 81 +- ...roofGenInfo.cs => AstToCfgProofGenInfo.cs} | 23 +- Source/Core/AstToCfgProofGenInfoManager.cs | 30 + Source/Core/Core.csproj | 1 + Source/Core/ObjectExtensions.cs | 159 ---- Source/Core/ProofGenInfoManager.cs | 39 - Source/ExecutionEngine/ExecutionEngine.cs | 4 +- Source/ProofGeneration/ASTRepr/ASTRepr.cs | 4 +- .../AstToCfg/AstToCfgEndToEnd.cs | 4 +- .../AstToCfg/AstToCfgLemmaManager.cs | 827 ++++++++++-------- .../AstToCfg/AstToCfgManager.cs | 13 +- .../BoogieIsaInterface/IsaBigBlockInfo.cs | 40 + .../BoogieIsaInterface/IsaBlockInfo.cs | 42 - .../BoogieIsaInterface/IsaBoogieTerm.cs | 6 +- .../BoogieIsaInterface/IsaProgramGenerator.cs | 2 +- ...forAst.cs => IsaProgramGeneratorForAst.cs} | 20 +- .../MembershipLemmaManager.cs | 46 +- ...Ast.cs => ProgramGeneratorHelperForAst.cs} | 4 +- .../DeBruijnFixedVarTranslation.cs | 9 - .../CfgToDag/CfgToDagEndToEnd.cs | 30 +- .../Passification/PassificationEndToEnd.cs | 7 +- .../ProofGeneration/ProofGenerationLayer.cs | 26 +- 23 files changed, 629 insertions(+), 792 deletions(-) rename Source/Core/{ProofGenInfo.cs => AstToCfgProofGenInfo.cs} (96%) create mode 100644 Source/Core/AstToCfgProofGenInfoManager.cs delete mode 100644 Source/Core/ObjectExtensions.cs delete mode 100644 Source/Core/ProofGenInfoManager.cs create mode 100644 Source/ProofGeneration/BoogieIsaInterface/IsaBigBlockInfo.cs rename Source/ProofGeneration/BoogieIsaInterface/{IsaProgramGenerator_forAst.cs => IsaProgramGeneratorForAst.cs} (97%) rename Source/ProofGeneration/BoogieIsaInterface/{ProgramGeneratorHelper_forAst.cs => ProgramGeneratorHelperForAst.cs} (98%) diff --git a/Source/Core/Absy.cs b/Source/Core/Absy.cs index f28d5d859..37f5bad7d 100644 --- a/Source/Core/Absy.cs +++ b/Source/Core/Absy.cs @@ -4471,8 +4471,8 @@ public Implementation(IToken /*!*/ tok, Blocks = ctx.Blocks; #region proofgen - IDictionary mapFromImplementationToProofGenInfo = ProofGenInfoManager.GetMapFromImplementationToProofGenInfo(); - ProofGenInfo correspondingProofGenInfo = ProofGenInfoManager.GetCurrentProofGenInfo(); + IDictionary mapFromImplementationToProofGenInfo = AstToCfgProofGenInfoManager.GetImplToProofGenInfo(); + AstToCfgProofGenInfo correspondingProofGenInfo = AstToCfgProofGenInfoManager.GetCurrentProofGenInfo(); mapFromImplementationToProofGenInfo.Add(this, correspondingProofGenInfo); #endregion diff --git a/Source/Core/AbsyCmd.cs b/Source/Core/AbsyCmd.cs index e58afb08d..253cd47db 100644 --- a/Source/Core/AbsyCmd.cs +++ b/Source/Core/AbsyCmd.cs @@ -437,9 +437,9 @@ public List /*!*/ Blocks get { #region proofgen - ProofGenInfo proofGenInfo = new ProofGenInfo(); + AstToCfgProofGenInfo proofGenInfo = new AstToCfgProofGenInfo(); proofGenInfo.SetStmtList(stmtList); - ProofGenInfoManager.SetCurrentProofGenInfo(proofGenInfo); + AstToCfgProofGenInfoManager.SetCurrentProofGenInfo(proofGenInfo); #endregion Contract.Ensures(cce.NonNullElements(Contract.Result>())); @@ -710,7 +710,7 @@ void RecordSuccessors(StmtList stmtList, BigBlock successor) // If the enclosing context is a loop, then "runOffTheEndLabel" is the loop head label; // otherwise, it is null. - void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, ProofGenInfo proofGenInfo) + void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, AstToCfgProofGenInfo proofGenInfo) { Contract.Requires(stmtList != null); Contract.Requires(blocks != null); @@ -741,15 +741,7 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, ProofGenInfo proo Block block = new Block(b.tok, b.LabelName, theSimpleCmds, b.tc); #region proofgen - if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(b)) - { - proofGenInfo.AddBigBlockToBlockPair(b, block); - - if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(b)) - { - proofGenInfo.AddBigBlockToHintsPair(b, (null, BranchIndicator.NoGuard)); - } - } + proofGenInfo.CreateBlockPairingWithHints(b, block, BranchIndicator.NoGuard, null); #endregion blocks.Add(block); @@ -771,14 +763,7 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, ProofGenInfo proo blocks.Add(block); #region proofgen - if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(b)) - { - proofGenInfo.AddBigBlockToBlockPair(b, block); - if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(b)) - { - proofGenInfo.AddBigBlockToHintsPair(b, (null, BranchIndicator.NoGuard)); - } - } + proofGenInfo.CreateBlockPairingWithHints(b, block, BranchIndicator.NoGuard, null); #endregion } else if (b.ec is BreakCmd) @@ -789,14 +774,7 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, ProofGenInfo proo blocks.Add(block); #region proofgen - if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(b)) - { - proofGenInfo.AddBigBlockToBlockPair(b, block); - if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(b)) - { - proofGenInfo.AddBigBlockToHintsPair(b, (null, BranchIndicator.NoGuard)); - } - } + proofGenInfo.CreateBlockPairingWithHints(b, block, BranchIndicator.NoGuard, null); #endregion } else if (b.ec is WhileCmd) @@ -830,14 +808,7 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, ProofGenInfo proo blocks.Add(block); #region proofgen - if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(b)) - { - proofGenInfo.AddBigBlockToBlockPair(b, block); - if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(b)) - { - proofGenInfo.AddBigBlockToHintsPair(b, (null, BranchIndicator.NoGuard)); - } - } + proofGenInfo.CreateBlockPairingWithHints(b, block, BranchIndicator.NoGuard, null); #endregion // LoopHead: assert/assume loop_invariant; goto LoopDone, LoopBody; @@ -873,14 +844,7 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, ProofGenInfo proo #region proofgen BigBlock loopBodyBeginning = wcmd.Body.BigBlocks[0]; - if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(loopBodyBeginning)) - { - proofGenInfo.AddBigBlockToBlockPair(loopBodyBeginning, block); - if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(loopBodyBeginning)) - { - proofGenInfo.AddBigBlockToHintsPair(loopBodyBeginning, (wcmd.Guard, BranchIndicator.GuardHolds)); - } - } + proofGenInfo.CreateBlockPairingWithHints(loopBodyBeginning, block, BranchIndicator.GuardHolds, wcmd.Guard); #endregion } @@ -978,15 +942,8 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, ProofGenInfo proo blocks.Add(block); #region proofgen - if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(b)) - { - proofGenInfo.AddBigBlockToBlockPair(b, block); - if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(b)) - { - proofGenInfo.AddBigBlockToHintsPair(b, (null, BranchIndicator.NoGuard)); - } - } - + proofGenInfo.CreateBlockPairingWithHints(b, block, BranchIndicator.NoGuard, null); + proofGenInfo.AddBigBlockToHintsPair(ifcmd.thn.BigBlocks.First(), (ifcmd.Guard, BranchIndicator.GuardHolds)); if (ifcmd.elseBlock != null) @@ -1004,14 +961,7 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, ProofGenInfo proo #region proofgen BigBlock thnBranchBeginning = ifcmd.thn.BigBlocks[0]; - if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(thnBranchBeginning)) - { - proofGenInfo.AddBigBlockToBlockPair(thnBranchBeginning, block); - if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(thnBranchBeginning)) - { - proofGenInfo.AddBigBlockToHintsPair(thnBranchBeginning, (ifcmd.Guard, BranchIndicator.GuardHolds)); - } - } + proofGenInfo.CreateBlockPairingWithHints(thnBranchBeginning, block, BranchIndicator.GuardHolds, ifcmd.Guard); #endregion } @@ -1029,14 +979,7 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, ProofGenInfo proo blocks.Add(block); #region proofgen BigBlock elseBranchBeginning = ifcmd.elseBlock.BigBlocks[0]; - if (!proofGenInfo.GetMappingOrigBigBlockToOrigBlock().ContainsKey(elseBranchBeginning)) - { - proofGenInfo.AddBigBlockToBlockPair(elseBranchBeginning, block); - if (!proofGenInfo.GetMappingCopyBigBlockToHints().ContainsKey(elseBranchBeginning)) - { - proofGenInfo.AddBigBlockToHintsPair(elseBranchBeginning, (ifcmd.Guard, BranchIndicator.GuardFails)); - } - } + proofGenInfo.CreateBlockPairingWithHints(elseBranchBeginning, block, BranchIndicator.GuardFails, ifcmd.Guard); #endregion } diff --git a/Source/Core/ProofGenInfo.cs b/Source/Core/AstToCfgProofGenInfo.cs similarity index 96% rename from Source/Core/ProofGenInfo.cs rename to Source/Core/AstToCfgProofGenInfo.cs index ca0f164ef..1ac68f96d 100644 --- a/Source/Core/ProofGenInfo.cs +++ b/Source/Core/AstToCfgProofGenInfo.cs @@ -3,6 +3,7 @@ using System.Diagnostics.Contracts; using System.Linq; using System.Reflection; +using ProofGenUtil; using Core; @@ -19,7 +20,7 @@ public enum BranchIndicator /// /// A class used to collect information needed for the generation of the AST-to-CFG part of the validation certificate for a Boogie procedure. /// - public class ProofGenInfo + public class AstToCfgProofGenInfo { /// The original object, which contains the original list of objects, which is Boogie's internal AST representation. private StmtList stmtList; @@ -40,7 +41,7 @@ public class ProofGenInfo //TODO: Fix this. /** A dictionary mapping a 'LoopHead' BigBlock to a tuple of two BigBlocks. - * A LoopHead is a special BigBlock that is a second copy (copy of a copy) has an empty list of simpleCmds and a as a . + * A LoopHead is a special BigBlock that is a second copy (copy of a copy), has an empty list of simpleCmds and a as a . * The first BigBlock in the tuple is the copied BigBlock, from which the LoopHead was created. * The second BigBlock in the tuple is the original BigBlock the copy corresponds to. */ private IDictionary mappingCopyBigblockToOrigBigblockWithTupleValue; @@ -202,8 +203,7 @@ public void AddBigBlockBeforeNamingAnonymous(BigBlock b, bool marker, BigBlock p { case BranchIndicator.NoGuard: FillEmptyElseBranches(b); - //injectEmptyBlockAtTheEndOfBranches(b); - + copy = CopyBigBlock(b); mappingCopyBigblockToOrigBigblock.Add(copy, b); mappingOrigBigblockToCopyBigblock.Add(b, copy); @@ -513,7 +513,7 @@ public IList CopyBlocks( //don't copy variables, since proof generation assumes sharing of variable identities Func copyCmd = cmd => deepCopyCmdPred(cmd) - ? cmd.Copy(t => t != typeof(IdentifierExpr) && t != typeof(TypeVariable) && t != typeof(QKeyValue)) + ? ProofGenUtil.ObjectExtensions.Copy(cmd, t => t != typeof(IdentifierExpr) && t != typeof(TypeVariable) && t != typeof(QKeyValue)) : (Cmd) CloneMethod.Invoke(cmd, null); foreach (var b in blocks) @@ -587,6 +587,19 @@ public Dictionary> ComputePredecessors(IEnumerable blo return predecessors; } + + public void CreateBlockPairingWithHints(BigBlock bigblock, Block block, BranchIndicator branchIndicator, Expr guard) + { + if (!GetMappingOrigBigBlockToOrigBlock().ContainsKey(bigblock)) + { + AddBigBlockToBlockPair(bigblock, block); + + if (!GetMappingCopyBigBlockToHints().ContainsKey(bigblock)) + { + AddBigBlockToHintsPair(bigblock, (guard, branchIndicator)); + } + } + } } } \ No newline at end of file diff --git a/Source/Core/AstToCfgProofGenInfoManager.cs b/Source/Core/AstToCfgProofGenInfoManager.cs new file mode 100644 index 000000000..3bfe6618f --- /dev/null +++ b/Source/Core/AstToCfgProofGenInfoManager.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; + +namespace Microsoft.Boogie +{ + public static class AstToCfgProofGenInfoManager + { + private static IDictionary implToProofGenInfo; + private static AstToCfgProofGenInfo currentProofGenInfo; + + public static IDictionary GetImplToProofGenInfo() + { + return implToProofGenInfo ??= new Dictionary(); + } + + public static AstToCfgProofGenInfo GetCurrentProofGenInfo() + { + return currentProofGenInfo ??= new AstToCfgProofGenInfo(); + } + + public static void SetCurrentProofGenInfo(AstToCfgProofGenInfo proofGenInfo) + { + currentProofGenInfo = proofGenInfo; + } + } +} \ No newline at end of file diff --git a/Source/Core/Core.csproj b/Source/Core/Core.csproj index 74241e141..13b6de5c1 100644 --- a/Source/Core/Core.csproj +++ b/Source/Core/Core.csproj @@ -9,6 +9,7 @@ + diff --git a/Source/Core/ObjectExtensions.cs b/Source/Core/ObjectExtensions.cs deleted file mode 100644 index c1ed7ef1d..000000000 --- a/Source/Core/ObjectExtensions.cs +++ /dev/null @@ -1,159 +0,0 @@ -/** - * -Deep copy utility method taken from https://github.com/Burtsev-Alexey/net-object-deep-copy and adjusted - -Source code is released under the MIT license. - -The MIT License (MIT) -Copyright (c) 2014 Burtsev Alexey - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -using System; -using System.Collections.Generic; -using System.Reflection; - -using Core.ArrayExtensions; - -namespace Core -{ - public static class ObjectExtensions - { - private static readonly MethodInfo CloneMethod = - typeof(object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance); - - public static bool IsPrimitive(this System.Type type) - { - if (type == typeof(string)) return true; - return type.IsValueType & type.IsPrimitive; - } - - /// - /// Do not deeply copy objects for which evaluates to false - /// - public static object Copy(this object originalObject, Predicate deepCopyPred) - { - return InternalCopy(originalObject, new Dictionary(new ReferenceEqualityComparer()), - deepCopyPred); - } - - private static object InternalCopy(object originalObject, IDictionary visited, - Predicate deepCopyPred) - { - if (originalObject == null) return null; - var typeToReflect = originalObject.GetType(); - if (IsPrimitive(typeToReflect) || !deepCopyPred(typeToReflect)) return originalObject; - if (visited.ContainsKey(originalObject)) return visited[originalObject]; - if (typeof(Delegate).IsAssignableFrom(typeToReflect)) return null; - var cloneObject = CloneMethod.Invoke(originalObject, null); - if (typeToReflect.IsArray) - { - var arrayType = typeToReflect.GetElementType(); - if (IsPrimitive(arrayType) == false && deepCopyPred(arrayType)) - { - var clonedArray = (Array) cloneObject; - clonedArray.ForEach((array, indices) => - array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited, deepCopyPred), indices)); - } - } - - visited.Add(originalObject, cloneObject); - CopyFields(originalObject, visited, cloneObject, typeToReflect, deepCopyPred); - RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect, deepCopyPred); - return cloneObject; - } - - private static void RecursiveCopyBaseTypePrivateFields(object originalObject, - IDictionary visited, object cloneObject, Type typeToReflect, Predicate deepCopyPred) - { - if (typeToReflect.BaseType != null) - { - RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType, - deepCopyPred); - CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType, deepCopyPred, - BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate); - } - } - - private static void CopyFields(object originalObject, IDictionary visited, object cloneObject, - Type typeToReflect, Predicate deepCopyPred, - BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | - BindingFlags.FlattenHierarchy, Func filter = null) - { - foreach (var fieldInfo in typeToReflect.GetFields(bindingFlags)) - { - if (filter != null && filter(fieldInfo) == false) continue; - if (IsPrimitive(fieldInfo.FieldType) || !deepCopyPred(fieldInfo.FieldType)) continue; - var originalFieldValue = fieldInfo.GetValue(originalObject); - var clonedFieldValue = InternalCopy(originalFieldValue, visited, deepCopyPred); - fieldInfo.SetValue(cloneObject, clonedFieldValue); - } - } - - public static T Copy(this T original, Predicate deepCopyPred) - { - return (T) Copy((object) original, deepCopyPred); - } - } - - public class ReferenceEqualityComparer : EqualityComparer - { - public override bool Equals(object x, object y) - { - return ReferenceEquals(x, y); - } - - public override int GetHashCode(object obj) - { - if (obj == null) return 0; - return obj.GetHashCode(); - } - } - - namespace ArrayExtensions - { - public static class ArrayExtensions - { - public static void ForEach(this Array array, Action action) - { - if (array.LongLength == 0) return; - var walker = new ArrayTraverse(array); - do - { - action(array, walker.Position); - } while (walker.Step()); - } - } - - internal class ArrayTraverse - { - private readonly int[] maxLengths; - public int[] Position; - - public ArrayTraverse(Array array) - { - maxLengths = new int[array.Rank]; - for (var i = 0; i < array.Rank; ++i) maxLengths[i] = array.GetLength(i) - 1; - Position = new int[array.Rank]; - } - - public bool Step() - { - for (var i = 0; i < Position.Length; ++i) - if (Position[i] < maxLengths[i]) - { - Position[i]++; - for (var j = 0; j < i; j++) Position[j] = 0; - return true; - } - - return false; - } - } - } -} \ No newline at end of file diff --git a/Source/Core/ProofGenInfoManager.cs b/Source/Core/ProofGenInfoManager.cs deleted file mode 100644 index e14f8122a..000000000 --- a/Source/Core/ProofGenInfoManager.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; -using System.Linq; -using System.Runtime.Serialization.Formatters.Binary; - -namespace Microsoft.Boogie -{ - public static class ProofGenInfoManager - { - private static IDictionary mapFromImplementationToProofGenInfo; - private static ProofGenInfo currentProofGenInfo; - - public static IDictionary GetMapFromImplementationToProofGenInfo() - { - /* - if (mapFromImplementationToProofGenInfo == null) - { - mapFromImplementationToProofGenInfo = new Dictionary(); - } - - return mapFromImplementationToProofGenInfo; - */ - - return mapFromImplementationToProofGenInfo ??= new Dictionary(); - } - - public static ProofGenInfo GetCurrentProofGenInfo() - { - return currentProofGenInfo ??= new ProofGenInfo(); - } - - public static void SetCurrentProofGenInfo(ProofGenInfo proofGenInfo) - { - currentProofGenInfo = proofGenInfo; - } - } -} \ No newline at end of file diff --git a/Source/ExecutionEngine/ExecutionEngine.cs b/Source/ExecutionEngine/ExecutionEngine.cs index 005a233ba..b8aec5bbe 100644 --- a/Source/ExecutionEngine/ExecutionEngine.cs +++ b/Source/ExecutionEngine/ExecutionEngine.cs @@ -504,10 +504,10 @@ public static bool ProcessProgram(Program program, string bplFileName, string pr #region proofgen - foreach (var tuple in ProofGenInfoManager.GetMapFromImplementationToProofGenInfo()) + foreach (var tuple in AstToCfgProofGenInfoManager.GetImplToProofGenInfo()) { Implementation impl = tuple.Key; - ProofGenInfo proofGenInfo = tuple.Value; + AstToCfgProofGenInfo proofGenInfo = tuple.Value; var predecessorMap = proofGenInfo.ComputePredecessors(impl.Blocks); var unoptimizedBlockCopies = proofGenInfo.CopyBlocks(impl.Blocks , predecessorMap, true, cmd => false, out var newVarsAfterDesugaring); diff --git a/Source/ProofGeneration/ASTRepr/ASTRepr.cs b/Source/ProofGeneration/ASTRepr/ASTRepr.cs index 58db5bc5f..1f195bfca 100644 --- a/Source/ProofGeneration/ASTRepr/ASTRepr.cs +++ b/Source/ProofGeneration/ASTRepr/ASTRepr.cs @@ -39,7 +39,7 @@ public int GetUniqueIntLabel(BigBlock b) return -1; } - public TermList GetAstAsTermList(ProofGenInfo proofGenInfo) + public TermList GetAstAsTermList(AstToCfgProofGenInfo proofGenInfo) { IList terms = new List(); for (var i = 0; i < bigblocks.Count; i++) @@ -54,7 +54,7 @@ public TermList GetAstAsTermList(ProofGenInfo proofGenInfo) return new TermList(terms); } - public List GetMainContinuations(ProofGenInfo proofGenInfo) + public List GetMainContinuations(AstToCfgProofGenInfo proofGenInfo) { List strings = new List(); for (var i = 0; i < bigblocks.Count; i++) diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs b/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs index 7233acc65..d5dabc50a 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs @@ -48,7 +48,7 @@ public IEnumerable EndToEndProof( IProgramAccessor beforeCfgProgramAccessor, IProgramAccessor afterCfgProgramAccessor, ASTRepr ast, - ProofGenInfo proofGenInfo) + AstToCfgProofGenInfo proofGenInfo) { this.beforeCfgProgramAccessor = beforeCfgProgramAccessor; //this.afterCfgProgramAccessor = afterCfgProgramAccessor; @@ -250,7 +250,7 @@ public IEnumerable EndToEndProof( private ContextElem LemmaContext( ASTRepr ast, Term vcAssm, - ProofGenInfo proofGenInfo + AstToCfgProofGenInfo proofGenInfo ) { BigBlock bigblock0 = ast.GetBlocksForwards().First(); diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs index 5ef81267b..4df5a2fc5 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs @@ -56,8 +56,6 @@ public AstToCfgLemmaManager( BoogieContextIsa cfgBoogieContext, CFGRepr afterCfg, string funContextWfName, - // CfgToDagHintManager hintManager, - // IDictionary> blocksToLoops, IDictionary beforeDagOrigBlock, IDictionary beforeToAfterBlock, BoogieMethodData beforeCfgData, @@ -69,8 +67,6 @@ IVariableTranslationFactory varFactory this.afterCfg = afterCfg; this.funContextWfName = funContextWfName; variableTranslation = varFactory.CreateTranslation().VarTranslation; - // this.hintManager = hintManager; - // this.blocksToLoops = blocksToLoops; this.beforeToAfterBlock = beforeToAfterBlock; this.beforeCfgData = beforeCfgData; @@ -81,7 +77,6 @@ IVariableTranslationFactory varFactory basicCmdIsaVisitor = new BasicCmdIsaVisitor(varFactory); mappingBigBlockToGlobalLemmaDecl = new Dictionary(); mappingBigBlockToLocalLemmaDecl = new Dictionary(); - //typingTacticGenerator = new TypingTacticGenerator(beforeCfgProgAccess, varFactory); this.beforeDagOrigBlock = beforeDagOrigBlock; } @@ -192,18 +187,6 @@ public LemmaDecl LocalLemma( proofSb.AppendLine(ProofUtil.Apply("rule cfgBlockDoesntFail")); proofSb.AppendLine(ProofUtil.Apply( ProofUtil.Repeat("simp add: " + afterCmdsDefName + "_def " + beforeBigblockDefName + "_def"))); proofSb.AppendLine("done"); - - // proofMethods = new List - // { - // ProofUtil.Apply("rule block_local_rel_generic"), - // ProofUtil.Apply("rule Rel_Main_test[of " + beforeBigblockDefName + "]"), - // ProofUtil.Apply("simp add: " + beforeBigblockDefName + "_def " + afterCmdsDefName + "_def"), - // ProofUtil.Apply("simp add: " + afterCmdsDefName + "_def)+", - // ProofUtil.Apply("rule astStep"), - // ProofUtil.Apply("rule cfgBlockDoesntFail"), - // ProofUtil.Apply("simp add: " + afterCmdsDefName + "_def " + beforeBigblockDefName + "_def)+", - // "done" - // }; } else if (indicator == BranchIndicator.GuardHolds) { @@ -218,21 +201,6 @@ public LemmaDecl LocalLemma( proofSb.AppendLine(ProofUtil.Apply("simp add: " + afterCmdsDefName + "_def")); proofSb.AppendLine(ProofUtil.Apply(ProofUtil.Repeat("simp add: assms(3) " + beforeBigblockDefName + "_def"))); proofSb.AppendLine("done"); - - // proofMethods = new List - // { - // "unfolding " + afterCmdsDefName + "_def", - // ProofUtil.Apply("rule guard_holds_push_through_assumption"), - // ProofUtil.Apply("rule block_local_rel_generic"), - // ProofUtil.Apply("rule Rel_Main_test[of " + beforeBigblockDefName + "]"), - // ProofUtil.Apply("simp add: " + beforeBigblockDefName + "_def"), - // ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), - // ProofUtil.Apply("rule astStep"), - // ProofUtil.Apply("rule push_through_assumption_test1, rule cfgBlockDoesntFail"), - // ProofUtil.Apply("simp add: " + afterCmdsDefName + "_def"), - // ProofUtil.Apply("simp add: assms(3) " + beforeBigblockDefName + "_def)+", - // "done" - // }; } else if (indicator == BranchIndicator.GuardFails) { @@ -253,27 +221,6 @@ public LemmaDecl LocalLemma( proofSb.AppendLine(ProofUtil.Apply(NegationRule(guardHint))); proofSb.AppendLine(ProofUtil.Apply("rule guardHint")); proofSb.AppendLine("done"); - - // proofMethods = new List - // { - // "unfolding " + afterCmdsDefName + "_def", - // ProofUtil.Apply("rule guard_fails_push_through_assumption"), - // ProofUtil.Apply("rule block_local_rel_generic"), - // ProofUtil.Apply("rule Rel_Main_test[of " + beforeBigblockDefName + "]"), - // ProofUtil.Apply("simp add: " + beforeBigblockDefName + "_def"), - // ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), - // ProofUtil.Apply("rule astStep"), - // ProofUtil.Apply("rule cfgBlockDoesntFail"), - // ProofUtil.Apply("simp add: " + afterCmdsDefName + "_def"), - // ProofUtil.Apply("rule push_through_assumption1"), - // ProofUtil.Apply(ProofUtil.Simp()), - // ProofUtil.Apply("" + NegationRule(guardHint) + ""), - // ProofUtil.Apply("rule guardHint"), - // ProofUtil.Apply("simp add: " + beforeBigblockDefName + "_def)+", - // ProofUtil.Apply("" + NegationRule(guardHint) + ""), - // ProofUtil.Apply("rule guardHint"), - // "done" - // }; } List assmsLabels = new List {"astStep", "cfgBlockDoesntFail"}; @@ -304,7 +251,7 @@ public LemmaDecl GenerateGlobalLemma( Term posts, (Expr, BranchIndicator) hints, Func globalBlockLemmaName, - ProofGenInfo proofGenInfo) + AstToCfgProofGenInfo proofGenInfo) { var assumptions = new List(); @@ -445,18 +392,9 @@ public LemmaDecl GenerateGlobalLemma( Block enclosingLoopCfgBlockCopy = origBlockBeforeDag[enclosingLoopCfgBlock]; Term blockIndex; - if (true /* enclosingLoopCfgBlockCopy.cmds.Any() */ ) - { - Block successorCfgBlock = afterCfg.GetSuccessorBlocks(enclosingLoopCfgBlockCopy).First(); - //Block successorCfgBlockCopy = origBlockBeforeDag[successorCfgBlock]; - - blockIndex = new NatConst(afterCfg.GetUniqueIntLabel(successorCfgBlock)); - } - else - { - blockIndex = new NatConst(afterCfg.GetUniqueIntLabel(enclosingLoopCfgBlockCopy)); - } - + Block successorCfgBlock = afterCfg.GetSuccessorBlocks(enclosingLoopCfgBlockCopy).First(); + blockIndex = new NatConst(afterCfg.GetUniqueIntLabel(successorCfgBlock)); + int unwrappedEnclosingLoopBigBlockIndex = proofGenInfo.GetMappingCopyBigBlockToIndex()[enclosingLoopCopy] + 1; Term succBigBlockTermId = IsaCommonTerms.TermIdentFromName(beforeCfgProgAccess.BigBlockInfo().TheoryName + ".bigblock_" + unwrappedEnclosingLoopBigBlockIndex); @@ -464,7 +402,7 @@ public LemmaDecl GenerateGlobalLemma( Term cfgBodyId = IsaCommonTerms.TermIdentFromName(afterCfgProgAccess.BlockInfo().getTheoryName() + ".proc_body"); //Term blockIndex = new NatConst(unwrappedEnclosingLoopBigBlockIndex); - Term loop_ih_assm = IsaBoogieTerm.LoopIH(astBoogieContext, cfgBoogieContext, astId, succBigBlockTermId, succContId, cfgBodyId, blockIndex, posts); + Term loop_ih_assm = IsaBoogieTerm.AstToCfgLoopIndHypothesis(astBoogieContext, cfgBoogieContext, astId, succBigBlockTermId, succContId, cfgBodyId, blockIndex, posts); hasLoopIH = true; assumptions.Add(loop_ih_assm); } @@ -609,11 +547,8 @@ private string NegationRule(Expr guard) return ProofUtil.Rule("neg_refl"); } - private string ExpandDefinitions(string contId, BigBlock startingBigBlock, ProofGenInfo proofGenInfo, BranchIndicator branchIndicator) + private string ExpandDefinitions(string contId, BigBlock startingBigBlock, AstToCfgProofGenInfo proofGenInfo, BranchIndicator branchIndicator) { - //BigBlock correspondingBigBlockOrig = proofGenInfo.getMappingCopyBigblockToOrigBigblock()[startingBigBlock]; - //IfCmd _if = (IfCmd) correspondingBigBlockOrig.ec; - IfCmd @if = (IfCmd) startingBigBlock.ec; string expansion = "apply (simp add: " + contId + "_def "; @@ -621,7 +556,7 @@ private string ExpandDefinitions(string contId, BigBlock startingBigBlock, Proof { foreach (var thenBb in @if.thn.BigBlocks) { - BigBlock thenBranchCopy = thenBb; //proofGenInfo.getMappingOrigBigblockToCopyBigblock()[then_bb]; + BigBlock thenBranchCopy = thenBb; string thenBranchId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(thenBranchCopy).First(); string thenBranchContId = "cont_" + (proofGenInfo.GetMappingCopyBigBlockToIndex()[thenBranchCopy]); expansion += thenBranchId + "_def " + thenBranchContId + "_def "; @@ -631,7 +566,7 @@ private string ExpandDefinitions(string contId, BigBlock startingBigBlock, Proof { foreach (var elseBb in @if.elseBlock.BigBlocks) { - BigBlock elseBranchCopy = elseBb; //proofGenInfo.getMappingOrigBigblockToCopyBigblock()[else_bb]; + BigBlock elseBranchCopy = elseBb; string elseBranchId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(elseBranchCopy).First(); string elseBranchContId = "cont_" + (proofGenInfo.GetMappingCopyBigBlockToIndex()[elseBranchCopy]); expansion += elseBranchId + "_def " + elseBranchContId + "_def "; @@ -647,7 +582,7 @@ private List GenerateFinalBlockProof( Block relatedBlock, Expr entryGuard, BranchIndicator indicator, - ProofGenInfo proofGenInfo) + AstToCfgProofGenInfo proofGenInfo) { string bigblockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(startingBigBlock).First(); string blockId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".block_" + afterCfg.GetUniqueIntLabel(relatedBlock); @@ -673,11 +608,10 @@ private List GenerateFinalBlockProof( finalPartofProof = new List { ProofUtil.Apply("rule " + nameLemmaLocal), - "apply assumption+", - (indicator != 0 && entryGuard != null) ? traceIsPossible : "", - "done", - "qed" + "apply assumption+" }; + + if (indicator != 0 && entryGuard != null) { finalPartofProof.Add(traceIsPossible); } } else if (startingBigBlock.tc is ReturnCmd) { @@ -686,9 +620,7 @@ private List GenerateFinalBlockProof( { ProofUtil.Apply("simp add: " + bigblockId + "_def"), ProofUtil.Apply("simp add: " + blockId + "_def"), - ProofUtil.Apply("simp add: end_return"), - "done", - "qed" + ProofUtil.Apply("simp add: end_return") }; } else @@ -697,12 +629,13 @@ private List GenerateFinalBlockProof( finalPartofProof = new List { ProofUtil.Apply("simp add: " + bigblockId + "_def"), - ProofUtil.Apply("simp add: end_static"), - "done", - "qed" + ProofUtil.Apply("simp add: end_static") }; } + finalPartofProof.Add("done"); + finalPartofProof.Add("qed"); + if (indicator == 0 || entryGuard == null) { middlePartofProof = new List @@ -772,14 +705,22 @@ private List GenerateFinalBlockProof( }; } - beginningOfProof = new List + List beginningOfProofA = new List + { + "proof -", + "show ?thesis", + ProofUtil.Apply("rule generic_ending_block_global_rel"), + syntacticRel, + ProofUtil.Apply("simp add: " + bigblockId + "_def") + }; + + if (mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock)) + { + beginningOfProofA.Add(ProofUtil.Apply(ProofUtil.Simp())); + } + + List beginningOfProofB = new List { - "proof -", - "show ?thesis", - ProofUtil.Apply("rule generic_ending_block_global_rel"), - syntacticRel, - ProofUtil.Apply("simp add: " + bigblockId + "_def"), - mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply(ProofUtil.Simp()) : "", ProofUtil.Apply("rule astTrace"), ProofUtil.Apply("simp add: " + bigblockId + "_def"), ProofUtil.Apply(ProofUtil.Simp()), @@ -788,6 +729,10 @@ private List GenerateFinalBlockProof( ProofUtil.Apply("rule " + nodeId) }; + beginningOfProof = new List(); + beginningOfProof.AddRange(beginningOfProofA); + beginningOfProof.AddRange(beginningOfProofB); + List proofMethods = new List(); proofMethods.AddRange(beginningOfProof); proofMethods.AddRange(middlePartofProof); @@ -800,7 +745,7 @@ private List GenerateLoopHeadProof( BigBlock startingBigBlock, Block relatedBlock, Expr personalGuard, - ProofGenInfo proofGenInfo) + AstToCfgProofGenInfo proofGenInfo) { List proofMethods = new List(); @@ -908,7 +853,7 @@ private List GenerateLoopHeadProof( #region construct proof var beginningOfProof = new List - { + { "using assms", "proof (induction j arbitrary: ns1 rule: less_induct)", "case (less j)", @@ -934,17 +879,27 @@ private List GenerateLoopHeadProof( ProofUtil.Apply(ProofUtil.Repeat("simp add:" + bigblockId + "_def")), ProofUtil.Apply(ProofUtil.Repeat("simp add:" + blockId + "_def " + nodeId)), ProofUtil.Apply("rule " + contId + "_def"), - ProofUtil.Apply("erule disjE"), - - personalGuard == null ? ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) : null, - personalGuard == null ? "apply (erule disjE)" : null, - //TODO: get rid of this - personalGuard == null ? "defer" : null, - + ProofUtil.Apply("erule disjE") + }; + if (personalGuard == null) + { + beginningOfProof.AddRange(new List + { + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), + "apply (erule disjE)", + //TODO: get rid of this + "defer" + }); + } + beginningOfProof.AddRange(new List + { ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succ2UniqueIntLabel + "]")), ProofUtil.Apply(ProofUtil.Repeat("simp add:" + outEdgesId)), - ProofUtil.Apply("simp add:member_rec(1)"), - personalGuard != null ? ProofUtil.Apply("erule conjE") : null, + ProofUtil.Apply("simp add:member_rec(1)") + }); + if (personalGuard != null) { beginningOfProof.Add(ProofUtil.Apply("erule conjE")); } + beginningOfProof.AddRange(new List + { ProofUtil.Apply("rule " + nameLemmaSucc1 + ""), unfoldedLoopBodyDefinitions, ProofUtil.Apply(ProofUtil.Repeat("blast")), @@ -955,13 +910,13 @@ private List GenerateLoopHeadProof( "unfolding " + contId + "_def " + bodyBigBlockContId + "_def", ProofUtil.Apply(ProofUtil.Simp()), ProofUtil.Apply("blast"), - ProofUtil.Apply("blast"), - - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) && - personalGuard == null - ? ProofUtil.Apply("rule guardHint") - : null, - }; + ProofUtil.Apply("blast") + }); + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) && + personalGuard == null) + { + beginningOfProof.Add(ProofUtil.Apply("rule guardHint")); + } var insideOfLoopAddition1 = new List { @@ -991,99 +946,150 @@ private List GenerateLoopHeadProof( ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), }; - var whileTrueEndingAfterSkippingEndBlock = new List + var whileTrueEndingAfterSkippingEndBlock = new List(); + if (personalGuard == null && !proofGenInfo.GetMappingBigBlockToLoopBigBlock() + .ContainsKey(correspondingBigBlockOrig)) + { + whileTrueEndingAfterSkippingEndBlock.Add(ProofUtil.Apply("rule guardHint")); + } + whileTrueEndingAfterSkippingEndBlock.AddRange(new List { - personalGuard == null && !proofGenInfo.GetMappingBigBlockToLoopBigBlock() - .ContainsKey(correspondingBigBlockOrig) - ? ProofUtil.Apply("rule guardHint") - : null, ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succ1UniqueIntLabel + "]")), ProofUtil.Apply(ProofUtil.Repeat("simp add:" + outEdgesId)), - ProofUtil.Apply("simp add:member_rec(1)"), - personalGuard != null ? ProofUtil.Apply("erule conjE") : null, + ProofUtil.Apply("simp add:member_rec(1)") + }); + if (personalGuard != null) { whileTrueEndingAfterSkippingEndBlock.Add(ProofUtil.Apply("erule conjE")); } + whileTrueEndingAfterSkippingEndBlock.AddRange(new List + { ProofUtil.Apply("rule ending_after_skipping_endblock2"), - //TODO: repeat is possibly redundant here! ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), - ProofUtil.Apply("blast"), - personalGuard != null ? ProofUtil.Apply("blast") : ProofUtil.Apply(ProofUtil.Repeat("blast")), - personalGuard != null ? ProofUtil.Apply(ProofUtil.Simp()) : null, - - personalGuard != null && !personalGuard.Equals(Expr.True) ? ProofUtil.Apply(ProofUtil.Simp()) : null, - personalGuard != null && !personalGuard.Equals(Expr.True) - ? ProofUtil.Apply("rule " + nameLemmaSucc2 + "") - : null, - - //TODO: repeat is redundant here! - personalGuard != null && !personalGuard.Equals(Expr.True) ? ProofUtil.Apply("blast") : null, - - //afterLoopBigBlockOrig.successorBigBlock != null ? "apply blast" : null, - personalGuard == null ? ProofUtil.Apply("rule " + nameLemmaSucc2) : null, - personalGuard == null ? ProofUtil.Apply(ProofUtil.Simp()) : null, - ProofUtil.Apply("blast") - }; - - var endingAfterSkippingEndblock = new List + }); + whileTrueEndingAfterSkippingEndBlock.Add(personalGuard != null + ? ProofUtil.Apply("blast") + : ProofUtil.Apply(ProofUtil.Repeat("blast"))); + if (personalGuard != null) { whileTrueEndingAfterSkippingEndBlock.Add(ProofUtil.Apply(ProofUtil.Simp())); } + if (personalGuard != null && !personalGuard.Equals(Expr.True)) + { + whileTrueEndingAfterSkippingEndBlock.AddRange(new List + { + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("rule " + nameLemmaSucc2 + ""), + ProofUtil.Apply("blast") + }); + } + if (personalGuard == null) + { + whileTrueEndingAfterSkippingEndBlock.AddRange(new List + { + ProofUtil.Apply("rule " + nameLemmaSucc2), + ProofUtil.Apply(ProofUtil.Simp()) + }); + } + whileTrueEndingAfterSkippingEndBlock.Add(ProofUtil.Apply("blast")); + + var endingAfterSkippingEndblock = new List(); + if (personalGuard == null && + !proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + endingAfterSkippingEndblock.Add(ProofUtil.Apply("rule guardHint")); + } + endingAfterSkippingEndblock.AddRange(new List { - personalGuard == null && !proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule guardHint") : null, ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succ1UniqueIntLabel + "]")), ProofUtil.Apply(ProofUtil.Repeat("simp add:" + outEdgesId)), - ProofUtil.Apply("simp add:member_rec(1)"), - personalGuard != null ? ProofUtil.Apply("erule conjE") : null, + ProofUtil.Apply("simp add:member_rec(1)") + }); + if (personalGuard != null) { endingAfterSkippingEndblock.Add(ProofUtil.Apply("erule conjE")); } + endingAfterSkippingEndblock.AddRange(new List + { ProofUtil.Apply("rule ending_after_skipping_endblock2"), - //TODO: repeat is possibly redundant here! ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), - ProofUtil.Apply("blast"), - personalGuard != null ? ProofUtil.Apply("blast") : ProofUtil.Apply(ProofUtil.Repeat("blast")), - personalGuard != null ? ProofUtil.Apply(ProofUtil.Simp()) : null, - - personalGuard != null && !personalGuard.Equals(Expr.True) ? ProofUtil.Apply(ProofUtil.Simp()) : null, - personalGuard != null && !personalGuard.Equals(Expr.True) ? ProofUtil.Apply("rule " + nameLemmaSucc2 + "") : null, - - //TODO: repeat is redundant here! - personalGuard != null && !personalGuard.Equals(Expr.True) ? ProofUtil.Apply("blast") : null, - - //afterLoopBigBlockOrig.successorBigBlock != null ? "apply blast" : null, - personalGuard == null ? ProofUtil.Apply("rule " + nameLemmaSucc2) : null, - personalGuard == null ? ProofUtil.Apply(ProofUtil.Simp()) : null, - - proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Repeat("blast")) : null, - - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) - ? (personalGuard != null - ? ProofUtil.Apply("rule correctness_propagates_through_assumption") - : ProofUtil.Apply("rule correctness_propagates_through_empty")) - : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? "apply blast" : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply("simp add: " + succNodeId1 + "") : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply("simp add: " + succBlockId1 + "_def") : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) - ? (personalGuard != null - ? ProofUtil.Apply(NegationRule(personalGuard)) - : null) - : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Simp()) : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply("simp add: " + succOutEdgesId1 + "") : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Repeat("simp add: member_rec")) : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) - ? (personalGuard != null - ? ProofUtil.Apply("rule correctness_propagates_through_assumption3") - : ProofUtil.Apply("rule correctness_propagates_through_empty2")) - : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? "apply blast" : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply("simp add: " + succNodeId1 + "") : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply("simp add: " + succBlockId1 + "_def") : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) - ? (personalGuard != null - ? ProofUtil.Apply(NegationRule(personalGuard)) - : null) - : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Simp()) : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply("simp add: " + succOutEdgesId1 + "") : null, - !proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Repeat("simp add: member_rec")) : null - }; + ProofUtil.Apply("blast") + }); + endingAfterSkippingEndblock.Add(personalGuard != null + ? ProofUtil.Apply("blast") + : ProofUtil.Apply(ProofUtil.Repeat("blast"))); + if (personalGuard != null) { endingAfterSkippingEndblock.Add(ProofUtil.Apply(ProofUtil.Simp())); } + if (personalGuard != null && !personalGuard.Equals(Expr.True)) + { + endingAfterSkippingEndblock.AddRange(new List + { + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("rule " + nameLemmaSucc2 + ""), + ProofUtil.Apply("blast") + }); + } + if (personalGuard == null) + { + endingAfterSkippingEndblock.AddRange(new List + { + ProofUtil.Apply("rule " + nameLemmaSucc2), + ProofUtil.Apply(ProofUtil.Simp()) + }); + } + if (proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig)) + { + endingAfterSkippingEndblock.Add(ProofUtil.Apply(ProofUtil.Repeat("blast"))); + } + if (!proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig)) + { + endingAfterSkippingEndblock.Add(personalGuard != null + ? ProofUtil.Apply("rule correctness_propagates_through_assumption") + : ProofUtil.Apply("rule correctness_propagates_through_empty")); + } + if (!proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig)) + { + endingAfterSkippingEndblock.AddRange(new List + { + "apply blast", + ProofUtil.Apply("simp add: " + succNodeId1 + ""), + ProofUtil.Apply("simp add: " + succBlockId1 + "_def") + }); + } + if (!proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) && (personalGuard != null)) + { + endingAfterSkippingEndblock.Add(ProofUtil.Apply(NegationRule(personalGuard))); + } + if (!proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig)) + { + endingAfterSkippingEndblock.AddRange(new List + { + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("simp add: " + succOutEdgesId1 + ""), + ProofUtil.Apply(ProofUtil.Repeat("simp add: member_rec")) + }); + } + if (!proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig)) + { + endingAfterSkippingEndblock.Add(personalGuard != null + ? ProofUtil.Apply("rule correctness_propagates_through_assumption3") + : ProofUtil.Apply("rule correctness_propagates_through_empty2")); + } + if (!proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig)) + { + endingAfterSkippingEndblock.AddRange(new List + { + "apply blast", + ProofUtil.Apply("simp add: " + succNodeId1 + ""), + ProofUtil.Apply("simp add: " + succBlockId1 + "_def") + }); + } + if (!proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig) && (personalGuard != null)) + { + endingAfterSkippingEndblock.Add(ProofUtil.Apply(NegationRule(personalGuard))); + } + if (!proofGenInfo.GetloopEndingBlocks().Contains(afterLoopBigBlockOrig)) + { + endingAfterSkippingEndblock.AddRange(new List + { + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("simp add: " + succOutEdgesId1 + ""), + ProofUtil.Apply(ProofUtil.Repeat("simp add: member_rec")) + }); + } var endingAfterSkippingEndBlockAndUnwrapping = new List { @@ -1138,14 +1144,6 @@ private List GenerateLoopHeadProof( { proofMethods.AddRange(endingAfterSkippingEndblock); } - // if (afterLoopBigBlockOrig.ec is WhileCmd && !afterLoopBigBlockCopy.simpleCmds.Any()) - // { - // proofMethods.AddRange(endingAfterSkippingEndBlockAndUnwrapping); - // } - // else - // { - // proofMethods.AddRange(endingAfterSkippingEndblock); - // } if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) { @@ -1171,7 +1169,7 @@ private List GenerateProofGeneric( Block relatedBlock, Expr entryGuard, BranchIndicator indicator, - ProofGenInfo proofGenInfo) + AstToCfgProofGenInfo proofGenInfo) { string bigblockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(startingBigBlock).First(); string blockId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".block_" + afterCfg.GetUniqueIntLabel(relatedBlock); @@ -1202,21 +1200,9 @@ private List GenerateProofGeneric( Block enclosingLoopCfgBlock = proofGenInfo.GetMappingOrigBigBlockToOrigBlock()[loop]; Block enclosingLoopCfgBlockCopy = origBlockBeforeDag[enclosingLoopCfgBlock]; - - if (true /* enclosingLoopCfgBlockCopy.cmds.Any() */) - { - Block successorCfgBlock = afterCfg.GetSuccessorBlocks(enclosingLoopCfgBlockCopy).First(); - //Block successorCfgBlockCopy = origBlockBeforeDag[successorCfgBlock]; - - succUniqueLoopLabel = afterCfg.GetUniqueIntLabel(successorCfgBlock); - } - else - { - succUniqueLoopLabel = afterCfg.GetUniqueIntLabel(enclosingLoopCfgBlockCopy); - } - //succUniqueLoopLabel = proofGenInfo.getMappingCopyBigBlockToIndex()[loopCopy]; - //succUniqueLoopLabel += 1; + Block successorCfgBlock = afterCfg.GetSuccessorBlocks(enclosingLoopCfgBlockCopy).First(); + succUniqueLoopLabel = afterCfg.GetUniqueIntLabel(successorCfgBlock); } var proofMethods = new List(); @@ -1239,19 +1225,29 @@ private List GenerateProofGeneric( nameLemmaSucc = mappingBigBlockToGlobalLemmaDecl[successorBigBlockCopy].Name; } - var beginningOfProof = new List + var beginningOfProofA = new List { "proof -", "show ?thesis ", ProofUtil.Apply("rule block_global_rel_generic"), startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply("rule Rel_Main_test[of " + bigblockId + "]") : ProofUtil.Apply("rule Rel_Invs[of " + bigblockId + "]") , - ProofUtil.Apply("simp add: " + bigblockId + "_def"), - startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, + ProofUtil.Apply("simp add: " + bigblockId + "_def") + }; + if (startingBigBlock.simpleCmds.Any()) + { + beginningOfProofA.Add(ProofUtil.Apply(ProofUtil.Simp())); + } + var beginningOfProofB = new List + { ProofUtil.Apply("rule astTrace"), ProofUtil.Apply("simp add: " + bigblockId + "_def"), ProofUtil.Apply("rule " + nodeId + "") }; + var beginningOfProof = new List(); + beginningOfProof.AddRange(beginningOfProofA); + beginningOfProof.AddRange(beginningOfProofB); + var middlePartOfProof = new List(); if (indicator == 0 || entryGuard == null) { @@ -1259,19 +1255,20 @@ private List GenerateProofGeneric( { ProofUtil.Apply("rule disjI1"), ProofUtil.Apply("rule " + blockId + "_def"), - // indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails ? ProofUtil.Apply("rule conjI") : null, - // indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails ? ProofUtil.Apply(ProofUtil.Simp()) : null, ProofUtil.Apply("rule cfgDoesntFail"), ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), ProofUtil.Apply("rule " + contId + "_def"), - ProofUtil.Apply("simp add: " + nodeId + ""), - // !startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, - startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply("rule " + nameLemmaLocal + "") : null, - startingBigBlock.simpleCmds.Any() ? "apply assumption" : null, - startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, + ProofUtil.Apply("simp add: " + nodeId + "") }; + + if (startingBigBlock.simpleCmds.Any()) + { + middlePartOfProof.Add(ProofUtil.Apply("rule " + nameLemmaLocal + "")); + middlePartOfProof.Add("apply assumption"); + middlePartOfProof.Add(ProofUtil.Apply(ProofUtil.Simp())); + } } else if (indicator == BranchIndicator.GuardFails) { @@ -1291,15 +1288,18 @@ private List GenerateProofGeneric( ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), ProofUtil.Apply("rule " + contId + "_def"), - ProofUtil.Apply("simp add: " + nodeId + ""), - //!startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, - startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply("rule " + nameLemmaLocal + "") : null, - startingBigBlock.simpleCmds.Any() ? "apply assumption" : null, - startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, - startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply("rule guardHint") : null, + ProofUtil.Apply("simp add: " + nodeId + "") }; + + if (startingBigBlock.simpleCmds.Any()) + { + middlePartOfProof.Add(ProofUtil.Apply("rule " + nameLemmaLocal + "")); + middlePartOfProof.Add("apply assumption"); + middlePartOfProof.Add(ProofUtil.Apply(ProofUtil.Simp())); + middlePartOfProof.Add(ProofUtil.Apply("rule guardHint")); + } } - //TODO: this check isn't correct! Why? + //TODO: this check needs revision, I don't understand why this condition works. It might fail for complex procedures. else if (indicator == BranchIndicator.GuardHolds || proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) { middlePartOfProof = new List @@ -1316,13 +1316,21 @@ private List GenerateProofGeneric( ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), ProofUtil.Apply("rule " + contId + "_def"), - ProofUtil.Apply("simp add: " + nodeId + ""), - //!startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, - startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply("rule " + nameLemmaLocal + "") : null, - startingBigBlock.simpleCmds.Any() ? "apply assumption" : null, - startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply(ProofUtil.Simp()) : null, - startingBigBlock.simpleCmds.Any() && indicator == BranchIndicator.GuardHolds ? ProofUtil.Apply("rule guardHint") : null, + ProofUtil.Apply("simp add: " + nodeId + "") }; + + if (startingBigBlock.simpleCmds.Any()) + { + middlePartOfProof.Add(ProofUtil.Apply("rule " + nameLemmaLocal + "")); + middlePartOfProof.Add("apply assumption"); + middlePartOfProof.Add(ProofUtil.Apply(ProofUtil.Simp())); + } + + if (startingBigBlock.simpleCmds.Any() && indicator == BranchIndicator.GuardHolds) + { + middlePartOfProof.Add(ProofUtil.Apply("rule guardHint")); + } + } var proofEnd = new List(); @@ -1346,18 +1354,27 @@ private List GenerateProofGeneric( ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succUniqueIntLabel + "]")), ProofUtil.Apply(ProofUtil.Repeat("simp add: " + outEdgesId)), ProofUtil.Apply("simp add: member_rec(1)"), - ProofUtil.Apply("rule " + nameLemmaSucc + ""), - !proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Simp()) : null, - "apply blast+", - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_prove") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_apply") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule inductionHypothesis") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule less_trans_inv") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? "apply blast+" : null, + ProofUtil.Apply("rule " + nameLemmaSucc + "") }; - } - //TODO: name the assumptions + if (!proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + proofEnd.Add(ProofUtil.Apply(ProofUtil.Simp())); + } + + proofEnd.Add("apply blast+"); + + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + proofEnd.Add(ProofUtil.Apply("rule loop_IH_prove")); + proofEnd.Add(ProofUtil.Apply("rule loop_IH_apply")); + proofEnd.Add(ProofUtil.Apply("rule inductionHypothesis")); + proofEnd.Add(ProofUtil.Apply("rule less_trans_inv")); + proofEnd.Add("apply blast+"); + } + + } + proofMethods.AddRange(beginningOfProof); proofMethods.AddRange(middlePartOfProof); proofMethods.AddRange(proofEnd); @@ -1377,7 +1394,7 @@ private List GenerateEndingAfterUnwrappingProof( Block relatedBlock, Expr entryGuard, BranchIndicator indicator, - ProofGenInfo proofGenInfo) + AstToCfgProofGenInfo proofGenInfo) { BigBlock correspondingOrigBigBlock = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; List loopExtension = new List(); @@ -1413,8 +1430,6 @@ private List GenerateEndingAfterUnwrappingProof( string contId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[startingBigBlock]; string succContId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[unwrappedBigBlockCopy]; - - //string nameLemmaLocal = mappingBigBlockToLocalLemmaDecl[startingBigBlock].Name; string nameLemmaSuccGlobal = mappingBigBlockToGlobalLemmaDecl[unwrappedBigBlockCopy].Name; string correctnessPropagates = null; @@ -1447,30 +1462,53 @@ private List GenerateEndingAfterUnwrappingProof( ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), ProofUtil.Apply(ProofUtil.Simp()), ProofUtil.Apply("rule " + nameLemmaSuccGlobal + ""), - ProofUtil.Apply("simp add: " + succBigBlockId + "_def " + contId + "_def " + succContId + "_def"), - correctnessPropagates, + ProofUtil.Apply("simp add: " + succBigBlockId + "_def " + contId + "_def " + succContId + "_def") + }; + + if (correctnessPropagates != null) { proofMethods.Add(correctnessPropagates); } + + proofMethods.AddRange( new List + { "using assms(2)", "apply blast", ProofUtil.Apply("simp add: " + nodeId + ""), - ProofUtil.Apply("simp add: " + blockId + "_def"), - indicator != BranchIndicator.NoGuard ? rule : null, - (indicator != BranchIndicator.NoGuard && entryGuard != null) ? ProofUtil.Apply("rule guardHint") : null, + ProofUtil.Apply("simp add: " + blockId + "_def") + }); + + if (indicator != BranchIndicator.NoGuard) { proofMethods.Add(rule); } + if (indicator != BranchIndicator.NoGuard && entryGuard != null) { proofMethods.Add(ProofUtil.Apply("rule guardHint")); } + + proofMethods.AddRange( new List + { ProofUtil.Apply("simp add: " + outEdgesId + ""), ProofUtil.Apply("simp add: member_rec"), - ProofUtil.Apply(ProofUtil.Simp()), - correctnessPropagatesPosts, + ProofUtil.Apply(ProofUtil.Simp()) + }); + + if (correctnessPropagatesPosts != null) { proofMethods.Add(correctnessPropagatesPosts); } + + proofMethods.AddRange( new List + { "using assms(3)", "apply blast", ProofUtil.Apply("simp add: " + nodeId + ""), - ProofUtil.Apply("simp add: " + blockId + "_def"), - indicator != BranchIndicator.NoGuard ? rule : null, - (indicator != BranchIndicator.NoGuard && entryGuard != null) ? ProofUtil.Apply("rule guardHint") : null, + ProofUtil.Apply("simp add: " + blockId + "_def") + }); + + if (indicator != BranchIndicator.NoGuard) { proofMethods.Add(rule); } + if (indicator != BranchIndicator.NoGuard && entryGuard != null) { proofMethods.Add(ProofUtil.Apply("rule guardHint")); } + + proofMethods.AddRange( new List + { ProofUtil.Apply("simp add: " + outEdgesId + ""), ProofUtil.Apply("simp add: member_rec"), ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) - }; - - proofMethods.AddRange(loopExtension); + }); + + if (loopExtension.Any()) + { + proofMethods.AddRange(loopExtension); + } proofMethods.Add("done"); return proofMethods; @@ -1482,7 +1520,7 @@ private List GenerateWhileSuccessorProof( Expr entryGuard, Expr personalGuard, BranchIndicator indicator, - ProofGenInfo proofGenInfo) + AstToCfgProofGenInfo proofGenInfo) { string bigblockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(startingBigBlock).First(); string blockId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".block_" + afterCfg.GetUniqueIntLabel(relatedBlock); @@ -1523,7 +1561,7 @@ private List GenerateWhileSuccessorProof( { nameLemmaLocal = mappingBigBlockToLocalLemmaDecl[startingBigBlock].Name; } - + proofMethods = new List { "proof -", @@ -1536,51 +1574,98 @@ private List GenerateWhileSuccessorProof( ProofUtil.Apply("simp add: " + bigblockId + "_def " + blockId + "_def"), ProofUtil.Apply("simp add: " + bigblockId + "_def " + blockId + "_def"), ProofUtil.Apply("simp add: " + blockId + "_def"), - ProofUtil.Apply("rule " + nodeId + ""), + ProofUtil.Apply("rule " + nodeId + "") + }; + + if (entryGuard == null) { proofMethods.Add(ProofUtil.Apply("rule disjI1")); } + if (entryGuard != null) + { + if (indicator == BranchIndicator.NoGuard) + { + proofMethods.Add(ProofUtil.Apply("rule disjI1")); + } + else + { + proofMethods.Add(ProofUtil.Apply("rule disjI2")); + } + } + if (entryGuard != null && indicator == BranchIndicator.GuardHolds) { proofMethods.Add(ProofUtil.Apply("rule disjI1")); } + if (entryGuard != null && indicator == BranchIndicator.GuardFails) { proofMethods.Add(ProofUtil.Apply("rule disjI2")); } - entryGuard == null ? ProofUtil.Apply("rule disjI1") : null, - - entryGuard != null ? (indicator == BranchIndicator.NoGuard ? ProofUtil.Apply("rule disjI1") : ProofUtil.Apply("rule disjI2")) : null, - entryGuard != null && indicator == BranchIndicator.GuardHolds ? ProofUtil.Apply("rule disjI1") : null, - entryGuard != null && indicator == BranchIndicator.GuardFails ? ProofUtil.Apply("rule disjI2") : null, - - ProofUtil.Apply("simp add: " + blockId + "_def"), - entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule conjI") : null, - entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply(ProofUtil.Simp()) : null, - entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule conjI") : null, - entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply(ProofUtil.Simp()) : null, - entryGuard != null && (indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule conjI") : null, - entryGuard != null && (indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("" + NegationRule(entryGuard) + "") : null, - entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule guardHint") : null, + proofMethods.Add(ProofUtil.Apply("simp add: " + blockId + "_def")); + + if (entryGuard != null && + (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails)) + { + proofMethods.Add(ProofUtil.Apply("rule conjI")); + proofMethods.Add(ProofUtil.Apply(ProofUtil.Simp())); + proofMethods.Add(ProofUtil.Apply("rule conjI")); + proofMethods.Add(ProofUtil.Apply(ProofUtil.Simp())); + } + + if (entryGuard != null && (indicator == BranchIndicator.GuardFails)) + { + proofMethods.Add(ProofUtil.Apply("rule conjI")); + proofMethods.Add(ProofUtil.Apply("" + NegationRule(entryGuard) + "")); + } + + if (entryGuard != null && + (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails)) + { + proofMethods.Add(ProofUtil.Apply("rule guardHint")); + } + + proofMethods.AddRange(new List + { ProofUtil.Apply("rule cfgDoesntFail, simp"), ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), - ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), - mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply("simp add: " + nodeId + "") : null, - mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply("rule " + nameLemmaLocal + "") : null, - mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply("simp add: " + bigblockId + "_def") : null, - mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) : null, - entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule guardHint") : null, - //personalGuard != null ? ProofUtil.Apply("erule disjE") : null, - //personalGuard == null ? ProofUtil.Apply("erule disjE, simp") : null, - //personalGuard == null ? ProofUtil.Apply("erule disjE, simp") : null, - //personalGuard == null ? ProofUtil.Apply("rule disjE, simp") : null, + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) + }); + + if (mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock)) + { + proofMethods.AddRange(new List + { + ProofUtil.Apply("simp add: " + nodeId + ""), + ProofUtil.Apply("rule " + nameLemmaLocal + ""), + ProofUtil.Apply("simp add: " + bigblockId + "_def"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) + }); + } + if (entryGuard != null && + (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails)) + { + proofMethods.Add(ProofUtil.Apply("rule guardHint")); + } + + proofMethods.AddRange(new List + { ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succUniqueIntLabel + "]")), ProofUtil.Apply(ProofUtil.Repeat("simp add: " + outEdgesId)), ProofUtil.Apply("simp add: member_rec(1)"), ProofUtil.Apply("rule " + nameLemmaSucc + ""), ProofUtil.Apply("simp add: " + succBigBlockId + "_def " + contId + "_def "+ successorContId + "_def"), - "apply blast+", - - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_prove") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_apply") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule inductionHypothesis") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule less_trans_inv") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) : null, + "apply blast+" + }); + + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + proofMethods.AddRange(new List + { + ProofUtil.Apply("rule loop_IH_prove"), + ProofUtil.Apply("rule loop_IH_apply"), + ProofUtil.Apply("rule inductionHypothesis"), + ProofUtil.Apply("rule less_trans_inv"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) + }); + } + proofMethods.AddRange(new List + { "done", - "qed", - }; + "qed" + }); } return proofMethods; } @@ -1591,7 +1676,7 @@ private List GenerateIfSuccessorProof( Expr personalGuard, Expr entryGuard, BranchIndicator indicator, - ProofGenInfo proofGenInfo) + AstToCfgProofGenInfo proofGenInfo) { string bigblockId = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(startingBigBlock).First(); string blockId = afterCfgProgAccess.BlockInfo().getTheoryName() + ".block_" + @@ -1646,42 +1731,76 @@ private List GenerateIfSuccessorProof( (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails ? ProofUtil.Apply("rule Rel_Main_test[of " + bigblockId + "]") : ProofUtil.Apply("rule Rel_Main_test[of " + bigblockId + " _ " + blockId + "]")) : ProofUtil.Apply("rule Rel_Invs[of " + bigblockId + "]"), - ProofUtil.Apply("simp add: " + blockId + "_def " + bigblockId + "_def"), - startingBigBlock.simpleCmds.Any() ? ProofUtil.Apply("simp add: " + blockId + "_def") : null, + ProofUtil.Apply("simp add: " + blockId + "_def " + bigblockId + "_def") + }; + if (startingBigBlock.simpleCmds.Any()) { beginningOfProof.Add(ProofUtil.Apply("simp add: " + blockId + "_def")); } + beginningOfProof.AddRange(new List + { ProofUtil.Apply("rule astTrace"), ProofUtil.Apply("simp add: " + bigblockId + "_def"), ProofUtil.Apply("rule " + nodeId + "") - }; + }); - var middlePartOfProof = new List + var middlePartOfProof = new List(); + if (entryGuard == null) { middlePartOfProof.Add(ProofUtil.Apply("rule disjI1")); } + if (entryGuard != null) + { + middlePartOfProof.Add(indicator == BranchIndicator.NoGuard + ? ProofUtil.Apply("rule disjI1") + : ProofUtil.Apply("rule disjI2")); + } + if (entryGuard != null && indicator == BranchIndicator.GuardHolds) { middlePartOfProof.Add(ProofUtil.Apply("rule disjI1")); } + if (entryGuard != null && indicator == BranchIndicator.GuardFails) { middlePartOfProof.Add(ProofUtil.Apply("rule disjI2")); } + middlePartOfProof.Add(ProofUtil.Apply("simp add: " + blockId + "_def")); + if (entryGuard != null && + (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails)) + { + middlePartOfProof.AddRange(new List + { + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply(ProofUtil.Simp()) + }); + } + if (entryGuard != null && (indicator == BranchIndicator.GuardFails)) + { + middlePartOfProof.AddRange(new List + { + ProofUtil.Apply("rule conjI"), + ProofUtil.Apply("" + NegationRule(entryGuard) + "") + }); + } + if (entryGuard != null && + (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails)) + { + middlePartOfProof.Add(ProofUtil.Apply("rule guardHint")); + } + middlePartOfProof.AddRange(new List { - entryGuard == null ? ProofUtil.Apply("rule disjI1") : null, - - entryGuard != null ? (indicator == BranchIndicator.NoGuard ? ProofUtil.Apply("rule disjI1") : ProofUtil.Apply("rule disjI2")) : null, - entryGuard != null && indicator == BranchIndicator.GuardHolds ? ProofUtil.Apply("rule disjI1") : null, - entryGuard != null && indicator == BranchIndicator.GuardFails ? ProofUtil.Apply("rule disjI2") : null, - ProofUtil.Apply("simp add: " + blockId + "_def"), - entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule conjI") : null, - entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply(ProofUtil.Simp()) : null, - entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule conjI") : null, - entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply(ProofUtil.Simp()) : null, - entryGuard != null && (indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule conjI") : null, - entryGuard != null && (indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("" + NegationRule(entryGuard) + "") : null, - entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule guardHint") : null, ProofUtil.Apply("rule cfgDoesntFail, simp"), ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), - ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), - mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply("simp add: " + nodeId + "") : null, - mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply("rule " + nameLemmaLocal + "") : null, - mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply("simp add: " + bigblockId + "_def") : null, - mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock) ? ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) : null, - entryGuard != null && startingBigBlock.simpleCmds.Any() && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails) ? ProofUtil.Apply("rule guardHint") : null, - personalGuard != null ? ProofUtil.Apply("erule disjE") : null, - //personalGuard == null ? ProofUtil.Apply("erule disjE, simp") : null, - //personalGuard == null ? ProofUtil.Apply("erule disjE, simp") : null, - personalGuard == null ? ProofUtil.Apply("rule disjE, simp") : null - }; + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) + }); + if (mappingBigBlockToLocalLemmaDecl.ContainsKey(startingBigBlock)) + { + middlePartOfProof.AddRange(new List + { + ProofUtil.Apply("simp add: " + nodeId + ""), + ProofUtil.Apply("rule " + nameLemmaLocal + ""), + ProofUtil.Apply("simp add: " + bigblockId + "_def"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) + }); + } + if (entryGuard != null && startingBigBlock.simpleCmds.Any() && (indicator == BranchIndicator.GuardHolds || + indicator == BranchIndicator.GuardFails)) + { + middlePartOfProof.Add(ProofUtil.Apply("rule guardHint")); + } + if (personalGuard != null) { middlePartOfProof.Add(ProofUtil.Apply("erule disjE")); } + if (personalGuard == null) { middlePartOfProof.Add(ProofUtil.Apply("rule disjE, simp")); } + var finalPartOfProof = new List { ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succUniqueIntLabel + "]")), @@ -1691,15 +1810,29 @@ private List GenerateIfSuccessorProof( ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), ProofUtil.Apply("rule " + nameLemmaThen + ""), ExpandDefinitions(contId, startingBigBlock, proofGenInfo, BranchIndicator.GuardHolds), - "apply blast+", - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_prove") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_apply") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule inductionHypothesis") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule less_trans_inv") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) : null, - personalGuard != null && !proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? - ProofUtil.Apply(ProofUtil.Simp()) : null, + "apply blast+" + }; + + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + finalPartOfProof.AddRange(new List + { + ProofUtil.Apply("rule loop_IH_prove"), + ProofUtil.Apply("rule loop_IH_apply"), + ProofUtil.Apply("rule inductionHypothesis"), + ProofUtil.Apply("rule less_trans_inv"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) + }); + } + if (personalGuard != null && + !proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + finalPartOfProof.Add(ProofUtil.Apply(ProofUtil.Simp())); + } + + finalPartOfProof.AddRange(new List + { ProofUtil.Apply(ProofUtil.Repeat("erule allE[where x = " + succUniqueIntLabel2 + "]")), ProofUtil.Apply(ProofUtil.Repeat("simp add: " + outEdgesId)), ProofUtil.Apply("simp add: member_rec(1)"), @@ -1707,17 +1840,27 @@ private List GenerateIfSuccessorProof( ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), ProofUtil.Apply("rule " + nameLemmaElse + ""), ExpandDefinitions(contId, startingBigBlock, proofGenInfo, BranchIndicator.GuardFails), - "apply blast+", - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_prove") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule loop_IH_apply") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule inductionHypothesis") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply("rule less_trans_inv") : null, - proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) ? ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) : null, + "apply blast+" + }); + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) + { + finalPartOfProof.AddRange(new List + { + ProofUtil.Apply("rule loop_IH_prove"), + ProofUtil.Apply("rule loop_IH_apply"), + ProofUtil.Apply("rule inductionHypothesis"), + ProofUtil.Apply("rule less_trans_inv"), + ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())) + }); + } + + finalPartOfProof.AddRange(new List + { "done", "qed" - }; - + }); + proofMethods.AddRange(beginningOfProof); proofMethods.AddRange(middlePartOfProof); proofMethods.AddRange(finalPartOfProof); diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs index d8ecb831c..9c8f34a99 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs @@ -16,9 +16,8 @@ internal class AstToCfgManager { public static Theory AstToCfgProof( PhasesTheories phasesTheories, - //bool generateEndToEndLemma, Term vcAssm, - ProofGenInfo proofGenInfo, + AstToCfgProofGenInfo proofGenInfo, ASTRepr beforeCfgAst, CFGRepr afterCfg, BoogieMethodData beforeCfgData, @@ -31,7 +30,6 @@ public static Theory AstToCfgProof( MultiCmdIsaVisitor multiCmdIsaVisitor) { LemmaDecl entryLemma = null; - //var afterToBefore = beforeToAfter.InverseDict(); var varContextName = "\\1"; var varContextAbbrev = new AbbreviationDecl( @@ -73,11 +71,9 @@ public static Theory AstToCfgProof( foreach (BigBlock beforeBlock in beforeCfgAst.GetBlocksBackwards()) { - //BigBlock beforeBlockOrig = proofGenInfo.getMappingCopyBigblockToOrigBigblock()[beforeBlock]; Block afterBlock = beforeToAfter[beforeBlock]; int bigblockIndex = proofGenInfo.GetMappingCopyBigBlockToIndex()[beforeBlock]; - //int blockIndex = afterCfg.GetUniqueIntLabel(afterBlock); BigBlock successorBigBlockOrig; BigBlock successorBigBlockCopy; @@ -181,13 +177,6 @@ public static bool PredHasLoop(BigBlock b, ASTRepr ast, out BigBlock predecessor for (var i = 0; i < bbsArray.Length; i++) { - // String test = bbsArray[i].simpleCmds.First().ToString(); - // String test2 = b.simpleCmds.First().ToString(); - // StructuredCmd ec1 = bbsArray[i].ec; - // StructuredCmd ec2 = b.ec; - // String name1 = bbsArray[i].LabelName; - // String name2 = b.LabelName; - if (bbsArray[i] == b && i != 0 && bbsArray[i - 1].ec is WhileCmd) { predecessor = bbsArray[i - 1]; diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBigBlockInfo.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBigBlockInfo.cs new file mode 100644 index 000000000..419e0ac8c --- /dev/null +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBigBlockInfo.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using Isabelle.Ast; +using Microsoft.Boogie; + +namespace ProofGeneration.BoogieIsaInterface +{ + public class IsaBigBlockInfo + { + public IsaBigBlockInfo( + string theoryName, + IDictionary bigblockIds, + IDictionary> bigblockDefs + ) + { + TheoryName = theoryName; + BigBlockIds = bigblockIds; + BigBlockDefs = bigblockDefs; + } + + public IDictionary BigBlockIds { get; } + public IDictionary> BigBlockDefs { get; } + public string TheoryName { get; } + + public IList CmdsQualifiedName(BigBlock b) + { + return QualifiedName(BigBlockDefs[b]); + } + + private IList QualifiedName(IList decls) + { + IList names = new List(); + foreach (var decl in decls) + { + names.Add(TheoryName + "." + decl.Name); + } + + return names; + } + } +} \ No newline at end of file diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBlockInfo.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBlockInfo.cs index 16f5cf628..1a46ccf90 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaBlockInfo.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBlockInfo.cs @@ -25,66 +25,24 @@ IDictionary blockCmdsLemmas public IDictionary BlockIds { get; } public IDictionary BlockCmdsDefs { get; } - public IDictionary BlockOutEdgesLemmas { get; } - public IDictionary BlockCmdsLemmas { get; } public string getTheoryName() { return theoryName; } - public string CmdsQualifiedName(Block b) { return QualifiedName(BlockCmdsDefs[b]); } - public string OutEdgesMembershipLemma(Block b) { return QualifiedName(BlockOutEdgesLemmas[b]); } - public string BlockCmdsMembershipLemma(Block b) { return QualifiedName(BlockCmdsLemmas[b]); } - private string QualifiedName(OuterDecl decl) { return theoryName + "." + decl.Name; } } - - public class IsaBigBlockInfo - { - //private readonly string theoryName; - - public IsaBigBlockInfo( - string theoryName, - IDictionary bigblockIds, - IDictionary> bigblockDefs - ) - { - TheoryName = theoryName; - BigBlockIds = bigblockIds; - BigBlockDefs = bigblockDefs; - } - - public IDictionary BigBlockIds { get; } - public IDictionary> BigBlockDefs { get; } - public string TheoryName { get; } - - public IList CmdsQualifiedName(BigBlock b) - { - return QualifiedName(BigBlockDefs[b]); - } - - private IList QualifiedName(IList decls) - { - IList names = new List(); - foreach (var decl in decls) - { - names.Add(TheoryName + "." + decl.Name); - } - - return names; - } - } } \ No newline at end of file diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs index a99aeb5e7..c059e892b 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs @@ -79,6 +79,7 @@ private static readonly TermIdent public static TermIdent ConvertValToBoolId { get; } = IsaCommonTerms.TermIdentFromName("convert_val_to_bool"); public static TermIdent ConvertValToIntId { get; } = IsaCommonTerms.TermIdentFromName("convert_val_to_int"); + public static TermIdent SematicsProcSpecSatisfied { get; } = IsaCommonTerms.TermIdentFromName("Semantics.proc_body_satisfies_spec"); //TODO initialize all the default constructors, so that they only need to be allocated once (Val, Var, etc...) @@ -523,8 +524,7 @@ public static Term StartConfigTerm(BigBlock b, Term cont0, IProgramAccessor befo { var beforeBigblockDefName = beforeCfgProgAccess.BigBlockInfo().CmdsQualifiedName(b).First(); Term beforeBigblock = IsaCommonTerms.TermIdentFromName(beforeBigblockDefName); - //Term cont0 = IsaCommonTerms.TermIdentFromName("cont0"); - + IList startConfigArgs = new List(); startConfigArgs.Add(beforeBigblock); startConfigArgs.Add(cont0); @@ -603,7 +603,7 @@ public static Term RedCFGKStep(BoogieContextIsa boogieContext, Term cfg, Term in }); } - public static Term LoopIH(BoogieContextIsa astBoogieContext, BoogieContextIsa cfgBoogieContext, Term ast, Term bigblock, Term cont, Term cfgBody, Term blockIndex, Term posts) + public static Term AstToCfgLoopIndHypothesis(BoogieContextIsa astBoogieContext, BoogieContextIsa cfgBoogieContext, Term ast, Term bigblock, Term cont, Term cfgBody, Term blockIndex, Term posts) { return new TermApp(astLoopIhId, diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs index e15cc494e..916a5a0c0 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs @@ -118,7 +118,7 @@ public IProgramAccessor GetIsaProgram( VariableDeclarationsName("locals"), cfgName, procDefName); - membershipLemmaManager = new MembershipLemmaManager(config, isaProgramRepr, blockInfo, + membershipLemmaManager = new MembershipLemmaManager(config, isaProgramRepr, blockInfo, null, Tuple.Create(globalsMax, localsMin), varTranslationFactory, theoryName); var nodesToBlocks = GetNodeToBlocksIsa(cfg, blockInfo.BlockCmdsDefs); diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator_forAst.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs similarity index 97% rename from Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator_forAst.cs rename to Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs index 98daf0168..2ff22c340 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator_forAst.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs @@ -15,7 +15,7 @@ namespace ProofGeneration { - internal class IsaProgramGenerator_forAst + internal class IsaProgramGeneratorForAst { private MultiCmdIsaVisitor cmdIsaVisitor; private BoogieVariableTranslation varTranslation; @@ -32,7 +32,7 @@ public IProgramAccessor GetIsaProgram( IVariableTranslationFactory varTranslationFactory, ASTRepr ast, ASTRepr originalAst, - ProofGenInfo proofGenInfo, + AstToCfgProofGenInfo proofGenInfo, out IList decls, bool generateMembershipLemmas = true, bool onlyGlobalData = false @@ -72,7 +72,7 @@ public IProgramAccessor GetIsaProgram( VariableDeclarationsName("locals"), astName, procDefName); - membershipLemmaManager = new MembershipLemmaManager(config, isaProgramRepr, bigblockInfo, + membershipLemmaManager = new MembershipLemmaManager(config, isaProgramRepr, null, bigblockInfo, Tuple.Create(globalsMax, localsMin), varTranslationFactory, theoryName); foreach (var decl_list in bigblockInfo.BigBlockDefs.Values) @@ -230,14 +230,11 @@ private DefDecl MethodDefinition(IProgramAccessor programAccessor, BoogieMethodD return methodDef; } - private IsaBigBlockInfo BigBlockToInfo(string theoryName, ASTRepr ast, ProofGenInfo proofGenInfo) + private IsaBigBlockInfo BigBlockToInfo(string theoryName, ASTRepr ast, AstToCfgProofGenInfo proofGenInfo) { var blockToDecl = new Dictionary>(); var blockToCounter = new Dictionary(); - //var astTerm = IsaCommonTerms.TermIdentFromName(astName); - //var astDef = astName + "_def"; - foreach (BigBlock b in ast.GetBlocksForwards()) { int flag = 0; @@ -251,9 +248,7 @@ private IsaBigBlockInfo BigBlockToInfo(string theoryName, ASTRepr ast, ProofGenI var translatedBigBlock = builder.makeBigBlockTerm(b, cmdIsaVisitor, flag, 0, nameToUse, out int updatedNestedBlockTracker); proofGenInfo.AddBigBlockToIndexPair(b, uniqueIntLabel); - - //var blockDecl = DefDecl.CreateWithoutArg("bigblock_" + ast.GetUniqueIntLabel(b), translatedBigBlock); - + IDictionary> bb_defs = builder.getBigblockDefDecls(); foreach(KeyValuePair> bb_def in bb_defs) { @@ -269,7 +264,7 @@ private IsaBigBlockInfo BigBlockToInfo(string theoryName, ASTRepr ast, ProofGenI return new IsaBigBlockInfo(theoryName, blockToCounter, blockToDecl); } - private IList getContinuations(ASTRepr originalAst, ProofGenInfo proofGenInfo) + private IList getContinuations(ASTRepr originalAst, AstToCfgProofGenInfo proofGenInfo) { IList declsToReturn = new List(); BigBlockTermBuilder builder = new BigBlockTermBuilder(); @@ -340,10 +335,7 @@ private IList getContinuations(ASTRepr originalAst, ProofGenInfo proo private DefDecl GetFunctionDeclarationsIsa(IEnumerable functions) { - //var equations = new List, Term>>(); var fdecls = new List(); - - foreach (var f in functions) fdecls.Add(IsaBoogieTerm.FunDecl(f, varTranslationFactory)); return DefDecl.CreateWithoutArg(FunctionDeclarationsName(), new TermList(fdecls)); diff --git a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs index e01bdb261..55c63a622 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs @@ -108,51 +108,6 @@ public MembershipLemmaManager( IsaProgramGeneratorConfig config, IsaProgramRepr isaProgramRepr, IsaBlockInfo isaBlockInfo, - Tuple GlobalsMaxLocalsMin, - IVariableTranslationFactory factory, - string theoryName - ) - { - parent = config.parentAccessor; - this.isaProgramRepr = isaProgramRepr; - this.factory = factory; - this.theoryName = theoryName; - this.config = config; - this.isaBlockInfo = isaBlockInfo; - typeIsaVisitor = new TypeIsaVisitor(factory.CreateTranslation().TypeVarTranslation); - basicCmdIsaVisitor = new BasicCmdIsaVisitor(factory); - paramsAndLocalsDefs = - new[] {isaProgramRepr.paramsDeclDef + "_def", isaProgramRepr.localVarsDeclDef + "_def"}; - - parameters = config.generateParamsAndLocals - ? QualifyAccessName(isaProgramRepr.paramsDeclDef) - : parent.ParamsDecl(); - locals = config.generateParamsAndLocals - ? QualifyAccessName(isaProgramRepr.localVarsDeclDef) - : parent.LocalsDecl(); - paramsAndLocalsList = - IsaCommonTerms.AppendList(IsaCommonTerms.TermIdentFromName(parameters), - IsaCommonTerms.TermIdentFromName(locals)); - - consts = config.generateGlobalsAndConstants - ? QualifyAccessName(isaProgramRepr.GlobalProgramRepr.constantsDeclDef) - : parent.ConstsDecl(); - globals = config.generateGlobalsAndConstants - ? QualifyAccessName(isaProgramRepr.GlobalProgramRepr.globalsDeclDef) - : parent.GlobalsDecl(); - - constsAndGlobalsDefs = - new[] {consts + "_def", globals + "_def"}; - constsAndGlobalsList = - IsaCommonTerms.AppendList(IsaCommonTerms.TermIdentFromName(consts), - IsaCommonTerms.TermIdentFromName(globals)); - AddDisjointnessLemmas(GlobalsMaxLocalsMin.Item1, GlobalsMaxLocalsMin.Item2); - AddWellFormednessLemmas(); - } - - public MembershipLemmaManager( - IsaProgramGeneratorConfig config, - IsaProgramRepr isaProgramRepr, IsaBigBlockInfo isaBigBlockInfo, Tuple GlobalsMaxLocalsMin, IVariableTranslationFactory factory, @@ -164,6 +119,7 @@ string theoryName this.factory = factory; this.theoryName = theoryName; this.config = config; + this.isaBlockInfo = isaBlockInfo; this.isaBigBlockInfo = isaBigBlockInfo; typeIsaVisitor = new TypeIsaVisitor(factory.CreateTranslation().TypeVarTranslation); basicCmdIsaVisitor = new BasicCmdIsaVisitor(factory); diff --git a/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelper_forAst.cs b/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs similarity index 98% rename from Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelper_forAst.cs rename to Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs index c54bd6a0b..6d45b14c7 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelper_forAst.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs @@ -91,8 +91,6 @@ public Term makeBigBlockTerm(BigBlock b, MultiCmdIsaVisitor cmdIsaVisitor, int f bigBlocksDefDecls.Add(b, bb_decls); } - //bigBlocksDefDecls.Add(b, bb_decls); - updatedNestedBlockTracker = updatedTrackerAfterStr; return bigblock; } @@ -209,7 +207,7 @@ public Term makeStructuredCmdTerm(BigBlock b, MultiCmdIsaVisitor cmdIsaVisitor, return strCmdTermOption; } - public Term makeContinuationTerm(BigBlock b, ProofGenInfo proofGenInfo, int successorIndex) + public Term makeContinuationTerm(BigBlock b, AstToCfgProofGenInfo proofGenInfo, int successorIndex) { Term continuationTerm; Term continuationStart; diff --git a/Source/ProofGeneration/BoogieIsaInterface/VariableTranslation/DeBruijnFixedVarTranslation.cs b/Source/ProofGeneration/BoogieIsaInterface/VariableTranslation/DeBruijnFixedVarTranslation.cs index bad0971ef..4b51a519c 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/VariableTranslation/DeBruijnFixedVarTranslation.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/VariableTranslation/DeBruijnFixedVarTranslation.cs @@ -46,16 +46,7 @@ void AddVarsToMapping(IEnumerable vars, IDictionary dic public int VariableId(Variable variable) { - foreach (var id in paramsAndLocalMapping.Keys) - { - if (variable.ToString() == id.ToString()) - { - variable = id; - } - } - if (paramsAndLocalMapping.TryGetValue(variable, out var localResult)) return localResult; - if (globalsMapping.TryGetValue(variable, out var globalResult)) return globalResult; throw new ProofGenUnexpectedStateException(GetType(), "cannot find variable " + variable); diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs index be4b0b7fb..33885c3a2 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs @@ -205,21 +205,21 @@ public static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term gl Term procedure) { var typeInterpId = new SimpleIdentifier("A"); - return - TermQuantifier.MetaAll( - new List{ typeInterpId}, - null, - new TermApp( - IsaCommonTerms.TermIdentFromName("Semantics.proc_is_correct"), - //TODO: here assuming that we use "'a" for the abstract value type carrier t --> make t a parameter somewhere - new TermWithExplicitType(new TermIdent(typeInterpId), IsaBoogieType.AbstractValueTyFunType(new VarType("a"))), - funDecls, - constantDecls, - globalDecls, - axioms, - procedure, - //TODO: define this elsewhere. - IsaCommonTerms.TermIdentFromName("Semantics.proc_body_satisfies_spec"))); + return + TermQuantifier.MetaAll( + new List {typeInterpId}, + null, + new TermApp( + IsaCommonTerms.TermIdentFromName("Semantics.proc_is_correct"), + //TODO: here assuming that we use "'a" for the abstract value type carrier t --> make t a parameter somewhere + new TermWithExplicitType(new TermIdent(typeInterpId), + IsaBoogieType.AbstractValueTyFunType(new VarType("a"))), + funDecls, + constantDecls, + globalDecls, + axioms, + procedure, + IsaBoogieTerm.SematicsProcSpecSatisfied)); } } } \ No newline at end of file diff --git a/Source/ProofGeneration/Passification/PassificationEndToEnd.cs b/Source/ProofGeneration/Passification/PassificationEndToEnd.cs index 505b954bb..295c9360c 100644 --- a/Source/ProofGeneration/Passification/PassificationEndToEnd.cs +++ b/Source/ProofGeneration/Passification/PassificationEndToEnd.cs @@ -253,12 +253,7 @@ private List GenerateLemma() { ProofUtil.Apply("rule " + ProofUtil.OF("nstate_old_rel_states_helper", constsGlobalsAssmName, oldGlobalEqualAssmName)), - ProofUtil.Apply("simp only: fst_conv snd_conv " + programAccessor.GlobalsLocalsDisjointLemma()), - - // generatedAstToCfgProof ? - // "unfolding " + beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def " + - // beforeCfgProgramAccessor.GlobalsDecl() + "_def " + beforeCfgProgramAccessor.ConstsDecl() + "_def" : null, - // generatedAstToCfgProof ? "apply simp" : null + ProofUtil.Apply("simp only: fst_conv snd_conv " + programAccessor.GlobalsLocalsDisjointLemma()) }; void ConvertRelPropertyToListElems() diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 84aaa5328..2574a77c2 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -27,7 +27,7 @@ public class ProofGenerationLayer private static Implementation beforeCFGtoDagImpl; //private static Implementation beforeDagImpl; - private static ProofGenInfo proofGenInfo; + private static AstToCfgProofGenInfo proofGenInfo; private static MultiCmdIsaVisitor cmdIsaVisitor; @@ -81,7 +81,7 @@ public class ProofGenerationLayer private static Block uniqueExitBlockOrig; private static ProofGenConfig _proofGenConfig = - new ProofGenConfig(false, true, true, true); + new ProofGenConfig(true, true, true, true); private static IProgramAccessor globalDataProgAccess; @@ -125,7 +125,7 @@ public static bool GenerateASTToCFGProof() return _proofGenConfig.GenerateAstToCfg; } - private static bool AstContainsGotoOrBreak(ProofGenInfo proofGenInfo) + private static bool AstContainsGotoOrBreak(AstToCfgProofGenInfo proofGenInfo) { IList ast = proofGenInfo.GetBigBlocks(); foreach (var b in ast) @@ -148,7 +148,6 @@ public static void BeforeOptimizations(Implementation impl) out beforeOptimizationsOrigBlock, out var newVarsFromDesugaring); beforeOptimizationsData = MethodDataFromImpl(impl, boogieGlobalData, newVarsFromDesugaring); - //uniqueExitBlockOrigBeforeOptimizations = null; } /// @@ -192,7 +191,7 @@ public static void GraphCfgToDag(Graph g) /// /// Provide the generated unified exit block. If no unified exit block is created (for example, when there is only /// one exit block), then invoke this method with null. - /// Impl + /// public static void CreateUnifiedExitBlock(Block generatedExitBlock) { uniqueExitBlockOrig = generatedExitBlock; @@ -543,7 +542,7 @@ public static void VCGenerateAllProofs( Boogie2VCExprTranslator translator, TypeAxiomBuilderPremisses axiomBuilder) { - var map = ProofGenInfoManager.GetMapFromImplementationToProofGenInfo(); + var map = AstToCfgProofGenInfoManager.GetImplToProofGenInfo(); proofGenInfo = map[afterPassificationImpl]; if (AstContainsGotoOrBreak(proofGenInfo)) @@ -557,8 +556,6 @@ public static void VCGenerateAllProofs( DesugarCmdsInBigBlock(b); } - //TODO: test - IList unoptimizedCFGBlocks = proofGenInfo.GetUnpotimizedBlocks(); var newToOldInternal = new Dictionary(); unoptimizedCFGBlocks.ZipDo(afterPassificationImpl.Blocks, (bNew, bOld) => newToOldInternal.Add(bNew, bOld)); @@ -640,7 +637,7 @@ public static void VCGenerateAllProofs( var beforeAstToCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, true, specsConfig_ast, true); - beforeAstToCfgProgAccess = new IsaProgramGenerator_forAst().GetIsaProgram( + beforeAstToCfgProgAccess = new IsaProgramGeneratorForAst().GetIsaProgram( beforeAstToCfgTheoryName, afterPassificationImpl.Name, mainData, beforeAstToCfgConfig, varTranslationFactory2, @@ -871,11 +868,6 @@ out var endToEndLemma var origBigBlock = pair.Key; var copyBigBlock = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[origBigBlock]; var origBlock = pair.Value; - - if (!mappingOrigBlockToCopyBlock.ContainsKey(origBlock)) - { - int debug = 5; - } var copyBlock = mappingOrigBlockToCopyBlock[origBlock]; var hints = mappingBigBlockToHints[origBigBlock]; @@ -885,19 +877,13 @@ out var endToEndLemma var astToCfgProofTheory = AstToCfgManager.AstToCfgProof( phasesTheories, - //_proofGenConfig.GenerateCfgDagE2E, vcAssm, proofGenInfo, beforeCfgAst, - //beforeOptimizationsCFG, beforeDagCfg, - //uniqueExitBlock, - //beforeOptimizationsData, beforeDagData, - //beforeOptimizationsOrigBlock, beforeDagOrigBlock, mappingWithHints, - //cfgToDagHintManager, beforeCfgAfterCfgBlock, beforeAstToCfgProgAccess, beforeCfgToDagProgAccess, From 0b9cf72607bd66e5aeed3a9cb47a1fd01a729099 Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Thu, 6 Oct 2022 06:31:44 +0200 Subject: [PATCH 004/123] added some comments for documentation --- Source/Core/AbsyCmd.cs | 3 ++ Source/Core/AstToCfgProofGenInfo.cs | 34 +++++++++++-------- .../AstToCfg/AstToCfgLemmaManager.cs | 5 ++- .../IsaProgramGeneratorForAst.cs | 16 +++++++-- .../ProgramGeneratorHelperForAst.cs | 7 +++- .../CfgToDag/CfgToDagEndToEnd.cs | 3 ++ .../ProofGeneration/ProofGenerationLayer.cs | 4 +-- 7 files changed, 48 insertions(+), 24 deletions(-) diff --git a/Source/Core/AbsyCmd.cs b/Source/Core/AbsyCmd.cs index 253cd47db..52b725f64 100644 --- a/Source/Core/AbsyCmd.cs +++ b/Source/Core/AbsyCmd.cs @@ -887,7 +887,10 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, AstToCfgProofGenI loopDone = new BigBlock(Token.NoToken, null, new List(), null, null);; b.successorBigBlock = loopDone; + //Record loop done as a successor big block in the AST to 'b'. proofGenInfo.RecordLoopDoneBlock(loopDone); + + //Add it to to all necessary mappings, in which it will be used when generating a proof. proofGenInfo.AddBigBlockBeforeNamingAnonymous(loopDone, true, parent, parentCopy, BranchIndicator.NoGuard); proofGenInfo.AddBigBlockToBlockPair(loopDone, block); diff --git a/Source/Core/AstToCfgProofGenInfo.cs b/Source/Core/AstToCfgProofGenInfo.cs index 1ac68f96d..76ea0f727 100644 --- a/Source/Core/AstToCfgProofGenInfo.cs +++ b/Source/Core/AstToCfgProofGenInfo.cs @@ -38,31 +38,31 @@ public class AstToCfgProofGenInfo private IDictionary mappingOrigBigBlockToOrigBlock; private IDictionary mappingCopyBigblockToOrigBigblock; private IDictionary mappingOrigBigblockToCopyBigblock; - - //TODO: Fix this. + + /** A dictionary mapping a 'LoopHead' BigBlock to a tuple of two BigBlocks. * A LoopHead is a special BigBlock that is a second copy (copy of a copy), has an empty list of simpleCmds and a as a . * The first BigBlock in the tuple is the copied BigBlock, from which the LoopHead was created. - * The second BigBlock in the tuple is the original BigBlock the copy corresponds to. */ + * The second BigBlock in the tuple is the original BigBlock the copy corresponds to. + */ private IDictionary mappingCopyBigblockToOrigBigblockWithTupleValue; - - //TODO: Consider changing to a set. + // A marker set to false indicates that a BigBlock is nested in another BigBlock. private IDictionary mappingCopyBigBlockToMarker; - - //TODO: This mapping uses Original BigBlocks, not copies. Fix. + /** The first hint is a guard (possibly null) that needs to be taken care of in the global lemma that's to be generated. * The second hint is a BranchIndicator that indicates how that needs to be done. */ - private IDictionary mappingCopyBigBlockToHints; + private IDictionary mappingBigBlockToHints; // Map a BigBlock (copy) to the unique integer label (index) of its corresponding Term object (in InnerAst.cs). private IDictionary mappingCopyBigBlockToIndex; // Map a BigBlock (original) to the Loop BigBlock (original) it's nested into. private IDictionary mappingBigBlockToOrigLoopBigBlock; - - // TODO: This doesn't need to be a list. - // List of BigBlocks added after a loop if that loop is the end of the procedure. + + // List of BigBlocks added after a loop if that loop is the end of the procedure or if that loop has no successors. + // I've never encountered an instance where this list contains more than one element, i.e, this doesn't need to be a list. + // However, this depends on the when successor Big Blocks are computed, so using a list is not wrong. private IList loopEndingBlocks; private List newVarsFromDesugaring; @@ -79,7 +79,7 @@ public void InstantiateVars() mappingOrigBigblockToCopyBigblock = new Dictionary(); mappingCopyBigblockToOrigBigblockWithTupleValue = new Dictionary(); - mappingCopyBigBlockToHints = new Dictionary(); + mappingBigBlockToHints = new Dictionary(); mappingCopyBigBlockToIndex = new Dictionary(); mappingBigBlockToOrigLoopBigBlock = new Dictionary(); @@ -155,7 +155,7 @@ public IDictionary GetMappingOrigBigblockToCopyBigblock() public IDictionary GetMappingCopyBigBlockToHints() { - return mappingCopyBigBlockToHints; + return mappingBigBlockToHints; } public IDictionary GetMappingBigBlockToLoopBigBlock() @@ -202,6 +202,8 @@ public void AddBigBlockBeforeNamingAnonymous(BigBlock b, bool marker, BigBlock p switch (branchIndicator) { case BranchIndicator.NoGuard: + + //If the elseBlock field of an is null, initialize it to a with one 'empty' BigBlock. FillEmptyElseBranches(b); copy = CopyBigBlock(b); @@ -283,8 +285,10 @@ public void AddBigBlockBeforeNamingAnonymous(BigBlock b, bool marker, BigBlock p else if (b.ec is WhileCmd) { BigBlock simpleCmdsRemoved = new BigBlock(copy.tok, copy.LabelName, new List(), copy.ec, copy.tc); - //simpleCmdsRemoved.successorBigBlock = b.successorBigBlock; BigBlock copy1 = simpleCmdsRemoved; + + //copy1 is a special loop head BigBlock + //that is a second copy (copy of a copy), has an empty list of simpleCmds and a as a . mappingCopyBigblockToOrigBigblock.Add(copy1, simpleCmdsRemoved); mappingCopyBigblockToOrigBigblockWithTupleValue.Add(copy1, (simpleCmdsRemoved, b)); mappingOrigBigblockToCopyBigblock.Add(simpleCmdsRemoved, copy1); @@ -327,7 +331,7 @@ public void AddBigBlockToBlockPair(BigBlock b0, Block b1) public void AddBigBlockToHintsPair(BigBlock b, (Expr, BranchIndicator) tuple) { - mappingCopyBigBlockToHints.Add(b, (tuple.Item1, tuple.Item2)); + mappingBigBlockToHints.Add(b, (tuple.Item1, tuple.Item2)); } public void AddBigBlockToIndexPair(BigBlock b, int index) diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs index 4df5a2fc5..aba7be9f1 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs @@ -126,8 +126,7 @@ public LemmaDecl LocalLemma( var localLemmas = new List(); #region local block lemma - - //TODO: write the proofs using ProofUtil + var assumptions = new List { IsaBoogieTerm.RedBigBlock(astBoogieContext, startConfig, endConfig, astId) @@ -1135,7 +1134,7 @@ private List GenerateLoopHeadProof( proofMethods.AddRange(insideOfLoopAddition1); } - //TODO: do the second check if BlockCoalescing is activated, otherwise keep as is + //TODO: do the second check if BlockCoalescing is activated, otherwise keep as is. if (personalGuard != null && personalGuard.Equals(Expr.True)) { proofMethods.AddRange(whileTrueEndingAfterSkippingEndBlock); diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs index 2ff22c340..c4e43b436 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs @@ -269,7 +269,9 @@ private IList getContinuations(ASTRepr originalAst, AstToCfgProofGenI IList declsToReturn = new List(); BigBlockTermBuilder builder = new BigBlockTermBuilder(); - //TODO: document this properly + //Loop through the big blocks in 'original AST' backwards. + //The name 'original AST' refers to the fact that the AST is in its original form, as constructed, i.e, it's not 'unrolled'. + //However, the big blocks inside it are copies. foreach (BigBlock b in originalAst.GetBlocksBackwards()) { BigBlock correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[b]; @@ -282,15 +284,18 @@ private IList getContinuations(ASTRepr originalAst, AstToCfgProofGenI successorIndex = proofGenInfo.GetMappingCopyBigBlockToIndex()[successorBigBlockCopy]; } + //This should be the same as big block 'b'? BigBlock correspondingBigBlockCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[correspondingBigBlockOrig]; + //Construct the continuation term, which corresponds to 'b' and which is to be used in the Isabelle proofs later. Term continuation = builder.makeContinuationTerm(correspondingBigBlockCopy, proofGenInfo, successorIndex); int bigblockIndex = proofGenInfo.GetMappingCopyBigBlockToIndex()[correspondingBigBlockCopy]; DefDecl continuationDecl = DefDecl.CreateWithoutArg("cont_" + bigblockIndex, continuation); declsToReturn.Add(continuationDecl); + //Special continuation term, which is used if 'b' contains a WhileCmd. DefDecl continuationDeclForUnwrappedBigBlock = null; - + if (b.ec is WhileCmd) { foreach (var pair in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) @@ -312,7 +317,8 @@ private IList getContinuations(ASTRepr originalAst, AstToCfgProofGenI WhileCmd wcmd = (WhileCmd) b.ec; ASTRepr body = new ASTRepr(wcmd.Body.BigBlocks); - + + //recursively construct continuation terms for the body of the while-loop (again from the end to the beginning). IList bodyConts = getContinuations(body, proofGenInfo); declsToReturn.AddRange(bodyConts); } @@ -320,11 +326,15 @@ private IList getContinuations(ASTRepr originalAst, AstToCfgProofGenI { IfCmd ifcmd = (IfCmd) b.ec; ASTRepr thn = new ASTRepr(ifcmd.thn.BigBlocks); + + //recursively construct continuation terms for the body of the thn-branch of the if-statement. declsToReturn.AddRange(getContinuations(thn, proofGenInfo)); if (ifcmd.elseBlock != null) { ASTRepr elseBlock = new ASTRepr(ifcmd.elseBlock.BigBlocks); + + //recursively construct continuation terms for the body of the else-branch of the if-statement. declsToReturn.AddRange(getContinuations(elseBlock, proofGenInfo)); } } diff --git a/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs b/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs index 6d45b14c7..8fb409506 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs @@ -220,13 +220,16 @@ public Term makeContinuationTerm(BigBlock b, AstToCfgProofGenInfo proofGenInfo, } BigBlock successorBigBlockOrig = correspondingBigBlockOrig.successorBigBlock; - + + //if the big block has no successors of any kind, make a 'KStop' continuation. if (successorBigBlockOrig == null) { continuationTerm = IsaCommonTerms.TermIdentFromName("KStop"); return continuationTerm; } + //if the big block is the last one in the body of a loop, + //update the successor index needed for the continuation and make a 'KSeq' continuation. if (successorBigBlockOrig.ec is WhileCmd) { WhileCmd wcmd = (WhileCmd) successorBigBlockOrig.ec; @@ -241,6 +244,7 @@ public Term makeContinuationTerm(BigBlock b, AstToCfgProofGenInfo proofGenInfo, } } + //if the big block is the special, artificially made, 'unwrapped' loop head big block, make a 'KEndBlock' continuation. if (b.ec is WhileCmd && proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().Keys.Contains(b)) { continuationStart = IsaCommonTerms.TermIdentFromName("KEndBlock (KSeq bigblock_" + successorIndex); @@ -249,6 +253,7 @@ public Term makeContinuationTerm(BigBlock b, AstToCfgProofGenInfo proofGenInfo, return continuationTerm; } + //in any other case, make a standard 'KSeq' continuation. continuationStart = IsaCommonTerms.TermIdentFromName("KSeq bigblock_" + successorIndex); continuationTerm = new TermApp(continuationStart, IsaCommonTerms.TermIdentFromName("cont_" + successorIndex)); diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs index 33885c3a2..5bd2126e1 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs @@ -43,6 +43,9 @@ public IEnumerable EndToEndProof( IProgramAccessor beforeCfgProgramAccessor, CFGRepr cfg) { + // both program accessors are needed because the End-to-End lemmas for the CFG-to-VC part + // need to have access to the 'before AST-to-CFG' program as well as the 'before CFG-to-DAG' program, + // so that the AST-to-VC End-to-End lemma can be composed. this.programAccessor = programAccessor; this.beforeCfgProgramAccessor = beforeCfgProgramAccessor; diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 2574a77c2..5fe273dd2 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -854,8 +854,8 @@ out var endToEndLemma IDictionary mappingWithHints = new Dictionary(); - IDictionary mappingCopyBigblockToOrigBigblock = - proofGenInfo.GetMappingCopyBigblockToOrigBigblock(); + //IDictionary mappingCopyBigblockToOrigBigblock = + //proofGenInfo.GetMappingCopyBigblockToOrigBigblock(); IDictionary mappingOrigBigBlockToOrigBlock = proofGenInfo.GetMappingOrigBigBlockToOrigBlock(); From de72fccbc988c26fac9c8202a28922cc78ad36db Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Mon, 10 Oct 2022 08:27:33 +0200 Subject: [PATCH 005/123] separation of AstCfg Proofs from the rest done, needs to be checked --- Source/Core/Absy.cs | 2 +- Source/Core/AbsyCmd.cs | 6 +- Source/Core/AstToCfgProofGenInfo.cs | 38 +++++++----- Source/ExecutionEngine/ExecutionEngine.cs | 31 +++++----- .../AstToCfg/AstToCfgLemmaManager.cs | 32 +++++----- .../AstToCfg/AstToCfgManager.cs | 28 +++++---- .../IsaProgramGeneratorForAst.cs | 6 +- .../ProgramGeneratorHelperForAst.cs | 12 ++-- .../CfgToDag/CfgToDagEndToEnd.cs | 2 +- Source/ProofGeneration/ProofGenConfig.cs | 10 ++-- .../ProofGeneration/ProofGenerationLayer.cs | 59 ++++++++++++------- 11 files changed, 127 insertions(+), 99 deletions(-) diff --git a/Source/Core/Absy.cs b/Source/Core/Absy.cs index 37f5bad7d..516cfb8c3 100644 --- a/Source/Core/Absy.cs +++ b/Source/Core/Absy.cs @@ -4475,7 +4475,7 @@ public Implementation(IToken /*!*/ tok, AstToCfgProofGenInfo correspondingProofGenInfo = AstToCfgProofGenInfoManager.GetCurrentProofGenInfo(); mapFromImplementationToProofGenInfo.Add(this, correspondingProofGenInfo); #endregion - + BlockPredecessorsComputed = false; scc = null; Attributes = kv; diff --git a/Source/Core/AbsyCmd.cs b/Source/Core/AbsyCmd.cs index 52b725f64..777d2c15c 100644 --- a/Source/Core/AbsyCmd.cs +++ b/Source/Core/AbsyCmd.cs @@ -823,11 +823,11 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, AstToCfgProofGenI blocks.Add(block); #region proofgen - foreach (var tuple in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().Values) + foreach (var tuple in proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock()) { - if (tuple.Item2 == b) + if (tuple.Value == b) { - BigBlock simpleCmdsRemoved = tuple.Item1; + BigBlock simpleCmdsRemoved = tuple.Key; proofGenInfo.AddBigBlockToBlockPair(simpleCmdsRemoved, block); proofGenInfo.AddBigBlockToHintsPair(simpleCmdsRemoved, (null, BranchIndicator.NoGuard)); break; diff --git a/Source/Core/AstToCfgProofGenInfo.cs b/Source/Core/AstToCfgProofGenInfo.cs index 76ea0f727..e24279051 100644 --- a/Source/Core/AstToCfgProofGenInfo.cs +++ b/Source/Core/AstToCfgProofGenInfo.cs @@ -34,18 +34,19 @@ public class AstToCfgProofGenInfo /// A list containing the same objects, which are in with all nested BigBlocks explicitly added. private IList bigblocksBeforeNamingAnonymous; + private IDictionary mappingOrigBlocktoUnoptimizedCopy; + // Dictionaries used to keep track of relations between different kinds of blocks. private IDictionary mappingOrigBigBlockToOrigBlock; private IDictionary mappingCopyBigblockToOrigBigblock; private IDictionary mappingOrigBigblockToCopyBigblock; - /** A dictionary mapping a 'LoopHead' BigBlock to a tuple of two BigBlocks. - * A LoopHead is a special BigBlock that is a second copy (copy of a copy), has an empty list of simpleCmds and a as a . - * The first BigBlock in the tuple is the copied BigBlock, from which the LoopHead was created. - * The second BigBlock in the tuple is the original BigBlock the copy corresponds to. + * A LoopHead is a special BigBlock that is a copy, has an empty list of simpleCmds and a as a . + * The key is the LoopHead. + * The value is the original BigBlock the LoopHead Big Block was created from. */ - private IDictionary mappingCopyBigblockToOrigBigblockWithTupleValue; + private IDictionary mappingLoopHeadBigBlocktoOrigLoopBigBlock; // A marker set to false indicates that a BigBlock is nested in another BigBlock. private IDictionary mappingCopyBigBlockToMarker; @@ -77,7 +78,7 @@ public void InstantiateVars() mappingOrigBigBlockToOrigBlock = new Dictionary(); mappingCopyBigblockToOrigBigblock = new Dictionary(); mappingOrigBigblockToCopyBigblock = new Dictionary(); - mappingCopyBigblockToOrigBigblockWithTupleValue = new Dictionary(); + mappingLoopHeadBigBlocktoOrigLoopBigBlock = new Dictionary(); mappingBigBlockToHints = new Dictionary(); mappingCopyBigBlockToIndex = new Dictionary(); @@ -128,6 +129,11 @@ public IList GetOriginalAst() return originalAst; } + public IDictionary GetMappingOrigBlockToUnoptimizedCopy() + { + return mappingOrigBlocktoUnoptimizedCopy; + } + public IDictionary GetMappingCopyBigBlockToMarker() { return mappingCopyBigBlockToMarker; @@ -148,9 +154,9 @@ public IDictionary GetMappingOrigBigblockToCopyBigblock() return mappingOrigBigblockToCopyBigblock; } - public IDictionary GetMappingCopyBigblockToOrigBigblockWithTupleValue() + public IDictionary GetMappingLoopHeadBigBlocktoOrigLoopBigBlock() { - return mappingCopyBigblockToOrigBigblockWithTupleValue; + return mappingLoopHeadBigBlocktoOrigLoopBigBlock; } public IDictionary GetMappingCopyBigBlockToHints() @@ -285,15 +291,14 @@ public void AddBigBlockBeforeNamingAnonymous(BigBlock b, bool marker, BigBlock p else if (b.ec is WhileCmd) { BigBlock simpleCmdsRemoved = new BigBlock(copy.tok, copy.LabelName, new List(), copy.ec, copy.tc); - BigBlock copy1 = simpleCmdsRemoved; + + //This is bad. + mappingCopyBigblockToOrigBigblock.Add(simpleCmdsRemoved, simpleCmdsRemoved); + mappingOrigBigblockToCopyBigblock.Add(simpleCmdsRemoved, simpleCmdsRemoved); - //copy1 is a special loop head BigBlock - //that is a second copy (copy of a copy), has an empty list of simpleCmds and a as a . - mappingCopyBigblockToOrigBigblock.Add(copy1, simpleCmdsRemoved); - mappingCopyBigblockToOrigBigblockWithTupleValue.Add(copy1, (simpleCmdsRemoved, b)); - mappingOrigBigblockToCopyBigblock.Add(simpleCmdsRemoved, copy1); - bigblocksBeforeNamingAnonymous.Add(copy1); - mappingCopyBigBlockToMarker.Add(copy1, false); + mappingLoopHeadBigBlocktoOrigLoopBigBlock.Add(simpleCmdsRemoved, b); + bigblocksBeforeNamingAnonymous.Add(simpleCmdsRemoved); + mappingCopyBigBlockToMarker.Add(simpleCmdsRemoved, false); WhileCmd whilecmd = (WhileCmd) b.ec; foreach (BigBlock bb in whilecmd.Body.BigBlocks) @@ -562,6 +567,7 @@ public IList CopyBlocks( copyBlock.Predecessors = copyBlock.Predecessors.Select(succ => oldToNewBlock[succ]).ToList(); } + mappingOrigBlocktoUnoptimizedCopy = oldToNewBlock; return copyBlocks; } diff --git a/Source/ExecutionEngine/ExecutionEngine.cs b/Source/ExecutionEngine/ExecutionEngine.cs index b8aec5bbe..9dc68399d 100644 --- a/Source/ExecutionEngine/ExecutionEngine.cs +++ b/Source/ExecutionEngine/ExecutionEngine.cs @@ -480,11 +480,24 @@ public static bool ProcessProgram(Program program, string bplFileName, string pr if (CommandLineOptions.Clo.PrintFile != null) { PrintBplFile(CommandLineOptions.Clo.PrintFile, program, false, true, CommandLineOptions.Clo.PrettyPrint); } - + PipelineOutcome oc = ResolveAndTypecheck(program, bplFileName, out var civlTypeChecker); if (oc != PipelineOutcome.ResolvedAndTypeChecked) { return true; } + + #region proofgen + foreach (var tuple in AstToCfgProofGenInfoManager.GetImplToProofGenInfo()) + { + Implementation impl = tuple.Key; + AstToCfgProofGenInfo proofGenInfo = tuple.Value; + + var predecessorMap = proofGenInfo.ComputePredecessors(impl.Blocks); + var unoptimizedBlockCopies = proofGenInfo.CopyBlocks(impl.Blocks , predecessorMap, true, cmd => false, out var newVarsAfterDesugaring); + proofGenInfo.SetUnoptimizedBlocks(unoptimizedBlockCopies); + proofGenInfo.SetNewVarsCFG(newVarsAfterDesugaring); + } + #endregion if (CommandLineOptions.Clo.PrintCFGPrefix != null) { foreach (var impl in program.Implementations) { @@ -501,24 +514,10 @@ public static bool ProcessProgram(Program program, string bplFileName, string pr CommandLineOptions.Clo.PrettyPrint); CommandLineOptions.Clo.PrintUnstructured = oldPrintUnstructured; } - - #region proofgen - - foreach (var tuple in AstToCfgProofGenInfoManager.GetImplToProofGenInfo()) - { - Implementation impl = tuple.Key; - AstToCfgProofGenInfo proofGenInfo = tuple.Value; - - var predecessorMap = proofGenInfo.ComputePredecessors(impl.Blocks); - var unoptimizedBlockCopies = proofGenInfo.CopyBlocks(impl.Blocks , predecessorMap, true, cmd => false, out var newVarsAfterDesugaring); - proofGenInfo.SetUnoptimizedBlocks(unoptimizedBlockCopies); - proofGenInfo.SetNewVarsCFG(newVarsAfterDesugaring); - } - #endregion EliminateDeadVariables(program); - //CoalesceBlocks(program); + CoalesceBlocks(program); Inline(program); diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs index aba7be9f1..7f7807667 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs @@ -337,7 +337,7 @@ public LemmaDecl GenerateGlobalLemma( guardSemantics = true; assumptions.Add(traceIsPossible); } - else if (proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().ContainsKey(startingBigBlock)) + else if (proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock().ContainsKey(startingBigBlock)) { WhileCmd wcmd = (WhileCmd) startingBigBlock.ec; if (wcmd.Guard == null) @@ -372,9 +372,9 @@ public LemmaDecl GenerateGlobalLemma( #endregion BigBlock correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; - if (proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().ContainsKey(startingBigBlock)) + if (proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock().ContainsKey(startingBigBlock)) { - correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()[startingBigBlock].Item2; + correspondingBigBlockOrig = proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock()[startingBigBlock]; } BigBlock successorBigBlockOrig = correspondingBigBlockOrig.successorBigBlock; @@ -421,7 +421,7 @@ public LemmaDecl GenerateGlobalLemma( } //TODO: Fix this. //A BigBlock is a LoopHead if it is a key in this dictionary. - else if (proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().ContainsKey(startingBigBlock)) + else if (proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock().ContainsKey(startingBigBlock)) { WhileCmd wcmd = (WhileCmd) startingBigBlock.ec; Expr guard = wcmd.Guard; @@ -749,9 +749,9 @@ private List GenerateLoopHeadProof( List proofMethods = new List(); BigBlock correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; - if (proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().Keys.Contains(startingBigBlock)) + if (proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock().Keys.Contains(startingBigBlock)) { - correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()[startingBigBlock].Item2; + correspondingBigBlockOrig = proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock()[startingBigBlock]; } //Get the BigBlock that comes after the loop. @@ -759,9 +759,9 @@ private List GenerateLoopHeadProof( BigBlock afterLoopBigBlockCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[afterLoopBigBlockOrig]; BigBlock unwrappedAfterLoopBigBlockCopy = null; - foreach (var tuple in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) + foreach (var tuple in proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock()) { - if (tuple.Value.Item2 == afterLoopBigBlockOrig) + if (tuple.Value == afterLoopBigBlockOrig) { unwrappedAfterLoopBigBlockCopy = tuple.Key; break; @@ -805,9 +805,9 @@ private List GenerateLoopHeadProof( } else { - foreach (var tuple in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) + foreach (var tuple in proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock()) { - if (tuple.Value.Item2 == bodyBb) + if (tuple.Value == bodyBb) { bodyBbCopy = tuple.Key; break; @@ -1180,9 +1180,9 @@ private List GenerateProofGeneric( BigBlock successorBigBlockOrig = correspondingBigBlockOrig.successorBigBlock; BigBlock successorBigBlockCopy = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[successorBigBlockOrig]; - foreach (var kvPair in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) + foreach (var kvPair in proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock()) { - if (kvPair.Value.Item2 == successorBigBlockOrig) + if (kvPair.Value == successorBigBlockOrig) { successorBigBlockCopy = kvPair.Key; break; @@ -1416,9 +1416,9 @@ private List GenerateEndingAfterUnwrappingProof( BigBlock correspondingOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; BigBlock unwrappedBigBlockCopy = null; - foreach (var tuple in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) + foreach (var tuple in proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock()) { - if (tuple.Value.Item2 == correspondingOrig) + if (tuple.Value == correspondingOrig) { unwrappedBigBlockCopy = tuple.Key; break; @@ -1528,9 +1528,9 @@ private List GenerateWhileSuccessorProof( BigBlock correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[startingBigBlock]; BigBlock successorBigBlockCopy = null; - foreach (var tuple in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) + foreach (var tuple in proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock()) { - if (correspondingBigBlockOrig == tuple.Value.Item2) + if (correspondingBigBlockOrig == tuple.Value) { successorBigBlockCopy = tuple.Key; break; diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs index 9c8f34a99..6ea8fab0c 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs @@ -16,6 +16,7 @@ internal class AstToCfgManager { public static Theory AstToCfgProof( PhasesTheories phasesTheories, + bool generateEndtoEnd, Term vcAssm, AstToCfgProofGenInfo proofGenInfo, ASTRepr beforeCfgAst, @@ -46,7 +47,7 @@ public static Theory AstToCfgProof( IsaCommonTerms.EmptyList); var cfgBoogieContext = new BoogieContextIsa( IsaCommonTerms.TermIdentFromName("A"), - IsaCommonTerms.TermIdentFromName("M'"), + IsaCommonTerms.TermIdentFromName("M"), IsaCommonTerms.TermIdentFromName(varContextName), IsaCommonTerms.TermIdentFromName("\\"), IsaCommonTerms.EmptyList); @@ -144,17 +145,20 @@ public static Theory AstToCfgProof( var theoryOuterDecls = new List(); theoryOuterDecls.Add(cfgToDagLemmasLocale); - var endToEndManager = new AstToCfgEndToEnd(); - var endToEndDecls = endToEndManager.EndToEndProof( - entryLemma.Name, - phasesTheories.EndToEndLemmaName(PhasesTheories.Phase.CfgToDag, false) + "_theorem_aux", - vcAssm, - beforeCfgProgAccess, - afterCfgProgAccess, - beforeCfgAst, - proofGenInfo - ); - theoryOuterDecls.AddRange(endToEndDecls); + if (generateEndtoEnd) + { + var endToEndManager = new AstToCfgEndToEnd(); + var endToEndDecls = endToEndManager.EndToEndProof( + entryLemma.Name, + phasesTheories.EndToEndLemmaName(PhasesTheories.Phase.CfgToDag, false) + "_theorem_aux", + vcAssm, + beforeCfgProgAccess, + afterCfgProgAccess, + beforeCfgAst, + proofGenInfo + ); + theoryOuterDecls.AddRange(endToEndDecls); + } return new Theory( phasesTheories.TheoryName(PhasesTheories.Phase.AstToCfg), diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs index c4e43b436..da92a6a7b 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs @@ -238,7 +238,7 @@ private IsaBigBlockInfo BigBlockToInfo(string theoryName, ASTRepr ast, AstToCfgP foreach (BigBlock b in ast.GetBlocksForwards()) { int flag = 0; - if (proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().Keys.Contains(b)) + if (proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock().Keys.Contains(b)) { flag = 1; } @@ -298,9 +298,9 @@ private IList getContinuations(ASTRepr originalAst, AstToCfgProofGenI if (b.ec is WhileCmd) { - foreach (var pair in proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()) + foreach (var pair in proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock()) { - if (pair.Value.Item2 == correspondingBigBlockOrig) + if (pair.Value == correspondingBigBlockOrig) { BigBlock unwrapped = pair.Key; diff --git a/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs b/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs index 8fb409506..5ec51f199 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs @@ -213,10 +213,14 @@ public Term makeContinuationTerm(BigBlock b, AstToCfgProofGenInfo proofGenInfo, Term continuationStart; Term continuationEnd; - BigBlock correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[b]; - if (proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().Keys.Contains(b)) + BigBlock correspondingBigBlockOrig; + if (proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock().Keys.Contains(b)) { - correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue()[b].Item2; + correspondingBigBlockOrig = proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock()[b]; + } + else + { + correspondingBigBlockOrig = proofGenInfo.GetMappingCopyBigblockToOrigBigblock()[b]; } BigBlock successorBigBlockOrig = correspondingBigBlockOrig.successorBigBlock; @@ -245,7 +249,7 @@ public Term makeContinuationTerm(BigBlock b, AstToCfgProofGenInfo proofGenInfo, } //if the big block is the special, artificially made, 'unwrapped' loop head big block, make a 'KEndBlock' continuation. - if (b.ec is WhileCmd && proofGenInfo.GetMappingCopyBigblockToOrigBigblockWithTupleValue().Keys.Contains(b)) + if (b.ec is WhileCmd && proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock().Keys.Contains(b)) { continuationStart = IsaCommonTerms.TermIdentFromName("KEndBlock (KSeq bigblock_" + successorIndex); continuationEnd = IsaCommonTerms.TermIdentFromName(")"); diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs index 5bd2126e1..d0c3e05e4 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs @@ -148,7 +148,7 @@ public IEnumerable EndToEndProof( } ) ); - if (!ProofGenerationLayer.GenerateASTToCFGProof()) + if (!ProofGenerationLayer.GenerateAstCfgE2E()) { result.Add(endToEndLemma); } diff --git a/Source/ProofGeneration/ProofGenConfig.cs b/Source/ProofGeneration/ProofGenConfig.cs index faa200902..4cfa18d6e 100644 --- a/Source/ProofGeneration/ProofGenConfig.cs +++ b/Source/ProofGeneration/ProofGenConfig.cs @@ -6,21 +6,21 @@ public class ProofGenConfig { public ProofGenConfig( - bool generateAstToCfg, + bool generateAstCfgE2E, bool generateCfgDagE2E, bool generatePassifE2E, bool generateVcE2E ) { - GenerateAstToCfg = generateAstToCfg; + GenerateAstCfgE2E = generateAstCfgE2E; GenerateCfgDagE2E = generateCfgDagE2E; GeneratePassifE2E = generatePassifE2E; GenerateVcE2E = generateVcE2E; } - public bool GenerateAstToCfg { get; set; } - public bool GenerateCfgDagE2E { get; } - public bool GeneratePassifE2E { get; } + public bool GenerateAstCfgE2E { get; set; } + public bool GenerateCfgDagE2E { get; set; } + public bool GeneratePassifE2E { get; set; } public bool GenerateVcE2E { get; } } } \ No newline at end of file diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 5fe273dd2..441e283ed 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -80,9 +80,13 @@ public class ProofGenerationLayer //private static Block uniqueExitBlockOrigBeforeOptimizations; private static Block uniqueExitBlockOrig; - private static ProofGenConfig _proofGenConfig = - new ProofGenConfig(true, true, true, true); + private static ProofGenConfig _proofGenConfig = new(false, true, true, true); + private static bool generateVCProof = true; + private static bool generatePassifProof = true; + private static bool generateCfgDagProof = true; + private static bool generateAstCfgProof = true; + private static IProgramAccessor globalDataProgAccess; private static IDictionary procNameToTopLevelPrograms = new Dictionary(); @@ -120,11 +124,6 @@ public static void Program(Program p) } } - public static bool GenerateASTToCFGProof() - { - return _proofGenConfig.GenerateAstToCfg; - } - private static bool AstContainsGotoOrBreak(AstToCfgProofGenInfo proofGenInfo) { IList ast = proofGenInfo.GetBigBlocks(); @@ -519,6 +518,11 @@ private static void DesugarCmdsInBigBlock(BigBlock b) } } + public static bool GenerateAstCfgE2E() + { + return _proofGenConfig.GenerateAstCfgE2E; + } + /// /// Generate all proofs for the current procedure. /// @@ -542,12 +546,15 @@ public static void VCGenerateAllProofs( Boogie2VCExprTranslator translator, TypeAxiomBuilderPremisses axiomBuilder) { + _proofGenConfig.GeneratePassifE2E = generateVCProof && _proofGenConfig.GenerateVcE2E && generatePassifProof; + _proofGenConfig.GenerateCfgDagE2E = generatePassifProof && _proofGenConfig.GeneratePassifE2E && generateCfgDagProof; + var map = AstToCfgProofGenInfoManager.GetImplToProofGenInfo(); proofGenInfo = map[afterPassificationImpl]; if (AstContainsGotoOrBreak(proofGenInfo)) { - _proofGenConfig.GenerateAstToCfg = false; + generateAstCfgProof = false; } IList bigBlocks = proofGenInfo.GetBigBlocks(); @@ -621,7 +628,9 @@ public static void VCGenerateAllProofs( cmdIsaVisitor = new MultiCmdIsaVisitor(varTranslationFactory2); IProgramAccessor beforeAstToCfgProgAccess = null; - if (_proofGenConfig.GenerateAstToCfg) + IProgramAccessor unoptimizedCfgProgAccess = null; + + if (generateAstCfgProof) { #region before ast to cfg program @@ -669,7 +678,7 @@ public static void VCGenerateAllProofs( : SpecsConfig.AllPreCheckedPost; var unoptimizedCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, true, _specsConfig, true); - var unoptimizedCfgProgAccess = new IsaProgramGenerator().GetIsaProgram( + unoptimizedCfgProgAccess = new IsaProgramGenerator().GetIsaProgram( unoptimizedCfgTheoryName, afterPassificationImpl.Name, mainData, unoptimizedCfgConfig, varTranslationFactory2, @@ -719,7 +728,7 @@ public static void VCGenerateAllProofs( #region before passive program - IProgramAccessor parentProgramAccessorForPassification = _proofGenConfig.GenerateAstToCfg ? beforeAstToCfgProgAccess : beforeCfgToDagProgAccess; + IProgramAccessor parentProgramAccessorForPassification = generateAstCfgProof ? beforeAstToCfgProgAccess : beforeCfgToDagProgAccess; var beforePassiveProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_passive_prog"); var beforePassiveConfig = @@ -772,7 +781,7 @@ public static void VCGenerateAllProofs( out var programDecls, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); - var theoryNameForParentImport = _proofGenConfig.GenerateAstToCfg ? beforeAstToCfgProgAccess.TheoryName() : beforeCfgToDagProgAccess.TheoryName(); + var theoryNameForParentImport = generateAstCfgProof ? beforeAstToCfgProgAccess.TheoryName() : beforeCfgToDagProgAccess.TheoryName(); var finalProgTheory = new Theory(finalProgTheoryName, @@ -824,7 +833,7 @@ out var endToEndLemma Console.WriteLine("Before passive prog mapping: " + fixedVarTranslation2.OutputMapping()); */ - IProgramAccessor beforePhaseProgramAccess = !_proofGenConfig.GenerateAstToCfg ? beforePassiveProgAccess : beforeAstToCfgProgAccess; + IProgramAccessor beforePhaseProgramAccess = !generateAstCfgProof ? beforePassiveProgAccess : beforeAstToCfgProgAccess; var passificationProofTheory = PassificationManager.PassificationProof( phasesTheories.TheoryName(PhasesTheories.Phase.Passification), @@ -846,7 +855,7 @@ out var endToEndLemma #endregion - if (_proofGenConfig.GenerateAstToCfg) + if (generateAstCfgProof) { #region ast to cfg @@ -858,8 +867,13 @@ out var endToEndLemma //proofGenInfo.GetMappingCopyBigblockToOrigBigblock(); IDictionary mappingOrigBigBlockToOrigBlock = proofGenInfo.GetMappingOrigBigBlockToOrigBlock(); - - IDictionary mappingOrigBlockToCopyBlock = beforeDagOrigBlock.InverseDict(); + + IDictionary mappingOrigBlockToUnoptimizedCopy = + proofGenInfo.GetMappingOrigBlockToUnoptimizedCopy(); + IDictionary mappingUnoptimizedCopyToOrigBlock = + mappingOrigBlockToUnoptimizedCopy.InverseDict(); + + // IDictionary mappingOrigBlockToCopyBlock = beforeDagOrigBlock.InverseDict(); IDictionary mappingBigBlockToHints = proofGenInfo.GetMappingCopyBigBlockToHints(); @@ -868,7 +882,7 @@ out var endToEndLemma var origBigBlock = pair.Key; var copyBigBlock = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[origBigBlock]; var origBlock = pair.Value; - var copyBlock = mappingOrigBlockToCopyBlock[origBlock]; + var copyBlock = mappingOrigBlockToUnoptimizedCopy[origBlock]; // mappingOrigBlockToCopyBlock[origBlock]; var hints = mappingBigBlockToHints[origBigBlock]; beforeCfgAfterCfgBlock.Add(copyBigBlock, copyBlock); @@ -877,16 +891,17 @@ out var endToEndLemma var astToCfgProofTheory = AstToCfgManager.AstToCfgProof( phasesTheories, + _proofGenConfig.GenerateAstCfgE2E, vcAssm, proofGenInfo, beforeCfgAst, - beforeDagCfg, - beforeDagData, - beforeDagOrigBlock, + beforeOptimizationsCFG, + beforeOptimizationsData, + mappingUnoptimizedCopyToOrigBlock, mappingWithHints, beforeCfgAfterCfgBlock, beforeAstToCfgProgAccess, - beforeCfgToDagProgAccess, + unoptimizedCfgProgAccess, varTranslationFactory2, cmdIsaVisitor); theories.Add(astToCfgProofTheory); @@ -905,7 +920,7 @@ out var endToEndLemma var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( phasesTheories, _proofGenConfig.GenerateCfgDagE2E, - _proofGenConfig.GenerateAstToCfg, + generateAstCfgProof, vcAssm, beforeDagCfg, beforePassificationCfg, From dbe99fb129abd5f72cc9c2ccc63f8a569f815307 Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Mon, 10 Oct 2022 11:03:19 +0200 Subject: [PATCH 006/123] ASTtoCFG proofs separated + added booleans per phase + small code cleanup, still need to run and check all examples --- Source/ExecutionEngine/ExecutionEngine.cs | 26 +++++++++---------- .../AstToCfg/AstToCfgLemmaManager.cs | 4 +-- .../BoogieIsaInterface/IsaBoogieTerm.cs | 2 +- .../CfgToDag/CfgToDagEndToEnd.cs | 8 +++++- .../ProofGeneration/ProofGenerationLayer.cs | 4 +-- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/Source/ExecutionEngine/ExecutionEngine.cs b/Source/ExecutionEngine/ExecutionEngine.cs index 9dc68399d..2598708b4 100644 --- a/Source/ExecutionEngine/ExecutionEngine.cs +++ b/Source/ExecutionEngine/ExecutionEngine.cs @@ -485,19 +485,6 @@ public static bool ProcessProgram(Program program, string bplFileName, string pr if (oc != PipelineOutcome.ResolvedAndTypeChecked) { return true; } - - #region proofgen - foreach (var tuple in AstToCfgProofGenInfoManager.GetImplToProofGenInfo()) - { - Implementation impl = tuple.Key; - AstToCfgProofGenInfo proofGenInfo = tuple.Value; - - var predecessorMap = proofGenInfo.ComputePredecessors(impl.Blocks); - var unoptimizedBlockCopies = proofGenInfo.CopyBlocks(impl.Blocks , predecessorMap, true, cmd => false, out var newVarsAfterDesugaring); - proofGenInfo.SetUnoptimizedBlocks(unoptimizedBlockCopies); - proofGenInfo.SetNewVarsCFG(newVarsAfterDesugaring); - } - #endregion if (CommandLineOptions.Clo.PrintCFGPrefix != null) { foreach (var impl in program.Implementations) { @@ -829,6 +816,19 @@ public static PipelineOutcome ResolveAndTypecheck(Program program, string bplFil CollectModSets(program); + #region proofgen + foreach (var tuple in AstToCfgProofGenInfoManager.GetImplToProofGenInfo()) + { + Implementation impl = tuple.Key; + AstToCfgProofGenInfo proofGenInfo = tuple.Value; + + var predecessorMap = proofGenInfo.ComputePredecessors(impl.Blocks); + var unoptimizedBlockCopies = proofGenInfo.CopyBlocks(impl.Blocks , predecessorMap, true, cmd => false, out var newVarsAfterDesugaring); + proofGenInfo.SetUnoptimizedBlocks(unoptimizedBlockCopies); + proofGenInfo.SetNewVarsCFG(newVarsAfterDesugaring); + } + #endregion + civlTypeChecker = new CivlTypeChecker(program); civlTypeChecker.TypeCheck(); if (civlTypeChecker.checkingContext.ErrorCount != 0) diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs index 7f7807667..8dcb677ae 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs @@ -409,8 +409,7 @@ public LemmaDecl GenerateGlobalLemma( #endregion Term conclusion = IsaBoogieTerm.AstValidConfiguration(astBoogieContext, posts); - - //TODO: Document the cases for the proofs + #region proof var proofMethods = new List(); @@ -419,7 +418,6 @@ public LemmaDecl GenerateGlobalLemma( { proofMethods = GenerateFinalBlockProof(startingBigBlock, relatedBlock, hints.Item1, hints.Item2, proofGenInfo); } - //TODO: Fix this. //A BigBlock is a LoopHead if it is a key in this dictionary. else if (proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock().ContainsKey(startingBigBlock)) { diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs index c059e892b..1b76b9164 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs @@ -612,7 +612,7 @@ public static Term AstToCfgLoopIndHypothesis(BoogieContextIsa astBoogieContext, IsaCommonTerms.TermIdentFromName("j"), astBoogieContext.absValTyMap, astBoogieContext.methodContext, - cfgBoogieContext.methodContext, + //cfgBoogieContext.methodContext, astBoogieContext.varContext, astBoogieContext.funContext, astBoogieContext.rtypeEnv, diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs index d0c3e05e4..a86241ba6 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs @@ -144,7 +144,13 @@ public IEnumerable EndToEndProof( programAccessor.PreconditionsDeclName() + "_def " + programAccessor.PostconditionsDeclName() + "_def " + programAccessor.ParamsDecl() + "_def " + programAccessor.LocalsDecl() + "_def " + beforeCfgProgramAccessor.PreconditionsDeclName() + "_def " + beforeCfgProgramAccessor.PostconditionsDeclName() + "_def " + - beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def") + beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def " + + + beforeCfgProgramAccessor.FunctionsDecl() + "_def " + programAccessor.FunctionsDecl() + "_def " + + beforeCfgProgramAccessor.AxiomsDecl() + "_def " + programAccessor.AxiomsDecl() + "_def " + + beforeCfgProgramAccessor.ConstsDecl() + "_def " + programAccessor.ConstsDecl() + "_def " + + beforeCfgProgramAccessor.GlobalsDecl() + "_def " + programAccessor.GlobalsDecl() + "_def " + + "exprs_to_only_checked_spec_def") } ) ); diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 441e283ed..d9c93516e 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -546,8 +546,8 @@ public static void VCGenerateAllProofs( Boogie2VCExprTranslator translator, TypeAxiomBuilderPremisses axiomBuilder) { - _proofGenConfig.GeneratePassifE2E = generateVCProof && _proofGenConfig.GenerateVcE2E && generatePassifProof; - _proofGenConfig.GenerateCfgDagE2E = generatePassifProof && _proofGenConfig.GeneratePassifE2E && generateCfgDagProof; + //_proofGenConfig.GeneratePassifE2E = generateVCProof && _proofGenConfig.GenerateVcE2E && generatePassifProof; + //_proofGenConfig.GenerateCfgDagE2E = generatePassifProof && _proofGenConfig.GeneratePassifE2E && generateCfgDagProof; var map = AstToCfgProofGenInfoManager.GetImplToProofGenInfo(); proofGenInfo = map[afterPassificationImpl]; From 9e505412aa8a06cb5babe702ac38b5ff75b818ef Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Tue, 11 Oct 2022 18:10:50 +0200 Subject: [PATCH 007/123] added conditional generation of AST-to-CFG end-to-end lemma --- Source/Core/Absy.cs | 11 +- Source/Core/AstToCfgProofGenInfo.cs | 12 ++ Source/ExecutionEngine/ExecutionEngine.cs | 31 ++++++ .../AstToCfg/AstToCfgEndToEnd.cs | 5 +- .../AstToCfg/AstToCfgManager.cs | 2 +- .../ProofGeneration/ProofGenerationLayer.cs | 103 +++++++++++------- 6 files changed, 121 insertions(+), 43 deletions(-) diff --git a/Source/Core/Absy.cs b/Source/Core/Absy.cs index 516cfb8c3..cf1767fed 100644 --- a/Source/Core/Absy.cs +++ b/Source/Core/Absy.cs @@ -4108,7 +4108,11 @@ public List /*!*/ [Rep] public StmtList StructuredStmts; [Rep] public List /*!*/ Blocks; public Procedure Proc; - + + #region proofgen + public bool unreachableBlocksPruned; + #endregion + // Blocks before applying passification etc. // Both are used only when /inline is set. public List OriginalBlocks; @@ -4993,6 +4997,11 @@ public void PruneUnreachableBlocks() { // This statement sequence will never reach the end, because of this "assume false" or "assert false". // Hence, it does not reach its successors. + + #region proofgen + unreachableBlocksPruned = true; + #endregion + b.TransferCmd = new ReturnCmd(b.TransferCmd.tok); goto NEXT_BLOCK; } diff --git a/Source/Core/AstToCfgProofGenInfo.cs b/Source/Core/AstToCfgProofGenInfo.cs index e24279051..f68c6c8bd 100644 --- a/Source/Core/AstToCfgProofGenInfo.cs +++ b/Source/Core/AstToCfgProofGenInfo.cs @@ -68,6 +68,8 @@ public class AstToCfgProofGenInfo private List newVarsFromDesugaring; + private bool optimizationsDone; + public void InstantiateVars() { originalAst = new List(); @@ -103,6 +105,16 @@ public void SetUnoptimizedBlocks(IList blocks) { unoptimizedBlocks = blocks; } + + public void SetOptimizationsFlag() + { + optimizationsDone = true; + } + + public bool GetOptimizationsFlag() + { + return optimizationsDone; + } public IList GetUnpotimizedBlocks() { diff --git a/Source/ExecutionEngine/ExecutionEngine.cs b/Source/ExecutionEngine/ExecutionEngine.cs index 2598708b4..0c3be0363 100644 --- a/Source/ExecutionEngine/ExecutionEngine.cs +++ b/Source/ExecutionEngine/ExecutionEngine.cs @@ -507,6 +507,37 @@ public static bool ProcessProgram(Program program, string bplFileName, string pr CoalesceBlocks(program); Inline(program); + + #region proofgen + foreach (var tuple in AstToCfgProofGenInfoManager.GetImplToProofGenInfo()) + { + Implementation impl = tuple.Key; + AstToCfgProofGenInfo proofGenInfo = tuple.Value; + + IList unoptimizedBlocksCopies = proofGenInfo.GetUnpotimizedBlocks(); + IList optimizedBlocksOriginal = impl.Blocks; + + int totalNumberOfCommandsA = 0; + int totalNumberOfCommandsB = 0; + + foreach (var block in unoptimizedBlocksCopies) + { + totalNumberOfCommandsA += block.cmds.Count; + } + + foreach (var block in optimizedBlocksOriginal) + { + totalNumberOfCommandsB += block.cmds.Count; + } + + if (impl.unreachableBlocksPruned || + totalNumberOfCommandsA != totalNumberOfCommandsB || + unoptimizedBlocksCopies.Count != optimizedBlocksOriginal.Count) + { + proofGenInfo.SetOptimizationsFlag(); + } + } + #endregion #region check if proof gen potentially supports input program diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs b/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs index d5dabc50a..777c7f6a1 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs @@ -55,7 +55,7 @@ public IEnumerable EndToEndProof( boogieContext = new BoogieContextIsa( IsaCommonTerms.TermIdentFromName("A"), - IsaCommonTerms.TermIdentFromName("M"), + IsaCommonTerms.TermIdentFromName("(M::mbodyCFG proc_context)"), IsaCommonTerms.TermIdentFromName(varContextName), IsaCommonTerms.TermIdentFromName("\\"), IsaCommonTerms.EmptyList @@ -316,8 +316,7 @@ private static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term g globalDecls, axioms, procedure, - //TODO: define this elsewhere - IsaCommonTerms.TermIdentFromName("Ast.proc_body_satisfies_spec"))); + IsaCommonTerms.TermIdentFromName("(Ast.proc_body_satisfies_spec :: 'a absval_ty_fun ⇒ mbodyCFG proc_context ⇒ var_context ⇒ 'a fun_interp ⇒ rtype_env ⇒ expr list ⇒ expr list ⇒ ast ⇒ 'a nstate ⇒ bool)"))); } } } \ No newline at end of file diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs index 6ea8fab0c..5b593b3b4 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs @@ -145,7 +145,7 @@ public static Theory AstToCfgProof( var theoryOuterDecls = new List(); theoryOuterDecls.Add(cfgToDagLemmasLocale); - if (generateEndtoEnd) + if (generateEndtoEnd && !proofGenInfo.GetOptimizationsFlag()) { var endToEndManager = new AstToCfgEndToEnd(); var endToEndDecls = endToEndManager.EndToEndProof( diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index d9c93516e..56e85e02d 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -80,7 +80,7 @@ public class ProofGenerationLayer //private static Block uniqueExitBlockOrigBeforeOptimizations; private static Block uniqueExitBlockOrig; - private static ProofGenConfig _proofGenConfig = new(false, true, true, true); + private static ProofGenConfig _proofGenConfig = new(true, true, true, true); private static bool generateVCProof = true; private static bool generatePassifProof = true; @@ -667,37 +667,40 @@ public static void VCGenerateAllProofs( theories.Add(beforeAstToCfgProgTheory); #endregion - - - #region unoptimized cfg program - - var unoptimizedCfgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_unoptimized_cfg_prog"); - //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) - var _specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs - ? SpecsConfig.All - : SpecsConfig.AllPreCheckedPost; - var unoptimizedCfgConfig = - new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, true, _specsConfig, true); - unoptimizedCfgProgAccess = new IsaProgramGenerator().GetIsaProgram( - unoptimizedCfgTheoryName, - afterPassificationImpl.Name, - mainData, unoptimizedCfgConfig, varTranslationFactory2, - beforeOptimizationsCFG, - out var programDeclsUnoptimizedCfg, - !CommandLineOptions.Clo.GenerateIsaProgNoProofs); - procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "unoptimized", - unoptimizedCfgProgAccess); - - var unoptimizedCfgProgTheory = new Theory(unoptimizedCfgTheoryName, - new List - { - "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", - "\"../" + globalDataProgAccess.TheoryName() + "\"" - }, - programDeclsUnoptimizedCfg); - theories.Add(unoptimizedCfgProgTheory); - - #endregion + + if (proofGenInfo.GetOptimizationsFlag()) + { + #region unoptimized cfg program + + var unoptimizedCfgTheoryName = + uniqueNamer.GetName(afterPassificationImpl.Name + "_unoptimized_cfg_prog"); + //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) + var _specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs + ? SpecsConfig.All + : SpecsConfig.AllPreCheckedPost; + var unoptimizedCfgConfig = + new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, true, _specsConfig, true); + unoptimizedCfgProgAccess = new IsaProgramGenerator().GetIsaProgram( + unoptimizedCfgTheoryName, + afterPassificationImpl.Name, + mainData, unoptimizedCfgConfig, varTranslationFactory2, + beforeOptimizationsCFG, + out var programDeclsUnoptimizedCfg, + !CommandLineOptions.Clo.GenerateIsaProgNoProofs); + procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "unoptimized", + unoptimizedCfgProgAccess); + + var unoptimizedCfgProgTheory = new Theory(unoptimizedCfgTheoryName, + new List + { + "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", + "\"../" + globalDataProgAccess.TheoryName() + "\"" + }, + programDeclsUnoptimizedCfg); + theories.Add(unoptimizedCfgProgTheory); + + #endregion + } } #region before cfg to dag program @@ -873,7 +876,7 @@ out var endToEndLemma IDictionary mappingUnoptimizedCopyToOrigBlock = mappingOrigBlockToUnoptimizedCopy.InverseDict(); - // IDictionary mappingOrigBlockToCopyBlock = beforeDagOrigBlock.InverseDict(); + IDictionary mappingOrigBlockToCopyBlock = beforeDagOrigBlock.InverseDict(); IDictionary mappingBigBlockToHints = proofGenInfo.GetMappingCopyBigBlockToHints(); @@ -882,26 +885,50 @@ out var endToEndLemma var origBigBlock = pair.Key; var copyBigBlock = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[origBigBlock]; var origBlock = pair.Value; - var copyBlock = mappingOrigBlockToUnoptimizedCopy[origBlock]; // mappingOrigBlockToCopyBlock[origBlock]; + + var blockToBlockMapToReferTo = proofGenInfo.GetOptimizationsFlag() ? mappingOrigBlockToUnoptimizedCopy : mappingOrigBlockToCopyBlock; + + var copyBlock = blockToBlockMapToReferTo[origBlock]; var hints = mappingBigBlockToHints[origBigBlock]; beforeCfgAfterCfgBlock.Add(copyBigBlock, copyBlock); mappingWithHints.Add(copyBigBlock, (copyBlock, hints.Item1, hints.Item2)); } + CFGRepr astCfgReprInput; + BoogieMethodData astCfgDataInput; + IDictionary blockToBlockMapInput; + IProgramAccessor beforeCfgToDagProgAccessInput; + + if (!proofGenInfo.GetOptimizationsFlag()) + { + astCfgReprInput = beforeDagCfg; + astCfgDataInput = beforeDagData; + blockToBlockMapInput = beforeDagOrigBlock; + beforeCfgToDagProgAccessInput = beforeCfgToDagProgAccess; + + } + else + { + astCfgReprInput = beforeOptimizationsCFG; + astCfgDataInput = beforeOptimizationsData; + blockToBlockMapInput = mappingUnoptimizedCopyToOrigBlock; + beforeCfgToDagProgAccessInput = unoptimizedCfgProgAccess; + } + var astToCfgProofTheory = AstToCfgManager.AstToCfgProof( phasesTheories, _proofGenConfig.GenerateAstCfgE2E, vcAssm, proofGenInfo, beforeCfgAst, - beforeOptimizationsCFG, - beforeOptimizationsData, - mappingUnoptimizedCopyToOrigBlock, + astCfgReprInput, + astCfgDataInput, + blockToBlockMapInput, mappingWithHints, beforeCfgAfterCfgBlock, beforeAstToCfgProgAccess, - unoptimizedCfgProgAccess, + beforeCfgToDagProgAccessInput, varTranslationFactory2, cmdIsaVisitor); theories.Add(astToCfgProofTheory); From 3bc02f23da782ce45f671dcd4051a67c697035ab Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Wed, 12 Oct 2022 10:28:40 +0200 Subject: [PATCH 008/123] refactored the booleans --- Source/ProofGeneration/ProofGenConfig.cs | 19 +++++++++++- .../ProofGeneration/ProofGenerationLayer.cs | 29 +++++++++---------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/Source/ProofGeneration/ProofGenConfig.cs b/Source/ProofGeneration/ProofGenConfig.cs index 4cfa18d6e..45df64556 100644 --- a/Source/ProofGeneration/ProofGenConfig.cs +++ b/Source/ProofGeneration/ProofGenConfig.cs @@ -9,18 +9,35 @@ public ProofGenConfig( bool generateAstCfgE2E, bool generateCfgDagE2E, bool generatePassifE2E, - bool generateVcE2E + bool generateVcE2E, + bool generateAstCfgProof, + bool generateCfgDagProof, + bool generatePassifProof, + bool generateVcProof ) { GenerateAstCfgE2E = generateAstCfgE2E; GenerateCfgDagE2E = generateCfgDagE2E; GeneratePassifE2E = generatePassifE2E; GenerateVcE2E = generateVcE2E; + + GenerateAstCfgProof = generateAstCfgProof; + GenerateCfgDagProof = generateCfgDagProof; + GeneratePassifProof = generatePassifProof; + GenerateVcProof = generateVcProof; + + } + public bool GenerateAstCfgE2E { get; set; } public bool GenerateCfgDagE2E { get; set; } public bool GeneratePassifE2E { get; set; } public bool GenerateVcE2E { get; } + + public bool GenerateAstCfgProof { get; set; } + public bool GenerateCfgDagProof { get; set; } + public bool GeneratePassifProof { get; set; } + public bool GenerateVcProof { get; } } } \ No newline at end of file diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 56e85e02d..278c75bd7 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -80,13 +80,9 @@ public class ProofGenerationLayer //private static Block uniqueExitBlockOrigBeforeOptimizations; private static Block uniqueExitBlockOrig; - private static ProofGenConfig _proofGenConfig = new(true, true, true, true); + private static ProofGenConfig _proofGenConfig = new(true, true, true, true, + true, true, true, true); - private static bool generateVCProof = true; - private static bool generatePassifProof = true; - private static bool generateCfgDagProof = true; - private static bool generateAstCfgProof = true; - private static IProgramAccessor globalDataProgAccess; private static IDictionary procNameToTopLevelPrograms = new Dictionary(); @@ -546,15 +542,12 @@ public static void VCGenerateAllProofs( Boogie2VCExprTranslator translator, TypeAxiomBuilderPremisses axiomBuilder) { - //_proofGenConfig.GeneratePassifE2E = generateVCProof && _proofGenConfig.GenerateVcE2E && generatePassifProof; - //_proofGenConfig.GenerateCfgDagE2E = generatePassifProof && _proofGenConfig.GeneratePassifE2E && generateCfgDagProof; - var map = AstToCfgProofGenInfoManager.GetImplToProofGenInfo(); proofGenInfo = map[afterPassificationImpl]; if (AstContainsGotoOrBreak(proofGenInfo)) { - generateAstCfgProof = false; + _proofGenConfig.GenerateAstCfgProof = false; } IList bigBlocks = proofGenInfo.GetBigBlocks(); @@ -562,6 +555,10 @@ public static void VCGenerateAllProofs( { DesugarCmdsInBigBlock(b); } + + _proofGenConfig.GeneratePassifE2E = _proofGenConfig.GenerateVcProof && _proofGenConfig.GenerateVcE2E && _proofGenConfig.GeneratePassifProof; + _proofGenConfig.GenerateCfgDagE2E = _proofGenConfig.GeneratePassifProof && _proofGenConfig.GeneratePassifE2E && _proofGenConfig.GenerateCfgDagProof; + _proofGenConfig.GenerateAstCfgE2E = _proofGenConfig.GenerateCfgDagProof && _proofGenConfig.GenerateCfgDagE2E && _proofGenConfig.GenerateAstCfgProof; IList unoptimizedCFGBlocks = proofGenInfo.GetUnpotimizedBlocks(); var newToOldInternal = new Dictionary(); @@ -630,7 +627,7 @@ public static void VCGenerateAllProofs( IProgramAccessor beforeAstToCfgProgAccess = null; IProgramAccessor unoptimizedCfgProgAccess = null; - if (generateAstCfgProof) + if (_proofGenConfig.GenerateAstCfgProof) { #region before ast to cfg program @@ -731,7 +728,7 @@ public static void VCGenerateAllProofs( #region before passive program - IProgramAccessor parentProgramAccessorForPassification = generateAstCfgProof ? beforeAstToCfgProgAccess : beforeCfgToDagProgAccess; + IProgramAccessor parentProgramAccessorForPassification = _proofGenConfig.GenerateAstCfgProof ? beforeAstToCfgProgAccess : beforeCfgToDagProgAccess; var beforePassiveProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_passive_prog"); var beforePassiveConfig = @@ -784,7 +781,7 @@ public static void VCGenerateAllProofs( out var programDecls, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); - var theoryNameForParentImport = generateAstCfgProof ? beforeAstToCfgProgAccess.TheoryName() : beforeCfgToDagProgAccess.TheoryName(); + var theoryNameForParentImport = _proofGenConfig.GenerateAstCfgProof ? beforeAstToCfgProgAccess.TheoryName() : beforeCfgToDagProgAccess.TheoryName(); var finalProgTheory = new Theory(finalProgTheoryName, @@ -836,7 +833,7 @@ out var endToEndLemma Console.WriteLine("Before passive prog mapping: " + fixedVarTranslation2.OutputMapping()); */ - IProgramAccessor beforePhaseProgramAccess = !generateAstCfgProof ? beforePassiveProgAccess : beforeAstToCfgProgAccess; + IProgramAccessor beforePhaseProgramAccess = !_proofGenConfig.GenerateAstCfgProof ? beforePassiveProgAccess : beforeAstToCfgProgAccess; var passificationProofTheory = PassificationManager.PassificationProof( phasesTheories.TheoryName(PhasesTheories.Phase.Passification), @@ -858,7 +855,7 @@ out var endToEndLemma #endregion - if (generateAstCfgProof) + if (_proofGenConfig.GenerateAstCfgProof) { #region ast to cfg @@ -947,7 +944,7 @@ out var endToEndLemma var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( phasesTheories, _proofGenConfig.GenerateCfgDagE2E, - generateAstCfgProof, + _proofGenConfig.GenerateAstCfgProof, vcAssm, beforeDagCfg, beforePassificationCfg, From ff89f0ef0c6c10ef06cc24a4a755b01dffa5a82f Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Thu, 13 Oct 2022 17:20:02 +0200 Subject: [PATCH 009/123] added comment about loop head big block map --- Source/Core/AstToCfgProofGenInfo.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/Core/AstToCfgProofGenInfo.cs b/Source/Core/AstToCfgProofGenInfo.cs index f68c6c8bd..fd977d817 100644 --- a/Source/Core/AstToCfgProofGenInfo.cs +++ b/Source/Core/AstToCfgProofGenInfo.cs @@ -304,7 +304,12 @@ public void AddBigBlockBeforeNamingAnonymous(BigBlock b, bool marker, BigBlock p { BigBlock simpleCmdsRemoved = new BigBlock(copy.tok, copy.LabelName, new List(), copy.ec, copy.tc); - //This is bad. + /* + * This is a special case where the newly created LoopHead BigBlock is mapped to itself. + * One could alternatively store the 'simpleCmdsRemoved' BigBlocks in a separate list but + * then one would need an additional if-statement or a for-loop to access that list during the creation of continuations + * and later on proofs. + */ mappingCopyBigblockToOrigBigblock.Add(simpleCmdsRemoved, simpleCmdsRemoved); mappingOrigBigblockToCopyBigblock.Add(simpleCmdsRemoved, simpleCmdsRemoved); From 030a99312f0ed5e53f32d09c1ca6b38789660ae8 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 18 Oct 2022 17:30:41 +0200 Subject: [PATCH 010/123] use type synonym instead of explicit type for "proc_body_satisfies_spec" the previous versoin used explicit symbols, which cannot be parsed by Isabelle's command line tool --- .../AstToCfg/AstToCfgEndToEnd.cs | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs b/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs index 777c7f6a1..33eb85c90 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs @@ -309,14 +309,19 @@ private static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term g new List{typeInterpId}, null, new TermApp( - IsaCommonTerms.TermIdentFromName("proc_is_correct"), - new TermWithExplicitType(new TermIdent(typeInterpId), IsaBoogieType.AbstractValueTyFunType(new VarType("a"))), - funDecls, - constantDecls, - globalDecls, - axioms, - procedure, - IsaCommonTerms.TermIdentFromName("(Ast.proc_body_satisfies_spec :: 'a absval_ty_fun ⇒ mbodyCFG proc_context ⇒ var_context ⇒ 'a fun_interp ⇒ rtype_env ⇒ expr list ⇒ expr list ⇒ ast ⇒ 'a nstate ⇒ bool)"))); + IsaCommonTerms.TermIdentFromName("proc_is_correct"), + new TermWithExplicitType(new TermIdent(typeInterpId), IsaBoogieType.AbstractValueTyFunType(new VarType("a"))), + funDecls, + constantDecls, + globalDecls, + axioms, + procedure, + new TermWithExplicitType( + IsaCommonTerms.TermIdentFromName("Ast.proc_body_satisfies_spec"), + new DataType("satisfies_spec_func_type", new VarType("a")) + ) + ) + ); } } } \ No newline at end of file From d6bb14bff56fb6dcdc33376ef8a7970e6c2d4f6e Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Thu, 27 Oct 2022 04:21:32 +0200 Subject: [PATCH 011/123] resolved naming issues for subdirectories, omitted numbers in titles --- Source/ExecutionEngine/ExecutionEngine.cs | 3 +- .../AstToCfg/AstToCfgManager.cs | 10 +- .../CfgToDag/CfgToDagManager.cs | 3 +- .../ProofGeneration/ProofGenerationLayer.cs | 199 ++++++++++-------- .../ProofGeneration/ProofGenerationOutput.cs | 8 +- Source/ProofGeneration/Util/IsaUniqueNamer.cs | 12 ++ etc/scripts/generate_proofs.py | 65 ------ 7 files changed, 143 insertions(+), 157 deletions(-) delete mode 100644 etc/scripts/generate_proofs.py diff --git a/Source/ExecutionEngine/ExecutionEngine.cs b/Source/ExecutionEngine/ExecutionEngine.cs index 0c3be0363..55fcc0948 100644 --- a/Source/ExecutionEngine/ExecutionEngine.cs +++ b/Source/ExecutionEngine/ExecutionEngine.cs @@ -547,7 +547,8 @@ public static bool ProcessProgram(Program program, string bplFileName, string pr if(!CommandLineOptions.Clo.OnlyCheckProofGenSupport) Console.WriteLine("Proof generation does not support this program, because of node " + resultNode); - Environment.Exit(0); + //temporarily set to 1 + Environment.Exit(1); } else if (CommandLineOptions.Clo.OnlyCheckProofGenSupport) { Console.WriteLine("Success:" + bplFileName); diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs index 5b593b3b4..14853377e 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs @@ -15,6 +15,7 @@ namespace ProofGeneration.AstToCfg internal class AstToCfgManager { public static Theory AstToCfgProof( + string uniqueTheoryName, PhasesTheories phasesTheories, bool generateEndtoEnd, Term vcAssm, @@ -161,14 +162,15 @@ public static Theory AstToCfgProof( } return new Theory( - phasesTheories.TheoryName(PhasesTheories.Phase.AstToCfg), + uniqueTheoryName, new List { "Boogie_Lang.Ast", "Boogie_Lang.Ast_Cfg_Transformation", "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.BackedgeElim", "Boogie_Lang.TypingML", beforeCfgProgAccess.TheoryName(), - afterCfgProgAccess.TheoryName(), phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag), - phasesTheories.TheoryName(PhasesTheories.Phase.Passification), - phasesTheories.TheoryName(PhasesTheories.Phase.Vc) + afterCfgProgAccess.TheoryName(), + //phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag), + //phasesTheories.TheoryName(PhasesTheories.Phase.Passification), + //phasesTheories.TheoryName(PhasesTheories.Phase.Vc) }, theoryOuterDecls ); diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs index c631ea59d..8f7e8b7f4 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs @@ -229,7 +229,8 @@ public static Theory CfgToDagProof( "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.BackedgeElim", "Boogie_Lang.TypingML", generatedAstToCfgProof ? beforeCfgProgAccess.TheoryName() : null, beforeDagProgAccess.TheoryName(), - afterDagProgAccess.TheoryName(), phasesTheories.TheoryName(PhasesTheories.Phase.Passification), + afterDagProgAccess.TheoryName(), + phasesTheories.TheoryName(PhasesTheories.Phase.Passification), phasesTheories.TheoryName(PhasesTheories.Phase.Vc) }, theoryOuterDecls diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 278c75bd7..f4bd6981e 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -80,8 +80,8 @@ public class ProofGenerationLayer //private static Block uniqueExitBlockOrigBeforeOptimizations; private static Block uniqueExitBlockOrig; - private static ProofGenConfig _proofGenConfig = new(true, true, true, true, - true, true, true, true); + private static ProofGenConfig _proofGenConfig = new(false, false, false, false, + true, false, false, false); private static IProgramAccessor globalDataProgAccess; @@ -606,8 +606,6 @@ public static void VCGenerateAllProofs( beforeOptimizationsCFG = new CFGRepr(outgoingBlocks, labeling, entryBlock); - // - var uniqueNamer = new IsaUniqueNamer(); var theories = new List(); if (axiomBuilder == null && typeAxioms != null) @@ -722,7 +720,7 @@ public static void VCGenerateAllProofs( if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) { - StoreResult("program_" + afterPassificationImpl.Proc.Name, theories); + StoreResult(uniqueNamer.GetName("program_" + afterPassificationImpl.Proc.Name), theories); return; } @@ -741,8 +739,53 @@ public static void VCGenerateAllProofs( !CommandLineOptions.Clo.GenerateIsaProgNoProofs); #endregion + + #region after passification program + + //use global version map for translation + var fixedVarTranslation = new SimpleFixedVarTranslation(globalVersionMap); + var fixedTyVarTranslation = new DeBruijnFixedTVarTranslation(finalProgData); + varTranslationFactory = + new DeBruijnVarFactory(fixedVarTranslation, fixedTyVarTranslation, boogieGlobalData); - var vcAllAxioms = AxiomHandler.AxiomInfo( + var finalProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_passive_prog"); + var passiveProgConfig = + new IsaProgramGeneratorConfig(beforePassiveProgAccess, false, false, false, true, SpecsConfig.None, false); + var passiveProgAccess = new IsaProgramGenerator().GetIsaProgram(finalProgTheoryName, + afterPassificationImpl.Name, + finalProgData, passiveProgConfig, varTranslationFactory, + //we use the CFG before the peep-hole transformations, so that we can directly use the VC to program proof in the passification phase + afterPassificationCfg, + out var programDecls, + !CommandLineOptions.Clo.GenerateIsaProgNoProofs); + + var theoryNameForParentImport = _proofGenConfig.GenerateAstCfgProof ? beforeAstToCfgProgAccess.TheoryName() : beforeCfgToDagProgAccess.TheoryName(); + + var afterPassificationProgTheory = + new Theory(finalProgTheoryName, + new List + {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, + programDecls); + theories.Add(afterPassificationProgTheory); + + #endregion + + #region before passive program (completion of theory construction) + + var beforePassificationProgTheory = new Theory(beforePassiveProgTheoryName, + new List {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, + programDeclsBeforePassive); + theories.Add(beforePassificationProgTheory); + + #endregion + + var phasesTheories = new PhasesTheories(afterPassificationImpl.Name); + Term vcAssm = null; + LemmaDecl endToEndLemma = null; + + if (_proofGenConfig.GenerateVcProof) + { + var vcAllAxioms = AxiomHandler.AxiomInfo( axiomBuilder != null, boogieGlobalData.Axioms, vcAxioms, @@ -750,7 +793,7 @@ public static void VCGenerateAllProofs( typeAxiomInfo, out var allAxiomsInfo); - var vcLocale = VCToIsaInterface.ConvertVC( + var vcLocale = VCToIsaInterface.ConvertVC( "vc", vc, vcAllAxioms, @@ -764,45 +807,19 @@ public static void VCGenerateAllProofs( out var vcTranslator, out var vcFunctions); - //use global version map for translation - var fixedVarTranslation = new SimpleFixedVarTranslation(globalVersionMap); - var fixedTyVarTranslation = new DeBruijnFixedTVarTranslation(finalProgData); - varTranslationFactory = - new DeBruijnVarFactory(fixedVarTranslation, fixedTyVarTranslation, boogieGlobalData); - - var finalProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_passive_prog"); - var passiveProgConfig = - new IsaProgramGeneratorConfig(beforePassiveProgAccess, false, false, false, true, SpecsConfig.None, false); - var passiveProgAccess = new IsaProgramGenerator().GetIsaProgram(finalProgTheoryName, - afterPassificationImpl.Name, - finalProgData, passiveProgConfig, varTranslationFactory, - //we use the CFG before the peep-hole transformations, so that we can directly use the VC to program proof in the passification phase - afterPassificationCfg, - out var programDecls, - !CommandLineOptions.Clo.GenerateIsaProgNoProofs); - - var theoryNameForParentImport = _proofGenConfig.GenerateAstCfgProof ? beforeAstToCfgProgAccess.TheoryName() : beforeCfgToDagProgAccess.TheoryName(); - - var finalProgTheory = - new Theory(finalProgTheoryName, - new List - {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, - programDecls); - theories.Add(finalProgTheory); + var vcBoogieInfo = new VcBoogieInfo(vcinst, vcinstAxiom, vcAllAxioms, allAxiomsInfo); - var vcBoogieInfo = new VcBoogieInfo(vcinst, vcinstAxiom, vcAllAxioms, allAxiomsInfo); - - var vcProofData = new ProgramVcProofData( + var vcProofData = new ProgramVcProofData( vcFunctions, vcBoogieInfo, vcHintManager, vcLocale, vcTranslator - ); + ); - var phasesTheories = new PhasesTheories(afterPassificationImpl.Name); + #region VC phase proof - var theoryPassive = VcPhaseManager.ProgramToVcProof( + var vcPhaseProofTheory = VcPhaseManager.ProgramToVcProof( phasesTheories.TheoryName(PhasesTheories.Phase.Vc), _proofGenConfig.GenerateVcE2E, afterUnreachablePruningCfg, @@ -816,28 +833,34 @@ public static void VCGenerateAllProofs( varTranslationFactory, typePremiseEraserFactory, gen, - out var vcAssm, - out var endToEndLemma - ); - theories.Add(theoryPassive); - - #region before passive + out var vcAssmPrelim, + out var endToEndLemmaPrelim + ); - var passificationProgTheory = new Theory(beforePassiveProgTheoryName, - new List {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, - programDeclsBeforePassive); - theories.Add(passificationProgTheory); + vcAssm = vcAssmPrelim; + endToEndLemma = endToEndLemmaPrelim; + + theories.Add(vcPhaseProofTheory); + #endregion + } + /* Console.WriteLine("Passive prog mapping: " + fixedVarTranslation.OutputMapping()); Console.WriteLine("Before passive prog mapping: " + fixedVarTranslation2.OutputMapping()); */ - IProgramAccessor beforePhaseProgramAccess = !_proofGenConfig.GenerateAstCfgProof ? beforePassiveProgAccess : beforeAstToCfgProgAccess; + if (_proofGenConfig.GeneratePassifProof) + { + #region passification proof + + IProgramAccessor beforePhaseProgramAccess = !_proofGenConfig.GenerateAstCfgProof + ? beforePassiveProgAccess + : beforeAstToCfgProgAccess; - var passificationProofTheory = PassificationManager.PassificationProof( + var passificationProofTheory = PassificationManager.PassificationProof( phasesTheories.TheoryName(PhasesTheories.Phase.Passification), - theoryPassive.TheoryName, + phasesTheories.TheoryName(PhasesTheories.Phase.Vc), _proofGenConfig.GeneratePassifE2E, endToEndLemma, vcAssm, @@ -850,10 +873,41 @@ out var endToEndLemma mainData, varTranslationFactory2, varTranslationFactory - ); - theories.Add(passificationProofTheory); + ); + theories.Add(passificationProofTheory); - #endregion + #endregion + } + + if (_proofGenConfig.GenerateCfgDagProof) + { + #region cfg to dag + + var uniqueExitBlock = + uniqueExitBlockOrig != null + ? beforePassiveOrigBlock.First(kv => kv.Value == uniqueExitBlockOrig).Key + : null; + + + var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( + phasesTheories, + _proofGenConfig.GenerateCfgDagE2E, + _proofGenConfig.GenerateAstCfgProof, + vcAssm, + beforeDagCfg, + beforePassificationCfg, + uniqueExitBlock, + beforeDagData, + cfgToDagHintManager, + beforeDagAfterDagBlock, + beforeAstToCfgProgAccess, + beforeCfgToDagProgAccess, + beforePassiveProgAccess, + varTranslationFactory2); + theories.Add(cfgToDagProofTheory); + + #endregion + } if (_proofGenConfig.GenerateAstCfgProof) { @@ -864,7 +918,7 @@ out var endToEndLemma new Dictionary(); //IDictionary mappingCopyBigblockToOrigBigblock = - //proofGenInfo.GetMappingCopyBigblockToOrigBigblock(); + //proofGenInfo.GetMappingCopyBigblockToOrigBigblock(); IDictionary mappingOrigBigBlockToOrigBlock = proofGenInfo.GetMappingOrigBigBlockToOrigBlock(); @@ -883,7 +937,9 @@ out var endToEndLemma var copyBigBlock = proofGenInfo.GetMappingOrigBigblockToCopyBigblock()[origBigBlock]; var origBlock = pair.Value; - var blockToBlockMapToReferTo = proofGenInfo.GetOptimizationsFlag() ? mappingOrigBlockToUnoptimizedCopy : mappingOrigBlockToCopyBlock; + var blockToBlockMapToReferTo = proofGenInfo.GetOptimizationsFlag() + ? mappingOrigBlockToUnoptimizedCopy + : mappingOrigBlockToCopyBlock; var copyBlock = blockToBlockMapToReferTo[origBlock]; var hints = mappingBigBlockToHints[origBigBlock]; @@ -912,8 +968,9 @@ out var endToEndLemma blockToBlockMapInput = mappingUnoptimizedCopyToOrigBlock; beforeCfgToDagProgAccessInput = unoptimizedCfgProgAccess; } - + var astToCfgProofTheory = AstToCfgManager.AstToCfgProof( + uniqueNamer.GetName(phasesTheories.TheoryName(PhasesTheories.Phase.AstToCfg)), phasesTheories, _proofGenConfig.GenerateAstCfgE2E, vcAssm, @@ -933,33 +990,7 @@ out var endToEndLemma #endregion } - #region cfg to dag - - var uniqueExitBlock = - uniqueExitBlockOrig != null - ? beforePassiveOrigBlock.First(kv => kv.Value == uniqueExitBlockOrig).Key - : null; - - - var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( - phasesTheories, - _proofGenConfig.GenerateCfgDagE2E, - _proofGenConfig.GenerateAstCfgProof, - vcAssm, - beforeDagCfg, - beforePassificationCfg, - uniqueExitBlock, - beforeDagData, - cfgToDagHintManager, - beforeDagAfterDagBlock, - beforeAstToCfgProgAccess, - beforeCfgToDagProgAccess, - beforePassiveProgAccess, - varTranslationFactory2); - theories.Add(cfgToDagProofTheory); - #endregion - - StoreResult(afterPassificationImpl.Proc.Name, theories); + StoreResult(uniqueNamer.GetName(afterPassificationImpl.Proc.Name), theories); } private static void StoreResult(string preferredDirName, IEnumerable theories) diff --git a/Source/ProofGeneration/ProofGenerationOutput.cs b/Source/ProofGeneration/ProofGenerationOutput.cs index 2ca8136c4..10b4cf73b 100644 --- a/Source/ProofGeneration/ProofGenerationOutput.cs +++ b/Source/ProofGeneration/ProofGenerationOutput.cs @@ -6,6 +6,7 @@ using Isabelle.Ast; using Isabelle.IsaPrettyPrint; using Microsoft.Boogie; +using ProofGeneration.Util; namespace ProofGeneration { @@ -15,6 +16,9 @@ public static class ProofGenerationOutput public static void CreateMainDirectory(string fileName, bool onlyUseFileName) { + IsaUniqueNamer namer = new IsaUniqueNamer(); + string filename_altered = namer.GetName(fileName); + if (CommandLineOptions.Clo.DontStoreProofGenFiles) return; @@ -22,9 +26,9 @@ public static void CreateMainDirectory(string fileName, bool onlyUseFileName) throw new ProofGenUnexpectedStateException("main directory already set"); if (!onlyUseFileName) - _mainDir = FreeDirName(Path.GetFileNameWithoutExtension(fileName) + "_proofs", false); + _mainDir = FreeDirName(Path.GetFileNameWithoutExtension(filename_altered) + "_proofs", false); else - _mainDir = fileName; + _mainDir = filename_altered; Directory.CreateDirectory(_mainDir); } diff --git a/Source/ProofGeneration/Util/IsaUniqueNamer.cs b/Source/ProofGeneration/Util/IsaUniqueNamer.cs index 140be41e3..904517459 100644 --- a/Source/ProofGeneration/Util/IsaUniqueNamer.cs +++ b/Source/ProofGeneration/Util/IsaUniqueNamer.cs @@ -54,8 +54,20 @@ public string GetName(object obj, string preferredName) var preferredNameMod = preferredName; foreach (var illegalChar in illegalChars) preferredNameMod = preferredNameMod.Replace(illegalChar, '_'); + if (preferredNameMod.Contains('0')) preferredNameMod = preferredNameMod.Replace('0', 'a'); + if (preferredNameMod.Contains('1')) preferredNameMod = preferredNameMod.Replace('1', 'b'); + if (preferredNameMod.Contains('2')) preferredNameMod = preferredNameMod.Replace('2', 'c'); + if (preferredNameMod.Contains('3')) preferredNameMod = preferredNameMod.Replace('3', 'd'); + if (preferredNameMod.Contains('4')) preferredNameMod = preferredNameMod.Replace('4', 'e'); + if (preferredNameMod.Contains('5')) preferredNameMod = preferredNameMod.Replace('5', 'f'); + if (preferredNameMod.Contains('6')) preferredNameMod = preferredNameMod.Replace('6', 'g'); + if (preferredNameMod.Contains('7')) preferredNameMod = preferredNameMod.Replace('7', 'h'); + if (preferredNameMod.Contains('8')) preferredNameMod = preferredNameMod.Replace('8', 'i'); + if (preferredNameMod.Contains('9')) preferredNameMod = preferredNameMod.Replace('9', 'j'); + if (reservedNames.Contains(preferredNameMod)) preferredNameMod = preferredNameMod + "ZZ"; if (preferredName.Length > 0 && preferredName.Last() == '_') preferredNameMod = preferredNameMod + "n"; + return uniqueNamer.GetName(obj, GetValidIsaString(preferredNameMod)); } diff --git a/etc/scripts/generate_proofs.py b/etc/scripts/generate_proofs.py deleted file mode 100644 index 3d3a8b716..000000000 --- a/etc/scripts/generate_proofs.py +++ /dev/null @@ -1,65 +0,0 @@ -import os -import subprocess -from datetime import datetime -import argparse - -# The following command should point to the Boogie proof generation binary -boogie_proofgen_bin = "boogieproof" - -def generate_proofs(input_dir, output_dir): - n_success = 0 - n_failure = 0 - - # turn input directory path into an absolute path, since we are going to - # change the working directory - input_dir_absolute = os.path.abspath(input_dir) - - os.mkdir(output_dir) - os.chdir(output_dir) - - for root, dirs, files in os.walk(input_dir_absolute): - for file in files: - if file.endswith('.bpl'): - boogie_file_path = os.path.join(root, file) - - # check whether Boogie can produce certificates - errorcode = subprocess.run([boogie_proofgen_bin, boogie_file_path],stdout=subprocess.DEVNULL) - if(errorcode.returncode == 0): - print("Generated proofs for: " + boogie_file_path) - n_success += 1 - else: - print("Could not generate proofs for: " + boogie_file_path) - n_failure += 1 - exit() - - print("Generated proofs for " + str(n_success) + " tests") - print("Could not generate proofs for " + str(n_failure) + " tests") - -def main(): - parser = argparse.ArgumentParser() - - parser.add_argument( - "-i", "--inputdir", - help="Directory where all Boogie files are located, for which proofs should be generated.", - required=True) - - parser.add_argument( - "-o", "--outputdir", - help="Directory in which the proofs should be stored. The directory should not exist yet.", - required=True - ) - - args = parser.parse_args() - - if (not(os.path.isdir(args.inputdir))): - print("The input directory " + args.inputdir + " does not point to an existing directory.") - exit(1) - - if (os.path.exists(args.outputdir)): - print("The desired path " + args.outputdir + " for the output directory already exists") - exit(1) - - generate_proofs(args.inputdir, args.outputdir) - -if __name__ == '__main__': - main() \ No newline at end of file From 1bf739836d1601275dc1897c9f33e96954f83c0b Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Wed, 9 Nov 2022 12:06:06 +0100 Subject: [PATCH 012/123] changes on proofs and naming --- .../AstToCfg/AstToCfgLemmaManager.cs | 78 +++++++++++-------- .../AstToCfg/AstToCfgManager.cs | 23 +++--- .../ApplicableIsaVisitor.cs | 1 + .../BoogieIsaInterface/IsaBoogieTerm.cs | 8 +- .../BoogieIsaInterface/IsaProgramGenerator.cs | 24 ++++-- .../IsaProgramGeneratorForAst.cs | 17 ++-- .../MembershipLemmaManager.cs | 10 +-- .../ProgramToVCProof/EndToEndVCProof.cs | 6 +- .../ProgramToVCProof/VcPhaseManager.cs | 2 + .../ProofGeneration/ProofGenerationLayer.cs | 23 +++++- Source/ProofGeneration/Util/IsaUniqueNamer.cs | 34 +++++++- 11 files changed, 154 insertions(+), 72 deletions(-) diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs index 8dcb677ae..bf6149881 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs @@ -198,7 +198,8 @@ public LemmaDecl LocalLemma( proofSb.AppendLine(ProofUtil.Apply("rule astStep")); proofSb.AppendLine(ProofUtil.Apply("rule push_through_assumption_test1, rule cfgBlockDoesntFail")); proofSb.AppendLine(ProofUtil.Apply("simp add: " + afterCmdsDefName + "_def")); - proofSb.AppendLine(ProofUtil.Apply(ProofUtil.Repeat("simp add: assms(3) " + beforeBigblockDefName + "_def"))); + proofSb.AppendLine("using guardHint "); + proofSb.AppendLine(ProofUtil.Apply(ProofUtil.Repeat("simp add: " + beforeBigblockDefName + "_def"))); proofSb.AppendLine("done"); } else if (indicator == BranchIndicator.GuardFails) @@ -215,10 +216,10 @@ public LemmaDecl LocalLemma( proofSb.AppendLine(ProofUtil.Apply("rule push_through_assumption1")); proofSb.AppendLine(ProofUtil.Apply("simp")); proofSb.AppendLine(ProofUtil.Apply(NegationRule(guardHint))); - proofSb.AppendLine(ProofUtil.Apply("rule guardHint")); + proofSb.AppendLine("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); proofSb.AppendLine(ProofUtil.Apply( ProofUtil.Repeat("simp add: " + beforeBigblockDefName + "_def"))); proofSb.AppendLine(ProofUtil.Apply(NegationRule(guardHint))); - proofSb.AppendLine(ProofUtil.Apply("rule guardHint")); + proofSb.AppendLine("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); proofSb.AppendLine("done"); } @@ -588,7 +589,7 @@ private List GenerateFinalBlockProof( string contId = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[startingBigBlock]; string syntacticRel; - string traceIsPossible = ProofUtil.Apply("rule guardHint"); + string traceIsPossible = "using guardHint " + ProofUtil.Apply(ProofUtil.Simp()); List finalPartofProof; List middlePartofProof; List beginningOfProof; @@ -638,7 +639,7 @@ private List GenerateFinalBlockProof( middlePartofProof = new List { ProofUtil.Apply("rule disjI1"), - ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("simp add: " + blockId + "_def"), ProofUtil.Apply("rule " + outEdgesId), ProofUtil.Apply("rule cfgDoesntFail"), ProofUtil.Apply(ProofUtil.Simp()), @@ -654,12 +655,12 @@ private List GenerateFinalBlockProof( ProofUtil.Apply("rule disjI2"), ProofUtil.Apply("rule disjI2"), ProofUtil.Apply("rule conjI"), - ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("simp add: " + blockId + "_def"), ProofUtil.Apply("rule conjI"), ProofUtil.Apply(ProofUtil.Simp()), ProofUtil.Apply("rule conjI"), ProofUtil.Apply(" " + NegationRule(entryGuard)), - ProofUtil.Apply("rule guardHint"), + "using guardHint " + ProofUtil.Apply((ProofUtil.Simp())), ProofUtil.Apply("rule " + outEdgesId), ProofUtil.Apply("rule cfgDoesntFail"), ProofUtil.Apply(ProofUtil.Simp()), @@ -675,10 +676,10 @@ private List GenerateFinalBlockProof( ProofUtil.Apply("rule disjI2"), ProofUtil.Apply("rule disjI1"), ProofUtil.Apply("rule conjI"), - ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("simp add: " + blockId + "_def"), ProofUtil.Apply("rule conjI"), ProofUtil.Apply(ProofUtil.Simp()), - ProofUtil.Apply("rule guardHint"), + "using guardHint " + ProofUtil.Apply((ProofUtil.Simp())), ProofUtil.Apply("rule " + outEdgesId), ProofUtil.Apply("rule cfgDoesntFail"), ProofUtil.Apply(ProofUtil.Simp()), @@ -692,7 +693,7 @@ private List GenerateFinalBlockProof( middlePartofProof = new List { ProofUtil.Apply("rule disjI1"), - ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("simp add: " + blockId + "_def"), ProofUtil.Apply("rule " + outEdgesId), ProofUtil.Apply("rule cfgDoesntFail"), ProofUtil.Apply(ProofUtil.Simp()), @@ -912,7 +913,7 @@ private List GenerateLoopHeadProof( if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) && personalGuard == null) { - beginningOfProof.Add(ProofUtil.Apply("rule guardHint")); + beginningOfProof.Add("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); } var insideOfLoopAddition1 = new List @@ -947,7 +948,7 @@ private List GenerateLoopHeadProof( if (personalGuard == null && !proofGenInfo.GetMappingBigBlockToLoopBigBlock() .ContainsKey(correspondingBigBlockOrig)) { - whileTrueEndingAfterSkippingEndBlock.Add(ProofUtil.Apply("rule guardHint")); + whileTrueEndingAfterSkippingEndBlock.Add("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); } whileTrueEndingAfterSkippingEndBlock.AddRange(new List { @@ -990,7 +991,7 @@ private List GenerateLoopHeadProof( if (personalGuard == null && !proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) { - endingAfterSkippingEndblock.Add(ProofUtil.Apply("rule guardHint")); + endingAfterSkippingEndblock.Add("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); } endingAfterSkippingEndblock.AddRange(new List { @@ -1251,7 +1252,7 @@ private List GenerateProofGeneric( middlePartOfProof = new List { ProofUtil.Apply("rule disjI1"), - ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("simp add: " + blockId + "_def"), ProofUtil.Apply("rule cfgDoesntFail"), ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), @@ -1274,12 +1275,12 @@ private List GenerateProofGeneric( ProofUtil.Apply("rule disjI2"), ProofUtil.Apply("rule disjI2"), ProofUtil.Apply("rule conjI"), - ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("simp add: " + blockId + "_def"), ProofUtil.Apply("rule conjI"), ProofUtil.Apply(ProofUtil.Simp()), ProofUtil.Apply("rule conjI"), ProofUtil.Apply("" + NegationRule(entryGuard) + ""), - ProofUtil.Apply("rule guardHint"), + "using guardHint " + ProofUtil.Apply((ProofUtil.Simp())), ProofUtil.Apply("rule cfgDoesntFail"), ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), @@ -1293,7 +1294,7 @@ private List GenerateProofGeneric( middlePartOfProof.Add(ProofUtil.Apply("rule " + nameLemmaLocal + "")); middlePartOfProof.Add("apply assumption"); middlePartOfProof.Add(ProofUtil.Apply(ProofUtil.Simp())); - middlePartOfProof.Add(ProofUtil.Apply("rule guardHint")); + middlePartOfProof.Add("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); } } //TODO: this check needs revision, I don't understand why this condition works. It might fail for complex procedures. @@ -1304,10 +1305,10 @@ private List GenerateProofGeneric( ProofUtil.Apply("rule disjI2"), ProofUtil.Apply("rule disjI1"), ProofUtil.Apply("rule conjI"), - ProofUtil.Apply("rule " + blockId + "_def"), + ProofUtil.Apply("simp add: " + blockId + "_def"), ProofUtil.Apply("rule conjI"), ProofUtil.Apply(ProofUtil.Simp()), - ProofUtil.Apply("rule guardHint"), + "using guardHint " + ProofUtil.Apply((ProofUtil.Simp())), ProofUtil.Apply("rule cfgDoesntFail"), ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), ProofUtil.Apply("rule cfgSatisfiesPosts, blast"), @@ -1325,7 +1326,7 @@ private List GenerateProofGeneric( if (startingBigBlock.simpleCmds.Any() && indicator == BranchIndicator.GuardHolds) { - middlePartOfProof.Add(ProofUtil.Apply("rule guardHint")); + middlePartOfProof.Add("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); } } @@ -1358,16 +1359,18 @@ private List GenerateProofGeneric( { proofEnd.Add(ProofUtil.Apply(ProofUtil.Simp())); } - - proofEnd.Add("apply blast+"); - + + proofEnd.Add(proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) + ? "apply blast+" + : "apply auto"); + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) { proofEnd.Add(ProofUtil.Apply("rule loop_IH_prove")); proofEnd.Add(ProofUtil.Apply("rule loop_IH_apply")); proofEnd.Add(ProofUtil.Apply("rule inductionHypothesis")); proofEnd.Add(ProofUtil.Apply("rule less_trans_inv")); - proofEnd.Add("apply blast+"); + proofEnd.Add("apply auto"); } } @@ -1473,7 +1476,7 @@ private List GenerateEndingAfterUnwrappingProof( }); if (indicator != BranchIndicator.NoGuard) { proofMethods.Add(rule); } - if (indicator != BranchIndicator.NoGuard && entryGuard != null) { proofMethods.Add(ProofUtil.Apply("rule guardHint")); } + if (indicator != BranchIndicator.NoGuard && entryGuard != null) { proofMethods.Add("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); } proofMethods.AddRange( new List { @@ -1493,7 +1496,7 @@ private List GenerateEndingAfterUnwrappingProof( }); if (indicator != BranchIndicator.NoGuard) { proofMethods.Add(rule); } - if (indicator != BranchIndicator.NoGuard && entryGuard != null) { proofMethods.Add(ProofUtil.Apply("rule guardHint")); } + if (indicator != BranchIndicator.NoGuard && entryGuard != null) { proofMethods.Add("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); } proofMethods.AddRange( new List { @@ -1609,7 +1612,7 @@ private List GenerateWhileSuccessorProof( if (entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails)) { - proofMethods.Add(ProofUtil.Apply("rule guardHint")); + proofMethods.Add("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); } proofMethods.AddRange(new List @@ -1633,7 +1636,7 @@ private List GenerateWhileSuccessorProof( if (entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails)) { - proofMethods.Add(ProofUtil.Apply("rule guardHint")); + proofMethods.Add("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); } proofMethods.AddRange(new List @@ -1642,10 +1645,14 @@ private List GenerateWhileSuccessorProof( ProofUtil.Apply(ProofUtil.Repeat("simp add: " + outEdgesId)), ProofUtil.Apply("simp add: member_rec(1)"), ProofUtil.Apply("rule " + nameLemmaSucc + ""), - ProofUtil.Apply("simp add: " + succBigBlockId + "_def " + contId + "_def "+ successorContId + "_def"), - "apply blast+" + ProofUtil.Apply("simp add: " + succBigBlockId + "_def " + contId + "_def "+ successorContId + "_def") }); + proofMethods.Add(proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) + ? "apply blast+" + : "apply auto"); + + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) { proofMethods.AddRange(new List @@ -1771,7 +1778,7 @@ private List GenerateIfSuccessorProof( if (entryGuard != null && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails)) { - middlePartOfProof.Add(ProofUtil.Apply("rule guardHint")); + middlePartOfProof.Add("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); } middlePartOfProof.AddRange(new List { @@ -1792,7 +1799,7 @@ private List GenerateIfSuccessorProof( if (entryGuard != null && startingBigBlock.simpleCmds.Any() && (indicator == BranchIndicator.GuardHolds || indicator == BranchIndicator.GuardFails)) { - middlePartOfProof.Add(ProofUtil.Apply("rule guardHint")); + middlePartOfProof.Add("using guardHint " + ProofUtil.Apply(ProofUtil.Simp())); } if (personalGuard != null) { middlePartOfProof.Add(ProofUtil.Apply("erule disjE")); } if (personalGuard == null) { middlePartOfProof.Add(ProofUtil.Apply("rule disjE, simp")); } @@ -1836,10 +1843,13 @@ private List GenerateIfSuccessorProof( ProofUtil.Apply("rule conjE"), ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), ProofUtil.Apply("rule " + nameLemmaElse + ""), - ExpandDefinitions(contId, startingBigBlock, proofGenInfo, BranchIndicator.GuardFails), - "apply blast+" + ExpandDefinitions(contId, startingBigBlock, proofGenInfo, BranchIndicator.GuardFails) }); + finalPartOfProof.Add(proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig) + ? "apply blast+" + : "apply auto"); + if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) { finalPartOfProof.AddRange(new List diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs index 14853377e..93619da90 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs @@ -18,6 +18,7 @@ public static Theory AstToCfgProof( string uniqueTheoryName, PhasesTheories phasesTheories, bool generateEndtoEnd, + ProofGenConfig config, Term vcAssm, AstToCfgProofGenInfo proofGenInfo, ASTRepr beforeCfgAst, @@ -161,17 +162,21 @@ public static Theory AstToCfgProof( theoryOuterDecls.AddRange(endToEndDecls); } + List importTheories = new List + { + "Boogie_Lang.Ast", "Boogie_Lang.Ast_Cfg_Transformation", "Boogie_Lang.Semantics", "Boogie_Lang.Util", + "Boogie_Lang.BackedgeElim", "Boogie_Lang.TypingML", + beforeCfgProgAccess.TheoryName(), + afterCfgProgAccess.TheoryName() + }; + + if (config.GenerateCfgDagProof) importTheories.Add(phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag)); + if (config.GeneratePassifProof) importTheories.Add(phasesTheories.TheoryName(PhasesTheories.Phase.Passification)); + if (config.GenerateVcProof) importTheories.Add(phasesTheories.TheoryName(PhasesTheories.Phase.Vc)); + return new Theory( uniqueTheoryName, - new List - { - "Boogie_Lang.Ast", "Boogie_Lang.Ast_Cfg_Transformation", "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.BackedgeElim", "Boogie_Lang.TypingML", - beforeCfgProgAccess.TheoryName(), - afterCfgProgAccess.TheoryName(), - //phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag), - //phasesTheories.TheoryName(PhasesTheories.Phase.Passification), - //phasesTheories.TheoryName(PhasesTheories.Phase.Vc) - }, + importTheories, theoryOuterDecls ); } diff --git a/Source/ProofGeneration/BoogieIsaInterface/ApplicableIsaVisitor.cs b/Source/ProofGeneration/BoogieIsaInterface/ApplicableIsaVisitor.cs index 5aa6ac770..e8b1320f5 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/ApplicableIsaVisitor.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/ApplicableIsaVisitor.cs @@ -3,6 +3,7 @@ using Isabelle.Ast; using Microsoft.Boogie; using ProofGeneration.BoogieIsaInterface.VariableTranslation; +using ProofGeneration.Util; namespace ProofGeneration { diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs index c0acddb74..cd40fc765 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs @@ -688,12 +688,12 @@ public static Term RedExpr(BoogieContextIsa boogieContext, Term expr, Term state }); } - public static Term FunDecl(Function f, IVariableTranslationFactory varTranslationFactory, + public static Term FunDecl(Function f, IVariableTranslationFactory varTranslationFactory, IsaUniqueNamer uniqueNamer, bool includeName = true) { var typeIsaVisitor = LemmaHelper.FunTypeIsaVisitor(f, varTranslationFactory); - Term fname = new StringConst(f.Name); + Term fname = new StringConst(uniqueNamer.RemoveApostropheInFunc(f.Name)); Term numTypeParams = new NatConst(f.TypeParameters.Count); var argTypes = new TermList(f.InParams.Select(v => typeIsaVisitor.Translate(v.TypedIdent.Type)).ToList()); var retType = typeIsaVisitor.Translate(f.OutParams.First().TypedIdent.Type); @@ -766,9 +766,9 @@ public static Term FunInterpWf(Term absValTyMap, Term fdecls, Term finterp) } public static Term FunInterpSingleWf(Function f, Term absValTyMap, Term fTerm, - IVariableTranslationFactory factory) + IVariableTranslationFactory factory, IsaUniqueNamer uniqueNamer) { - return FunInterpSingleWf(absValTyMap, FunDecl(f, factory), fTerm); + return FunInterpSingleWf(absValTyMap, FunDecl(f, factory, uniqueNamer), fTerm); } public static Term FunInterpSingleWf(Term absValTyMap, Term fdecl, Term fun) diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs index 916a5a0c0..0957f94e3 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs @@ -63,6 +63,7 @@ public IProgramAccessor GetIsaProgram( IsaProgramGeneratorConfig config, IVariableTranslationFactory varTranslationFactory, CFGRepr cfg, + IsaUniqueNamer uniqueNamer, out IList decls, bool generateMembershipLemmas = true, bool onlyGlobalData = false @@ -179,14 +180,14 @@ public IProgramAccessor GetIsaProgram( if (config.generateAxioms) { - decls.Add(GetAxioms(methodData.Axioms)); - if(generateMembershipLemmas) membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms); + decls.Add(GetAxioms(methodData.Axioms, uniqueNamer)); + if(generateMembershipLemmas) membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms, uniqueNamer); } if (config.generateFunctions) { - decls.Add(GetFunctionDeclarationsIsa(methodData.Functions)); - if(generateMembershipLemmas) membershipLemmaManager.AddFunctionMembershipLemmas(methodData.Functions); + decls.Add(GetFunctionDeclarationsIsa(methodData.Functions, uniqueNamer)); + if(generateMembershipLemmas) membershipLemmaManager.AddFunctionMembershipLemmas(methodData.Functions, uniqueNamer); } if (config.generateGlobalsAndConstants) @@ -211,15 +212,22 @@ public IProgramAccessor GetIsaProgram( return membershipLemmaManager; } - private DefDecl GetAxioms(IEnumerable axioms) + private DefDecl GetAxioms(IEnumerable axioms, IsaUniqueNamer uniqueNamer) { var axiomsExpr = new List(); foreach (var ax in axioms) { var axTerms = cmdIsaVisitor.Translate(ax.Expr); + if (axTerms.Count != 1) throw new ProofGenUnexpectedStateException(GetType(), "axiom not translated into single term"); - axiomsExpr.Add(axTerms.First()); + + if (axTerms.First().ToString().Contains("fun")) + { + string test = axTerms.First().ToString(); + } + + axiomsExpr.Add( IsaCommonTerms.TermIdentFromName(uniqueNamer.RemoveApostrophe(axTerms.First().ToString()) ) ); } var equation = new Tuple, Term>(new List(), new TermList(axiomsExpr)); @@ -362,13 +370,13 @@ private OuterDecl GetNodeToBlocksIsa(CFGRepr cfg, IDictionary return DefDecl.CreateWithoutArg(nodeToBlocksName, new TermList(nodeList)); } - private DefDecl GetFunctionDeclarationsIsa(IEnumerable functions) + private DefDecl GetFunctionDeclarationsIsa(IEnumerable functions, IsaUniqueNamer uniqueNamer) { //var equations = new List, Term>>(); var fdecls = new List(); - foreach (var f in functions) fdecls.Add(IsaBoogieTerm.FunDecl(f, varTranslationFactory)); + foreach (var f in functions) fdecls.Add(IsaBoogieTerm.FunDecl(f, varTranslationFactory, uniqueNamer)); return DefDecl.CreateWithoutArg(FunctionDeclarationsName(), new TermList(fdecls)); } diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs index da92a6a7b..ae69d6846 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs @@ -33,6 +33,7 @@ public IProgramAccessor GetIsaProgram( ASTRepr ast, ASTRepr originalAst, AstToCfgProofGenInfo proofGenInfo, + IsaUniqueNamer uniqueNamer, out IList decls, bool generateMembershipLemmas = true, bool onlyGlobalData = false @@ -141,14 +142,14 @@ public IProgramAccessor GetIsaProgram( if (config.generateAxioms) { - decls.Add(GetAxioms(methodData.Axioms)); - if(generateMembershipLemmas) membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms); + decls.Add(GetAxioms(methodData.Axioms, uniqueNamer)); + if(generateMembershipLemmas) membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms, uniqueNamer); } if (config.generateFunctions) { - decls.Add(GetFunctionDeclarationsIsa(methodData.Functions)); - if(generateMembershipLemmas) membershipLemmaManager.AddFunctionMembershipLemmas(methodData.Functions); + decls.Add(GetFunctionDeclarationsIsa(methodData.Functions, uniqueNamer)); + if(generateMembershipLemmas) membershipLemmaManager.AddFunctionMembershipLemmas(methodData.Functions, uniqueNamer); } if (config.generateGlobalsAndConstants) @@ -173,7 +174,7 @@ public IProgramAccessor GetIsaProgram( return membershipLemmaManager; } - private DefDecl GetAxioms(IEnumerable axioms) + private DefDecl GetAxioms(IEnumerable axioms, IsaUniqueNamer uniqueNamer) { var axiomsExpr = new List(); foreach (var ax in axioms) @@ -181,7 +182,7 @@ private DefDecl GetAxioms(IEnumerable axioms) var axTerms = cmdIsaVisitor.Translate(ax.Expr); if (axTerms.Count != 1) throw new ProofGenUnexpectedStateException(GetType(), "axiom not translated into single term"); - axiomsExpr.Add(axTerms.First()); + axiomsExpr.Add(IsaCommonTerms.TermIdentFromName(uniqueNamer.RemoveApostrophe(axTerms.First().ToString()))); } var equation = new Tuple, Term>(new List(), new TermList(axiomsExpr)); @@ -343,10 +344,10 @@ private IList getContinuations(ASTRepr originalAst, AstToCfgProofGenI return declsToReturn; } - private DefDecl GetFunctionDeclarationsIsa(IEnumerable functions) + private DefDecl GetFunctionDeclarationsIsa(IEnumerable functions, IsaUniqueNamer uniqueNamer) { var fdecls = new List(); - foreach (var f in functions) fdecls.Add(IsaBoogieTerm.FunDecl(f, varTranslationFactory)); + foreach (var f in functions) fdecls.Add(IsaBoogieTerm.FunDecl(f, varTranslationFactory, uniqueNamer)); return DefDecl.CreateWithoutArg(FunctionDeclarationsName(), new TermList(fdecls)); } diff --git a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs index 55c63a622..da68d4c1e 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs @@ -375,13 +375,13 @@ public IEnumerable OuterDecls() return result; } - public void AddFunctionMembershipLemmas(IEnumerable functions) + public void AddFunctionMembershipLemmas(IEnumerable functions, IsaUniqueNamer uniqueNamer) { AddNamedDeclsMembershipLemmas(functions, IsaCommonTerms.TermIdentFromName(isaProgramRepr.GlobalProgramRepr.funcsDeclDef), new[] {isaProgramRepr.GlobalProgramRepr.funcsDeclDef+ "_def"}, - d => new StringConst(d.Name), - d => IsaBoogieTerm.FunDecl((Function) d, factory, false), + d => new StringConst(uniqueNamer.RemoveApostropheInFunc(d.Name)), + d => IsaBoogieTerm.FunDecl((Function) d, factory, uniqueNamer, false), false ); } @@ -503,14 +503,14 @@ private void AddLookupVarDeclTyLemmas( } } - public void AddAxiomMembershipLemmas(IEnumerable axioms) + public void AddAxiomMembershipLemmas(IEnumerable axioms, IsaUniqueNamer uniqueNamer) { var axiomSet = IsaCommonTerms.SetOfList(IsaCommonTerms.TermIdentFromName(isaProgramRepr.GlobalProgramRepr.axiomsDeclDef)); var id = 0; foreach (var axiom in axioms) { var axiomTerm = basicCmdIsaVisitor.Translate(axiom.Expr); - var elemAssm = IsaCommonTerms.Elem(axiomTerm, axiomSet); + var elemAssm = IsaCommonTerms.Elem(IsaCommonTerms.TermIdentFromName(uniqueNamer.RemoveApostrophe(axiomTerm.ToString())), axiomSet); var proof = new Proof(new List {"by (simp add: " + isaProgramRepr.GlobalProgramRepr.axiomsDeclDef+ "_def)"}); membershipLemmas.Add(axiom, new LemmaDecl(MembershipName(axiom, id), elemAssm, proof)); diff --git a/Source/ProofGeneration/ProgramToVCProof/EndToEndVCProof.cs b/Source/ProofGeneration/ProgramToVCProof/EndToEndVCProof.cs index a18200f15..023121183 100644 --- a/Source/ProofGeneration/ProgramToVCProof/EndToEndVCProof.cs +++ b/Source/ProofGeneration/ProgramToVCProof/EndToEndVCProof.cs @@ -56,6 +56,8 @@ internal class EndToEndVCProof private readonly IsaUniqueNamer stateCorresNamer = new IsaUniqueNamer(); private readonly TypeIsaVisitor typeIsaVisitor; + private readonly IsaUniqueNamer namerForFunctions; + private readonly IVariableTranslationFactory varTranslationFactory; private readonly string vcAssmName = "VC"; @@ -83,6 +85,7 @@ public EndToEndVCProof( IVariableTranslationFactory varTranslationFactory, IVCVarFunTranslator vcVarFunTranslator, TypePremiseEraserFactory eraserFactory, + IsaUniqueNamer namerForFunctions, VCExpressionGenerator vcExprGen) { this.methodData = methodData; @@ -97,6 +100,7 @@ public EndToEndVCProof( this.varTranslationFactory = varTranslationFactory; this.vcVarFunTranslator = vcVarFunTranslator; this.eraserFactory = eraserFactory; + this.namerForFunctions = namerForFunctions; this.vcExprGen = vcExprGen; basicCmdIsaVisitor = new BasicCmdIsaVisitor(varTranslationFactory); typeIsaVisitor = new TypeIsaVisitor(varTranslationFactory.CreateTranslation().TypeVarTranslation); @@ -326,7 +330,7 @@ string TypeOfArgAssmLabel(int i) //funtion interpretation well-formed assumption assms.Add(IsaBoogieTerm.FunInterpSingleWf(boogieContext.absValTyMap, - IsaBoogieTerm.FunDecl(f, varTranslationFactory, false), funTerm)); + IsaBoogieTerm.FunDecl(f, varTranslationFactory, namerForFunctions, false), funTerm)); assmLabels.Add(finterpAssmName); //type variables closed assumption diff --git a/Source/ProofGeneration/ProgramToVCProof/VcPhaseManager.cs b/Source/ProofGeneration/ProgramToVCProof/VcPhaseManager.cs index 2d006ba33..8519c418e 100644 --- a/Source/ProofGeneration/ProgramToVCProof/VcPhaseManager.cs +++ b/Source/ProofGeneration/ProgramToVCProof/VcPhaseManager.cs @@ -54,6 +54,7 @@ public static Theory ProgramToVcProof( IVariableTranslationFactory varFactory, TypePremiseEraserFactory eraserFactory, VCExpressionGenerator gen, + IsaUniqueNamer namerForFunctions, out Term vcAssm, out LemmaDecl endToEndLemma) { @@ -133,6 +134,7 @@ public static Theory ProgramToVcProof( varFactory, vcProofData.VcTranslator, eraserFactory, + namerForFunctions, gen); passiveOuterDecls.AddRange(endToEnd.GenerateProof(out vcAssm, out endToEndLemma)); } diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index f4bd6981e..8f39bcab6 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -85,6 +85,8 @@ public class ProofGenerationLayer private static IProgramAccessor globalDataProgAccess; + private static IsaUniqueNamer uniqueNamer; + private static IDictionary procNameToTopLevelPrograms = new Dictionary(); /// @@ -92,10 +94,15 @@ public class ProofGenerationLayer /// public static void Program(Program p) { + if (uniqueNamer == null) + { + uniqueNamer = new IsaUniqueNamer(); + } + if (boogieGlobalData == null) { boogieGlobalData = new BoogieGlobalData(p.Functions, p.Axioms, p.GlobalVariables, p.Constants); - + var methodData = BoogieMethodData.CreateOnlyGlobal(boogieGlobalData); var fixedVarTranslation = new DeBruijnFixedVarTranslation(methodData); var fixedTyVarTranslation = new DeBruijnFixedTVarTranslation(methodData); @@ -108,6 +115,7 @@ public static void Program(Program p) "proc", methodData, globalDataConfig, factory, null, + uniqueNamer, out var declsGlobalData, !CommandLineOptions.Clo.GenerateIsaProgNoProofs, true @@ -606,7 +614,11 @@ public static void VCGenerateAllProofs( beforeOptimizationsCFG = new CFGRepr(outgoingBlocks, labeling, entryBlock); - var uniqueNamer = new IsaUniqueNamer(); + if (uniqueNamer == null) + { + uniqueNamer = new IsaUniqueNamer(); + } + var theories = new List(); if (axiomBuilder == null && typeAxioms != null) throw new ArgumentException("type axioms can only be null if axiom builder is null"); @@ -648,6 +660,7 @@ public static void VCGenerateAllProofs( beforeCfgAst, originalAst, proofGenInfo, + uniqueNamer, out var programDeclsBeforeAstToCfg, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "ast", beforeAstToCfgProgAccess); @@ -680,6 +693,7 @@ public static void VCGenerateAllProofs( afterPassificationImpl.Name, mainData, unoptimizedCfgConfig, varTranslationFactory2, beforeOptimizationsCFG, + uniqueNamer, out var programDeclsUnoptimizedCfg, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "unoptimized", @@ -708,6 +722,7 @@ public static void VCGenerateAllProofs( afterPassificationImpl.Name, mainData, beforeCfgToDagConfig, varTranslationFactory2, beforeDagCfg, + uniqueNamer, out var programDeclsBeforeCfgToDag, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name, beforeCfgToDagProgAccess); @@ -735,6 +750,7 @@ public static void VCGenerateAllProofs( afterPassificationImpl.Name, mainData, beforePassiveConfig, varTranslationFactory2, beforePassificationCfg, + uniqueNamer, out var programDeclsBeforePassive, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); @@ -756,6 +772,7 @@ public static void VCGenerateAllProofs( finalProgData, passiveProgConfig, varTranslationFactory, //we use the CFG before the peep-hole transformations, so that we can directly use the VC to program proof in the passification phase afterPassificationCfg, + uniqueNamer, out var programDecls, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); @@ -833,6 +850,7 @@ public static void VCGenerateAllProofs( varTranslationFactory, typePremiseEraserFactory, gen, + uniqueNamer, out var vcAssmPrelim, out var endToEndLemmaPrelim ); @@ -973,6 +991,7 @@ out var endToEndLemmaPrelim uniqueNamer.GetName(phasesTheories.TheoryName(PhasesTheories.Phase.AstToCfg)), phasesTheories, _proofGenConfig.GenerateAstCfgE2E, + _proofGenConfig, vcAssm, proofGenInfo, beforeCfgAst, diff --git a/Source/ProofGeneration/Util/IsaUniqueNamer.cs b/Source/ProofGeneration/Util/IsaUniqueNamer.cs index 904517459..813e176c6 100644 --- a/Source/ProofGeneration/Util/IsaUniqueNamer.cs +++ b/Source/ProofGeneration/Util/IsaUniqueNamer.cs @@ -43,6 +43,16 @@ public string GetName(string preferredName) { return GetName(preferredName, preferredName); } + + public string RemoveApostrophe(string preferredName) + { + return RemoveApostrophe(preferredName, preferredName); + } + + public string RemoveApostropheInFunc(string preferredName) + { + return RemoveApostropheInFunc(preferredName, preferredName); + } /// /// Returns a unique, legal Isabelle name resembling . @@ -63,7 +73,7 @@ public string GetName(object obj, string preferredName) if (preferredNameMod.Contains('6')) preferredNameMod = preferredNameMod.Replace('6', 'g'); if (preferredNameMod.Contains('7')) preferredNameMod = preferredNameMod.Replace('7', 'h'); if (preferredNameMod.Contains('8')) preferredNameMod = preferredNameMod.Replace('8', 'i'); - if (preferredNameMod.Contains('9')) preferredNameMod = preferredNameMod.Replace('9', 'j'); + if (preferredNameMod.Contains('9')) preferredNameMod = preferredNameMod.Replace('9', 'j'); if (reservedNames.Contains(preferredNameMod)) preferredNameMod = preferredNameMod + "ZZ"; if (preferredName.Length > 0 && preferredName.Last() == '_') preferredNameMod = preferredNameMod + "n"; @@ -71,6 +81,28 @@ public string GetName(object obj, string preferredName) return uniqueNamer.GetName(obj, GetValidIsaString(preferredNameMod)); } + public string RemoveApostrophe(object obj, string preferredName) + { + var preferredNameMod = preferredName; + if (preferredNameMod.Contains("\'" + "\'" + "\'")) + { + preferredNameMod = preferredNameMod.Replace("\'" + "\'" + "\'", "AA" + "\'" + "\'"); + } + + return uniqueNamer.GetName(obj, preferredNameMod); + } + + public string RemoveApostropheInFunc(object obj, string preferredName) + { + var preferredNameMod = preferredName; + if (preferredNameMod.Contains("\'")) + { + preferredNameMod = preferredNameMod.Replace("\'", "AA"); + } + + return uniqueNamer.GetName(obj, preferredNameMod); + } + public string GetLocalName(object obj, string preferredName) { return uniqueNamer.GetLocalName(obj, GetValidIsaString(preferredName)); From cd737c0a34504dd48c00f71d98e098228f3bc538 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Thu, 10 Nov 2022 19:40:50 +0100 Subject: [PATCH 013/123] update flags to avoid generating redundant definitions --- Source/ProofGeneration/ProofGenerationLayer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 8f39bcab6..d59d63bc6 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -650,7 +650,7 @@ public static void VCGenerateAllProofs( var specsConfig_ast = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; - var beforeAstToCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, + var beforeAstToCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, false, false, false, true, specsConfig_ast, true); beforeAstToCfgProgAccess = new IsaProgramGeneratorForAst().GetIsaProgram( @@ -687,7 +687,7 @@ public static void VCGenerateAllProofs( ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; var unoptimizedCfgConfig = - new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, true, _specsConfig, true); + new IsaProgramGeneratorConfig(globalDataProgAccess, false, false, false, false, _specsConfig, false); unoptimizedCfgProgAccess = new IsaProgramGenerator().GetIsaProgram( unoptimizedCfgTheoryName, afterPassificationImpl.Name, @@ -716,7 +716,7 @@ public static void VCGenerateAllProofs( var beforeCfgToDagTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_cfg_to_dag_prog"); //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) var specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; - var beforeCfgToDagConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, true, true, true, true, specsConfig, true); + var beforeCfgToDagConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, false, false, false, true, specsConfig, true); var beforeCfgToDagProgAccess = new IsaProgramGenerator().GetIsaProgram( beforeCfgToDagTheoryName, afterPassificationImpl.Name, From eb05cff2ddd0d33772bc149eb693d134263f4a81 Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Sat, 12 Nov 2022 22:44:44 +0100 Subject: [PATCH 014/123] bigblock definitions redone and 'blast+' removed from most proofs --- Source/Core/AstToCfgProofGenInfo.cs | 2 +- .../AstToCfg/AstToCfgLemmaManager.cs | 4 +- .../BoogieIsaInterface/IsaBigBlockInfo.cs | 6 +- .../BoogieIsaInterface/IsaProgramGenerator.cs | 3 +- .../IsaProgramGeneratorForAst.cs | 16 +++-- .../ProgramGeneratorHelperForAst.cs | 65 +++++++++++++------ .../ProofGeneration/ProofGenerationLayer.cs | 36 ++++++++-- 7 files changed, 93 insertions(+), 39 deletions(-) diff --git a/Source/Core/AstToCfgProofGenInfo.cs b/Source/Core/AstToCfgProofGenInfo.cs index fd977d817..a94dc6db5 100644 --- a/Source/Core/AstToCfgProofGenInfo.cs +++ b/Source/Core/AstToCfgProofGenInfo.cs @@ -55,7 +55,7 @@ public class AstToCfgProofGenInfo * The second hint is a BranchIndicator that indicates how that needs to be done. */ private IDictionary mappingBigBlockToHints; - // Map a BigBlock (copy) to the unique integer label (index) of its corresponding Term object (in InnerAst.cs). + // Map a BigBlock (copy) to the unique integer label (index) of its corresponding Term object (Term object definition is in InnerAst.cs). private IDictionary mappingCopyBigBlockToIndex; // Map a BigBlock (original) to the Loop BigBlock (original) it's nested into. diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs index bf6149881..cf67ecf9c 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs @@ -1814,13 +1814,15 @@ private List GenerateIfSuccessorProof( ProofUtil.Apply(ProofUtil.Repeat(ProofUtil.Simp())), ProofUtil.Apply("rule " + nameLemmaThen + ""), ExpandDefinitions(contId, startingBigBlock, proofGenInfo, BranchIndicator.GuardHolds), - "apply blast+" + "apply blast", + "apply blast" }; if (proofGenInfo.GetMappingBigBlockToLoopBigBlock().ContainsKey(correspondingBigBlockOrig)) { finalPartOfProof.AddRange(new List { + ProofUtil.Apply(ProofUtil.Simp()), ProofUtil.Apply("rule loop_IH_prove"), ProofUtil.Apply("rule loop_IH_apply"), ProofUtil.Apply("rule inductionHypothesis"), diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBigBlockInfo.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBigBlockInfo.cs index 419e0ac8c..58854eef6 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaBigBlockInfo.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBigBlockInfo.cs @@ -9,7 +9,7 @@ public class IsaBigBlockInfo public IsaBigBlockInfo( string theoryName, IDictionary bigblockIds, - IDictionary> bigblockDefs + IDictionary> bigblockDefs ) { TheoryName = theoryName; @@ -18,7 +18,7 @@ IDictionary> bigblockDefs } public IDictionary BigBlockIds { get; } - public IDictionary> BigBlockDefs { get; } + public IDictionary> BigBlockDefs { get; } public string TheoryName { get; } public IList CmdsQualifiedName(BigBlock b) @@ -26,7 +26,7 @@ public IList CmdsQualifiedName(BigBlock b) return QualifiedName(BigBlockDefs[b]); } - private IList QualifiedName(IList decls) + private IList QualifiedName(IList decls) { IList names = new List(); foreach (var decl in decls) diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs index 0957f94e3..563770ecc 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs @@ -65,7 +65,7 @@ public IProgramAccessor GetIsaProgram( CFGRepr cfg, IsaUniqueNamer uniqueNamer, out IList decls, - bool generateMembershipLemmas = true, + bool generateMembershipLemmas, bool onlyGlobalData = false ) { @@ -217,6 +217,7 @@ private DefDecl GetAxioms(IEnumerable axioms, IsaUniqueNamer uniqueNamer) var axiomsExpr = new List(); foreach (var ax in axioms) { + string test1 = ax.Expr.ToString(); var axTerms = cmdIsaVisitor.Translate(ax.Expr); if (axTerms.Count != 1) diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs index ae69d6846..07ae00339 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs @@ -35,7 +35,7 @@ public IProgramAccessor GetIsaProgram( AstToCfgProofGenInfo proofGenInfo, IsaUniqueNamer uniqueNamer, out IList decls, - bool generateMembershipLemmas = true, + bool generateMembershipLemmas, bool onlyGlobalData = false ) { @@ -233,25 +233,27 @@ private DefDecl MethodDefinition(IProgramAccessor programAccessor, BoogieMethodD private IsaBigBlockInfo BigBlockToInfo(string theoryName, ASTRepr ast, AstToCfgProofGenInfo proofGenInfo) { - var blockToDecl = new Dictionary>(); + var blockToDecl = new Dictionary>(); var blockToCounter = new Dictionary(); + + BigBlockTermBuilder builder = new BigBlockTermBuilder(); - foreach (BigBlock b in ast.GetBlocksForwards()) + foreach (BigBlock b in ast.GetBlocksBackwards()) { int flag = 0; if (proofGenInfo.GetMappingLoopHeadBigBlocktoOrigLoopBigBlock().Keys.Contains(b)) { flag = 1; } - BigBlockTermBuilder builder = new BigBlockTermBuilder(); + int uniqueIntLabel = ast.GetUniqueIntLabel(b); string nameToUse = "bigblock_" + uniqueIntLabel; - var translatedBigBlock = builder.makeBigBlockTerm(b, cmdIsaVisitor, flag, 0, nameToUse, out int updatedNestedBlockTracker); + var translatedBigBlock = builder.makeBigBlockTerm(b, proofGenInfo, cmdIsaVisitor, flag, 0, nameToUse, out int updatedNestedBlockTracker); proofGenInfo.AddBigBlockToIndexPair(b, uniqueIntLabel); - IDictionary> bb_defs = builder.getBigblockDefDecls(); - foreach(KeyValuePair> bb_def in bb_defs) + IDictionary> bb_defs = builder.getBigblockDefDecls(); + foreach(KeyValuePair> bb_def in bb_defs) { if (!blockToDecl.ContainsKey(bb_def.Key)) { diff --git a/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs b/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs index 5ec51f199..0ac11c6f1 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/ProgramGeneratorHelperForAst.cs @@ -15,34 +15,26 @@ namespace ProofGeneration { internal class BigBlockTermBuilder { - private IDictionary> bigBlocksDefDecls; + private IDictionary> bigBlocksDefDecls; public BigBlockTermBuilder() { - bigBlocksDefDecls = new Dictionary>(); + bigBlocksDefDecls = new Dictionary>(); } - public IDictionary> getBigblockDefDecls() + public IDictionary> getBigblockDefDecls() { return bigBlocksDefDecls; } - public Term makeBigBlockTerm(BigBlock b, MultiCmdIsaVisitor cmdIsaVisitor, int flag, int nestedBlockTracker, string nameToUse, + public Term makeBigBlockTerm(BigBlock b, AstToCfgProofGenInfo proofGenInfo, MultiCmdIsaVisitor cmdIsaVisitor, int flag, int nestedBlockTracker, string nameToUse, out int updatedNestedBlockTracker) { var bigblock_term = IsaCommonTerms.TermIdentFromName("BigBlock"); IList bigblock_args = new List(); - IList bigblock_args_no_cmds = new List(); Term name_option; - if (b.LabelName == null) - { - name_option = IsaCommonTerms.NoneOption(); - } - else - { - name_option = IsaCommonTerms.SomeOption(IsaCommonTerms.TermIdentFromName(b.LabelName)); - } + name_option = b.LabelName == null ? IsaCommonTerms.NoneOption() : IsaCommonTerms.SomeOption(IsaCommonTerms.TermIdentFromName(b.LabelName)); bigblock_args.Add(name_option); @@ -51,7 +43,7 @@ public Term makeBigBlockTerm(BigBlock b, MultiCmdIsaVisitor cmdIsaVisitor, int f bigblock_args.Add(cmdsList); - Term structure_option = makeStructuredCmdTerm(b, cmdIsaVisitor, nestedBlockTracker + 1, flag, nameToUse, + Term structure_option = makeStructuredCmdTerm(b, proofGenInfo, cmdIsaVisitor, nestedBlockTracker + 1, flag, nameToUse, out int updatedTrackerAfterStr); bigblock_args.Add(structure_option); @@ -81,12 +73,12 @@ public Term makeBigBlockTerm(BigBlock b, MultiCmdIsaVisitor cmdIsaVisitor, int f } bigblock_args.Add(transfer_option); - IList bb_decls = new List(); + IList bb_decls = new List(); Term bigblock = new TermApp(bigblock_term, bigblock_args); if (nestedBlockTracker == 0) { - OuterDecl bigblock_def = DefDecl.CreateWithoutArg(nameToUse, bigblock); + DefDecl bigblock_def = DefDecl.CreateWithoutArg(nameToUse, bigblock); bb_decls.Add(bigblock_def); bigBlocksDefDecls.Add(b, bb_decls); } @@ -95,7 +87,7 @@ public Term makeBigBlockTerm(BigBlock b, MultiCmdIsaVisitor cmdIsaVisitor, int f return bigblock; } - public Term makeStructuredCmdTerm(BigBlock b, MultiCmdIsaVisitor cmdIsaVisitor, int nestedBlockTracker, int flag, string nameToUse, + public Term makeStructuredCmdTerm(BigBlock b, AstToCfgProofGenInfo proofGenInfo, MultiCmdIsaVisitor cmdIsaVisitor, int nestedBlockTracker, int flag, string nameToUse, out int updatedNestedBlockTracker) { Term strCmdTermOption = null; @@ -123,8 +115,19 @@ public Term makeStructuredCmdTerm(BigBlock b, MultiCmdIsaVisitor cmdIsaVisitor, IList then_branch_bigblock_terms = new List(); foreach (BigBlock bb in then_branch) { - Term translated_bb = makeBigBlockTerm(bb, cmdIsaVisitor, 0, nestedBlockTracker, nameToUse, + Term translated_bb = makeBigBlockTerm(bb, proofGenInfo, cmdIsaVisitor, 0, nestedBlockTracker, nameToUse, out int updatedTrackerAfterBlock); + + foreach (var pair in bigBlocksDefDecls) + { + if (pair.Value.First().Equation.Item2.ToString() == translated_bb.ToString() && + proofGenInfo.GetMappingCopyBigBlockToIndex()[pair.Key] == proofGenInfo.GetMappingCopyBigBlockToIndex()[bb]) + { + translated_bb = IsaCommonTerms.TermIdentFromName(pair.Value.First().Name); + break; + } + } + then_branch_bigblock_terms.Add(translated_bb); nestedBlockTracker = updatedTrackerAfterBlock + 1; } @@ -134,8 +137,19 @@ public Term makeStructuredCmdTerm(BigBlock b, MultiCmdIsaVisitor cmdIsaVisitor, IList else_branch_bigblock_terms = new List(); foreach (BigBlock bb in else_branch) { - Term translated_bb = makeBigBlockTerm(bb, cmdIsaVisitor, 0, nestedBlockTracker, nameToUse, + Term translated_bb = makeBigBlockTerm(bb, proofGenInfo, cmdIsaVisitor, 0, nestedBlockTracker, nameToUse, out int updatedTrackerAfterBlock); + + foreach (var pair in bigBlocksDefDecls) + { + if (pair.Value.First().Equation.Item2.ToString() == translated_bb.ToString() && + proofGenInfo.GetMappingCopyBigBlockToIndex()[pair.Key] == proofGenInfo.GetMappingCopyBigBlockToIndex()[bb]) + { + translated_bb = IsaCommonTerms.TermIdentFromName(pair.Value.First().Name); + break; + } + } + else_branch_bigblock_terms.Add(translated_bb); nestedBlockTracker = updatedTrackerAfterBlock + 1; } @@ -178,8 +192,19 @@ public Term makeStructuredCmdTerm(BigBlock b, MultiCmdIsaVisitor cmdIsaVisitor, IList body_bigblock_terms = new List(); foreach (BigBlock bb in bodyBigBlocks) { - Term translated_bb = makeBigBlockTerm(bb, cmdIsaVisitor, 0, nestedBlockTracker, nameToUse, + Term translated_bb = makeBigBlockTerm(bb, proofGenInfo, cmdIsaVisitor, 0, nestedBlockTracker, nameToUse, out int updatedTrackerAfterBlock); + + foreach (var pair in bigBlocksDefDecls) + { + if (pair.Value.First().Equation.Item2.ToString() == translated_bb.ToString() && + proofGenInfo.GetMappingCopyBigBlockToIndex()[pair.Key] == proofGenInfo.GetMappingCopyBigBlockToIndex()[bb]) + { + translated_bb = IsaCommonTerms.TermIdentFromName(pair.Value.First().Name); + break; + } + } + body_bigblock_terms.Add(translated_bb); nestedBlockTracker = updatedTrackerAfterBlock + 1; } diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index d59d63bc6..78d4a8891 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -109,7 +109,13 @@ public static void Program(Program p) var factory = new DeBruijnVarFactory(fixedVarTranslation, fixedTyVarTranslation, boogieGlobalData); var globalDataTheoryName = "global_data"; - var globalDataConfig = new IsaProgramGeneratorConfig(null, true, true, true, false, SpecsConfig.None, false); + var globalDataConfig = new IsaProgramGeneratorConfig(null, + true, + true, + true, + false, + SpecsConfig.None, + false); globalDataProgAccess = new IsaProgramGenerator().GetIsaProgram( globalDataTheoryName, "proc", @@ -650,8 +656,13 @@ public static void VCGenerateAllProofs( var specsConfig_ast = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; - var beforeAstToCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, false, false, false, - true, specsConfig_ast, true); + var beforeAstToCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, + false, + false, + false, + true, + specsConfig_ast, + true); beforeAstToCfgProgAccess = new IsaProgramGeneratorForAst().GetIsaProgram( beforeAstToCfgTheoryName, @@ -687,7 +698,14 @@ public static void VCGenerateAllProofs( ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; var unoptimizedCfgConfig = - new IsaProgramGeneratorConfig(globalDataProgAccess, false, false, false, false, _specsConfig, false); + new IsaProgramGeneratorConfig(beforeAstToCfgProgAccess, + false, + false, + false, + false, + _specsConfig, + false); + unoptimizedCfgProgAccess = new IsaProgramGenerator().GetIsaProgram( unoptimizedCfgTheoryName, afterPassificationImpl.Name, @@ -703,7 +721,7 @@ public static void VCGenerateAllProofs( new List { "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", - "\"../" + globalDataProgAccess.TheoryName() + "\"" + "\"../" + beforeAstToCfgProgAccess.TheoryName() + "\"" }, programDeclsUnoptimizedCfg); theories.Add(unoptimizedCfgProgTheory); @@ -716,7 +734,13 @@ public static void VCGenerateAllProofs( var beforeCfgToDagTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_cfg_to_dag_prog"); //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) var specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; - var beforeCfgToDagConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, false, false, false, true, specsConfig, true); + var beforeCfgToDagConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, + false, + false, + false, + true, + specsConfig, + true); var beforeCfgToDagProgAccess = new IsaProgramGenerator().GetIsaProgram( beforeCfgToDagTheoryName, afterPassificationImpl.Name, From 88ee90f0004fadcf727d0bc5f620d1b30401d807 Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Sat, 19 Nov 2022 20:36:29 +0100 Subject: [PATCH 015/123] finalizing branch, proof generation for all phases enabled --- .../ProofGeneration/ProofGenerationLayer.cs | 6 +- etc/scripts/generate_proofs.py | 64 +++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 etc/scripts/generate_proofs.py diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 78d4a8891..dc3bd4027 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -80,8 +80,8 @@ public class ProofGenerationLayer //private static Block uniqueExitBlockOrigBeforeOptimizations; private static Block uniqueExitBlockOrig; - private static ProofGenConfig _proofGenConfig = new(false, false, false, false, - true, false, false, false); + private static ProofGenConfig _proofGenConfig = new(true, true, true, true, + true, true, true, true); private static IProgramAccessor globalDataProgAccess; @@ -721,7 +721,7 @@ public static void VCGenerateAllProofs( new List { "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", - "\"../" + beforeAstToCfgProgAccess.TheoryName() + "\"" + beforeAstToCfgProgAccess.TheoryName() }, programDeclsUnoptimizedCfg); theories.Add(unoptimizedCfgProgTheory); diff --git a/etc/scripts/generate_proofs.py b/etc/scripts/generate_proofs.py new file mode 100644 index 000000000..6a9a259d5 --- /dev/null +++ b/etc/scripts/generate_proofs.py @@ -0,0 +1,64 @@ +import os +import subprocess +from datetime import datetime +import argparse + +# The following command should point to the Boogie proof generation binary +boogie_proofgen_bin = "boogieproof" + +def generate_proofs(input_dir, output_dir): + n_success = 0 + n_failure = 0 + + # turn input directory path into an absolute path, since we are going to + # change the working directory + input_dir_absolute = os.path.abspath(input_dir) + + os.mkdir(output_dir) + os.chdir(output_dir) + + for root, dirs, files in os.walk(input_dir_absolute): + for file in files: + if file.endswith('.bpl'): + boogie_file_path = os.path.join(root, file) + + # check whether Boogie can produce certificates + errorcode = subprocess.run([boogie_proofgen_bin, boogie_file_path],stdout=subprocess.DEVNULL) + if(errorcode.returncode == 0): + print("Generated proofs for: " + boogie_file_path) + n_success += 1 + else: + print("Could not generate proofs for: " + boogie_file_path) + n_failure += 1 + + print("Generated proofs for " + str(n_success) + " tests") + print("Could not generate proofs for " + str(n_failure) + " tests") + +def main(): + parser = argparse.ArgumentParser() + + parser.add_argument( + "-i", "--inputdir", + help="Directory where all Boogie files are located, for which proofs should be generated.", + required=True) + + parser.add_argument( + "-o", "--outputdir", + help="Directory in which the proofs should be stored. The directory should not exist yet.", + required=True + ) + + args = parser.parse_args() + + if (not(os.path.isdir(args.inputdir))): + print("The input directory " + args.inputdir + " does not point to an existing directory.") + exit(1) + + if (os.path.exists(args.outputdir)): + print("The desired path " + args.outputdir + " for the output directory already exists") + exit(1) + + generate_proofs(args.inputdir, args.outputdir) + +if __name__ == '__main__': + main() \ No newline at end of file From 153df566bb4d32c173196e8ba0bbb3090bdf72f2 Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Tue, 22 Nov 2022 12:56:24 +0100 Subject: [PATCH 016/123] forcing squeezing of assume commands in the beginning of if-blocks regardless of labels --- Source/Core/AbsyCmd.cs | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/Source/Core/AbsyCmd.cs b/Source/Core/AbsyCmd.cs index 777d2c15c..74d54b064 100644 --- a/Source/Core/AbsyCmd.cs +++ b/Source/Core/AbsyCmd.cs @@ -211,7 +211,7 @@ public void Emit(TokenTextWriter stream, int level) /// Note, to be conservative (that is, ignoring the possible optimization that this /// method enables), this method can do nothing and return false. /// - public bool PrefixFirstBlock([Captured] List prefixCmds, ref string suggestedLabel) + public bool PrefixFirstBlock([Captured] List prefixCmds, ref string suggestedLabel, bool containsGotos) { Contract.Requires(suggestedLabel != null); Contract.Requires(prefixCmds != null); @@ -240,7 +240,7 @@ public bool PrefixFirstBlock([Captured] List prefixCmds, ref string suggest { // There really is something to insert. We can do this inline only if the first // block is anonymous (which implies there is no branch to it from within the block). - if (bb0.Anonymous) + if (bb0.Anonymous || !containsGotos) { PrefixCommands = prefixCmds; bb0.LabelName = suggestedLabel; @@ -708,10 +708,36 @@ void RecordSuccessors(StmtList stmtList, BigBlock successor) } } + public bool checkForGotos(StmtList stmtList) + { + foreach (var bb in stmtList.BigBlocks) + { + if (bb.tc is GotoCmd) + { + return true; + } + + if (bb.ec is IfCmd ifcmd) + { + checkForGotos(ifcmd.thn); + checkForGotos(ifcmd.elseBlock); + } + else if (bb.ec is WhileCmd whilecmd) + { + checkForGotos(whilecmd.Body); + } + } + + return false; + } + // If the enclosing context is a loop, then "runOffTheEndLabel" is the loop head label; // otherwise, it is null. void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, AstToCfgProofGenInfo proofGenInfo) { + + bool containsGotos = checkForGotos(stmtList); + Contract.Requires(stmtList != null); Contract.Requires(blocks != null); List cmdPrefixToApply = stmtList.PrefixCommands; @@ -800,7 +826,7 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, AstToCfgProofGenI } // Try to squeeze in ssBody into the first block of wcmd.Body - bool bodyGuardTakenCareOf = wcmd.Body.PrefixFirstBlock(ssBody, ref loopBodyLabel); + bool bodyGuardTakenCareOf = wcmd.Body.PrefixFirstBlock(ssBody, ref loopBodyLabel, containsGotos); // ... goto LoopHead; Block block = new Block(b.tok, b.LabelName, theSimpleCmds, @@ -932,11 +958,11 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, AstToCfgProofGenI } // Try to squeeze in ssThen/ssElse into the first block of ifcmd.thn/ifcmd.elseBlock - bool thenGuardTakenCareOf = ifcmd.thn.PrefixFirstBlock(ssThen, ref thenLabel); + bool thenGuardTakenCareOf = ifcmd.thn.PrefixFirstBlock(ssThen, ref thenLabel, containsGotos); bool elseGuardTakenCareOf = false; if (ifcmd.elseBlock != null) { - elseGuardTakenCareOf = ifcmd.elseBlock.PrefixFirstBlock(ssElse, ref elseLabel); + elseGuardTakenCareOf = ifcmd.elseBlock.PrefixFirstBlock(ssElse, ref elseLabel, containsGotos); } // ... goto Then, Else; From 2d3da1f1e13bbfe09096716838b92401d5136021 Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Thu, 24 Nov 2022 15:02:39 +0100 Subject: [PATCH 017/123] small bug fix regarding naming --- Source/ProofGeneration/CfgToDag/CfgToDagManager.cs | 8 +++++--- Source/ProofGeneration/ProofGenerationLayer.cs | 10 ++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs index 8f7e8b7f4..d56105cac 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs @@ -23,8 +23,10 @@ public class CfgToDagManager */ public static Theory CfgToDagProof( PhasesTheories phasesTheories, + IsaUniqueNamer uniqueNamer, bool generateEndToEndLemma, bool generatedAstToCfgProof, + bool generateVcProof, Term vcAssm, CFGRepr beforeDagCfg, CFGRepr afterDagCfg, @@ -223,15 +225,15 @@ public static Theory CfgToDagProof( } return new Theory( - phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag), + uniqueNamer.GetName(phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag)), new List { "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.BackedgeElim", "Boogie_Lang.TypingML", generatedAstToCfgProof ? beforeCfgProgAccess.TheoryName() : null, beforeDagProgAccess.TheoryName(), afterDagProgAccess.TheoryName(), - phasesTheories.TheoryName(PhasesTheories.Phase.Passification), - phasesTheories.TheoryName(PhasesTheories.Phase.Vc) + uniqueNamer.GetName(phasesTheories.TheoryName(PhasesTheories.Phase.Passification)), + generateVcProof ? phasesTheories.TheoryName(PhasesTheories.Phase.Vc) : "" }, theoryOuterDecls ); diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index dc3bd4027..0365495bc 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -80,8 +80,8 @@ public class ProofGenerationLayer //private static Block uniqueExitBlockOrigBeforeOptimizations; private static Block uniqueExitBlockOrig; - private static ProofGenConfig _proofGenConfig = new(true, true, true, true, - true, true, true, true); + private static ProofGenConfig _proofGenConfig = new(false, false, false, false, + false, true, true, false); private static IProgramAccessor globalDataProgAccess; @@ -901,8 +901,8 @@ out var endToEndLemmaPrelim : beforeAstToCfgProgAccess; var passificationProofTheory = PassificationManager.PassificationProof( - phasesTheories.TheoryName(PhasesTheories.Phase.Passification), - phasesTheories.TheoryName(PhasesTheories.Phase.Vc), + uniqueNamer.GetName(phasesTheories.TheoryName(PhasesTheories.Phase.Passification)), + _proofGenConfig.GenerateVcProof ? phasesTheories.TheoryName(PhasesTheories.Phase.Vc) : "", _proofGenConfig.GeneratePassifE2E, endToEndLemma, vcAssm, @@ -933,8 +933,10 @@ out var endToEndLemmaPrelim var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( phasesTheories, + uniqueNamer, _proofGenConfig.GenerateCfgDagE2E, _proofGenConfig.GenerateAstCfgProof, + _proofGenConfig.GenerateVcProof, vcAssm, beforeDagCfg, beforePassificationCfg, From 6134eaa15c3970798eb4aab78f76f809d4eb5ffc Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Fri, 25 Nov 2022 07:08:06 +0100 Subject: [PATCH 018/123] reverted forceful squeezing of assume-commands and added condition generation of the before-phase programs --- Source/Core/AbsyCmd.cs | 35 +-- Source/Core/AstToCfgProofGenInfo.cs | 6 +- Source/ProofGeneration/ProofGenConfig.cs | 28 ++- .../ProofGeneration/ProofGenerationLayer.cs | 203 +++++++++++------- 4 files changed, 157 insertions(+), 115 deletions(-) diff --git a/Source/Core/AbsyCmd.cs b/Source/Core/AbsyCmd.cs index 74d54b064..da1745a2e 100644 --- a/Source/Core/AbsyCmd.cs +++ b/Source/Core/AbsyCmd.cs @@ -211,7 +211,7 @@ public void Emit(TokenTextWriter stream, int level) /// Note, to be conservative (that is, ignoring the possible optimization that this /// method enables), this method can do nothing and return false. /// - public bool PrefixFirstBlock([Captured] List prefixCmds, ref string suggestedLabel, bool containsGotos) + public bool PrefixFirstBlock([Captured] List prefixCmds, ref string suggestedLabel) { Contract.Requires(suggestedLabel != null); Contract.Requires(prefixCmds != null); @@ -240,7 +240,7 @@ public bool PrefixFirstBlock([Captured] List prefixCmds, ref string suggest { // There really is something to insert. We can do this inline only if the first // block is anonymous (which implies there is no branch to it from within the block). - if (bb0.Anonymous || !containsGotos) + if (bb0.Anonymous) { PrefixCommands = prefixCmds; bb0.LabelName = suggestedLabel; @@ -708,35 +708,10 @@ void RecordSuccessors(StmtList stmtList, BigBlock successor) } } - public bool checkForGotos(StmtList stmtList) - { - foreach (var bb in stmtList.BigBlocks) - { - if (bb.tc is GotoCmd) - { - return true; - } - - if (bb.ec is IfCmd ifcmd) - { - checkForGotos(ifcmd.thn); - checkForGotos(ifcmd.elseBlock); - } - else if (bb.ec is WhileCmd whilecmd) - { - checkForGotos(whilecmd.Body); - } - } - - return false; - } - // If the enclosing context is a loop, then "runOffTheEndLabel" is the loop head label; // otherwise, it is null. void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, AstToCfgProofGenInfo proofGenInfo) { - - bool containsGotos = checkForGotos(stmtList); Contract.Requires(stmtList != null); Contract.Requires(blocks != null); @@ -826,7 +801,7 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, AstToCfgProofGenI } // Try to squeeze in ssBody into the first block of wcmd.Body - bool bodyGuardTakenCareOf = wcmd.Body.PrefixFirstBlock(ssBody, ref loopBodyLabel, containsGotos); + bool bodyGuardTakenCareOf = wcmd.Body.PrefixFirstBlock(ssBody, ref loopBodyLabel); // ... goto LoopHead; Block block = new Block(b.tok, b.LabelName, theSimpleCmds, @@ -958,11 +933,11 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, AstToCfgProofGenI } // Try to squeeze in ssThen/ssElse into the first block of ifcmd.thn/ifcmd.elseBlock - bool thenGuardTakenCareOf = ifcmd.thn.PrefixFirstBlock(ssThen, ref thenLabel, containsGotos); + bool thenGuardTakenCareOf = ifcmd.thn.PrefixFirstBlock(ssThen, ref thenLabel); bool elseGuardTakenCareOf = false; if (ifcmd.elseBlock != null) { - elseGuardTakenCareOf = ifcmd.elseBlock.PrefixFirstBlock(ssElse, ref elseLabel, containsGotos); + elseGuardTakenCareOf = ifcmd.elseBlock.PrefixFirstBlock(ssElse, ref elseLabel); } // ... goto Then, Else; diff --git a/Source/Core/AstToCfgProofGenInfo.cs b/Source/Core/AstToCfgProofGenInfo.cs index a94dc6db5..dec6229d0 100644 --- a/Source/Core/AstToCfgProofGenInfo.cs +++ b/Source/Core/AstToCfgProofGenInfo.cs @@ -62,8 +62,10 @@ public class AstToCfgProofGenInfo private IDictionary mappingBigBlockToOrigLoopBigBlock; // List of BigBlocks added after a loop if that loop is the end of the procedure or if that loop has no successors. - // I've never encountered an instance where this list contains more than one element, i.e, this doesn't need to be a list. - // However, this depends on the when successor Big Blocks are computed, so using a list is not wrong. + // I've never encountered an instance where this list contains more than one element, i.e, this doesn't need to be a list in our setting. + // However, this depends on when successor Big Blocks are computed. + // If successor BigBlocks were to be computed after the check on line 886 in AbsyCmd.cs is done, + // then this list will contain a BigBlock corresponding to every loop. private IList loopEndingBlocks; private List newVarsFromDesugaring; diff --git a/Source/ProofGeneration/ProofGenConfig.cs b/Source/ProofGeneration/ProofGenConfig.cs index 45df64556..5df0273ef 100644 --- a/Source/ProofGeneration/ProofGenConfig.cs +++ b/Source/ProofGeneration/ProofGenConfig.cs @@ -6,6 +6,11 @@ public class ProofGenConfig { public ProofGenConfig( + bool generateBeforeAstCfgProg, + bool generateUnoptimizedCfgProg, + bool generateBeforeCfgDagProg, + bool generateBeforePassifProg, + bool generatePassifiedProg, bool generateAstCfgE2E, bool generateCfgDagE2E, bool generatePassifE2E, @@ -16,6 +21,12 @@ public ProofGenConfig( bool generateVcProof ) { + GenerateBeforeAstCfgProg = generateBeforeAstCfgProg; + GenerateUnoptimizedCfgProg = generateUnoptimizedCfgProg; + GenerateBeforeCfgDagProg = generateBeforeCfgDagProg; + GenerateBeforePassifProg = generateBeforePassifProg; + GeneratePassifiedProg = generatePassifiedProg; + GenerateAstCfgE2E = generateAstCfgE2E; GenerateCfgDagE2E = generateCfgDagE2E; GeneratePassifE2E = generatePassifE2E; @@ -25,18 +36,21 @@ bool generateVcProof GenerateCfgDagProof = generateCfgDagProof; GeneratePassifProof = generatePassifProof; GenerateVcProof = generateVcProof; - - } - - public bool GenerateAstCfgE2E { get; set; } - public bool GenerateCfgDagE2E { get; set; } + public bool GenerateBeforeAstCfgProg { get; set; } + public bool GenerateUnoptimizedCfgProg { get; set; } + public bool GenerateBeforeCfgDagProg { get; set; } + public bool GenerateBeforePassifProg { get; set; } + public bool GeneratePassifiedProg { get; set; } + + public bool GenerateAstCfgE2E { get; set; } + public bool GenerateCfgDagE2E { get; set; } public bool GeneratePassifE2E { get; set; } public bool GenerateVcE2E { get; } - public bool GenerateAstCfgProof { get; set; } - public bool GenerateCfgDagProof { get; set; } + public bool GenerateAstCfgProof { get; set; } + public bool GenerateCfgDagProof { get; set; } public bool GeneratePassifProof { get; set; } public bool GenerateVcProof { get; } } diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 0365495bc..8312bdd61 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -80,8 +80,10 @@ public class ProofGenerationLayer //private static Block uniqueExitBlockOrigBeforeOptimizations; private static Block uniqueExitBlockOrig; - private static ProofGenConfig _proofGenConfig = new(false, false, false, false, - false, true, true, false); + private static ProofGenConfig _proofGenConfig = + new(false, false, false, false, true, + false, false, false, false, + true, false, false, false); private static IProgramAccessor globalDataProgAccess; @@ -148,6 +150,29 @@ private static bool AstContainsGotoOrBreak(AstToCfgProofGenInfo proofGenInfo) return false; } + private static bool checkForGotos(StmtList stmtList) + { + foreach (var bb in stmtList.BigBlocks) + { + if (bb.tc is GotoCmd) + { + return true; + } + + if (bb.ec is IfCmd ifcmd) + { + checkForGotos(ifcmd.thn); + checkForGotos(ifcmd.elseBlock); + } + else if (bb.ec is WhileCmd whilecmd) + { + checkForGotos(whilecmd.Body); + } + } + + return false; + } + public static void BeforeOptimizations(Implementation impl) { var config = new CFGReprConfigBuilder().SetIsAcyclic(false).SetBlockCopy(true).SetDesugarCalls(true) @@ -574,6 +599,13 @@ public static void VCGenerateAllProofs( _proofGenConfig.GenerateCfgDagE2E = _proofGenConfig.GeneratePassifProof && _proofGenConfig.GeneratePassifE2E && _proofGenConfig.GenerateCfgDagProof; _proofGenConfig.GenerateAstCfgE2E = _proofGenConfig.GenerateCfgDagProof && _proofGenConfig.GenerateCfgDagE2E && _proofGenConfig.GenerateAstCfgProof; + _proofGenConfig.GenerateBeforeAstCfgProg = _proofGenConfig.GenerateAstCfgProof; + _proofGenConfig.GenerateUnoptimizedCfgProg = proofGenInfo.GetOptimizationsFlag() && _proofGenConfig.GenerateAstCfgProof; + _proofGenConfig.GenerateBeforeCfgDagProg = (proofGenInfo.GetOptimizationsFlag() && _proofGenConfig.GenerateCfgDagProof) || + (!proofGenInfo.GetOptimizationsFlag() && (_proofGenConfig.GenerateAstCfgProof || _proofGenConfig.GenerateCfgDagProof)); + _proofGenConfig.GenerateBeforePassifProg = _proofGenConfig.GenerateCfgDagProof || _proofGenConfig.GeneratePassifProof; + _proofGenConfig.GeneratePassifiedProg = _proofGenConfig.GeneratePassifProof || _proofGenConfig.GenerateVcProof; + IList unoptimizedCFGBlocks = proofGenInfo.GetUnpotimizedBlocks(); var newToOldInternal = new Dictionary(); unoptimizedCFGBlocks.ZipDo(afterPassificationImpl.Blocks, (bNew, bOld) => newToOldInternal.Add(bNew, bOld)); @@ -642,8 +674,11 @@ public static void VCGenerateAllProofs( IProgramAccessor beforeAstToCfgProgAccess = null; IProgramAccessor unoptimizedCfgProgAccess = null; - - if (_proofGenConfig.GenerateAstCfgProof) + IProgramAccessor beforeCfgToDagProgAccess = null; + IProgramAccessor beforePassiveProgAccess = null; + IProgramAccessor passiveProgAccess = null; + + if (_proofGenConfig.GenerateBeforeAstCfgProg) { #region before ast to cfg program @@ -656,12 +691,12 @@ public static void VCGenerateAllProofs( var specsConfig_ast = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; - var beforeAstToCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, - false, - false, + var beforeAstToCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, false, - true, - specsConfig_ast, + false, + false, + true, + specsConfig_ast, true); beforeAstToCfgProgAccess = new IsaProgramGeneratorForAst().GetIsaProgram( @@ -686,9 +721,10 @@ public static void VCGenerateAllProofs( theories.Add(beforeAstToCfgProgTheory); #endregion - - if (proofGenInfo.GetOptimizationsFlag()) - { + } + + if (_proofGenConfig.GenerateUnoptimizedCfgProg) + { #region unoptimized cfg program var unoptimizedCfgTheoryName = @@ -727,21 +763,22 @@ public static void VCGenerateAllProofs( theories.Add(unoptimizedCfgProgTheory); #endregion - } } - #region before cfg to dag program - var beforeCfgToDagTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_cfg_to_dag_prog"); - //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) - var specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; - var beforeCfgToDagConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, - false, - false, - false, - true, - specsConfig, - true); - var beforeCfgToDagProgAccess = new IsaProgramGenerator().GetIsaProgram( + if (_proofGenConfig.GenerateBeforeCfgDagProg) + { + #region before cfg to dag program + var beforeCfgToDagTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_cfg_to_dag_prog"); + //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) + var specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; + var beforeCfgToDagConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, + false, + false, + false, + true, + specsConfig, + true); + beforeCfgToDagProgAccess = new IsaProgramGenerator().GetIsaProgram( beforeCfgToDagTheoryName, afterPassificationImpl.Name, mainData, beforeCfgToDagConfig, varTranslationFactory2, @@ -749,13 +786,15 @@ public static void VCGenerateAllProofs( uniqueNamer, out var programDeclsBeforeCfgToDag, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); - procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name, beforeCfgToDagProgAccess); + procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name, beforeCfgToDagProgAccess); - var beforeCfgToDagProgTheory = new Theory(beforeCfgToDagTheoryName, + var beforeCfgToDagProgTheory = new Theory(beforeCfgToDagTheoryName, new List {"Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", "\"../"+globalDataProgAccess.TheoryName()+"\""}, programDeclsBeforeCfgToDag); - theories.Add(beforeCfgToDagProgTheory); - #endregion + theories.Add(beforeCfgToDagProgTheory); + #endregion + } + if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) { @@ -763,14 +802,20 @@ public static void VCGenerateAllProofs( return; } - #region before passive program - - IProgramAccessor parentProgramAccessorForPassification = _proofGenConfig.GenerateAstCfgProof ? beforeAstToCfgProgAccess : beforeCfgToDagProgAccess; - - var beforePassiveProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_passive_prog"); - var beforePassiveConfig = - new IsaProgramGeneratorConfig(parentProgramAccessorForPassification, false, false, false, false, SpecsConfig.None, false); - var beforePassiveProgAccess = new IsaProgramGenerator().GetIsaProgram(beforePassiveProgTheoryName, + if (_proofGenConfig.GenerateBeforePassifProg) + { + #region before passive program + + IProgramAccessor parentProgramAccessorForPassification = _proofGenConfig.GenerateAstCfgProof + ? beforeAstToCfgProgAccess + : beforeCfgToDagProgAccess; + + var beforePassiveProgTheoryName = + uniqueNamer.GetName(afterPassificationImpl.Name + "_before_passive_prog"); + var beforePassiveConfig = + new IsaProgramGeneratorConfig(parentProgramAccessorForPassification, false, false, false, false, + SpecsConfig.None, false); + beforePassiveProgAccess = new IsaProgramGenerator().GetIsaProgram(beforePassiveProgTheoryName, afterPassificationImpl.Name, mainData, beforePassiveConfig, varTranslationFactory2, beforePassificationCfg, @@ -778,48 +823,54 @@ public static void VCGenerateAllProofs( out var programDeclsBeforePassive, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); - #endregion - - #region after passification program - - //use global version map for translation - var fixedVarTranslation = new SimpleFixedVarTranslation(globalVersionMap); - var fixedTyVarTranslation = new DeBruijnFixedTVarTranslation(finalProgData); - varTranslationFactory = - new DeBruijnVarFactory(fixedVarTranslation, fixedTyVarTranslation, boogieGlobalData); - - var finalProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_passive_prog"); - var passiveProgConfig = - new IsaProgramGeneratorConfig(beforePassiveProgAccess, false, false, false, true, SpecsConfig.None, false); - var passiveProgAccess = new IsaProgramGenerator().GetIsaProgram(finalProgTheoryName, - afterPassificationImpl.Name, - finalProgData, passiveProgConfig, varTranslationFactory, - //we use the CFG before the peep-hole transformations, so that we can directly use the VC to program proof in the passification phase - afterPassificationCfg, - uniqueNamer, - out var programDecls, - !CommandLineOptions.Clo.GenerateIsaProgNoProofs); - - var theoryNameForParentImport = _proofGenConfig.GenerateAstCfgProof ? beforeAstToCfgProgAccess.TheoryName() : beforeCfgToDagProgAccess.TheoryName(); - - var afterPassificationProgTheory = - new Theory(finalProgTheoryName, - new List - {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, - programDecls); - theories.Add(afterPassificationProgTheory); - - #endregion - - #region before passive program (completion of theory construction) + #endregion + + var theoryNameForParentImport = _proofGenConfig.GenerateAstCfgProof + ? beforeAstToCfgProgAccess.TheoryName() + : beforeCfgToDagProgAccess.TheoryName(); + + if (_proofGenConfig.GeneratePassifiedProg) + { + #region after passification program + + //use global version map for translation + var fixedVarTranslation = new SimpleFixedVarTranslation(globalVersionMap); + var fixedTyVarTranslation = new DeBruijnFixedTVarTranslation(finalProgData); + varTranslationFactory = + new DeBruijnVarFactory(fixedVarTranslation, fixedTyVarTranslation, boogieGlobalData); + + var finalProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_passive_prog"); + var passiveProgConfig = + new IsaProgramGeneratorConfig(beforePassiveProgAccess, false, false, false, true, SpecsConfig.None, false); + passiveProgAccess = new IsaProgramGenerator().GetIsaProgram(finalProgTheoryName, + afterPassificationImpl.Name, + finalProgData, passiveProgConfig, varTranslationFactory, + //we use the CFG before the peep-hole transformations, so that we can directly use the VC to program proof in the passification phase + afterPassificationCfg, + uniqueNamer, + out var programDecls, + !CommandLineOptions.Clo.GenerateIsaProgNoProofs); - var beforePassificationProgTheory = new Theory(beforePassiveProgTheoryName, - new List {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, - programDeclsBeforePassive); - theories.Add(beforePassificationProgTheory); + var afterPassificationProgTheory = + new Theory(finalProgTheoryName, + new List + {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, + programDecls); + theories.Add(afterPassificationProgTheory); - #endregion + #endregion + } + #region before passive program (completion of theory construction) + + var beforePassificationProgTheory = new Theory(beforePassiveProgTheoryName, + new List {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, + programDeclsBeforePassive); + theories.Add(beforePassificationProgTheory); + + #endregion + } + var phasesTheories = new PhasesTheories(afterPassificationImpl.Name); Term vcAssm = null; LemmaDecl endToEndLemma = null; From 06180da5d417c548360ff883616f9f506066714d Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Thu, 8 Dec 2022 20:11:28 +0100 Subject: [PATCH 019/123] selective generation of phases done --- Source/Core/AbsyCmd.cs | 2 ++ Source/ProofGeneration/CfgToDag/CfgToDagManager.cs | 3 ++- Source/ProofGeneration/ProofGenerationLayer.cs | 9 ++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Source/Core/AbsyCmd.cs b/Source/Core/AbsyCmd.cs index da1745a2e..170b3b6c6 100644 --- a/Source/Core/AbsyCmd.cs +++ b/Source/Core/AbsyCmd.cs @@ -886,6 +886,8 @@ void CreateBlocks(StmtList stmtList, string runOffTheEndLabel, AstToCfgProofGenI if (loopDone == null) { loopDone = new BigBlock(Token.NoToken, null, new List(), null, null);; + + //Set new loopDone Big block as a successor to 'b' in the original AST b.successorBigBlock = loopDone; //Record loop done as a successor big block in the AST to 'b'. diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs index d56105cac..059d94351 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs @@ -26,6 +26,7 @@ public static Theory CfgToDagProof( IsaUniqueNamer uniqueNamer, bool generateEndToEndLemma, bool generatedAstToCfgProof, + bool generatePassificationProof, bool generateVcProof, Term vcAssm, CFGRepr beforeDagCfg, @@ -232,7 +233,7 @@ public static Theory CfgToDagProof( generatedAstToCfgProof ? beforeCfgProgAccess.TheoryName() : null, beforeDagProgAccess.TheoryName(), afterDagProgAccess.TheoryName(), - uniqueNamer.GetName(phasesTheories.TheoryName(PhasesTheories.Phase.Passification)), + generatePassificationProof ? uniqueNamer.GetName(phasesTheories.TheoryName(PhasesTheories.Phase.Passification)) : "", generateVcProof ? phasesTheories.TheoryName(PhasesTheories.Phase.Vc) : "" }, theoryOuterDecls diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 8312bdd61..31eb77876 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -83,7 +83,7 @@ public class ProofGenerationLayer private static ProofGenConfig _proofGenConfig = new(false, false, false, false, true, false, false, false, false, - true, false, false, false); + true, false, false, true); private static IProgramAccessor globalDataProgAccess; @@ -602,8 +602,10 @@ public static void VCGenerateAllProofs( _proofGenConfig.GenerateBeforeAstCfgProg = _proofGenConfig.GenerateAstCfgProof; _proofGenConfig.GenerateUnoptimizedCfgProg = proofGenInfo.GetOptimizationsFlag() && _proofGenConfig.GenerateAstCfgProof; _proofGenConfig.GenerateBeforeCfgDagProg = (proofGenInfo.GetOptimizationsFlag() && _proofGenConfig.GenerateCfgDagProof) || - (!proofGenInfo.GetOptimizationsFlag() && (_proofGenConfig.GenerateAstCfgProof || _proofGenConfig.GenerateCfgDagProof)); - _proofGenConfig.GenerateBeforePassifProg = _proofGenConfig.GenerateCfgDagProof || _proofGenConfig.GeneratePassifProof; + (!proofGenInfo.GetOptimizationsFlag() && (_proofGenConfig.GenerateAstCfgProof || _proofGenConfig.GenerateCfgDagProof)) || + _proofGenConfig.GeneratePassifProof || + _proofGenConfig.GenerateVcProof; + _proofGenConfig.GenerateBeforePassifProg = _proofGenConfig.GenerateCfgDagProof || _proofGenConfig.GeneratePassifProof || _proofGenConfig.GenerateVcProof; _proofGenConfig.GeneratePassifiedProg = _proofGenConfig.GeneratePassifProof || _proofGenConfig.GenerateVcProof; IList unoptimizedCFGBlocks = proofGenInfo.GetUnpotimizedBlocks(); @@ -987,6 +989,7 @@ out var endToEndLemmaPrelim uniqueNamer, _proofGenConfig.GenerateCfgDagE2E, _proofGenConfig.GenerateAstCfgProof, + _proofGenConfig.GeneratePassifProof, _proofGenConfig.GenerateVcProof, vcAssm, beforeDagCfg, From a8c60ae36c0d86b01310f7390ba87f8b37fadd87 Mon Sep 17 00:00:00 2001 From: ahubanov-eth Date: Thu, 8 Dec 2022 20:44:34 +0100 Subject: [PATCH 020/123] selective phase gen now done --- .../ProgramToVCProof/VcPhaseManager.cs | 3 +- .../ProofGeneration/ProofGenerationLayer.cs | 48 ++++++++----------- 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/Source/ProofGeneration/ProgramToVCProof/VcPhaseManager.cs b/Source/ProofGeneration/ProgramToVCProof/VcPhaseManager.cs index 8519c418e..6ba41bd43 100644 --- a/Source/ProofGeneration/ProgramToVCProof/VcPhaseManager.cs +++ b/Source/ProofGeneration/ProgramToVCProof/VcPhaseManager.cs @@ -149,7 +149,8 @@ public static Theory ProgramToVcProof( new List { "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.VCHints", "Boogie_Lang.VCPhaseML", - passiveProgAccess.TheoryName(), beforePassiveProgAccess.TheoryName() + passiveProgAccess.TheoryName(), + beforePassiveProgAccess != null ? beforePassiveProgAccess.TheoryName() : "" }, passiveOuterDecls); } diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 31eb77876..41d882bb0 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -81,9 +81,9 @@ public class ProofGenerationLayer private static Block uniqueExitBlockOrig; private static ProofGenConfig _proofGenConfig = - new(false, false, false, false, true, + new(false, false, false, false, false, false, false, false, false, - true, false, false, true); + false, false, true, false); private static IProgramAccessor globalDataProgAccess; @@ -602,10 +602,8 @@ public static void VCGenerateAllProofs( _proofGenConfig.GenerateBeforeAstCfgProg = _proofGenConfig.GenerateAstCfgProof; _proofGenConfig.GenerateUnoptimizedCfgProg = proofGenInfo.GetOptimizationsFlag() && _proofGenConfig.GenerateAstCfgProof; _proofGenConfig.GenerateBeforeCfgDagProg = (proofGenInfo.GetOptimizationsFlag() && _proofGenConfig.GenerateCfgDagProof) || - (!proofGenInfo.GetOptimizationsFlag() && (_proofGenConfig.GenerateAstCfgProof || _proofGenConfig.GenerateCfgDagProof)) || - _proofGenConfig.GeneratePassifProof || - _proofGenConfig.GenerateVcProof; - _proofGenConfig.GenerateBeforePassifProg = _proofGenConfig.GenerateCfgDagProof || _proofGenConfig.GeneratePassifProof || _proofGenConfig.GenerateVcProof; + (!proofGenInfo.GetOptimizationsFlag() && (_proofGenConfig.GenerateAstCfgProof || _proofGenConfig.GenerateCfgDagProof)); + _proofGenConfig.GenerateBeforePassifProg = _proofGenConfig.GenerateCfgDagProof || _proofGenConfig.GeneratePassifProof; _proofGenConfig.GeneratePassifiedProg = _proofGenConfig.GeneratePassifProof || _proofGenConfig.GenerateVcProof; IList unoptimizedCFGBlocks = proofGenInfo.GetUnpotimizedBlocks(); @@ -803,6 +801,10 @@ public static void VCGenerateAllProofs( StoreResult(uniqueNamer.GetName("program_" + afterPassificationImpl.Proc.Name), theories); return; } + + var theoryNameForParentImport = _proofGenConfig.GenerateAstCfgProof + ? beforeAstToCfgProgAccess.TheoryName() + : _proofGenConfig.GenerateBeforeCfgDagProg ? beforeCfgToDagProgAccess.TheoryName() : ""; if (_proofGenConfig.GenerateBeforePassifProg) { @@ -815,7 +817,7 @@ public static void VCGenerateAllProofs( var beforePassiveProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_passive_prog"); var beforePassiveConfig = - new IsaProgramGeneratorConfig(parentProgramAccessorForPassification, false, false, false, false, + new IsaProgramGeneratorConfig(parentProgramAccessorForPassification, parentProgramAccessorForPassification == null, parentProgramAccessorForPassification == null, parentProgramAccessorForPassification == null, parentProgramAccessorForPassification == null, SpecsConfig.None, false); beforePassiveProgAccess = new IsaProgramGenerator().GetIsaProgram(beforePassiveProgTheoryName, afterPassificationImpl.Name, @@ -825,15 +827,17 @@ public static void VCGenerateAllProofs( out var programDeclsBeforePassive, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); - #endregion - - var theoryNameForParentImport = _proofGenConfig.GenerateAstCfgProof - ? beforeAstToCfgProgAccess.TheoryName() - : beforeCfgToDagProgAccess.TheoryName(); + var beforePassificationProgTheory = new Theory(beforePassiveProgTheoryName, + new List {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, + programDeclsBeforePassive); + theories.Add(beforePassificationProgTheory); - if (_proofGenConfig.GeneratePassifiedProg) - { - #region after passification program + #endregion + } + + if (_proofGenConfig.GeneratePassifiedProg) + { + #region after passification program //use global version map for translation var fixedVarTranslation = new SimpleFixedVarTranslation(globalVersionMap); @@ -843,7 +847,7 @@ public static void VCGenerateAllProofs( var finalProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_passive_prog"); var passiveProgConfig = - new IsaProgramGeneratorConfig(beforePassiveProgAccess, false, false, false, true, SpecsConfig.None, false); + new IsaProgramGeneratorConfig(beforePassiveProgAccess, beforePassiveProgAccess==null, beforePassiveProgAccess==null, beforePassiveProgAccess==null, true, SpecsConfig.None, false); passiveProgAccess = new IsaProgramGenerator().GetIsaProgram(finalProgTheoryName, afterPassificationImpl.Name, finalProgData, passiveProgConfig, varTranslationFactory, @@ -856,20 +860,10 @@ public static void VCGenerateAllProofs( var afterPassificationProgTheory = new Theory(finalProgTheoryName, new List - {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, + {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport, beforePassiveProgAccess != null ? beforePassiveProgAccess.TheoryName() : ""}, programDecls); theories.Add(afterPassificationProgTheory); - #endregion - } - - #region before passive program (completion of theory construction) - - var beforePassificationProgTheory = new Theory(beforePassiveProgTheoryName, - new List {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, - programDeclsBeforePassive); - theories.Add(beforePassificationProgTheory); - #endregion } From 489c5c571e394c9dca363a6f3621c5de5aa4bc3f Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Sun, 15 Jan 2023 17:51:26 +0100 Subject: [PATCH 021/123] generate all proofs (ProofGenConfig initialization adjustments) --- Source/ProofGeneration/ProofGenerationLayer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 41d882bb0..d0076ed20 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -81,9 +81,9 @@ public class ProofGenerationLayer private static Block uniqueExitBlockOrig; private static ProofGenConfig _proofGenConfig = - new(false, false, false, false, false, - false, false, false, false, - false, false, true, false); + new(true, true, true, true, true, + true, true, true, true, + true, true, true, true); private static IProgramAccessor globalDataProgAccess; From 93df447e9077ca7ba465cf0c877f44c1b4565800 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Sun, 15 Jan 2023 18:10:09 +0100 Subject: [PATCH 022/123] set foundational boogie commit to ast version --- foundational_boogie | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundational_boogie b/foundational_boogie index aab277ddf..58d1183fb 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit aab277ddf17fdace6fb562badffc39614daabee4 +Subproject commit 58d1183fbda06a6fea330b0b11717abd0bfdaa9f From a2c98ee62320c47d559e262ff64b5d777602f20c Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Sun, 15 Jan 2023 19:54:55 +0100 Subject: [PATCH 023/123] fix bug: initialize phaseTheories directly with unique namer --- Source/ProofGeneration/CfgToDag/CfgToDagManager.cs | 5 ++--- Source/ProofGeneration/ProofGenerationLayer.cs | 7 +++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs index 059d94351..cd4847aca 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs @@ -23,7 +23,6 @@ public class CfgToDagManager */ public static Theory CfgToDagProof( PhasesTheories phasesTheories, - IsaUniqueNamer uniqueNamer, bool generateEndToEndLemma, bool generatedAstToCfgProof, bool generatePassificationProof, @@ -226,14 +225,14 @@ public static Theory CfgToDagProof( } return new Theory( - uniqueNamer.GetName(phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag)), + phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag), new List { "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.BackedgeElim", "Boogie_Lang.TypingML", generatedAstToCfgProof ? beforeCfgProgAccess.TheoryName() : null, beforeDagProgAccess.TheoryName(), afterDagProgAccess.TheoryName(), - generatePassificationProof ? uniqueNamer.GetName(phasesTheories.TheoryName(PhasesTheories.Phase.Passification)) : "", + generatePassificationProof ? phasesTheories.TheoryName(PhasesTheories.Phase.Passification) : "", generateVcProof ? phasesTheories.TheoryName(PhasesTheories.Phase.Vc) : "" }, theoryOuterDecls diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index d0076ed20..de1b2afa8 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -867,7 +867,7 @@ public static void VCGenerateAllProofs( #endregion } - var phasesTheories = new PhasesTheories(afterPassificationImpl.Name); + var phasesTheories = new PhasesTheories(uniqueNamer.GetName(afterPassificationImpl.Name)); Term vcAssm = null; LemmaDecl endToEndLemma = null; @@ -948,7 +948,7 @@ out var endToEndLemmaPrelim : beforeAstToCfgProgAccess; var passificationProofTheory = PassificationManager.PassificationProof( - uniqueNamer.GetName(phasesTheories.TheoryName(PhasesTheories.Phase.Passification)), + phasesTheories.TheoryName(PhasesTheories.Phase.Passification), _proofGenConfig.GenerateVcProof ? phasesTheories.TheoryName(PhasesTheories.Phase.Vc) : "", _proofGenConfig.GeneratePassifE2E, endToEndLemma, @@ -980,7 +980,6 @@ out var endToEndLemmaPrelim var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( phasesTheories, - uniqueNamer, _proofGenConfig.GenerateCfgDagE2E, _proofGenConfig.GenerateAstCfgProof, _proofGenConfig.GeneratePassifProof, @@ -1062,7 +1061,7 @@ out var endToEndLemmaPrelim } var astToCfgProofTheory = AstToCfgManager.AstToCfgProof( - uniqueNamer.GetName(phasesTheories.TheoryName(PhasesTheories.Phase.AstToCfg)), + phasesTheories.TheoryName(PhasesTheories.Phase.AstToCfg), phasesTheories, _proofGenConfig.GenerateAstCfgE2E, _proofGenConfig, From 6c42d23f905ddfdb9a3769eb7fb526fe101ec3ce Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 16 Jan 2023 12:29:50 +0100 Subject: [PATCH 024/123] add conditional expression example --- .../test2/IfThenElse1.bpl | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 ProofGenerationBenchmarks/boogie_testsuite_benchmarks/test2/IfThenElse1.bpl diff --git a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/test2/IfThenElse1.bpl b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/test2/IfThenElse1.bpl new file mode 100644 index 000000000..409dd9583 --- /dev/null +++ b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/test2/IfThenElse1.bpl @@ -0,0 +1,20 @@ +type t1; + +procedure ok() +{ + var b:bool, x:int, y:int; + + assert x == if b then x else x; + assert x == if true then x else y; +} + +procedure ok2() +{ + var x:int, y:int; + var a:t1, b:t1, c:t1; + + c := if x > y then a else b; + assert c == a || c == b; + assume x > y; + assert c == a; +} \ No newline at end of file From ab3012f08b029a00575b2d536444e700221eca69 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 16 Jan 2023 12:32:21 +0100 Subject: [PATCH 025/123] add support for conditional expressions --- .../BoogieIsaInterface/ApplicableIsaVisitor.cs | 4 +++- .../ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs | 7 +++++++ Source/ProofGeneration/VCProofGen/VCExprOpIsaVisitor.cs | 8 +++++++- foundational_boogie | 2 +- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Source/ProofGeneration/BoogieIsaInterface/ApplicableIsaVisitor.cs b/Source/ProofGeneration/BoogieIsaInterface/ApplicableIsaVisitor.cs index 5aa6ac770..53aa8c342 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/ApplicableIsaVisitor.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/ApplicableIsaVisitor.cs @@ -75,7 +75,9 @@ public Term Visit(ArithmeticCoercion arithCoercion) public Term Visit(IfThenElse ifThenElse) { - throw new NotImplementedException(); + if (_args.Count != 3) throw new ExprArgException(); + + return IsaBoogieTerm.CondExp(_args[0], _args[1], _args[2]); } } diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs index 8547da60b..40c2bae7e 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs @@ -26,6 +26,8 @@ public static class IsaBoogieTerm private static readonly TermIdent varId = IsaCommonTerms.TermIdentFromName("Var"); private static readonly TermIdent bvarId = IsaCommonTerms.TermIdentFromName("BVar"); private static readonly TermIdent oldVarId = IsaCommonTerms.TermIdentFromName("Old"); + + private static readonly TermIdent condExpId = IsaCommonTerms.TermIdentFromName("CondExp"); private static readonly TermIdent lookupVarId = IsaCommonTerms.TermIdentFromName("lookup_var"); private static readonly TermIdent lookupVarDeclId = IsaCommonTerms.TermIdentFromName("lookup_var_decl"); @@ -112,6 +114,11 @@ public static Term Old(Term body) return new TermApp(oldVarId, body); } + public static Term CondExp(Term cond, Term thn, Term els) + { + return new TermApp(condExpId, cond, thn, els); + } + public static Term Literal(LiteralExpr node) { if (node.Type.IsBool) diff --git a/Source/ProofGeneration/VCProofGen/VCExprOpIsaVisitor.cs b/Source/ProofGeneration/VCProofGen/VCExprOpIsaVisitor.cs index 6e53b0fce..3267a1542 100644 --- a/Source/ProofGeneration/VCProofGen/VCExprOpIsaVisitor.cs +++ b/Source/ProofGeneration/VCProofGen/VCExprOpIsaVisitor.cs @@ -159,7 +159,13 @@ public Term VisitGtOp(VCExprNAry node, List arg) public Term VisitIfThenElseOp(VCExprNAry node, List arg) { - throw new NotImplementedException(); + if (arg.Count != 3) + { + throw new ProofGenUnexpectedStateException("VisitIfThenElseOp not invoked with three arguments"); + } + + //TODO: potentially put if-then-else expressions into the InnerAST directly + return new TermApp(IsaCommonTerms.TermIdentFromName("ite_vc"), arg[0], arg[1], arg[2]); } public Term VisitImpliesOp(VCExprNAry node, List arg) diff --git a/foundational_boogie b/foundational_boogie index aab277ddf..31d709925 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit aab277ddf17fdace6fb562badffc39614daabee4 +Subproject commit 31d709925b0eddacf88e34712c0ebfe1fb526b38 From ea6fdcae57feee47b264364c33ec052ffeccf489 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 16 Jan 2023 13:55:00 +0100 Subject: [PATCH 026/123] proof output directory should be as specified in the options in particular need not be an Isabelle identifier --- Source/ProofGeneration/ProofGenerationLayer.cs | 6 +++--- Source/ProofGeneration/ProofGenerationOutput.cs | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index d0076ed20..8e9040d60 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -81,9 +81,9 @@ public class ProofGenerationLayer private static Block uniqueExitBlockOrig; private static ProofGenConfig _proofGenConfig = - new(true, true, true, true, true, - true, true, true, true, - true, true, true, true); + new(true, false, false, false, false, + false, false, false, false, + false, false, false, false); private static IProgramAccessor globalDataProgAccess; diff --git a/Source/ProofGeneration/ProofGenerationOutput.cs b/Source/ProofGeneration/ProofGenerationOutput.cs index 10b4cf73b..141116b24 100644 --- a/Source/ProofGeneration/ProofGenerationOutput.cs +++ b/Source/ProofGeneration/ProofGenerationOutput.cs @@ -16,9 +16,6 @@ public static class ProofGenerationOutput public static void CreateMainDirectory(string fileName, bool onlyUseFileName) { - IsaUniqueNamer namer = new IsaUniqueNamer(); - string filename_altered = namer.GetName(fileName); - if (CommandLineOptions.Clo.DontStoreProofGenFiles) return; @@ -26,9 +23,9 @@ public static void CreateMainDirectory(string fileName, bool onlyUseFileName) throw new ProofGenUnexpectedStateException("main directory already set"); if (!onlyUseFileName) - _mainDir = FreeDirName(Path.GetFileNameWithoutExtension(filename_altered) + "_proofs", false); + _mainDir = FreeDirName(Path.GetFileNameWithoutExtension(fileName) + "_proofs", false); else - _mainDir = filename_altered; + _mainDir = fileName; Directory.CreateDirectory(_mainDir); } @@ -123,7 +120,10 @@ public static void FinishStoring() throw new ProofGenUnexpectedStateException("main directory not yet set"); using var sw = new StreamWriter(Path.Combine(_mainDir, "ROOT")); - sw.WriteLine("session " + SessionName(Path.GetFileName(_mainDir)) + " = " + "Boogie_Lang + "); + + var sessionName = new IsaUniqueNamer().GetName(Path.GetFileName(_mainDir)); + + sw.WriteLine("session " + SessionName(sessionName) + " = " + "Boogie_Lang + "); var subDirs = Directory.EnumerateDirectories(_mainDir).ToList(); if (subDirs.Any()) From 480c0cd323abdcdf626f83cc0463d93cddb04aac Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Thu, 19 Jan 2023 16:34:58 +0100 Subject: [PATCH 027/123] generalize "GenerateIsaProgNoProofs" option to allow one to optionally produce membership lemmas even if no phase correctness proofs are generated --- Source/Core/CommandLineOptions.cs | 29 +++++++--- .../ProofGeneration/ProofGenerationLayer.cs | 53 +++++++++---------- 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/Source/Core/CommandLineOptions.cs b/Source/Core/CommandLineOptions.cs index 4ee03d1da..8c37abb4f 100644 --- a/Source/Core/CommandLineOptions.cs +++ b/Source/Core/CommandLineOptions.cs @@ -1044,7 +1044,26 @@ public enum TypeEncoding public string ProofOutputDir = null; public bool OnlyCheckProofGenSupport = false; public bool DontStoreProofGenFiles = false; - public bool GenerateIsaProgNoProofs = false; + + /* + * 0: disabled -> proofs are generated + * 1: partially enabled -> only AST program is generated but with membership lemmas + * 2: enabled -> only AST program is generated + */ + public int GenerateIsaProgNoProofs = 0; + + public bool OnlyGenerateInitialProgramIsa() + { + return GenerateIsaProgNoProofs != 0; + } + + public bool GenerateMembershipLemmas() + { + return GenerateIsaProgNoProofs <= 1; + } + + + public bool DesugarMaps = false; #endregion @@ -1821,13 +1840,9 @@ protected override bool ParseOption(string name, CommandLineOptionEngine.Command return true; case "isaProgNoProofs": - if (ps.ConfirmArgumentCount(0)) - { - GenerateIsaProgNoProofs = true; - } - + ps.GetNumericArgument(ref GenerateIsaProgNoProofs, 2); return true; - + case "desugarMaps": if (ps.ConfirmArgumentCount(0)) { diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 8e9040d60..ec30f102f 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -125,7 +125,7 @@ public static void Program(Program p) null, uniqueNamer, out var declsGlobalData, - !CommandLineOptions.Clo.GenerateIsaProgNoProofs, + CommandLineOptions.Clo.GenerateMembershipLemmas(), true ); @@ -237,7 +237,7 @@ public static void CreateUnifiedExitBlock(Block generatedExitBlock) /// public static void BeforePassification(Implementation impl) { - if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) + if (CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) return; var config = new CFGReprConfigBuilder().SetIsAcyclic(true).SetBlockCopy(true).SetDesugarCalls(true) @@ -309,7 +309,7 @@ public static void RecordInitialVariableMapping(Block b, IDictionary(variableToExpr)); @@ -339,7 +339,7 @@ private static bool TypeCheckBeforeVcMaybeRewritesCmd(Cmd cmd) public static void AfterPassificationCheckGlobalMap(Implementation impl) { afterPassificationImpl = impl; - if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) + if (CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) return; finalProgData = MethodDataFromImpl(impl, boogieGlobalData); @@ -406,7 +406,7 @@ private static IDictionary DictionaryComposition(IDictionary public static void AfterUnreachablePruning(Implementation impl) { - if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) + if (CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) return; var config = new CFGReprConfigBuilder().SetIsAcyclic(true).SetBlockCopy(true).SetDesugarCalls(false) @@ -435,7 +435,7 @@ public static void NextVcHintForBlock( CommandLineOptions.SubsumptionOption subsumptionOption ) { - if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) + if (CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) return; vcHintManager.NextHintForBlock(cmd, block, exprVC, postVC, resultVC, subsumptionOption); } @@ -456,7 +456,7 @@ public static void VcIsTrivial() /// public static void NextPassificationHint(Block block, Cmd cmd, Variable origVar, Expr passiveExpr) { - if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) + if (CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) return; passificationHintManager.AddHint(block, cmd, origVar, passiveExpr); } @@ -467,7 +467,7 @@ public static void NextPassificationHint(Block block, Cmd cmd, Variable origVar, /// public static void LoopHeadHint(Block block, IEnumerable varsToHavoc, IEnumerable invariants) { - if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) + if (CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) return; cfgToDagHintManager.AddHint(block, new LoopHeadHint(varsToHavoc, invariants)); } @@ -478,14 +478,14 @@ public static void LoopHeadHint(Block block, IEnumerable varsToHavoc, /// public static void NewBackedgeBlock(Block oldBackedgeBlock, Block newBackedgeBlock, Block loopHead) { - if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) + if (CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) return; cfgToDagHintManager.AddNewBackedgeBlock(newBackedgeBlock, loopHead); } public static void SetTypeEraserFactory(TypePremiseEraserFactory factory) { - if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) + if (CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) return; typePremiseEraserFactory = factory; var uniqueNamer = new IsaUniqueNamer(); @@ -663,7 +663,7 @@ public static void VCGenerateAllProofs( /* Since in the proofs calls are desugared, there can be more variables in "beforePassiveData". If only the program should be generated, then these variables should be ignored. */ - var mainData = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? beforeDagData : beforePassiveData; + var mainData = CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa() ? beforeDagData : beforePassiveData; var fixedVarTranslation2 = new DeBruijnFixedVarTranslation(mainData); var fixedTyVarTranslation2 = new DeBruijnFixedTVarTranslation(mainData); @@ -678,7 +678,7 @@ public static void VCGenerateAllProofs( IProgramAccessor beforePassiveProgAccess = null; IProgramAccessor passiveProgAccess = null; - if (_proofGenConfig.GenerateBeforeAstCfgProg) + if (_proofGenConfig.GenerateBeforeAstCfgProg || CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) { #region before ast to cfg program @@ -688,7 +688,7 @@ public static void VCGenerateAllProofs( var beforeAstToCfgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_ast_to_cfg_prog"); //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) - var specsConfig_ast = CommandLineOptions.Clo.GenerateIsaProgNoProofs + var specsConfig_ast = CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa() ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; var beforeAstToCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, @@ -708,7 +708,7 @@ public static void VCGenerateAllProofs( proofGenInfo, uniqueNamer, out var programDeclsBeforeAstToCfg, - !CommandLineOptions.Clo.GenerateIsaProgNoProofs); + CommandLineOptions.Clo.GenerateMembershipLemmas()); procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "ast", beforeAstToCfgProgAccess); var beforeAstToCfgProgTheory = new Theory(beforeAstToCfgTheoryName, @@ -719,6 +719,12 @@ public static void VCGenerateAllProofs( }, programDeclsBeforeAstToCfg); theories.Add(beforeAstToCfgProgTheory); + + if(CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) + { + StoreResult(uniqueNamer.GetName(afterPassificationImpl.Proc.Name), theories); + return; + } #endregion } @@ -730,7 +736,7 @@ public static void VCGenerateAllProofs( var unoptimizedCfgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_unoptimized_cfg_prog"); //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) - var _specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs + var _specsConfig = CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa() ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; var unoptimizedCfgConfig = @@ -749,7 +755,7 @@ public static void VCGenerateAllProofs( beforeOptimizationsCFG, uniqueNamer, out var programDeclsUnoptimizedCfg, - !CommandLineOptions.Clo.GenerateIsaProgNoProofs); + CommandLineOptions.Clo.GenerateMembershipLemmas()); procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "unoptimized", unoptimizedCfgProgAccess); @@ -770,7 +776,7 @@ public static void VCGenerateAllProofs( #region before cfg to dag program var beforeCfgToDagTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_cfg_to_dag_prog"); //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) - var specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; + var specsConfig = CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa() ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; var beforeCfgToDagConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, false, false, @@ -785,7 +791,7 @@ public static void VCGenerateAllProofs( beforeDagCfg, uniqueNamer, out var programDeclsBeforeCfgToDag, - !CommandLineOptions.Clo.GenerateIsaProgNoProofs); + CommandLineOptions.Clo.GenerateMembershipLemmas()); procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name, beforeCfgToDagProgAccess); var beforeCfgToDagProgTheory = new Theory(beforeCfgToDagTheoryName, @@ -795,13 +801,6 @@ public static void VCGenerateAllProofs( #endregion } - - if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) - { - StoreResult(uniqueNamer.GetName("program_" + afterPassificationImpl.Proc.Name), theories); - return; - } - var theoryNameForParentImport = _proofGenConfig.GenerateAstCfgProof ? beforeAstToCfgProgAccess.TheoryName() : _proofGenConfig.GenerateBeforeCfgDagProg ? beforeCfgToDagProgAccess.TheoryName() : ""; @@ -825,7 +824,7 @@ public static void VCGenerateAllProofs( beforePassificationCfg, uniqueNamer, out var programDeclsBeforePassive, - !CommandLineOptions.Clo.GenerateIsaProgNoProofs); + CommandLineOptions.Clo.GenerateMembershipLemmas()); var beforePassificationProgTheory = new Theory(beforePassiveProgTheoryName, new List {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, @@ -855,7 +854,7 @@ public static void VCGenerateAllProofs( afterPassificationCfg, uniqueNamer, out var programDecls, - !CommandLineOptions.Clo.GenerateIsaProgNoProofs); + CommandLineOptions.Clo.GenerateMembershipLemmas()); var afterPassificationProgTheory = new Theory(finalProgTheoryName, From 39c64291de19598ad701e5ef43405c5877546d33 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Fri, 20 Jan 2023 09:56:28 +0100 Subject: [PATCH 028/123] id based lemma naming option --- Source/Core/CommandLineOptions.cs | 13 ++++ .../MembershipLemmaManager.cs | 63 ++++++++++++++----- 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/Source/Core/CommandLineOptions.cs b/Source/Core/CommandLineOptions.cs index 8c37abb4f..2a27d7125 100644 --- a/Source/Core/CommandLineOptions.cs +++ b/Source/Core/CommandLineOptions.cs @@ -1045,6 +1045,11 @@ public enum TypeEncoding public bool OnlyCheckProofGenSupport = false; public bool DontStoreProofGenFiles = false; + /* If use id-based lemma naming, then whenever lemmas are specific to an entity that is represented using an id (i.e., a natural number), + then the lemma name is uniquely determined by that id. For example, if variables are represented using natural numbers, + then the membership lemmas for those variables are uniquely determined by the corresponding natural number. */ + public bool UseIdBasedLemmaNaming = false; + /* * 0: disabled -> proofs are generated * 1: partially enabled -> only AST program is generated but with membership lemmas @@ -1839,6 +1844,14 @@ protected override bool ParseOption(string name, CommandLineOptionEngine.Command return true; + case "useIdBasedLemmaNaming": + if (ps.ConfirmArgumentCount(0)) + { + UseIdBasedLemmaNaming = true; + } + + return true; + case "isaProgNoProofs": ps.GetNumericArgument(ref GenerateIsaProgNoProofs, 2); return true; diff --git a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs index da68d4c1e..f967486eb 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs @@ -48,12 +48,12 @@ public class MembershipLemmaManager : IProgramAccessor private readonly string localsMinName = "locals_min"; private readonly string localsWfName = "locals_wf"; private readonly IDictionary lookupVarTyLemmas = new Dictionary(); - private readonly IsaUniqueNamer lookupVarTyNamer = new IsaUniqueNamer(); + private readonly IsaUniqueNamer lookupVarTyNamer = new(); private readonly IDictionary membershipLemmas = new Dictionary(); - private readonly IsaUniqueNamer membershipNamer = new IsaUniqueNamer(); + private readonly IsaUniqueNamer membershipNamer = new(); private readonly string parameters; private readonly string[] paramsAndLocalsDefs; @@ -72,6 +72,12 @@ private readonly IDictionary //indicates whether this instance or any of its ancestors contains local method information (i.e., parameters, etc...) private readonly bool containsLocalInformation = true; + /* There are two membership lemmas for each constant. So we need two different prefixes for the corresponding names. + The following prefix is for the constant membership lemma that is declared first and used by the second + membership lemma. + */ + private readonly string separateConstantMembershipLemmaPrefix = "mconst"; + /// /// Initializes a new instance of the class. /// Generated instance only has information about global data. @@ -443,6 +449,18 @@ public void AddVariableMembershipLemmas(IEnumerable variables, VarKind } } + private string MembershipLemmaPrefix(NamedDeclaration d) + { + if (d is Function) + { + return "mfun"; + } + else + { + return "mvar"; + } + } + private void AddNamedDeclsMembershipLemmas( IEnumerable decls, Term sourceList, @@ -453,7 +471,8 @@ private void AddNamedDeclsMembershipLemmas( { foreach (var d in decls) { - Term lhs = new TermApp(IsaCommonTerms.TermIdentFromName("map_of"), new List {sourceList, nameOf(d)}); + var nameOfDecl = nameOf(d); + Term lhs = new TermApp(IsaCommonTerms.TermIdentFromName("map_of"), new List {sourceList, nameOfDecl}); var rhs = IsaCommonTerms.SomeOption(declOf(d)); Term statement = TermBinary.Eq(lhs, rhs); @@ -463,12 +482,12 @@ private void AddNamedDeclsMembershipLemmas( proof = new Proof(new List {"by " + ProofUtil.Simp(definitions)}); else proof = new Proof(new List - {"by " + "(simp add: " + ConstantMembershipName(d) + " del: Nat.One_nat_def)"}); + {"by " + "(simp add: " + ConstantMembershipName(d, nameOfDecl, separateConstantMembershipLemmaPrefix) + " del: Nat.One_nat_def)"}); if (!separateConstantLemmas) - membershipLemmas.Add(d, new LemmaDecl(MembershipName(d), statement, proof)); + membershipLemmas.Add(d, new LemmaDecl(MembershipName(d, nameOfDecl, MembershipLemmaPrefix(d)), statement, proof)); else - constantMembershipLemmas.Add(d, new LemmaDecl(ConstantMembershipName(d), statement, proof)); + constantMembershipLemmas.Add(d, new LemmaDecl(ConstantMembershipName(d, nameOfDecl, separateConstantMembershipLemmaPrefix), statement, proof)); } } @@ -480,12 +499,13 @@ private void AddLookupVarDeclTyLemmas( { foreach (var v in vars) { + var nameOfDecl = nameOf(v); var (ty, whereClause) = declOf(v); - var lookupDeclLhs = IsaBoogieTerm.LookupVarDecl(VarContext(), nameOf(v)); + var lookupDeclLhs = IsaBoogieTerm.LookupVarDecl(VarContext(), nameOfDecl); var lookupDeclRhs = IsaCommonTerms.SomeOption(new TermTuple(ty, whereClause)); Term lookupDeclStmt = TermBinary.Eq(lookupDeclLhs, lookupDeclRhs); - var lookupTyLhs = IsaBoogieTerm.LookupVarTy(VarContext(), nameOf(v)); + var lookupTyLhs = IsaBoogieTerm.LookupVarTy(VarContext(), nameOfDecl); var lookupTyRhs = IsaCommonTerms.SomeOption(ty); Term lookupTyStmt = TermBinary.Eq(lookupTyLhs, lookupTyRhs); @@ -496,7 +516,7 @@ private void AddLookupVarDeclTyLemmas( "by (simp_all add: lookup_var_decl_global_2 lookup_var_decl_local lookup_var_decl_ty_Some)" }); lookupVarTyLemmas.Add(v, new LemmaDecl( - lookupVarTyNamer.GetName(v, "l_" + v.Name), + MembershipName(() => lookupVarTyNamer.GetName(v, "l_" + v.Name), "lvar", nameOfDecl), new List {lookupDeclStmt, lookupTyStmt}, proof) ); @@ -517,19 +537,28 @@ public void AddAxiomMembershipLemmas(IEnumerable axioms, IsaUniqueNamer u id++; } } + + private string MembershipName(Func normalNameFunc, string membershipPrefix, Term memberTerm) + { + if (CommandLineOptions.Clo.UseIdBasedLemmaNaming && memberTerm is NatConst natConst) + { + return membershipPrefix + natConst; + } + + return membershipPrefix + normalNameFunc(); + } - private string MembershipName(NamedDeclaration d) + private string MembershipName(NamedDeclaration d, Term memberTerm, String membershipPrefix) { - var name = membershipNamer.GetName(d, d.Name); - if (d is Function) - return "mfun_" + name; - return "m_" + name; + var normalNameFunc = () => membershipNamer.GetName(d, d.Name); + + return MembershipName(normalNameFunc, membershipPrefix, memberTerm); } - private string ConstantMembershipName(NamedDeclaration d) + private string ConstantMembershipName(NamedDeclaration d, Term constId, String membershipPrefix) { - var name = membershipNamer.GetName(d, d.Name); - return "mconst_" + name; + var normalNameFunc = () => membershipNamer.GetName(d, d.Name); + return MembershipName(normalNameFunc, membershipPrefix, constId); } private string MembershipName(Axiom a, int id) From 974779e359a91ce7d88c2099aed82f23599a87e9 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 23 Jan 2023 15:04:53 +0100 Subject: [PATCH 029/123] isaProgNoProofs option limit fix --- Source/Core/CommandLineOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/CommandLineOptions.cs b/Source/Core/CommandLineOptions.cs index 2a27d7125..d07ad8dcb 100644 --- a/Source/Core/CommandLineOptions.cs +++ b/Source/Core/CommandLineOptions.cs @@ -1853,7 +1853,7 @@ protected override bool ParseOption(string name, CommandLineOptionEngine.Command return true; case "isaProgNoProofs": - ps.GetNumericArgument(ref GenerateIsaProgNoProofs, 2); + ps.GetNumericArgument(ref GenerateIsaProgNoProofs, 3); return true; case "desugarMaps": From 9a07ce26d95eadaf640a20a51e75e68266835d67 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Sun, 29 Jan 2023 11:57:42 +0100 Subject: [PATCH 030/123] remove redundant changes to Parser.cs (i.e., revert Parser.cs to commit ce40e357ebb48008c539, which was the last non-proof-generation commit for Parser.cs from the main Boogie repository) --- Source/Core/Parser.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/Core/Parser.cs b/Source/Core/Parser.cs index 6d2d60bb7..335f4c868 100644 --- a/Source/Core/Parser.cs +++ b/Source/Core/Parser.cs @@ -20,7 +20,6 @@ using System; using System.Diagnostics.Contracts; -using System.Linq; using System.Reflection; namespace Microsoft.Boogie { @@ -564,7 +563,7 @@ void Procedure(out Procedure/*!*/ proc, out /*maybe null*/ Implementation impl) Spec(pre, mods, post); } ImplBody(out locals, out stmtList); - impl = new Implementation(x, x.val, typeParams.ConvertAll(tp => new TypeVariable(tp.tok, tp.Name)), + impl = new Implementation(x, x.val, typeParams.ConvertAll(tp => new TypeVariable(tp.tok, tp.Name)), Formal.StripWhereClauses(ins), Formal.StripWhereClauses(outs), locals, stmtList, kv == null ? null : (QKeyValue)kv.Clone(), this.errors); } else SynErr(112); @@ -582,7 +581,7 @@ void Implementation(out Implementation/*!*/ impl) { Expect(35); ProcSignature(false, out x, out typeParams, out ins, out outs, out kv); ImplBody(out locals, out stmtList); - impl = new Implementation(x, x.val, typeParams, ins, outs, locals, stmtList, kv, this.errors); + impl = new Implementation(x, x.val, typeParams, ins, outs, locals, stmtList, kv, this.errors); } void Attribute(ref QKeyValue kv) { From 2ee733ae6e3283a9468f64291fb27852bd9366b6 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 6 Feb 2023 18:01:49 +0100 Subject: [PATCH 031/123] fix bug --- Source/ProofGeneration/ProofGenerationLayer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index de1b2afa8..107549810 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -446,6 +446,8 @@ CommandLineOptions.SubsumptionOption subsumptionOption /// public static void VcIsTrivial() { + if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) + return; vcHintManager.TransformHintsToTrivialVc(); } From a7e8865cdf7bd5937103e5e1c0066f2c9952b004 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 28 Feb 2023 09:21:11 +0100 Subject: [PATCH 032/123] minor fix --- Source/ProofGeneration/ProofGenerationLayer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index ec30f102f..4d7b32d90 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -446,6 +446,8 @@ CommandLineOptions.SubsumptionOption subsumptionOption /// public static void VcIsTrivial() { + if (CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) + return; vcHintManager.TransformHintsToTrivialVc(); } From 6b90aef8086b2ee372aa91ff40926002a182ddc7 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Sun, 19 Mar 2023 21:10:42 +0100 Subject: [PATCH 033/123] handle case when unoptimized program is generated but AST-to-CFG program is not --- .../ProofGeneration/ProofGenerationLayer.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 107549810..531002e48 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -735,14 +735,15 @@ public static void VCGenerateAllProofs( var _specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; - var unoptimizedCfgConfig = - new IsaProgramGeneratorConfig(beforeAstToCfgProgAccess, - false, - false, - false, - false, - _specsConfig, - false); + var unoptimizedCfgConfig = + new IsaProgramGeneratorConfig( + _proofGenConfig.GenerateBeforeAstCfgProg ? beforeAstToCfgProgAccess : globalDataProgAccess, + false, + false, + false, + !_proofGenConfig.GenerateBeforeAstCfgProg, + _specsConfig, + !_proofGenConfig.GenerateBeforeAstCfgProg); unoptimizedCfgProgAccess = new IsaProgramGenerator().GetIsaProgram( unoptimizedCfgTheoryName, @@ -759,7 +760,7 @@ public static void VCGenerateAllProofs( new List { "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", - beforeAstToCfgProgAccess.TheoryName() + _proofGenConfig.GenerateBeforeAstCfgProg ? beforeAstToCfgProgAccess.TheoryName() : globalDataProgAccess.TheoryName() }, programDeclsUnoptimizedCfg); theories.Add(unoptimizedCfgProgTheory); From 6b5c0f1432bfcface87394a098afea5f955180b9 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 9 May 2023 16:02:13 +0200 Subject: [PATCH 034/123] take dead variable elimination into account: now use different local variable declarations before and after optimizations The change also adjusts the selective phase generation. In particular, one does not need to give the AstToCfg program accessor to phases that are not connected to it. This is achieved by making the AstToCfg program accessor a parent of those program accessors right below it. --- Source/Core/AstToCfgProofGenInfo.cs | 18 ++ Source/ExecutionEngine/ExecutionEngine.cs | 7 +- .../AstToCfg/AstToCfgLemmaManager.cs | 4 - .../AstToCfg/AstToCfgManager.cs | 2 - .../CfgToDag/CfgToDagEndToEnd.cs | 32 +- .../CfgToDag/CfgToDagManager.cs | 3 +- Source/ProofGeneration/ProofGenConfig.cs | 152 +++++++--- .../ProofGeneration/ProofGenerationLayer.cs | 276 +++++++++--------- 8 files changed, 290 insertions(+), 204 deletions(-) diff --git a/Source/Core/AstToCfgProofGenInfo.cs b/Source/Core/AstToCfgProofGenInfo.cs index dec6229d0..9ae7a614c 100644 --- a/Source/Core/AstToCfgProofGenInfo.cs +++ b/Source/Core/AstToCfgProofGenInfo.cs @@ -3,6 +3,7 @@ using System.Diagnostics.Contracts; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices.ComTypes; using ProofGenUtil; using Core; @@ -25,7 +26,24 @@ public class AstToCfgProofGenInfo /// The original object, which contains the original list of objects, which is Boogie's internal AST representation. private StmtList stmtList; + private List _unoptimizedLocalVars; + + public List UnoptimizedLocalVars + { + get => _unoptimizedLocalVars; + set => _unoptimizedLocalVars = value; + } + + private bool _eliminatedDeadVars = false; + + public bool EliminatedDeadVars + { + get => _eliminatedDeadVars; + set => _eliminatedDeadVars = value; + } + private IList unoptimizedBlocks; + private List newVarsAfterDesugaringinCFGBlocks; /// A list of copies of the objects in . diff --git a/Source/ExecutionEngine/ExecutionEngine.cs b/Source/ExecutionEngine/ExecutionEngine.cs index 0d305b365..08b85caba 100644 --- a/Source/ExecutionEngine/ExecutionEngine.cs +++ b/Source/ExecutionEngine/ExecutionEngine.cs @@ -530,9 +530,12 @@ public static bool ProcessProgram(Program program, string bplFileName, string pr totalNumberOfCommandsB += block.cmds.Count; } + bool eliminatedDeadVars = impl.LocVars.Count != proofGenInfo.UnoptimizedLocalVars.Count; + proofGenInfo.EliminatedDeadVars = eliminatedDeadVars; if (impl.unreachableBlocksPruned || totalNumberOfCommandsA != totalNumberOfCommandsB || - unoptimizedBlocksCopies.Count != optimizedBlocksOriginal.Count) + unoptimizedBlocksCopies.Count != optimizedBlocksOriginal.Count || + eliminatedDeadVars) { proofGenInfo.SetOptimizationsFlag(); } @@ -851,6 +854,8 @@ public static PipelineOutcome ResolveAndTypecheck(Program program, string bplFil Implementation impl = tuple.Key; AstToCfgProofGenInfo proofGenInfo = tuple.Value; + proofGenInfo.UnoptimizedLocalVars = new List(impl.LocVars); + var predecessorMap = proofGenInfo.ComputePredecessors(impl.Blocks); var unoptimizedBlockCopies = proofGenInfo.CopyBlocks(impl.Blocks , predecessorMap, true, cmd => false, out var newVarsAfterDesugaring); proofGenInfo.SetUnoptimizedBlocks(unoptimizedBlockCopies); diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs index cf67ecf9c..33fd24170 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgLemmaManager.cs @@ -45,8 +45,6 @@ public class AstToCfgLemmaManager //private readonly TypingTacticGenerator typingTacticGenerator; private readonly IVariableTranslation variableTranslation; - private readonly BoogieMethodData beforeCfgData; - private readonly IDictionary beforeDagOrigBlock; public AstToCfgLemmaManager( @@ -58,7 +56,6 @@ public AstToCfgLemmaManager( string funContextWfName, IDictionary beforeDagOrigBlock, IDictionary beforeToAfterBlock, - BoogieMethodData beforeCfgData, IVariableTranslationFactory varFactory ) { @@ -68,7 +65,6 @@ IVariableTranslationFactory varFactory this.funContextWfName = funContextWfName; variableTranslation = varFactory.CreateTranslation().VarTranslation; this.beforeToAfterBlock = beforeToAfterBlock; - this.beforeCfgData = beforeCfgData; this.astBoogieContext = astBoogieContext; this.cfgBoogieContext = cfgBoogieContext; diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs index 93619da90..d534250c2 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs @@ -23,7 +23,6 @@ public static Theory AstToCfgProof( AstToCfgProofGenInfo proofGenInfo, ASTRepr beforeCfgAst, CFGRepr afterCfg, - BoogieMethodData beforeCfgData, IDictionary beforeDagOrigBlock, IDictionary mappingWithHints, IDictionary beforeToAfter, @@ -63,7 +62,6 @@ public static Theory AstToCfgProof( funContextWfName, beforeDagOrigBlock, beforeToAfter, - beforeCfgData, varFactory); var lemmaNamer = new IsaUniqueNamer(); diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs index a86241ba6..2455d1e29 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs @@ -31,7 +31,6 @@ public class CfgToDagEndToEnd private BoogieContextIsa boogieContext; private IProgramAccessor programAccessor; - private IProgramAccessor beforeCfgProgramAccessor; private readonly string varContextName = "\\0"; @@ -40,14 +39,9 @@ public IEnumerable EndToEndProof( string passificationEndToEndLemma, Term vcAssm, IProgramAccessor programAccessor, - IProgramAccessor beforeCfgProgramAccessor, CFGRepr cfg) { - // both program accessors are needed because the End-to-End lemmas for the CFG-to-VC part - // need to have access to the 'before AST-to-CFG' program as well as the 'before CFG-to-DAG' program, - // so that the AST-to-VC End-to-End lemma can be composed. this.programAccessor = programAccessor; - this.beforeCfgProgramAccessor = beforeCfgProgramAccessor; boogieContext = new BoogieContextIsa( IsaCommonTerms.TermIdentFromName("A"), @@ -60,14 +54,14 @@ public IEnumerable EndToEndProof( var abbrev = new AbbreviationDecl( varContextName, new Tuple, Term>(new List(), - new TermTuple(beforeCfgProgramAccessor.ConstsAndGlobalsDecl(), beforeCfgProgramAccessor.ParamsAndLocalsDecl())) + new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl())) ); var result = new List {abbrev}; var kStepRed = IsaBoogieTerm.RedCFGKStep( BoogieContextIsa.CreateWithNewVarContext( boogieContext, - new TermTuple(beforeCfgProgramAccessor.ConstsAndGlobalsDecl(), beforeCfgProgramAccessor.ParamsAndLocalsDecl()) + new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl()) ), programAccessor.CfgDecl(), IsaBoogieTerm.CFGConfigNode(new NatConst(cfg.GetUniqueIntLabel(cfg.entry)), @@ -117,7 +111,7 @@ public IEnumerable EndToEndProof( new LemmaDecl( helperLemmaName, LemmaContext(cfg, vcAssm), - CfgToDagLemmaManager.CfgLemmaConclusion(boogieContext, beforeCfgProgramAccessor.PostconditionsDecl(), + CfgToDagLemmaManager.CfgLemmaConclusion(boogieContext, programAccessor.PostconditionsDecl(), finalNodeOrReturn, finalState), new Proof(new List {proofSb.ToString()}) ); @@ -143,13 +137,13 @@ public IEnumerable EndToEndProof( programAccessor.ProcDeclName() + "_def " + programAccessor.CfgDeclName() + "_def " + programAccessor.PreconditionsDeclName() + "_def " + programAccessor.PostconditionsDeclName() + "_def " + programAccessor.ParamsDecl() + "_def " + programAccessor.LocalsDecl() + "_def " + - beforeCfgProgramAccessor.PreconditionsDeclName() + "_def " + beforeCfgProgramAccessor.PostconditionsDeclName() + "_def " + - beforeCfgProgramAccessor.ParamsDecl() + "_def " + beforeCfgProgramAccessor.LocalsDecl() + "_def " + + programAccessor.PreconditionsDeclName() + "_def " + programAccessor.PostconditionsDeclName() + "_def " + + programAccessor.ParamsDecl() + "_def " + programAccessor.LocalsDecl() + "_def " + - beforeCfgProgramAccessor.FunctionsDecl() + "_def " + programAccessor.FunctionsDecl() + "_def " + - beforeCfgProgramAccessor.AxiomsDecl() + "_def " + programAccessor.AxiomsDecl() + "_def " + - beforeCfgProgramAccessor.ConstsDecl() + "_def " + programAccessor.ConstsDecl() + "_def " + - beforeCfgProgramAccessor.GlobalsDecl() + "_def " + programAccessor.GlobalsDecl() + "_def " + + programAccessor.FunctionsDecl() + "_def " + programAccessor.FunctionsDecl() + "_def " + + programAccessor.AxiomsDecl() + "_def " + programAccessor.AxiomsDecl() + "_def " + + programAccessor.ConstsDecl() + "_def " + programAccessor.ConstsDecl() + "_def " + + programAccessor.GlobalsDecl() + "_def " + programAccessor.GlobalsDecl() + "_def " + "exprs_to_only_checked_spec_def") } ) ); @@ -170,7 +164,7 @@ Term vcAssm var multiRed = IsaBoogieTerm.RedCFGMulti( BoogieContextIsa.CreateWithNewVarContext( boogieContext, - new TermTuple(beforeCfgProgramAccessor.ConstsAndGlobalsDecl(), beforeCfgProgramAccessor.ParamsAndLocalsDecl()) + new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl()) ), programAccessor.CfgDecl(), IsaBoogieTerm.CFGConfigNode(new NatConst(cfg.GetUniqueIntLabel(cfg.entry)), @@ -179,14 +173,14 @@ Term vcAssm ); var closedAssm = EndToEndAssumptions.ClosednessAssumption(boogieContext.absValTyMap); var nonEmptyTypesAssm = EndToEndAssumptions.NonEmptyTypesAssumption(boogieContext.absValTyMap); - var finterpAssm = IsaBoogieTerm.FunInterpWf(boogieContext.absValTyMap, beforeCfgProgramAccessor.FunctionsDecl(), + 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, beforeCfgProgramAccessor, + var axiomAssm = EndToEndAssumptions.AxiomAssumption(boogieContext, programAccessor, new TermWithExplicitType(normalInitState, IsaBoogieType.NormalStateType(absValType))); var presAssm = - IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState, beforeCfgProgramAccessor.PreconditionsDecl()); + IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState, programAccessor.PreconditionsDecl()); var localsAssm = EndToEndAssumptions.LocalStateAssumption(boogieContext, IsaCommonTerms.Snd(boogieContext.varContext), normalInitState); var globalsAssm = EndToEndAssumptions.GlobalStateAssumption(boogieContext, diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs index cd4847aca..34f98aa60 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs @@ -74,7 +74,7 @@ public static Theory CfgToDagProof( var varContextName = "\\1"; var varContextAbbrev = new AbbreviationDecl( varContextName, - new Tuple, Term>(new List(), beforeCfgProgAccess.VarContext()) + new Tuple, Term>(new List(), beforeDagProgAccess.VarContext()) ); var funContextWfName = "Wf_Fun"; @@ -218,7 +218,6 @@ public static Theory CfgToDagProof( phasesTheories.EndToEndLemmaName(PhasesTheories.Phase.Passification, true), vcAssm, beforeDagProgAccess, - beforeCfgProgAccess, beforeDagCfg ); theoryOuterDecls.AddRange(endToEndDecls); diff --git a/Source/ProofGeneration/ProofGenConfig.cs b/Source/ProofGeneration/ProofGenConfig.cs index 5df0273ef..9c3fc4424 100644 --- a/Source/ProofGeneration/ProofGenConfig.cs +++ b/Source/ProofGeneration/ProofGenConfig.cs @@ -5,53 +5,115 @@ /// public class ProofGenConfig { - public ProofGenConfig( - bool generateBeforeAstCfgProg, - bool generateUnoptimizedCfgProg, - bool generateBeforeCfgDagProg, - bool generateBeforePassifProg, - bool generatePassifiedProg, - bool generateAstCfgE2E, - bool generateCfgDagE2E, - bool generatePassifE2E, - bool generateVcE2E, - bool generateAstCfgProof, - bool generateCfgDagProof, - bool generatePassifProof, - bool generateVcProof - ) - { - GenerateBeforeAstCfgProg = generateBeforeAstCfgProg; - GenerateUnoptimizedCfgProg = generateUnoptimizedCfgProg; - GenerateBeforeCfgDagProg = generateBeforeCfgDagProg; - GenerateBeforePassifProg = generateBeforePassifProg; - GeneratePassifiedProg = generatePassifiedProg; - - GenerateAstCfgE2E = generateAstCfgE2E; - GenerateCfgDagE2E = generateCfgDagE2E; - GeneratePassifE2E = generatePassifE2E; - GenerateVcE2E = generateVcE2E; - - GenerateAstCfgProof = generateAstCfgProof; - GenerateCfgDagProof = generateCfgDagProof; - GeneratePassifProof = generatePassifProof; - GenerateVcProof = generateVcProof; + private bool _generateAstCfgE2E; + private bool _generateCfgDagE2E; + private bool _generatePassifE2E; + private bool _generateVcE2E; + private bool _generateAstCfgProof; + private bool _generateCfgDagProof; + private bool _generatePassifProof; + private bool _generateVcProof; + + public ProofGenConfig AllOptionsEnabled() + { + _generateAstCfgE2E = true; + _generateCfgDagE2E = true; + _generatePassifE2E = true; + _generateVcE2E = true; + _generateAstCfgProof = true; + _generateCfgDagProof = true; + _generatePassifProof = true; + _generateVcProof = true; + return this; + } + + /* + _proofGenConfig.GeneratePassifE2E = _proofGenConfig.GenerateVcProof && _proofGenConfig.GenerateVcE2E && _proofGenConfig.GeneratePassifProof; + _proofGenConfig.GenerateCfgDagE2E = _proofGenConfig.GeneratePassifE2E && _proofGenConfig.GenerateCfgDagProof; + _proofGenConfig.GenerateAstCfgE2E = _proofGenConfig.GenerateCfgDagE2E && _proofGenConfig.GenerateAstCfgProof; + + _proofGenConfig.GenerateBeforeAstCfgProg = _proofGenConfig.GenerateAstCfgProof; + _proofGenConfig.GenerateUnoptimizedCfgProg = proofGenInfo.GetOptimizationsFlag() && _proofGenConfig.GenerateAstCfgProof; + _proofGenConfig.GenerateBeforeCfgDagProg = (proofGenInfo.GetOptimizationsFlag() && _proofGenConfig.GenerateCfgDagProof) || + (!proofGenInfo.GetOptimizationsFlag() && (_proofGenConfig.GenerateAstCfgProof || _proofGenConfig.GenerateCfgDagProof)); + _proofGenConfig.GenerateBeforePassifProg = _proofGenConfig.GenerateCfgDagProof || _proofGenConfig.GeneratePassifProof; + _proofGenConfig.GeneratePassifiedProg = _proofGenConfig.GeneratePassifProof || _proofGenConfig.GenerateVcProof; + */ + public bool GenerateAstCfgE2E => _generateAstCfgE2E && GenerateAstCfgProof; + + public ProofGenConfig SetAstCfgE2E(bool flag) + { + _generateAstCfgE2E = flag; + return this; + } + + public bool GenerateCfgDagE2E => _generateCfgDagE2E && GenerateCfgDagProof; + public ProofGenConfig SetCfgDagE2E(bool flag) + { + _generateCfgDagE2E = flag; + return this; + } + + public bool GeneratePassifE2E => _generatePassifE2E && GeneratePassifProof && GenerateVcE2E; + + public ProofGenConfig SetPassifE2E(bool flag) + { + _generatePassifE2E = flag; + return this; + } + + public bool GenerateVcE2E => _generateVcE2E && GenerateVcProof; + + public ProofGenConfig SetVcE2E(bool flag) + { + _generateVcE2E = flag; + return this; + } + + public bool GenerateAstCfgProof => _generateAstCfgProof; + public ProofGenConfig SetAstCfgProof(bool flag) + { + _generateAstCfgProof = flag; + return this; + } + + public bool GenerateCfgDagProof => _generateCfgDagProof; + public ProofGenConfig SetCfgDagProof(bool flag) + { + _generateCfgDagProof = flag; + return this; } + + public bool GeneratePassifProof => _generatePassifProof; + public ProofGenConfig SetPassifProof(bool flag) + { + _generatePassifProof = flag; + return this; + } + + public bool GenerateVcProof => _generateVcProof; - public bool GenerateBeforeAstCfgProg { get; set; } - public bool GenerateUnoptimizedCfgProg { get; set; } - public bool GenerateBeforeCfgDagProg { get; set; } - public bool GenerateBeforePassifProg { get; set; } - public bool GeneratePassifiedProg { get; set; } - - public bool GenerateAstCfgE2E { get; set; } - public bool GenerateCfgDagE2E { get; set; } - public bool GeneratePassifE2E { get; set; } - public bool GenerateVcE2E { get; } + public ProofGenConfig SetVcProof(bool flag) + { + _generateVcProof = flag; + return this; + } + + /** Program Generation Getters */ - public bool GenerateAstCfgProof { get; set; } - public bool GenerateCfgDagProof { get; set; } - public bool GeneratePassifProof { get; set; } - public bool GenerateVcProof { get; } + public bool GenerateBeforeAstCfgProg => GenerateAstCfgProof; + + public bool GenerateUnoptimizedCfgProg(bool optimizationsHaveAnEffect) + { + return optimizationsHaveAnEffect && GenerateAstCfgProof; + } + + public bool GenerateBeforeCfgDagProg(bool optimizationsHaveAnEffect) + { + return GenerateCfgDagProof || (optimizationsHaveAnEffect && GenerateAstCfgProof); + } + + public bool GenerateBeforePassiveProg => GenerateCfgDagProof || GeneratePassifProof; + public bool GeneratePassifiedProg => GeneratePassifProof || GenerateVcProof; } } \ No newline at end of file diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 531002e48..546d5be19 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -33,7 +33,6 @@ public class ProofGenerationLayer private static ASTRepr beforeCfgAst; private static IDictionary beforeCfgAfterCfgBlock; - //private static BoogieMethodData beforeCfgData; private static IDictionary beforeOptimizationsOrigBlock; private static IDictionary beforeDagOrigBlock; @@ -43,7 +42,6 @@ public class ProofGenerationLayer private static CFGRepr beforeDagCfg; - private static BoogieMethodData beforeOptimizationsData; private static BoogieMethodData beforeDagData; private static IDictionary beforePassiveToAfterPassiveBlock; @@ -80,10 +78,7 @@ public class ProofGenerationLayer //private static Block uniqueExitBlockOrigBeforeOptimizations; private static Block uniqueExitBlockOrig; - private static ProofGenConfig _proofGenConfig = - new(true, true, true, true, true, - true, true, true, true, - true, true, true, true); + private static ProofGenConfig _proofGenConfig = new ProofGenConfig().AllOptionsEnabled(); private static IProgramAccessor globalDataProgAccess; @@ -173,17 +168,6 @@ private static bool checkForGotos(StmtList stmtList) return false; } - public static void BeforeOptimizations(Implementation impl) - { - var config = new CFGReprConfigBuilder().SetIsAcyclic(false).SetBlockCopy(true).SetDesugarCalls(true) - .Build(); - beforeOptimizationsCFG = CFGReprTransformer.GetCfgRepresentation(impl, - config, - out beforeOptimizationsOrigBlock, - out var newVarsFromDesugaring); - beforeOptimizationsData = MethodDataFromImpl(impl, boogieGlobalData, newVarsFromDesugaring); - } - /// /// Provide source CFG for CFG-to-DAG phase /// @@ -262,11 +246,12 @@ out var newVarsFromDesugaring private static BoogieMethodData MethodDataFromImpl( Implementation impl, BoogieGlobalData globalData, - List extraLocalVariables = null + List extraLocalVariables = null, + List overrideLocals = null ) { //add out params to local variables for now - var locals = new List(impl.LocVars).Union(impl.OutParams); + var locals = new List(overrideLocals ?? impl.LocVars).Union(impl.OutParams); if (extraLocalVariables != null) locals = locals.Union(extraLocalVariables); @@ -588,7 +573,7 @@ public static void VCGenerateAllProofs( if (AstContainsGotoOrBreak(proofGenInfo)) { - _proofGenConfig.GenerateAstCfgProof = false; + _proofGenConfig.SetAstCfgProof(false); } IList bigBlocks = proofGenInfo.GetBigBlocks(); @@ -597,62 +582,41 @@ public static void VCGenerateAllProofs( DesugarCmdsInBigBlock(b); } - _proofGenConfig.GeneratePassifE2E = _proofGenConfig.GenerateVcProof && _proofGenConfig.GenerateVcE2E && _proofGenConfig.GeneratePassifProof; - _proofGenConfig.GenerateCfgDagE2E = _proofGenConfig.GeneratePassifProof && _proofGenConfig.GeneratePassifE2E && _proofGenConfig.GenerateCfgDagProof; - _proofGenConfig.GenerateAstCfgE2E = _proofGenConfig.GenerateCfgDagProof && _proofGenConfig.GenerateCfgDagE2E && _proofGenConfig.GenerateAstCfgProof; - - _proofGenConfig.GenerateBeforeAstCfgProg = _proofGenConfig.GenerateAstCfgProof; - _proofGenConfig.GenerateUnoptimizedCfgProg = proofGenInfo.GetOptimizationsFlag() && _proofGenConfig.GenerateAstCfgProof; - _proofGenConfig.GenerateBeforeCfgDagProg = (proofGenInfo.GetOptimizationsFlag() && _proofGenConfig.GenerateCfgDagProof) || - (!proofGenInfo.GetOptimizationsFlag() && (_proofGenConfig.GenerateAstCfgProof || _proofGenConfig.GenerateCfgDagProof)); - _proofGenConfig.GenerateBeforePassifProg = _proofGenConfig.GenerateCfgDagProof || _proofGenConfig.GeneratePassifProof; - _proofGenConfig.GeneratePassifiedProg = _proofGenConfig.GeneratePassifProof || _proofGenConfig.GenerateVcProof; - - IList unoptimizedCFGBlocks = proofGenInfo.GetUnpotimizedBlocks(); + IList unoptimizedCfgBlocks = proofGenInfo.GetUnpotimizedBlocks(); var newToOldInternal = new Dictionary(); - unoptimizedCFGBlocks.ZipDo(afterPassificationImpl.Blocks, (bNew, bOld) => newToOldInternal.Add(bNew, bOld)); + unoptimizedCfgBlocks.ZipDo(afterPassificationImpl.Blocks, (bNew, bOld) => newToOldInternal.Add(bNew, bOld)); beforeOptimizationsOrigBlock = newToOldInternal; - - beforeOptimizationsData = MethodDataFromImpl(afterPassificationImpl, boogieGlobalData, proofGenInfo.GetNewVarsCFG()); - var config = new CFGReprConfigBuilder().SetIsAcyclic(false).SetBlockCopy(true).SetDesugarCalls(true) - .Build(); - - IDictionary labeling; - if (config.IsAcyclic) - { - labeling = CFGReprTransformer.GetTopologicalLabeling(unoptimizedCFGBlocks); - } - else - { - labeling = new Dictionary(); - var idx = 0; - foreach (var b in unoptimizedCFGBlocks) - { - labeling.Add(b, idx); - idx++; - } - } - - IDictionary> outgoingBlocks = new Dictionary>(); - foreach (var block in unoptimizedCFGBlocks) - { - var curOutgoing = new List(); - if (block.TransferCmd is GotoCmd gotoCmd) curOutgoing.AddRange(gotoCmd.labelTargets); - outgoingBlocks.Add(block, curOutgoing); - } - Block entryBlock = null; - foreach (var block in unoptimizedCFGBlocks) + BoogieMethodData beforeOptimizationsData; + + if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) { - if (block.Predecessors.Count == 0) - { - if (entryBlock != null) - throw new ProofGenUnexpectedStateException(typeof(CFGReprTransformer), "no unique CFG entry"); - entryBlock = block; - } + beforeOptimizationsData = MethodDataFromImpl( + afterPassificationImpl, + boogieGlobalData, + /* Since in the proofs calls are desugared, there can be more variables after desugarging. If only + the program should be generated, then these variables should be ignored. */ + null, + proofGenInfo.UnoptimizedLocalVars + ); + } else if(proofGenInfo.EliminatedDeadVars) { + beforeOptimizationsData = MethodDataFromImpl( + afterPassificationImpl, + boogieGlobalData, + proofGenInfo.GetNewVarsCFG(), + proofGenInfo.UnoptimizedLocalVars + ); + } else { + /* If no dead variables were eliminated then we pick the same data as for the rest of the CFGs before the passification. + Note that picking `beforeDagData` would not work as intended because it does not contain the desugared variables + from calls. + */ + beforeOptimizationsData = beforePassiveData; } - beforeOptimizationsCFG = new CFGRepr(outgoingBlocks, labeling, entryBlock); + var afterOptimizationsData = beforePassiveData; + + beforeOptimizationsCFG = GetCfgBeforeOptimizations(unoptimizedCfgBlocks); if (uniqueNamer == null) { @@ -662,23 +626,32 @@ public static void VCGenerateAllProofs( var theories = new List(); if (axiomBuilder == null && typeAxioms != null) throw new ArgumentException("type axioms can only be null if axiom builder is null"); - - /* Since in the proofs calls are desugared, there can be more variables in "beforePassiveData". If only - the program should be generated, then these variables should be ignored. */ - var mainData = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? beforeDagData : beforePassiveData; + + var beforeOptimizationsVarTranslationFactory = + new DeBruijnVarFactory( + new DeBruijnFixedVarTranslation(beforeOptimizationsData), + new DeBruijnFixedTVarTranslation(beforeOptimizationsData), + boogieGlobalData); - var fixedVarTranslation2 = new DeBruijnFixedVarTranslation(mainData); - var fixedTyVarTranslation2 = new DeBruijnFixedTVarTranslation(mainData); - var varTranslationFactory2 = - new DeBruijnVarFactory(fixedVarTranslation2, fixedTyVarTranslation2, boogieGlobalData); + var afterOptimizationsVarTranslationFactory = + new DeBruijnVarFactory( + new DeBruijnFixedVarTranslation(afterOptimizationsData), + new DeBruijnFixedTVarTranslation(afterOptimizationsData), + boogieGlobalData); - cmdIsaVisitor = new MultiCmdIsaVisitor(varTranslationFactory2); + cmdIsaVisitor = new MultiCmdIsaVisitor(afterOptimizationsVarTranslationFactory); IProgramAccessor beforeAstToCfgProgAccess = null; IProgramAccessor unoptimizedCfgProgAccess = null; IProgramAccessor beforeCfgToDagProgAccess = null; IProgramAccessor beforePassiveProgAccess = null; IProgramAccessor passiveProgAccess = null; + + //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) + var specsConfigDefault = + CommandLineOptions.Clo.GenerateIsaProgNoProofs + ? SpecsConfig.All + : SpecsConfig.AllPreCheckedPost; if (_proofGenConfig.GenerateBeforeAstCfgProg) { @@ -689,22 +662,18 @@ public static void VCGenerateAllProofs( var beforeAstToCfgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_ast_to_cfg_prog"); - //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) - var specsConfig_ast = CommandLineOptions.Clo.GenerateIsaProgNoProofs - ? SpecsConfig.All - : SpecsConfig.AllPreCheckedPost; var beforeAstToCfgConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, false, false, false, true, - specsConfig_ast, + specsConfigDefault, true); beforeAstToCfgProgAccess = new IsaProgramGeneratorForAst().GetIsaProgram( beforeAstToCfgTheoryName, afterPassificationImpl.Name, - mainData, beforeAstToCfgConfig, varTranslationFactory2, + beforeOptimizationsData, beforeAstToCfgConfig, beforeOptimizationsVarTranslationFactory, beforeCfgAst, originalAst, proofGenInfo, @@ -725,30 +694,27 @@ public static void VCGenerateAllProofs( #endregion } - if (_proofGenConfig.GenerateUnoptimizedCfgProg) + if (_proofGenConfig.GenerateUnoptimizedCfgProg(proofGenInfo.GetOptimizationsFlag())) { #region unoptimized cfg program var unoptimizedCfgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_unoptimized_cfg_prog"); - //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) - var _specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs - ? SpecsConfig.All - : SpecsConfig.AllPreCheckedPost; + var parentAccessorForUnoptimizedCfg = beforeAstToCfgProgAccess; var unoptimizedCfgConfig = new IsaProgramGeneratorConfig( - _proofGenConfig.GenerateBeforeAstCfgProg ? beforeAstToCfgProgAccess : globalDataProgAccess, + parentAccessorForUnoptimizedCfg ?? globalDataProgAccess, false, false, false, - !_proofGenConfig.GenerateBeforeAstCfgProg, - _specsConfig, + parentAccessorForUnoptimizedCfg == null, + parentAccessorForUnoptimizedCfg != null ? SpecsConfig.None : specsConfigDefault, !_proofGenConfig.GenerateBeforeAstCfgProg); unoptimizedCfgProgAccess = new IsaProgramGenerator().GetIsaProgram( unoptimizedCfgTheoryName, afterPassificationImpl.Name, - mainData, unoptimizedCfgConfig, varTranslationFactory2, + beforeOptimizationsData, unoptimizedCfgConfig, beforeOptimizationsVarTranslationFactory, beforeOptimizationsCFG, uniqueNamer, out var programDeclsUnoptimizedCfg, @@ -768,23 +734,25 @@ public static void VCGenerateAllProofs( #endregion } - if (_proofGenConfig.GenerateBeforeCfgDagProg) + if (_proofGenConfig.GenerateBeforeCfgDagProg(proofGenInfo.GetOptimizationsFlag())) { #region before cfg to dag program var beforeCfgToDagTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_cfg_to_dag_prog"); - //Hack: specs config used to distinguish between all (free + checks) (--> expression tuples) or just checked (no tuples) - var specsConfig = CommandLineOptions.Clo.GenerateIsaProgNoProofs ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; - var beforeCfgToDagConfig = new IsaProgramGeneratorConfig(globalDataProgAccess, + + var parentAccessorForBeforeCfgToDag = beforeAstToCfgProgAccess; + var beforeCfgToDagConfig = new IsaProgramGeneratorConfig( + parentAccessorForBeforeCfgToDag ?? globalDataProgAccess, false, false, false, - true, - specsConfig, - true); + proofGenInfo.GetOptimizationsFlag(), + parentAccessorForBeforeCfgToDag != null ? SpecsConfig.None : specsConfigDefault, + proofGenInfo.GetOptimizationsFlag()); + beforeCfgToDagProgAccess = new IsaProgramGenerator().GetIsaProgram( beforeCfgToDagTheoryName, afterPassificationImpl.Name, - mainData, beforeCfgToDagConfig, varTranslationFactory2, + afterOptimizationsData, beforeCfgToDagConfig, afterOptimizationsVarTranslationFactory, beforeDagCfg, uniqueNamer, out var programDeclsBeforeCfgToDag, @@ -792,12 +760,12 @@ public static void VCGenerateAllProofs( procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name, beforeCfgToDagProgAccess); var beforeCfgToDagProgTheory = new Theory(beforeCfgToDagTheoryName, - new List {"Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", "\"../"+globalDataProgAccess.TheoryName()+"\""}, + new List {"Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", + parentAccessorForBeforeCfgToDag != null ? parentAccessorForBeforeCfgToDag.TheoryName() : "\"../"+globalDataProgAccess.TheoryName()+"\""}, programDeclsBeforeCfgToDag); theories.Add(beforeCfgToDagProgTheory); #endregion } - if (CommandLineOptions.Clo.GenerateIsaProgNoProofs) { @@ -805,33 +773,34 @@ public static void VCGenerateAllProofs( return; } - var theoryNameForParentImport = _proofGenConfig.GenerateAstCfgProof - ? beforeAstToCfgProgAccess.TheoryName() - : _proofGenConfig.GenerateBeforeCfgDagProg ? beforeCfgToDagProgAccess.TheoryName() : ""; - - if (_proofGenConfig.GenerateBeforePassifProg) + if (_proofGenConfig.GenerateBeforePassiveProg) { #region before passive program - IProgramAccessor parentProgramAccessorForPassification = _proofGenConfig.GenerateAstCfgProof - ? beforeAstToCfgProgAccess - : beforeCfgToDagProgAccess; + IProgramAccessor parentProgramAccessorForPassification = beforeCfgToDagProgAccess; var beforePassiveProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_passive_prog"); var beforePassiveConfig = - new IsaProgramGeneratorConfig(parentProgramAccessorForPassification, parentProgramAccessorForPassification == null, parentProgramAccessorForPassification == null, parentProgramAccessorForPassification == null, parentProgramAccessorForPassification == null, - SpecsConfig.None, false); + new IsaProgramGeneratorConfig( + parentProgramAccessorForPassification ?? globalDataProgAccess, + false, + false, + false, + parentProgramAccessorForPassification == null, + parentProgramAccessorForPassification != null ? SpecsConfig.None : specsConfigDefault, + false); beforePassiveProgAccess = new IsaProgramGenerator().GetIsaProgram(beforePassiveProgTheoryName, afterPassificationImpl.Name, - mainData, beforePassiveConfig, varTranslationFactory2, + afterOptimizationsData, beforePassiveConfig, afterOptimizationsVarTranslationFactory, beforePassificationCfg, uniqueNamer, out var programDeclsBeforePassive, !CommandLineOptions.Clo.GenerateIsaProgNoProofs); var beforePassificationProgTheory = new Theory(beforePassiveProgTheoryName, - new List {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport}, + new List {"Boogie_Lang.Semantics", "Boogie_Lang.Util", + parentProgramAccessorForPassification != null ? parentProgramAccessorForPassification.TheoryName() : globalDataProgAccess.TheoryName()}, programDeclsBeforePassive); theories.Add(beforePassificationProgTheory); @@ -849,8 +818,18 @@ public static void VCGenerateAllProofs( new DeBruijnVarFactory(fixedVarTranslation, fixedTyVarTranslation, boogieGlobalData); var finalProgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_passive_prog"); + + IProgramAccessor parentProgramAccessorFoPassiveProg = beforePassiveProgAccess; + var passiveProgConfig = - new IsaProgramGeneratorConfig(beforePassiveProgAccess, beforePassiveProgAccess==null, beforePassiveProgAccess==null, beforePassiveProgAccess==null, true, SpecsConfig.None, false); + new IsaProgramGeneratorConfig( + parentProgramAccessorFoPassiveProg ?? globalDataProgAccess, + false, + false, + false, + true, + parentProgramAccessorFoPassiveProg != null ? SpecsConfig.None : specsConfigDefault, + false); passiveProgAccess = new IsaProgramGenerator().GetIsaProgram(finalProgTheoryName, afterPassificationImpl.Name, finalProgData, passiveProgConfig, varTranslationFactory, @@ -863,7 +842,7 @@ public static void VCGenerateAllProofs( var afterPassificationProgTheory = new Theory(finalProgTheoryName, new List - {"Boogie_Lang.Semantics", "Boogie_Lang.Util", theoryNameForParentImport, beforePassiveProgAccess != null ? beforePassiveProgAccess.TheoryName() : ""}, + {"Boogie_Lang.Semantics", "Boogie_Lang.Util", parentProgramAccessorFoPassiveProg != null ? parentProgramAccessorFoPassiveProg.TheoryName() : ""}, programDecls); theories.Add(afterPassificationProgTheory); @@ -946,10 +925,6 @@ out var endToEndLemmaPrelim { #region passification proof - IProgramAccessor beforePhaseProgramAccess = !_proofGenConfig.GenerateAstCfgProof - ? beforePassiveProgAccess - : beforeAstToCfgProgAccess; - var passificationProofTheory = PassificationManager.PassificationProof( phasesTheories.TheoryName(PhasesTheories.Phase.Passification), _proofGenConfig.GenerateVcProof ? phasesTheories.TheoryName(PhasesTheories.Phase.Vc) : "", @@ -959,11 +934,11 @@ out var endToEndLemmaPrelim beforePassificationCfg, beforePassiveToAfterPassiveBlock, passiveRelationGen, - beforePhaseProgramAccess, + beforePassiveProgAccess, beforePassiveProgAccess, passiveProgAccess, - mainData, - varTranslationFactory2, + afterOptimizationsData, + afterOptimizationsVarTranslationFactory, varTranslationFactory ); theories.Add(passificationProofTheory); @@ -997,7 +972,7 @@ out var endToEndLemmaPrelim beforeAstToCfgProgAccess, beforeCfgToDagProgAccess, beforePassiveProgAccess, - varTranslationFactory2); + afterOptimizationsVarTranslationFactory); theories.Add(cfgToDagProofTheory); #endregion @@ -1043,14 +1018,12 @@ out var endToEndLemmaPrelim } CFGRepr astCfgReprInput; - BoogieMethodData astCfgDataInput; IDictionary blockToBlockMapInput; IProgramAccessor beforeCfgToDagProgAccessInput; if (!proofGenInfo.GetOptimizationsFlag()) { astCfgReprInput = beforeDagCfg; - astCfgDataInput = beforeDagData; blockToBlockMapInput = beforeDagOrigBlock; beforeCfgToDagProgAccessInput = beforeCfgToDagProgAccess; @@ -1058,7 +1031,6 @@ out var endToEndLemmaPrelim else { astCfgReprInput = beforeOptimizationsCFG; - astCfgDataInput = beforeOptimizationsData; blockToBlockMapInput = mappingUnoptimizedCopyToOrigBlock; beforeCfgToDagProgAccessInput = unoptimizedCfgProgAccess; } @@ -1072,13 +1044,12 @@ out var endToEndLemmaPrelim proofGenInfo, beforeCfgAst, astCfgReprInput, - astCfgDataInput, blockToBlockMapInput, mappingWithHints, beforeCfgAfterCfgBlock, beforeAstToCfgProgAccess, beforeCfgToDagProgAccessInput, - varTranslationFactory2, + afterOptimizationsVarTranslationFactory, cmdIsaVisitor); theories.Add(astToCfgProofTheory); @@ -1088,6 +1059,49 @@ out var endToEndLemmaPrelim StoreResult(uniqueNamer.GetName(afterPassificationImpl.Proc.Name), theories); } + private static CFGRepr GetCfgBeforeOptimizations(IList unoptimizedCFGBlocks) + { + var config = new CFGReprConfigBuilder().SetIsAcyclic(false).SetBlockCopy(true).SetDesugarCalls(true) + .Build(); + + IDictionary labeling; + if (config.IsAcyclic) + { + labeling = CFGReprTransformer.GetTopologicalLabeling(unoptimizedCFGBlocks); + } + else + { + labeling = new Dictionary(); + var idx = 0; + foreach (var b in unoptimizedCFGBlocks) + { + labeling.Add(b, idx); + idx++; + } + } + + IDictionary> outgoingBlocks = new Dictionary>(); + foreach (var block in unoptimizedCFGBlocks) + { + var curOutgoing = new List(); + if (block.TransferCmd is GotoCmd gotoCmd) curOutgoing.AddRange(gotoCmd.labelTargets); + outgoingBlocks.Add(block, curOutgoing); + } + + Block entryBlock = null; + foreach (var block in unoptimizedCFGBlocks) + { + if (block.Predecessors.Count == 0) + { + if (entryBlock != null) + throw new ProofGenUnexpectedStateException(typeof(CFGReprTransformer), "no unique CFG entry"); + entryBlock = block; + } + } + + return new CFGRepr(outgoingBlocks, labeling, entryBlock); + } + private static void StoreResult(string preferredDirName, IEnumerable theories) { ProofGenerationOutput.StoreTheoriesInNewDirWithSession(preferredDirName, theories); From 2bb37ad024dba784018b480a4fc6692f24ecdf3c Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 9 May 2023 19:42:56 +0200 Subject: [PATCH 035/123] fix and get rid of more accessors other than the two that are required for a phase --- .../Passification/PassificationEndToEnd.cs | 8 ++------ .../Passification/PassificationLemmaManager.cs | 7 ++----- .../ProofGeneration/Passification/PassificationManager.cs | 7 ++----- Source/ProofGeneration/ProofGenerationLayer.cs | 7 +++---- 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/Source/ProofGeneration/Passification/PassificationEndToEnd.cs b/Source/ProofGeneration/Passification/PassificationEndToEnd.cs index 295c9360c..630d9556c 100644 --- a/Source/ProofGeneration/Passification/PassificationEndToEnd.cs +++ b/Source/ProofGeneration/Passification/PassificationEndToEnd.cs @@ -43,8 +43,6 @@ public class PassificationEndToEnd private StateRelationData oldRelationData; private IProgramAccessor passiveProgramAccessor; - private IProgramAccessor beforePhaseProgramAccessor; - private TermIdent passiveVarContext; private IProgramAccessor programAccessor; private IVariableTranslation varTranslation; @@ -60,7 +58,6 @@ public IEnumerable EndToEndProof( string entryCfgLemma, string boogieToVcLemma, Term vcAssm, - IProgramAccessor beforePhaseProgramAccessor, IProgramAccessor programAccessor, IProgramAccessor passiveProgramAccessor, Tuple varContextNonPassivePassive, @@ -72,7 +69,6 @@ public IEnumerable EndToEndProof( this.entryCfgLemma = entryCfgLemma; this.boogieToVcLemma = boogieToVcLemma; this.vcAssm = vcAssm; - this.beforePhaseProgramAccessor = beforePhaseProgramAccessor; this.programAccessor = programAccessor; this.passiveProgramAccessor = passiveProgramAccessor; boogieContext = new BoogieContextIsa( @@ -171,7 +167,7 @@ private List GenerateLemma() foreach (var idVar in varIds) relWfProofMethods.Add( - ProofUtil.Apply(ProofUtil.Simp(beforePhaseProgramAccessor.LookupVarTyLemma(idVar.Item2), + ProofUtil.Apply(ProofUtil.Simp(programAccessor.LookupVarTyLemma(idVar.Item2), passiveProgramAccessor.LookupVarTyLemma(idVar.Item2))) ); @@ -444,7 +440,7 @@ private ContextElem Context() var multiRed = IsaBoogieTerm.RedCFGMulti( BoogieContextIsa.CreateWithNewVarContext( boogieContext, - new TermTuple(beforePhaseProgramAccessor.ConstsAndGlobalsDecl(), beforePhaseProgramAccessor.ParamsAndLocalsDecl()) + new TermTuple(programAccessor.ConstsAndGlobalsDecl(), programAccessor.ParamsAndLocalsDecl()) ), programAccessor.CfgDecl(), IsaBoogieTerm.CFGConfigNode(new NatConst(cfg.GetUniqueIntLabel(cfg.entry)), diff --git a/Source/ProofGeneration/Passification/PassificationLemmaManager.cs b/Source/ProofGeneration/Passification/PassificationLemmaManager.cs index c5d7021ce..defcf34d5 100644 --- a/Source/ProofGeneration/Passification/PassificationLemmaManager.cs +++ b/Source/ProofGeneration/Passification/PassificationLemmaManager.cs @@ -29,7 +29,7 @@ internal class PassificationLemmaManager private readonly TermIdent normalInitState = IsaCommonTerms.TermIdentFromName("n_s"); - private readonly OldVarFinder oldVarFinder = new OldVarFinder(); + private readonly OldVarFinder oldVarFinder = new(); private readonly IDictionary origToPassiveBlock; private readonly IProgramAccessor passiveProgramAccessor; @@ -38,7 +38,6 @@ internal class PassificationLemmaManager private readonly IVariableTranslation passiveVarTranslation; private readonly IProgramAccessor programAccessor; - private readonly IProgramAccessor beforePhaseProgramAccessor; private readonly Dictionary smallestRequiredVersionDict = new Dictionary(); private readonly TermIdent stateRel = IsaCommonTerms.TermIdentFromName("R"); @@ -50,7 +49,6 @@ internal class PassificationLemmaManager public PassificationLemmaManager( CFGRepr cfg, IDictionary origToPassiveBlock, - IProgramAccessor beforePhaseProgramAccessor, IProgramAccessor programAccessor, IProgramAccessor passiveProgramAccessor, Tuple varContextNonPassivePassive, @@ -61,7 +59,6 @@ public PassificationLemmaManager( { this.cfg = cfg; this.origToPassiveBlock = origToPassiveBlock; - this.beforePhaseProgramAccessor = beforePhaseProgramAccessor; this.programAccessor = programAccessor; this.passiveProgramAccessor = passiveProgramAccessor; _oldStateRelationData = oldStateRelationData; @@ -116,7 +113,7 @@ public Tuple GenerateBlockLemma(Block block, string localL * in which case the variable is not newly constrained */ if (!tuple.Item3) constrainedPassiveVars.Add(passiveVarTerm); lookupTyUpdatesLemmas.Add( - Tuple.Create(beforePhaseProgramAccessor.LookupVarTyLemma(origVar), + Tuple.Create(programAccessor.LookupVarTyLemma(origVar), passiveProgramAccessor.LookupVarTyLemma(passiveVar)) ); } diff --git a/Source/ProofGeneration/Passification/PassificationManager.cs b/Source/ProofGeneration/Passification/PassificationManager.cs index a31c640f7..006d36dae 100644 --- a/Source/ProofGeneration/Passification/PassificationManager.cs +++ b/Source/ProofGeneration/Passification/PassificationManager.cs @@ -34,7 +34,6 @@ public static Theory PassificationProof( CFGRepr beforePassificationCfg, IDictionary nonPassiveToPassiveBlock, PassiveRelationGen relationGen, - IProgramAccessor beforePhaseProgramAccess, IProgramAccessor beforePassiveProgAccess, IProgramAccessor passiveProgAccess, BoogieMethodData beforePassiveData, @@ -63,7 +62,6 @@ public static Theory PassificationProof( var beforePassiveLemmaManager = new PassificationLemmaManager( beforePassificationCfg, nonPassiveToPassiveBlock, - beforePhaseProgramAccess, beforePassiveProgAccess, passiveProgAccess, varContextNonPassivePassive, @@ -77,7 +75,7 @@ public static Theory PassificationProof( var varContextAbbrev = new AbbreviationDecl( varContextName, - new Tuple, Term>(new List(), beforePhaseProgramAccess.VarContext()) + new Tuple, Term>(new List(), beforePassiveProgAccess.VarContext()) ); var passiveVarContextAbbrev = new AbbreviationDecl( @@ -120,7 +118,6 @@ relation used to construct the initial passive state set in the end-to-end proof GetCfgLemmaName(beforePassificationCfg.entry, lemmaNamer), boogieToVcTheoryName + "." + boogieToVcLemma.Name, vcAssm, - beforePhaseProgramAccess, beforePassiveProgAccess, passiveProgAccess, varContextNonPassivePassive, @@ -133,7 +130,7 @@ relation used to construct the initial passive state set in the end-to-end proof var imports = new List { - "Boogie_Lang.Semantics", "Boogie_Lang.Util", beforePhaseProgramAccess.TheoryName(), + "Boogie_Lang.Semantics", "Boogie_Lang.Util", beforePassiveProgAccess.TheoryName(), passiveProgAccess.TheoryName(), "Boogie_Lang.PassificationML", boogieToVcTheoryName }; diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 546d5be19..bae0e33d8 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -745,9 +745,9 @@ from calls. false, false, false, - proofGenInfo.GetOptimizationsFlag(), + parentAccessorForBeforeCfgToDag == null || proofGenInfo.GetOptimizationsFlag(), parentAccessorForBeforeCfgToDag != null ? SpecsConfig.None : specsConfigDefault, - proofGenInfo.GetOptimizationsFlag()); + parentAccessorForBeforeCfgToDag == null || proofGenInfo.GetOptimizationsFlag()); beforeCfgToDagProgAccess = new IsaProgramGenerator().GetIsaProgram( beforeCfgToDagTheoryName, @@ -789,7 +789,7 @@ from calls. false, parentProgramAccessorForPassification == null, parentProgramAccessorForPassification != null ? SpecsConfig.None : specsConfigDefault, - false); + parentProgramAccessorForPassification == null); beforePassiveProgAccess = new IsaProgramGenerator().GetIsaProgram(beforePassiveProgTheoryName, afterPassificationImpl.Name, afterOptimizationsData, beforePassiveConfig, afterOptimizationsVarTranslationFactory, @@ -935,7 +935,6 @@ out var endToEndLemmaPrelim beforePassiveToAfterPassiveBlock, passiveRelationGen, beforePassiveProgAccess, - beforePassiveProgAccess, passiveProgAccess, afterOptimizationsData, afterOptimizationsVarTranslationFactory, From fdcda032cf8679547f57397c7dd9e00764e0df81 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 10 May 2023 21:11:52 +0200 Subject: [PATCH 036/123] fix and get rid of more accessors other than the two that are required for a phase --- Source/Core/AstToCfgProofGenInfo.cs | 2 +- Source/ExecutionEngine/ExecutionEngine.cs | 2 +- .../CfgToDag/CfgToDagLemmaManager.cs | 29 ++++++++----------- .../CfgToDag/CfgToDagManager.cs | 11 +------ .../ProofGeneration/ProofGenerationLayer.cs | 4 +-- 5 files changed, 16 insertions(+), 32 deletions(-) diff --git a/Source/Core/AstToCfgProofGenInfo.cs b/Source/Core/AstToCfgProofGenInfo.cs index 9ae7a614c..e0039b7cb 100644 --- a/Source/Core/AstToCfgProofGenInfo.cs +++ b/Source/Core/AstToCfgProofGenInfo.cs @@ -136,7 +136,7 @@ public bool GetOptimizationsFlag() return optimizationsDone; } - public IList GetUnpotimizedBlocks() + public IList GetUnoptimizedBlocks() { return unoptimizedBlocks; } diff --git a/Source/ExecutionEngine/ExecutionEngine.cs b/Source/ExecutionEngine/ExecutionEngine.cs index 08b85caba..4c2c940c8 100644 --- a/Source/ExecutionEngine/ExecutionEngine.cs +++ b/Source/ExecutionEngine/ExecutionEngine.cs @@ -514,7 +514,7 @@ public static bool ProcessProgram(Program program, string bplFileName, string pr Implementation impl = tuple.Key; AstToCfgProofGenInfo proofGenInfo = tuple.Value; - IList unoptimizedBlocksCopies = proofGenInfo.GetUnpotimizedBlocks(); + IList unoptimizedBlocksCopies = proofGenInfo.GetUnoptimizedBlocks(); IList optimizedBlocksOriginal = impl.Blocks; int totalNumberOfCommandsA = 0; diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagLemmaManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagLemmaManager.cs index 814bd4490..467bc13ad 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagLemmaManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagLemmaManager.cs @@ -18,8 +18,6 @@ public class CfgToDagLemmaManager private readonly IProgramAccessor afterDagProgAccess; private readonly Block afterExitBlock; - private readonly IProgramAccessor beforeCfgProgAccess; - private readonly BasicCmdIsaVisitor basicCmdIsaVisitor; private readonly IProgramAccessor beforeDagProgAccess; @@ -53,7 +51,6 @@ public class CfgToDagLemmaManager //afterExitBlock is non-null iff afterExitBlock is a newly generated unique exit block after the CFG-to-DAG transformation public CfgToDagLemmaManager( - IProgramAccessor beforeCfgProgAccess, IProgramAccessor beforeDagProgAccess, IProgramAccessor afterDagProgAccess, BoogieContextIsa boogieContext, @@ -67,7 +64,6 @@ public CfgToDagLemmaManager( IVariableTranslationFactory varFactory ) { - this.beforeCfgProgAccess = beforeCfgProgAccess; this.beforeDagProgAccess = beforeDagProgAccess; this.afterDagProgAccess = afterDagProgAccess; this.afterDagCfg = afterDagCfg; @@ -82,7 +78,7 @@ IVariableTranslationFactory varFactory initState1 = IsaBoogieTerm.Normal(normalInitState1); initState2 = IsaBoogieTerm.Normal(normalInitState2); basicCmdIsaVisitor = new BasicCmdIsaVisitor(varFactory); - typingTacticGenerator = new TypingTacticGenerator(beforeCfgProgAccess, varFactory); + typingTacticGenerator = new TypingTacticGenerator(beforeDagProgAccess, varFactory); } private TermList HavocedVarsTerm(IEnumerable vars) @@ -285,7 +281,7 @@ public LemmaDecl EntryLemma(string lemmaName, Block beforeEntryBlock, Block afte assumptions.Add(dagVerifiesCfgAssm); var preAssm = - IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState2, beforeCfgProgAccess.PreconditionsDecl()); + IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState2, beforeDagProgAccess.PreconditionsDecl()); assumptions.Add(preAssm); var afterEntrySuccessors = afterDagCfg.GetSuccessorBlocks(afterEntryBlock); @@ -305,10 +301,10 @@ public LemmaDecl EntryLemma(string lemmaName, Block beforeEntryBlock, Block afte ProofUtil.Apply("erule assms(3)"), ProofUtil.Apply("rule assms(2)"), "unfolding " + afterDagProgAccess.BlockInfo().CmdsQualifiedName(afterEntryBlock) + "_def", - ProofUtil.Apply("rule assume_pres_normal[where ?es=" + beforeCfgProgAccess.PreconditionsDeclName() + + ProofUtil.Apply("rule assume_pres_normal[where ?es=" + beforeDagProgAccess.PreconditionsDeclName() + "]"), ProofUtil.Apply("rule assms(4)"), - "unfolding " + beforeCfgProgAccess.PreconditionsDeclName() + "_def", + "unfolding " + beforeDagProgAccess.PreconditionsDeclName() + "_def", "apply simp", ProofUtil.Apply("rule " + afterDagProgAccess.BlockInfo().OutEdgesMembershipLemma(afterEntryBlock)), ProofUtil.Apply(ProofUtil.Simp( @@ -345,7 +341,7 @@ public IList UnifiedExitLemma(string lemmaName) }; var conclusion = IsaBoogieTerm.ExprAllSat(boogieContext, normalInitState2, - beforeCfgProgAccess.PostconditionsDecl()); + beforeDagProgAccess.PostconditionsDecl()); var typingTactics = new List(); var lemmas = new List(); @@ -367,7 +363,7 @@ public IList UnifiedExitLemma(string lemmaName) conclusion, new Proof(new List { - "unfolding expr_all_sat_def " + beforeCfgProgAccess.PostconditionsDeclName() + "_def ", + "unfolding expr_all_sat_def " + beforeDagProgAccess.PostconditionsDeclName() + "_def ", ProofUtil.Apply("rule cfg_dag_rel_post_invs_3"), "apply (erule assms(1))", ProofUtil.Apply("rule " + @@ -526,7 +522,7 @@ public Tuple, LemmaDecl> BlockLemma( if (blockHeadHint != null) foreach (var x in blockHeadHint.ModifiedVars) - proofMethods.Add(ProofUtil.Apply(ProofUtil.Simp(beforeCfgProgAccess.LookupVarDeclLemma(x)))); + proofMethods.Add(ProofUtil.Apply(ProofUtil.Simp(beforeDagProgAccess.LookupVarDeclLemma(x)))); //TODO proof that post invariants reduce to booleans proofMethods.Add(TypingTactics(typingTactics, null)); @@ -630,7 +626,7 @@ public Tuple, LemmaDecl> BlockLemma( private Term CfgLemmaConclusion(Term finalNode, Term finalState) { - return CfgLemmaConclusion(boogieContext, beforeCfgProgAccess.PostconditionsDecl(), + return CfgLemmaConclusion(boogieContext, beforeDagProgAccess.PostconditionsDecl(), finalNode, finalState); } @@ -913,9 +909,8 @@ private string TypingTactics(IEnumerable typingTactics, string stateWtTh ProofUtil.OF("" + "type_safety_top_level_inv", funContextWfName, - beforeCfgProgAccess.FuncsWfTyLemma(), - beforeCfgProgAccess - .VarContextWfTyLemma()))); + beforeDagProgAccess.FuncsWfTyLemma(), + beforeDagProgAccess.VarContextWfTyLemma()))); if (stateWtThm != null) sb.AppendLine(ProofUtil.Apply("rule " + stateWtThm)); @@ -981,7 +976,7 @@ Func cfgLemmaName .BlockCmdsMembershipLemma(afterBlock))); sb.AppendLine(ProofUtil.Apply("erule " + dagVerifiesName)); sb.AppendLine(ProofUtil.Apply("rule " + dagAssmsName)); - sb.AppendLine("unfolding " + beforeCfgProgAccess.PostconditionsDeclName() + "_def"); + sb.AppendLine("unfolding " + beforeDagProgAccess.PostconditionsDeclName() + "_def"); sb.AppendLine(ProofUtil.Apply("rule " + blockLemmaName(beforeBlock))); sb.AppendLine("apply assumption+"); sb.AppendLine( @@ -1157,7 +1152,7 @@ Term numSteps cfg, modVars, invs, - beforeCfgProgAccess.PostconditionsDecl(), + beforeDagProgAccess.PostconditionsDecl(), normalState, finalState, loopHeadNode, diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs index 34f98aa60..987e44234 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs @@ -24,7 +24,6 @@ public class CfgToDagManager public static Theory CfgToDagProof( PhasesTheories phasesTheories, bool generateEndToEndLemma, - bool generatedAstToCfgProof, bool generatePassificationProof, bool generateVcProof, Term vcAssm, @@ -34,16 +33,10 @@ public static Theory CfgToDagProof( BoogieMethodData beforeDagData, CfgToDagHintManager hintManager, IDictionary beforeToAfter, - IProgramAccessor beforeCfgProgAccess, IProgramAccessor beforeDagProgAccess, IProgramAccessor afterDagProgAccess, IVariableTranslationFactory varFactory) { - if (!generatedAstToCfgProof) - { - beforeCfgProgAccess = beforeDagProgAccess; - } - 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 @@ -85,7 +78,6 @@ public static Theory CfgToDagProof( IsaCommonTerms.TermIdentFromName("\\"), IsaCommonTerms.EmptyList); var lemmaManager = new CfgToDagLemmaManager( - beforeCfgProgAccess, beforeDagProgAccess, afterDagProgAccess, boogieContext, @@ -199,7 +191,7 @@ public static Theory CfgToDagProof( }, new List { - IsaBoogieTerm.FunInterpWf(boogieContext.absValTyMap, beforeCfgProgAccess.FunctionsDecl(), + IsaBoogieTerm.FunInterpWf(boogieContext.absValTyMap, beforeDagProgAccess.FunctionsDecl(), boogieContext.funContext) }, new List {funContextWfName} @@ -228,7 +220,6 @@ public static Theory CfgToDagProof( new List { "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.BackedgeElim", "Boogie_Lang.TypingML", - generatedAstToCfgProof ? beforeCfgProgAccess.TheoryName() : null, beforeDagProgAccess.TheoryName(), afterDagProgAccess.TheoryName(), generatePassificationProof ? phasesTheories.TheoryName(PhasesTheories.Phase.Passification) : "", diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index bae0e33d8..f8ec7922b 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -582,7 +582,7 @@ public static void VCGenerateAllProofs( DesugarCmdsInBigBlock(b); } - IList unoptimizedCfgBlocks = proofGenInfo.GetUnpotimizedBlocks(); + IList unoptimizedCfgBlocks = proofGenInfo.GetUnoptimizedBlocks(); var newToOldInternal = new Dictionary(); unoptimizedCfgBlocks.ZipDo(afterPassificationImpl.Blocks, (bNew, bOld) => newToOldInternal.Add(bNew, bOld)); beforeOptimizationsOrigBlock = newToOldInternal; @@ -958,7 +958,6 @@ out var endToEndLemmaPrelim var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( phasesTheories, _proofGenConfig.GenerateCfgDagE2E, - _proofGenConfig.GenerateAstCfgProof, _proofGenConfig.GeneratePassifProof, _proofGenConfig.GenerateVcProof, vcAssm, @@ -968,7 +967,6 @@ out var endToEndLemmaPrelim beforeDagData, cfgToDagHintManager, beforeDagAfterDagBlock, - beforeAstToCfgProgAccess, beforeCfgToDagProgAccess, beforePassiveProgAccess, afterOptimizationsVarTranslationFactory); From 741cbb413e6cf55503570445ad259864430111b9 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 10 May 2023 21:14:29 +0200 Subject: [PATCH 037/123] added FIXME for optimization flag --- Source/ExecutionEngine/ExecutionEngine.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/ExecutionEngine/ExecutionEngine.cs b/Source/ExecutionEngine/ExecutionEngine.cs index 4c2c940c8..d39e80c4c 100644 --- a/Source/ExecutionEngine/ExecutionEngine.cs +++ b/Source/ExecutionEngine/ExecutionEngine.cs @@ -516,6 +516,7 @@ public static bool ProcessProgram(Program program, string bplFileName, string pr IList unoptimizedBlocksCopies = proofGenInfo.GetUnoptimizedBlocks(); IList optimizedBlocksOriginal = impl.Blocks; + // FIXME: optimizedBlocksOriginal does not contain desugared commands while optimized does --> too many false positives int totalNumberOfCommandsA = 0; int totalNumberOfCommandsB = 0; From b5d91811d710ce3a5d38d95ae8ec689cad1c59f3 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 10 May 2023 21:29:10 +0200 Subject: [PATCH 038/123] comment out number replacement for preferred names --- Source/ProofGeneration/Util/IsaUniqueNamer.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/ProofGeneration/Util/IsaUniqueNamer.cs b/Source/ProofGeneration/Util/IsaUniqueNamer.cs index 813e176c6..c214fa9ac 100644 --- a/Source/ProofGeneration/Util/IsaUniqueNamer.cs +++ b/Source/ProofGeneration/Util/IsaUniqueNamer.cs @@ -64,6 +64,7 @@ public string GetName(object obj, string preferredName) var preferredNameMod = preferredName; foreach (var illegalChar in illegalChars) preferredNameMod = preferredNameMod.Replace(illegalChar, '_'); + /* TODO: might need to replace numbers in some cases for ROOT file if (preferredNameMod.Contains('0')) preferredNameMod = preferredNameMod.Replace('0', 'a'); if (preferredNameMod.Contains('1')) preferredNameMod = preferredNameMod.Replace('1', 'b'); if (preferredNameMod.Contains('2')) preferredNameMod = preferredNameMod.Replace('2', 'c'); @@ -74,6 +75,7 @@ public string GetName(object obj, string preferredName) if (preferredNameMod.Contains('7')) preferredNameMod = preferredNameMod.Replace('7', 'h'); if (preferredNameMod.Contains('8')) preferredNameMod = preferredNameMod.Replace('8', 'i'); if (preferredNameMod.Contains('9')) preferredNameMod = preferredNameMod.Replace('9', 'j'); + */ if (reservedNames.Contains(preferredNameMod)) preferredNameMod = preferredNameMod + "ZZ"; if (preferredName.Length > 0 && preferredName.Last() == '_') preferredNameMod = preferredNameMod + "n"; From 8a27db81e8525784583dc6dc21773c672da7baba Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 16 May 2023 21:19:39 +0200 Subject: [PATCH 039/123] fix bug --- .../BoogieIsaInterface/MembershipLemmaManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs index da68d4c1e..6cfdf8e92 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs @@ -298,7 +298,7 @@ public string LookupVarDeclLemma(Variable v) if (lookupVarTyLemmas.TryGetValue(v, out var result)) return QualifyAccessName(result.Name+"(1)"); - return parent.LookupVarTyLemma(v); + return parent.LookupVarDeclLemma(v); } public string LookupVarTyLemma(Variable v) From 9775867a928cd132123f5389346108da451142a5 Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Wed, 7 Jun 2023 09:09:59 +0200 Subject: [PATCH 040/123] First try optimizations proof generations --- .../CFGOptimizationsLemmaManager.cs | 60 ++++++++++ .../CFGOptimizationsManager.cs | 111 ++++++++++++++++++ Source/ProofGeneration/PhasesTheories.cs | 5 + .../ProofGeneration/ProofGenerationLayer.cs | 18 +++ 4 files changed, 194 insertions(+) create mode 100644 Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs create mode 100644 Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs new file mode 100644 index 000000000..c4f4effd4 --- /dev/null +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -0,0 +1,60 @@ +using Isabelle.Ast; +using ProofGeneration.BoogieIsaInterface; +using System; +using System.Collections.Generic; +using System.Linq; +using Isabelle.Ast; +using Isabelle.Util; +using Microsoft.Boogie; +using ProofGeneration.BoogieIsaInterface; +using ProofGeneration.BoogieIsaInterface.VariableTranslation; +using ProofGeneration.CFGRepresentation; +using ProofGeneration.Util; + + +namespace ProofGeneration.CFGOptimizations; + +public class CFGOptimizationsLemmaManager +{ + public CFGOptimizationsLemmaManager( + IProgramAccessor beforeDagProgAcces, + IProgramAccessor afterCfgProgAccess, + BoogieContextIsa boogieContext, + CFGRepr beforeOptimizations, + CFGRepr afterOptimizations, + string funContextWfName, + IDictionary beforeToAfterBlock + ) + { + + } + + public LemmaDecl GlobalBlockLemmaPruning( + Block beforeBlock, + Block afterBlock, + Func blockLemmaName, + Func cfgLemmaName) + { + var proofMethods = new List + { + "apply (rule pruning_not_coalesced_loop)", + "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeBlock.UniqueId + ")", + "apply (rule p_before_cfg_to_dag_prog.outEdges_" + afterBlock.UniqueId + ")", + "apply (rule p_unoptimized_cfg_prog.node_" + beforeBlock.UniqueId + ")", + "apply (unfold p_unoptimized_cfg_prog.block_" + beforeBlock.UniqueId + "_def)", + "apply simp", + "apply (unfold p_before_cfg_to_dag_prog.block_" + afterBlock.UniqueId + "_def)", + "by simp" + }; + + //var blockLemma = new LemmaDecl( + // blockLemmaName(beforeBlock), + // assumptions, //not sure what my assumptions should be + //conclusion, //not sure what my conclusion should be + // new Proof(proofMethods) + //); + return null; + } + + +} \ No newline at end of file diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs new file mode 100644 index 000000000..e46f3de3b --- /dev/null +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -0,0 +1,111 @@ +using Isabelle.Ast; +using ProofGeneration.BoogieIsaInterface; +using System; +using System.Collections.Generic; +using System.Linq; +using Isabelle.Ast; +using Isabelle.Util; +using Microsoft.Boogie; +using ProofGeneration.BoogieIsaInterface; +using ProofGeneration.BoogieIsaInterface.VariableTranslation; +using ProofGeneration.CFGRepresentation; +using ProofGeneration.Util; + + +namespace ProofGeneration.CFGOptimizations; + +public class CfgOptimizationsManager +{ + + //string uniqueTheoryName, + //PhasesTheories phasesTheories, + public static Theory CfgOptProof( + PhasesTheories phasesTheories, + CFGRepr beforeOptimizations, + CFGRepr afterOptimizations, + IDictionary beforeToAfter, // mapping from current block to target block + IProgramAccessor afterCfgProgAccess, //before CFG optimizations + IProgramAccessor beforeDagProgAcces) //after CFG optimizations + + { + + var varContextName = "\\"; + var varContextAbbrev = new AbbreviationDecl( + varContextName, + new Tuple, Term>(new List(), beforeDagProgAcces.VarContext())); + + var funContextWfName = "Wf_Fun"; + + + var BoogieContext = new BoogieContextIsa( + IsaCommonTerms.TermIdentFromName("A"), + IsaCommonTerms.TermIdentFromName("M"), + IsaCommonTerms.TermIdentFromName(varContextName), + IsaCommonTerms.TermIdentFromName("\\"), + IsaCommonTerms.TermIdentFromName("\\")); + + + var lemmaManager = new CFGOptimizationsLemmaManager( + beforeDagProgAcces, + afterCfgProgAccess, + BoogieContext, + beforeOptimizations, + afterOptimizations, + funContextWfName, + beforeToAfter); //TODO: Add necessary declarations + + var lemmaNamer = new IsaUniqueNamer(); + var outerDecls = new List(); + + + outerDecls.Add(varContextAbbrev); + outerDecls.Add(new DeclareDecl("Nat.One_nat_def[simp del]")); + List proofMethods = new List(); + + //In a first try I assume that there is no block coalescing and no loops + foreach (Block beforeBlock in beforeOptimizations.GetBlocksBackwards()) + { + Block afterBlock = beforeToAfter[beforeBlock]; + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //If there is an assume or assert false statement in the block + { + var pruning = lemmaManager.GlobalBlockLemmaPruning(beforeBlock, afterBlock, null, null); + outerDecls.Add(pruning); + } + else //otherwhise we just need to apply the normal global block lemma + { + if (beforeBlock.succCount == 0) //if the block has no successors + { + proofMethods.Add(ProofUtil.Apply("rule loopBlock_global_block")); + proofMethods.Add(ProofUtil.Apply("rule p_unoptimized_cfg_prog.outEdges_" + beforeBlock.UniqueId)); + proofMethods.Add(ProofUtil.Apply("auto[1]")); + proofMethods.Add(ProofUtil.Apply("auto[1]")); + proofMethods.Add(ProofUtil.Apply("rule p_before_cfg_to_dag_prog.node_" + afterBlock.UniqueId)); + proofMethods.Add(ProofUtil.Apply("rule p_unoptimized_cfg_prog.node_" + beforeBlock.UniqueId)); + proofMethods.Add(ProofUtil.Apply("unfold p_before_cfg_to_dag_prog.block_" + afterBlock.UniqueId + "_def p_unoptimized_cfg_prog.block_" + beforeBlock.UniqueId + "_def")); + proofMethods.Add(ProofUtil.Apply("simp")); + proofMethods.Add("done"); + + } + else //Block was not coalesced and has successors. Assumption: Global Block Lemma holds for all successors + { + proofMethods.Add(""); + } + } + } + + List importTheories = new List + { + "Boogie_Lang.Ast", "Boogie_Lang.Ast_Cfg_Transformation", "Boogie_Lang.Semantics", "Boogie_Lang.Util", "CFGOptimizationsLoop", + beforeDagProgAcces.TheoryName(), + afterCfgProgAccess.TheoryName() + }; + + return new Theory( + phasesTheories.TheoryName(PhasesTheories.Phase.CfgOptimizations), //TODO: Make sure that I did that correctly + importTheories, + outerDecls + ); + } + + +} \ No newline at end of file diff --git a/Source/ProofGeneration/PhasesTheories.cs b/Source/ProofGeneration/PhasesTheories.cs index 793b7dc07..cc713b553 100644 --- a/Source/ProofGeneration/PhasesTheories.cs +++ b/Source/ProofGeneration/PhasesTheories.cs @@ -7,12 +7,14 @@ public enum Phase Vc, Passification, CfgToDag, + CfgOptimizations, AstToCfg } private readonly string astToCfgTheoryName; private readonly string cfgToDagTheoryName; private readonly string passificationTheoryName; + private readonly string CfgOptimizationsTheoryName; private readonly string vcPhaseTheoryName; @@ -22,6 +24,7 @@ public PhasesTheories(string prefix) vcPhaseTheoryName = prefix + "_vcphase_proof"; passificationTheoryName = prefix + "_passification_proof"; cfgToDagTheoryName = prefix + "_cfgtodag_proof"; + CfgOptimizationsTheoryName = prefix + "_cfgoptimizations_proof"; astToCfgTheoryName = prefix + "_asttocfg_proof"; } @@ -35,6 +38,8 @@ public string TheoryName(Phase phase) return passificationTheoryName; case Phase.CfgToDag: return cfgToDagTheoryName; + case Phase.CfgOptimizations: + return CfgOptimizationsTheoryName; case Phase.AstToCfg: return astToCfgTheoryName; default: diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index f8ec7922b..99960acea 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -12,6 +12,7 @@ using ProofGeneration.AstToCfg; using ProofGeneration.BoogieIsaInterface; using ProofGeneration.BoogieIsaInterface.VariableTranslation; +using ProofGeneration.CFGOptimizations; using ProofGeneration.CFGRepresentation; using ProofGeneration.CfgToDag; using ProofGeneration.Passification; @@ -975,6 +976,23 @@ out var endToEndLemmaPrelim #endregion } + //TODO: change flag to proof flag + if (_proofGenConfig.GenerateUnoptimizedCfgProg(proofGenInfo.GetOptimizationsFlag())) + { + #region cfg optimizations + + var cfgOptimizationsProofTheory = CfgOptimizationsManager.CfgOptProof( + phasesTheories, + beforeOptimizationsCFG, + beforeDagCfg, + beforeOptimizationsOrigBlock, + beforeAstToCfgProgAccess, + beforeCfgToDagProgAccess); + theories.Add(cfgOptimizationsProofTheory); + + #endregion + } + if (_proofGenConfig.GenerateAstCfgProof) { #region ast to cfg From 32cbe2b3a66a71315df9c0db31414aa0024bcc27 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 7 Jun 2023 09:35:35 +0200 Subject: [PATCH 041/123] generate unoptimized program also if AST-to-CFG proof is not generated --- Source/ProofGeneration/ProofGenConfig.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ProofGeneration/ProofGenConfig.cs b/Source/ProofGeneration/ProofGenConfig.cs index 9c3fc4424..2c659a9ed 100644 --- a/Source/ProofGeneration/ProofGenConfig.cs +++ b/Source/ProofGeneration/ProofGenConfig.cs @@ -105,7 +105,7 @@ public ProofGenConfig SetVcProof(bool flag) public bool GenerateUnoptimizedCfgProg(bool optimizationsHaveAnEffect) { - return optimizationsHaveAnEffect && GenerateAstCfgProof; + return optimizationsHaveAnEffect; } public bool GenerateBeforeCfgDagProg(bool optimizationsHaveAnEffect) From ca93f23e33255a2d1ca9372e8b467a786b82804f Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 7 Jun 2023 09:36:33 +0200 Subject: [PATCH 042/123] input unoptimized CFG program access to CFGOptimizationsLemmaManager, rename program accessors --- .../CFGOptimizations/CFGOptimizationsManager.cs | 14 +++++++------- Source/ProofGeneration/ProofGenerationLayer.cs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index e46f3de3b..51d4aa70d 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -24,15 +24,15 @@ public static Theory CfgOptProof( CFGRepr beforeOptimizations, CFGRepr afterOptimizations, IDictionary beforeToAfter, // mapping from current block to target block - IProgramAccessor afterCfgProgAccess, //before CFG optimizations - IProgramAccessor beforeDagProgAcces) //after CFG optimizations + IProgramAccessor beforeOptCfgProgAcccess, //before CFG optimizations + IProgramAccessor afterOptCfgProgAccess) //after CFG optimizations { var varContextName = "\\"; var varContextAbbrev = new AbbreviationDecl( varContextName, - new Tuple, Term>(new List(), beforeDagProgAcces.VarContext())); + new Tuple, Term>(new List(), afterOptCfgProgAccess.VarContext())); var funContextWfName = "Wf_Fun"; @@ -46,8 +46,8 @@ public static Theory CfgOptProof( var lemmaManager = new CFGOptimizationsLemmaManager( - beforeDagProgAcces, - afterCfgProgAccess, + afterOptCfgProgAccess, + beforeOptCfgProgAcccess, BoogieContext, beforeOptimizations, afterOptimizations, @@ -96,8 +96,8 @@ public static Theory CfgOptProof( List importTheories = new List { "Boogie_Lang.Ast", "Boogie_Lang.Ast_Cfg_Transformation", "Boogie_Lang.Semantics", "Boogie_Lang.Util", "CFGOptimizationsLoop", - beforeDagProgAcces.TheoryName(), - afterCfgProgAccess.TheoryName() + afterOptCfgProgAccess.TheoryName(), + beforeOptCfgProgAcccess.TheoryName() }; return new Theory( diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 99960acea..b71fa4bb6 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -986,7 +986,7 @@ out var endToEndLemmaPrelim beforeOptimizationsCFG, beforeDagCfg, beforeOptimizationsOrigBlock, - beforeAstToCfgProgAccess, + unoptimizedCfgProgAccess, beforeCfgToDagProgAccess); theories.Add(cfgOptimizationsProofTheory); From de015242a36bb9688d428c6e766cb7ee4171f2e8 Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Wed, 7 Jun 2023 16:00:54 +0200 Subject: [PATCH 043/123] Work in progress Work in progress: First attempt to generate proofs for unreachable blocks and the normal global block lemma without successors. --- .../CFGOptimizationsLemmaManager.cs | 111 ++++++++++++++++-- .../CFGOptimizationsManager.cs | 51 ++++---- Source/ProofGeneration/ProofGenConfig.cs | 2 +- .../ProofGeneration/ProofGenerationLayer.cs | 11 +- 4 files changed, 132 insertions(+), 43 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index c4f4effd4..3ae295755 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -2,6 +2,7 @@ using ProofGeneration.BoogieIsaInterface; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using Isabelle.Ast; using Isabelle.Util; @@ -24,22 +25,21 @@ public CFGOptimizationsLemmaManager( CFGRepr afterOptimizations, string funContextWfName, IDictionary beforeToAfterBlock - ) + ) { } - public LemmaDecl GlobalBlockLemmaPruning( + public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable blocks where no coalescing happened Block beforeBlock, Block afterBlock, - Func blockLemmaName, - Func cfgLemmaName) + string blockLemmaName) { var proofMethods = new List { "apply (rule pruning_not_coalesced_loop)", "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeBlock.UniqueId + ")", - "apply (rule p_before_cfg_to_dag_prog.outEdges_" + afterBlock.UniqueId + ")", + "apply (rule p_before_cfg_to_dag_prog.node_" + afterBlock.UniqueId + ")", "apply (rule p_unoptimized_cfg_prog.node_" + beforeBlock.UniqueId + ")", "apply (unfold p_unoptimized_cfg_prog.block_" + beforeBlock.UniqueId + "_def)", "apply simp", @@ -47,13 +47,100 @@ public LemmaDecl GlobalBlockLemmaPruning( "by simp" }; - //var blockLemma = new LemmaDecl( - // blockLemmaName(beforeBlock), - // assumptions, //not sure what my assumptions should be - //conclusion, //not sure what my conclusion should be - // new Proof(proofMethods) - //); - return null; + var varContextName = "\\"; + IList terms = new List(); + terms.Add(IsaCommonTerms.TermIdentFromName("A")); + terms.Add(IsaCommonTerms.TermIdentFromName("M")); + terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(new NatConst(beforeBlock.UniqueId)); + terms.Add(new NatConst(afterBlock.UniqueId)); + terms.Add(IsaCommonTerms.EmptySet); + Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + + + var blockLemma = new LemmaDecl( + blockLemmaName, + conclusion, + new Proof(proofMethods)); + return blockLemma; + } + + public LemmaDecl GlobalBlockLemma( //normal global block lemma where the global block lemma needs to hold for all successors + Block beforeBlock, + Block afterBlock, + string blockLemmaName) + { + if (beforeBlock.succCount == 0) + { + var proofMethods = new List + { + "apply (rule loopBlock_global_block)", + "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeBlock.UniqueId + ")", + "apply (auto)", + "apply (unfold p_before_cfg_to_dag_prog.node_" + afterBlock.UniqueId + ")", + "apply (unfold p_unoptimized_cfg_prog.node_" + beforeBlock.UniqueId + ")", + "apply (unfold p_before_cfg_to_dag_prog.block_" + afterBlock.UniqueId + "_def p_unoptimized_cfg_prog.block_" + + beforeBlock.UniqueId + "_def)", + "by simp" + }; + + + var varContextName = "\\"; + IList terms = new List(); + terms.Add(IsaCommonTerms.TermIdentFromName("A")); + terms.Add(IsaCommonTerms.TermIdentFromName("M")); + terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(new NatConst(beforeBlock.UniqueId)); + terms.Add(new NatConst(afterBlock.UniqueId)); + terms.Add(IsaCommonTerms.EmptySet); + Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + + + var blockLemma = new LemmaDecl( + blockLemmaName, + conclusion, + new Proof(proofMethods)); + return blockLemma; + } + else + { + var proofMethods = new List + { + "apply (rule loopBlock_global_block[where ?f = \"how\" ]", + "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeBlock.UniqueId + ")", + "apply (unfold how_def)", + "apply simp", + "apply (intro conjI)" + }; + //foreach (Block succ in beforeBlock.Predecessors) + var varContextName = "\\"; + IList terms = new List(); + terms.Add(IsaCommonTerms.TermIdentFromName("A")); + terms.Add(IsaCommonTerms.TermIdentFromName("M")); + terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(new NatConst(beforeBlock.UniqueId)); + terms.Add(new NatConst(afterBlock.UniqueId)); + terms.Add(IsaCommonTerms.EmptySet); + Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + + var blockLemma = new LemmaDecl( + blockLemmaName, + conclusion, + new Proof(proofMethods)); + return blockLemma; + } } diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index e46f3de3b..7713060e8 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -24,15 +24,15 @@ public static Theory CfgOptProof( CFGRepr beforeOptimizations, CFGRepr afterOptimizations, IDictionary beforeToAfter, // mapping from current block to target block - IProgramAccessor afterCfgProgAccess, //before CFG optimizations - IProgramAccessor beforeDagProgAcces) //after CFG optimizations + IProgramAccessor beforeOptCfgProgAcccess, //before CFG optimizations + IProgramAccessor afterOptCfgProgAccess) //after CFG optimizations { var varContextName = "\\"; var varContextAbbrev = new AbbreviationDecl( varContextName, - new Tuple, Term>(new List(), beforeDagProgAcces.VarContext())); + new Tuple, Term>(new List(), afterOptCfgProgAccess.VarContext())); var funContextWfName = "Wf_Fun"; @@ -46,8 +46,8 @@ public static Theory CfgOptProof( var lemmaManager = new CFGOptimizationsLemmaManager( - beforeDagProgAcces, - afterCfgProgAccess, + afterOptCfgProgAccess, + beforeOptCfgProgAcccess, BoogieContext, beforeOptimizations, afterOptimizations, @@ -68,44 +68,39 @@ public static Theory CfgOptProof( Block afterBlock = beforeToAfter[beforeBlock]; if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //If there is an assume or assert false statement in the block { - var pruning = lemmaManager.GlobalBlockLemmaPruning(beforeBlock, afterBlock, null, null); + var pruning = lemmaManager.GlobalBlockLemmaPruningNotCoalesced(beforeBlock, afterBlock, GetGlobalBlockLemmaName(beforeBlock, lemmaNamer)); outerDecls.Add(pruning); } - else //otherwhise we just need to apply the normal global block lemma + else //otherwhise we just need to apply the normal global block lemma. Assumption: Global Block Lemma holds for all successors { - if (beforeBlock.succCount == 0) //if the block has no successors - { - proofMethods.Add(ProofUtil.Apply("rule loopBlock_global_block")); - proofMethods.Add(ProofUtil.Apply("rule p_unoptimized_cfg_prog.outEdges_" + beforeBlock.UniqueId)); - proofMethods.Add(ProofUtil.Apply("auto[1]")); - proofMethods.Add(ProofUtil.Apply("auto[1]")); - proofMethods.Add(ProofUtil.Apply("rule p_before_cfg_to_dag_prog.node_" + afterBlock.UniqueId)); - proofMethods.Add(ProofUtil.Apply("rule p_unoptimized_cfg_prog.node_" + beforeBlock.UniqueId)); - proofMethods.Add(ProofUtil.Apply("unfold p_before_cfg_to_dag_prog.block_" + afterBlock.UniqueId + "_def p_unoptimized_cfg_prog.block_" + beforeBlock.UniqueId + "_def")); - proofMethods.Add(ProofUtil.Apply("simp")); - proofMethods.Add("done"); - - } - else //Block was not coalesced and has successors. Assumption: Global Block Lemma holds for all successors - { - proofMethods.Add(""); - } + var globalBlock = lemmaManager.GlobalBlockLemma(beforeBlock, afterBlock, GetGlobalBlockLemmaName(beforeBlock, lemmaNamer)); + outerDecls.Add(globalBlock); } } List importTheories = new List { - "Boogie_Lang.Ast", "Boogie_Lang.Ast_Cfg_Transformation", "Boogie_Lang.Semantics", "Boogie_Lang.Util", "CFGOptimizationsLoop", - beforeDagProgAcces.TheoryName(), - afterCfgProgAccess.TheoryName() + "Boogie_Lang.Ast", "Boogie_Lang.Ast_Cfg_Transformation", "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.CFGOptimizationsLoop", + afterOptCfgProgAccess.TheoryName(), + beforeOptCfgProgAcccess.TheoryName() }; return new Theory( - phasesTheories.TheoryName(PhasesTheories.Phase.CfgOptimizations), //TODO: Make sure that I did that correctly + phasesTheories.TheoryName(PhasesTheories.Phase.CfgOptimizations), importTheories, outerDecls ); } + + private static string GetGlobalBlockLemmaName(Block b, IsaUniqueNamer namer) + { + return "global_block_lemma_" + namer.GetName(b, "block_" + b.Label); + } + + private static string GetHybridBlockLemmaName(Block b, IsaUniqueNamer namer) + { + return "hybrid_block_lemma_" + namer.GetName(b, "block_" + b.Label); + } } \ No newline at end of file diff --git a/Source/ProofGeneration/ProofGenConfig.cs b/Source/ProofGeneration/ProofGenConfig.cs index 9c3fc4424..2c659a9ed 100644 --- a/Source/ProofGeneration/ProofGenConfig.cs +++ b/Source/ProofGeneration/ProofGenConfig.cs @@ -105,7 +105,7 @@ public ProofGenConfig SetVcProof(bool flag) public bool GenerateUnoptimizedCfgProg(bool optimizationsHaveAnEffect) { - return optimizationsHaveAnEffect && GenerateAstCfgProof; + return optimizationsHaveAnEffect; } public bool GenerateBeforeCfgDagProg(bool optimizationsHaveAnEffect) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 99960acea..c705632df 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -38,6 +38,7 @@ public class ProofGenerationLayer private static IDictionary beforeOptimizationsOrigBlock; private static IDictionary beforeDagOrigBlock; private static IDictionary beforeDagAfterDagBlock; + private static IDictionary beforeOptAfterOptBlock; private static CFGRepr beforeOptimizationsCFG; @@ -240,6 +241,7 @@ out var newVarsFromDesugaring // compute mapping between copied blocks (before dag -> after dag) var origToAfterDag = beforePassiveOrigBlock.InverseDict(); + beforeDagAfterDagBlock = DictionaryComposition(beforeDagOrigBlock, origToAfterDag); } @@ -981,12 +983,17 @@ out var endToEndLemmaPrelim { #region cfg optimizations + // compute mapping between copied blocks (before opt -> after opt) + var origToAfterOpt = beforeDagOrigBlock.InverseDict(); + beforeOptAfterOptBlock = DictionaryComposition(beforeOptimizationsOrigBlock, origToAfterOpt); + + var cfgOptimizationsProofTheory = CfgOptimizationsManager.CfgOptProof( phasesTheories, beforeOptimizationsCFG, beforeDagCfg, - beforeOptimizationsOrigBlock, - beforeAstToCfgProgAccess, + beforeOptAfterOptBlock, //not sure if this is correct + unoptimizedCfgProgAccess, beforeCfgToDagProgAccess); theories.Add(cfgOptimizationsProofTheory); From f7d26dd1921f6e25bd28cb3662fccb88f9b25acd Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Thu, 8 Jun 2023 09:41:56 +0200 Subject: [PATCH 044/123] unreachable blocks and normal global block lemma Work in progress: Finished with unreachable blocks and normal global block lemma. There is a small mistake that the lemmas are generated in the wrong order. --- .../CFGOptimizationsLemmaManager.cs | 94 +++++++++++++------ .../CFGOptimizationsManager.cs | 23 +++-- .../ProofGeneration/ProofGenerationLayer.cs | 11 ++- 3 files changed, 86 insertions(+), 42 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index 3ae295755..b26fa9f37 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -17,9 +17,16 @@ namespace ProofGeneration.CFGOptimizations; public class CFGOptimizationsLemmaManager { + private readonly IProgramAccessor beforeOptProgAccess; + private readonly IProgramAccessor afterOptProgAccess; + private readonly BoogieContextIsa boogieContext; + private readonly CFGRepr beforeOptimizations; + private readonly CFGRepr afterOptimizations; + private readonly string funContextWfName; + private readonly IDictionary beforeToAfterBlock; public CFGOptimizationsLemmaManager( - IProgramAccessor beforeDagProgAcces, - IProgramAccessor afterCfgProgAccess, + IProgramAccessor beforeOptProgAccess, + IProgramAccessor afterOptProgAccess, BoogieContextIsa boogieContext, CFGRepr beforeOptimizations, CFGRepr afterOptimizations, @@ -27,7 +34,13 @@ public CFGOptimizationsLemmaManager( IDictionary beforeToAfterBlock ) { - + this.beforeOptProgAccess = beforeOptProgAccess; + this.afterOptProgAccess = afterOptProgAccess; + this.boogieContext = boogieContext; + this.beforeOptimizations = beforeOptimizations; + this.afterOptimizations = afterOptimizations; + this.funContextWfName = funContextWfName; + this.beforeToAfterBlock = beforeToAfterBlock; } public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable blocks where no coalescing happened @@ -37,13 +50,14 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b { var proofMethods = new List { + "apply (rule pruning_not_coalesced_loop)", - "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeBlock.UniqueId + ")", - "apply (rule p_before_cfg_to_dag_prog.node_" + afterBlock.UniqueId + ")", - "apply (rule p_unoptimized_cfg_prog.node_" + beforeBlock.UniqueId + ")", - "apply (unfold p_unoptimized_cfg_prog.block_" + beforeBlock.UniqueId + "_def)", + "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply (rule p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")", + "apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply (unfold p_unoptimized_cfg_prog.block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + "_def)", "apply simp", - "apply (unfold p_before_cfg_to_dag_prog.block_" + afterBlock.UniqueId + "_def)", + "apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def)", "by simp" }; @@ -56,8 +70,8 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b terms.Add(IsaCommonTerms.TermIdentFromName("\\")); terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); - terms.Add(new NatConst(beforeBlock.UniqueId)); - terms.Add(new NatConst(afterBlock.UniqueId)); + terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); terms.Add(IsaCommonTerms.EmptySet); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); @@ -72,19 +86,20 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b public LemmaDecl GlobalBlockLemma( //normal global block lemma where the global block lemma needs to hold for all successors Block beforeBlock, Block afterBlock, - string blockLemmaName) + Func blockLemmaName) { - if (beforeBlock.succCount == 0) + + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() == 0) { var proofMethods = new List { "apply (rule loopBlock_global_block)", - "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeBlock.UniqueId + ")", + "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", "apply (auto)", - "apply (unfold p_before_cfg_to_dag_prog.node_" + afterBlock.UniqueId + ")", - "apply (unfold p_unoptimized_cfg_prog.node_" + beforeBlock.UniqueId + ")", - "apply (unfold p_before_cfg_to_dag_prog.block_" + afterBlock.UniqueId + "_def p_unoptimized_cfg_prog.block_" + - beforeBlock.UniqueId + "_def)", + "apply (unfold p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")", + "apply (unfold p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def p_unoptimized_cfg_prog.block_" + + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + "_def)", "by simp" }; @@ -98,29 +113,54 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b terms.Add(IsaCommonTerms.TermIdentFromName("\\")); terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); - terms.Add(new NatConst(beforeBlock.UniqueId)); - terms.Add(new NatConst(afterBlock.UniqueId)); + terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); terms.Add(IsaCommonTerms.EmptySet); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( - blockLemmaName, + blockLemmaName(beforeBlock), conclusion, new Proof(proofMethods)); return blockLemma; } else { + var function = new List(); + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + { + if (beforeToAfterBlock.Keys.Contains(succ)) + { + Block succAfter = beforeToAfterBlock[succ]; + function.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[succ] + "," + afterOptProgAccess.BlockInfo().BlockIds[succAfter] + ")"); + } + } + + var proofMethods = new List { - "apply (rule loopBlock_global_block[where ?f = \"how\" ]", - "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeBlock.UniqueId + ")", - "apply (unfold how_def)", + "apply (rule loopBlock_global_block[where ?f = \"the ∘ map_of [" + string.Join(",", function) + "]\"])", + "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", "apply simp", "apply (intro conjI)" }; - //foreach (Block succ in beforeBlock.Predecessors) + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + { + proofMethods.Add("apply (rule " + blockLemmaName(succ) + ")"); + } + proofMethods.Add("apply simp"); + proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.outEdges_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); + proofMethods.Add("apply (intro conjI)"); + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + { + proofMethods.Add("apply simp"); + } + proofMethods.Add("apply (rule p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); + proofMethods.Add("apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")"); + proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def p_unoptimized_cfg_prog.block_" + + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + "_def)"); + proofMethods.Add("by simp"); var varContextName = "\\"; IList terms = new List(); terms.Add(IsaCommonTerms.TermIdentFromName("A")); @@ -130,13 +170,13 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b terms.Add(IsaCommonTerms.TermIdentFromName("\\")); terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); - terms.Add(new NatConst(beforeBlock.UniqueId)); - terms.Add(new NatConst(afterBlock.UniqueId)); + terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); terms.Add(IsaCommonTerms.EmptySet); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( - blockLemmaName, + blockLemmaName(beforeBlock), conclusion, new Proof(proofMethods)); return blockLemma; diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index 7713060e8..13dbbb723 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -46,8 +46,8 @@ public static Theory CfgOptProof( var lemmaManager = new CFGOptimizationsLemmaManager( - afterOptCfgProgAccess, beforeOptCfgProgAcccess, + afterOptCfgProgAccess, BoogieContext, beforeOptimizations, afterOptimizations, @@ -65,16 +65,19 @@ public static Theory CfgOptProof( //In a first try I assume that there is no block coalescing and no loops foreach (Block beforeBlock in beforeOptimizations.GetBlocksBackwards()) { - Block afterBlock = beforeToAfter[beforeBlock]; - if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //If there is an assume or assert false statement in the block - { - var pruning = lemmaManager.GlobalBlockLemmaPruningNotCoalesced(beforeBlock, afterBlock, GetGlobalBlockLemmaName(beforeBlock, lemmaNamer)); - outerDecls.Add(pruning); - } - else //otherwhise we just need to apply the normal global block lemma. Assumption: Global Block Lemma holds for all successors + if (beforeToAfter.Keys.Contains(beforeBlock)) { - var globalBlock = lemmaManager.GlobalBlockLemma(beforeBlock, afterBlock, GetGlobalBlockLemmaName(beforeBlock, lemmaNamer)); - outerDecls.Add(globalBlock); + Block afterBlock = beforeToAfter[beforeBlock]; + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //If there is an assume or assert false statement in the block + { + var pruning = lemmaManager.GlobalBlockLemmaPruningNotCoalesced(beforeBlock, afterBlock, GetGlobalBlockLemmaName(beforeBlock, lemmaNamer)); + outerDecls.Add(pruning); + } + else //otherwhise we just need to apply the normal global block lemma. Assumption: Global Block Lemma holds for all successors + { + var globalBlock = lemmaManager.GlobalBlockLemma(beforeBlock, afterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer)); + outerDecls.Add(globalBlock); + } } } diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index c705632df..5ccdf615e 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -588,7 +588,11 @@ public static void VCGenerateAllProofs( IList unoptimizedCfgBlocks = proofGenInfo.GetUnoptimizedBlocks(); var newToOldInternal = new Dictionary(); unoptimizedCfgBlocks.ZipDo(afterPassificationImpl.Blocks, (bNew, bOld) => newToOldInternal.Add(bNew, bOld)); - beforeOptimizationsOrigBlock = newToOldInternal; + IDictionary mappingOrigBlockToUnoptimizedCopy = + proofGenInfo.GetMappingOrigBlockToUnoptimizedCopy(); + IDictionary mappingUnoptimizedCopyToOrigBlock = + mappingOrigBlockToUnoptimizedCopy.InverseDict(); + beforeOptimizationsOrigBlock = mappingUnoptimizedCopyToOrigBlock; BoogieMethodData beforeOptimizationsData; @@ -1013,10 +1017,7 @@ out var endToEndLemmaPrelim IDictionary mappingOrigBigBlockToOrigBlock = proofGenInfo.GetMappingOrigBigBlockToOrigBlock(); - IDictionary mappingOrigBlockToUnoptimizedCopy = - proofGenInfo.GetMappingOrigBlockToUnoptimizedCopy(); - IDictionary mappingUnoptimizedCopyToOrigBlock = - mappingOrigBlockToUnoptimizedCopy.InverseDict(); + IDictionary mappingOrigBlockToCopyBlock = beforeDagOrigBlock.InverseDict(); From ac203ffa8f0c767912313ec95805ad3ecbd43ca4 Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Wed, 14 Jun 2023 08:52:50 +0200 Subject: [PATCH 045/123] Proof Generation work in progress Proof Generation for Block Coalescing and Pruning of Unreachable Blocks finished (without loops) --- Source/Core/Absy.cs | 2 + Source/Core/DeadVarElim.cs | 26 +- .../CFGOptimizationsLemmaManager.cs | 328 +++++++++++++----- .../CFGOptimizationsManager.cs | 98 ++++-- .../ProofGeneration/ProofGenerationLayer.cs | 11 +- 5 files changed, 351 insertions(+), 114 deletions(-) diff --git a/Source/Core/Absy.cs b/Source/Core/Absy.cs index cf1767fed..49a058eca 100644 --- a/Source/Core/Absy.cs +++ b/Source/Core/Absy.cs @@ -4116,6 +4116,8 @@ public List /*!*/ // Blocks before applying passification etc. // Both are used only when /inline is set. public List OriginalBlocks; + public IDictionary> ListCoalescedBlocks; + public IDictionary CoalescedBlocksToTarget; public List OriginalLocVars; public readonly ISet AssertionChecksums = new HashSet(ChecksumComparer.Default); diff --git a/Source/Core/DeadVarElim.cs b/Source/Core/DeadVarElim.cs index 11a542ef6..66ba21e53 100644 --- a/Source/Core/DeadVarElim.cs +++ b/Source/Core/DeadVarElim.cs @@ -4,6 +4,7 @@ using Microsoft.Boogie.GraphUtil; using System.Diagnostics.Contracts; + namespace Microsoft.Boogie { public class UnusedVarEliminator : VariableCollector @@ -478,14 +479,19 @@ public static void CoalesceBlocks(Program program) return multiPredBlocks; } + + public override Implementation VisitImplementation(Implementation impl) { + + IDictionary CoalescedBlocksToTarget = new Dictionary(); + IDictionary> ListCoalescedBlocks = new Dictionary>(); + //Contract.Requires(impl != null); Contract.Ensures(Contract.Result() != null); //Console.WriteLine("Procedure {0}", impl.Name); //Console.WriteLine("Initial number of blocks = {0}", impl.Blocks.Count); - HashSet multiPredBlocks = ComputeMultiPredecessorBlocks(impl); Contract.Assert(cce.NonNullElements(multiPredBlocks)); HashSet visitedBlocks = new HashSet(); @@ -524,8 +530,24 @@ public override Implementation VisitImplementation(Implementation impl) { Block /*!*/ succ = cce.NonNull(gotoCmd.labelTargets[0]); + if (!multiPredBlocks.Contains(succ)) { + if (!ListCoalescedBlocks.ContainsKey(b.UniqueId)) + { + List newList = new List(); + newList.Add(b.UniqueId); + ListCoalescedBlocks.Add(b.UniqueId, newList); + } + ListCoalescedBlocks[b.UniqueId].Add(succ.UniqueId); + if (!CoalescedBlocksToTarget.ContainsKey(succ.UniqueId)) + { + CoalescedBlocksToTarget.Add(succ.UniqueId, b.UniqueId); + } + if (!CoalescedBlocksToTarget.ContainsKey(b.UniqueId)) + { + CoalescedBlocksToTarget.Add(b.UniqueId, b.UniqueId); + } foreach (Cmd /*!*/ cmd in succ.Cmds) { Contract.Assert(cmd != null); @@ -579,6 +601,8 @@ public override Implementation VisitImplementation(Implementation impl) } } + impl.CoalescedBlocksToTarget = CoalescedBlocksToTarget; + impl.ListCoalescedBlocks = ListCoalescedBlocks; // Console.WriteLine("Final number of blocks = {0}", impl.Blocks.Count); return impl; } diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index b26fa9f37..ee51c6615 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -19,7 +19,6 @@ public class CFGOptimizationsLemmaManager { private readonly IProgramAccessor beforeOptProgAccess; private readonly IProgramAccessor afterOptProgAccess; - private readonly BoogieContextIsa boogieContext; private readonly CFGRepr beforeOptimizations; private readonly CFGRepr afterOptimizations; private readonly string funContextWfName; @@ -27,7 +26,6 @@ public class CFGOptimizationsLemmaManager public CFGOptimizationsLemmaManager( IProgramAccessor beforeOptProgAccess, IProgramAccessor afterOptProgAccess, - BoogieContextIsa boogieContext, CFGRepr beforeOptimizations, CFGRepr afterOptimizations, string funContextWfName, @@ -36,7 +34,6 @@ IDictionary beforeToAfterBlock { this.beforeOptProgAccess = beforeOptProgAccess; this.afterOptProgAccess = afterOptProgAccess; - this.boogieContext = boogieContext; this.beforeOptimizations = beforeOptimizations; this.afterOptimizations = afterOptimizations; this.funContextWfName = funContextWfName; @@ -88,100 +85,263 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b Block afterBlock, Func blockLemmaName) { - - if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() == 0) + var function = new List(); + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) { - var proofMethods = new List + if (beforeToAfterBlock.Keys.Contains(succ)) { - "apply (rule loopBlock_global_block)", - "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", - "apply (auto)", - "apply (unfold p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")", - "apply (unfold p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", - "apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def p_unoptimized_cfg_prog.block_" + - beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + "_def)", - "by simp" - }; - - - var varContextName = "\\"; - IList terms = new List(); - terms.Add(IsaCommonTerms.TermIdentFromName("A")); - terms.Add(IsaCommonTerms.TermIdentFromName("M")); - terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); - terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); - terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.EmptySet); - Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + Block succAfter = beforeToAfterBlock[succ]; + function.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[succ] + "," + afterOptProgAccess.BlockInfo().BlockIds[succAfter] + ")"); + } + } + var proofMethods = new List + { + "apply (rule loopBlock_global_block[where ?f = \"the ∘ map_of [" + string.Join(",", function) + "]\"])", + "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply simp" + }; + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1) + { + proofMethods.Add("apply (intro conjI)"); + } + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + { + proofMethods.Add("apply (rule " + blockLemmaName(succ) + ")"); + } + proofMethods.Add("apply simp"); + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 0) + { + proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.outEdges_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); + } - var blockLemma = new LemmaDecl( - blockLemmaName(beforeBlock), - conclusion, - new Proof(proofMethods)); - return blockLemma; + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1) + { + proofMethods.Add("apply (intro conjI)"); } - else + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) { - var function = new List(); - foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) - { - if (beforeToAfterBlock.Keys.Contains(succ)) - { - Block succAfter = beforeToAfterBlock[succ]; - function.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[succ] + "," + afterOptProgAccess.BlockInfo().BlockIds[succAfter] + ")"); - } - } - + proofMethods.Add("apply simp"); + } + proofMethods.Add("apply (rule p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); + proofMethods.Add("apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")"); + proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def p_unoptimized_cfg_prog.block_" + + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + "_def)"); + proofMethods.Add("by simp"); + var varContextName = "\\"; + IList terms = new List(); + terms.Add(IsaCommonTerms.TermIdentFromName("A")); + terms.Add(IsaCommonTerms.TermIdentFromName("M")); + terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); + terms.Add(IsaCommonTerms.EmptySet); + Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); - var proofMethods = new List - { - "apply (rule loopBlock_global_block[where ?f = \"the ∘ map_of [" + string.Join(",", function) + "]\"])", - "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", - "apply simp", - "apply (intro conjI)" - }; - foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + var blockLemma = new LemmaDecl( + blockLemmaName(beforeBlock), + conclusion, + new Proof(proofMethods)); + return blockLemma; + } + public LemmaDecl HybridBlockLemmaTail( //show the hybrid block lemma for the tail of coalesced blocks + Block beforeBlock, + Block afterBlock, + Func GlobalblockLemmaName, + Func HybridblockLemmaName) + { + var function = new List(); + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + { + if (beforeToAfterBlock.Keys.Contains(succ)) { - proofMethods.Add("apply (rule " + blockLemmaName(succ) + ")"); + Block succAfter = beforeToAfterBlock[succ]; + function.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[succ] + "," + afterOptProgAccess.BlockInfo().BlockIds[succAfter] + ")"); } - proofMethods.Add("apply simp"); - proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.outEdges_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); + } + + var proofMethods = new List + { + + "apply (rule loopBlock_global_block_hybrid[where ?f = \"the ∘ map_of [" + string.Join(",", function) + "]\"])", + "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply simp" + }; + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1) + { proofMethods.Add("apply (intro conjI)"); - foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) - { - proofMethods.Add("apply simp"); - } - proofMethods.Add("apply (rule p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); - proofMethods.Add("apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")"); - proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def p_unoptimized_cfg_prog.block_" + - beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + "_def)"); - proofMethods.Add("by simp"); - var varContextName = "\\"; - IList terms = new List(); - terms.Add(IsaCommonTerms.TermIdentFromName("A")); - terms.Add(IsaCommonTerms.TermIdentFromName("M")); - terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); - terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); - terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.EmptySet); - Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + } + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + { + proofMethods.Add("apply (rule " + GlobalblockLemmaName(succ) + ")"); + } + proofMethods.Add("apply simp"); + proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.outEdges_" + + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); + proofMethods.Add("apply simp"); + proofMethods.Add("apply (unfold p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + " block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock]+ "_def)"); + proofMethods.Add("by simp"); + + var varContextName = "\\"; + IList terms = new List(); + terms.Add(IsaCommonTerms.TermIdentFromName("A")); + terms.Add(IsaCommonTerms.TermIdentFromName("M")); + terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); + terms.Add(IsaCommonTerms.TermIdentFromName("block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(IsaCommonTerms.EmptySet); + Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("hybrid_block_lemma_loop"), terms); + + var blockLemma = new LemmaDecl( + HybridblockLemmaName(beforeBlock), + conclusion, + new Proof(proofMethods)); + return blockLemma; + } + + public LemmaDecl HybridBlockLemma( //extend hybrid block lemma + Block beforeBlock, + Block afterBlock, + Block succ, + Func GlobalblockLemmaName, + Func HybridblockLemmaName) + { + var proofMethods = new List + { + "apply (rule extend_hybrid_global_block_lemma_loop)", + "apply (rule " + HybridblockLemmaName(succ) + ")", + "apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] +")", + "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "by simp" + }; + + List listCoalescedBlocks = new List(); + Block curr = beforeBlock; + listCoalescedBlocks.Add("block_" + beforeOptProgAccess.BlockInfo().BlockIds[curr]); + while ((beforeOptimizations.GetSuccessorBlocks(curr).Count() == 1 && + beforeOptimizations.GetSuccessorBlocks(curr).First().Predecessors.Count() == 1)) + { + curr = beforeOptimizations.GetSuccessorBlocks(curr).First(); + listCoalescedBlocks.Add("block_" + beforeOptProgAccess.BlockInfo().BlockIds[curr]); - var blockLemma = new LemmaDecl( - blockLemmaName(beforeBlock), - conclusion, - new Proof(proofMethods)); - return blockLemma; } + + var varContextName = "\\"; + IList terms = new List(); + terms.Add(IsaCommonTerms.TermIdentFromName("A")); + terms.Add(IsaCommonTerms.TermIdentFromName("M")); + terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); + terms.Add(IsaCommonTerms.TermIdentFromName("(" + string.Join("@", listCoalescedBlocks) + ")")); //this is still missing + terms.Add(IsaCommonTerms.EmptySet); + Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("hybrid_block_lemma_loop"), terms); + + var blockLemma = new LemmaDecl( + HybridblockLemmaName(beforeBlock), + conclusion, + new Proof(proofMethods)); + return blockLemma; } + public LemmaDecl ConvertHybridToGlobal( //show the hybrid block lemma for the head of coalesced blocks + Block beforeBlock, + Block afterBlock, + Func GlobalblockLemmaName, + Func HybridblockLemmaName) + { + var proofMethods = new List + { + "apply (rule convert_hybrid_global_block_lemma_loop)", + "apply (rule " + HybridblockLemmaName(beforeBlock) + ")" + }; + + List listCoalescedBlocks = new List(); + Block curr = beforeBlock; + listCoalescedBlocks.Add("block_" + beforeOptProgAccess.BlockInfo().BlockIds[curr]); + while ((beforeOptimizations.GetSuccessorBlocks(curr).Count() == 1 && + beforeOptimizations.GetSuccessorBlocks(curr).First().Predecessors.Count() == 1)) + { + curr = beforeOptimizations.GetSuccessorBlocks(curr).First(); + listCoalescedBlocks.Add("block_" + beforeOptProgAccess.BlockInfo().BlockIds[curr]); + + } + + foreach (string b in listCoalescedBlocks) + { + proofMethods.Add("apply (unfold " + b + "_def)"); + } + proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + " p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def)"); + proofMethods.Add("by simp"); + var varContextName = "\\"; + IList terms = new List(); + terms.Add(IsaCommonTerms.TermIdentFromName("A")); + terms.Add(IsaCommonTerms.TermIdentFromName("M")); + terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); + terms.Add(IsaCommonTerms.EmptySet); + Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + + var blockLemma = new LemmaDecl( + GlobalblockLemmaName(beforeBlock), + conclusion, + new Proof(proofMethods)); + return blockLemma; + } + + public LemmaDecl HybridBlockLemmaPruning( //Pruning of unreachable blocks with block coalescing + Block beforeBlock, + Block afterBlock, + Func blockLemmaName) + { + var proofMethods = new List + { + "apply (rule pruning_coalesced_loop)", + "apply (rule p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")", + "apply (unfold p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + " p_unoptimized_cfg_prog.block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + "_def)", + "apply simp", + "apply simp", + "apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def)", + "by simp" + }; + var varContextName = "\\"; + IList terms = new List(); + terms.Add(IsaCommonTerms.TermIdentFromName("A")); + terms.Add(IsaCommonTerms.TermIdentFromName("M")); + terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); + terms.Add(IsaCommonTerms.TermIdentFromName("block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(IsaCommonTerms.EmptySet); + Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("hybrid_block_lemma_loop"), terms); + + var blockLemma = new LemmaDecl( + blockLemmaName(beforeBlock), + conclusion, + new Proof(proofMethods)); + return blockLemma; + } } \ No newline at end of file diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index 13dbbb723..d9c1bd8ed 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -12,6 +12,7 @@ using ProofGeneration.Util; + namespace ProofGeneration.CFGOptimizations; public class CfgOptimizationsManager @@ -25,8 +26,9 @@ public static Theory CfgOptProof( CFGRepr afterOptimizations, IDictionary beforeToAfter, // mapping from current block to target block IProgramAccessor beforeOptCfgProgAcccess, //before CFG optimizations - IProgramAccessor afterOptCfgProgAccess) //after CFG optimizations - + IProgramAccessor afterOptCfgProgAccess, //after CFG optimizationsList<(Block, Block)> CoalescedBlocks + IDictionary> ListCoalescedBlocks, //TODO: Optimize CFGOptimizationsLemmaManager by using this dictionary + IDictionary CoalescedBlocksToTarget) { var varContextName = "\\"; @@ -36,19 +38,10 @@ public static Theory CfgOptProof( var funContextWfName = "Wf_Fun"; - - var BoogieContext = new BoogieContextIsa( - IsaCommonTerms.TermIdentFromName("A"), - IsaCommonTerms.TermIdentFromName("M"), - IsaCommonTerms.TermIdentFromName(varContextName), - IsaCommonTerms.TermIdentFromName("\\"), - IsaCommonTerms.TermIdentFromName("\\")); - - + var lemmaManager = new CFGOptimizationsLemmaManager( beforeOptCfgProgAcccess, afterOptCfgProgAccess, - BoogieContext, beforeOptimizations, afterOptimizations, funContextWfName, @@ -61,29 +54,74 @@ public static Theory CfgOptProof( outerDecls.Add(varContextAbbrev); outerDecls.Add(new DeclareDecl("Nat.One_nat_def[simp del]")); List proofMethods = new List(); - - //In a first try I assume that there is no block coalescing and no loops - foreach (Block beforeBlock in beforeOptimizations.GetBlocksBackwards()) + Block coalescedAfterBlock = new Block(); + //assumption: no loops + foreach (Block beforeBlock in beforeOptimizations.GetBlocksForwards()) { - if (beforeToAfter.Keys.Contains(beforeBlock)) + if (CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //in this case we have block coalescing { - Block afterBlock = beforeToAfter[beforeBlock]; - if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //If there is an assume or assert false statement in the block + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //Pruning of Unreachable Blocks Coalesced + { + coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + var pruningCoalesced = lemmaManager.HybridBlockLemmaPruning(beforeBlock, coalescedAfterBlock, + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer)); + outerDecls.Add(pruningCoalesced); + } + else if (beforeToAfter.ContainsKey(beforeBlock)) //head + { + Block afterBlock = beforeToAfter[beforeBlock]; + var head = lemmaManager.HybridBlockLemma(beforeBlock, afterBlock, + beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault(), + bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer)); + outerDecls.Add(head); + var convertGlobalBlock = lemmaManager.ConvertHybridToGlobal(beforeBlock, afterBlock, + bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer)); + outerDecls.Add(convertGlobalBlock); + } + else if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() != 1 || beforeOptimizations.GetSuccessorBlocks(beforeBlock).First().Predecessors.Count() != 1) //tail { - var pruning = lemmaManager.GlobalBlockLemmaPruningNotCoalesced(beforeBlock, afterBlock, GetGlobalBlockLemmaName(beforeBlock, lemmaNamer)); - outerDecls.Add(pruning); + coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + + var tail = lemmaManager.HybridBlockLemmaTail(beforeBlock, coalescedAfterBlock, + bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer)); + outerDecls.Add(tail); } - else //otherwhise we just need to apply the normal global block lemma. Assumption: Global Block Lemma holds for all successors + else //in Between Block { - var globalBlock = lemmaManager.GlobalBlockLemma(beforeBlock, afterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer)); - outerDecls.Add(globalBlock); + coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + var inBetweenBlock = lemmaManager.HybridBlockLemma(beforeBlock, coalescedAfterBlock, + beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault(), + bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer)); + outerDecls.Add(inBetweenBlock); } } + else //no block coalescing + { + if (beforeToAfter.Keys.Contains(beforeBlock)) + { + Block afterBlock = beforeToAfter[beforeBlock]; + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //If there is an assume or assert false statement in the block + { + var pruning = lemmaManager.GlobalBlockLemmaPruningNotCoalesced(beforeBlock, afterBlock, GetGlobalBlockLemmaName(beforeBlock, lemmaNamer)); + outerDecls.Add(pruning); + } + else //otherwhise we just need to apply the normal global block lemma. Assumption: Global Block Lemma holds for all successors + { + var globalBlock = lemmaManager.GlobalBlockLemma(beforeBlock, afterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer)); + outerDecls.Add(globalBlock); + } + } + } + } List importTheories = new List { - "Boogie_Lang.Ast", "Boogie_Lang.Ast_Cfg_Transformation", "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.CFGOptimizationsLoop", + "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.CFGOptimizations", "Boogie_Lang.CFGOptimizationsLoop", afterOptCfgProgAccess.TheoryName(), beforeOptCfgProgAcccess.TheoryName() }; @@ -105,5 +143,17 @@ private static string GetHybridBlockLemmaName(Block b, IsaUniqueNamer namer) return "hybrid_block_lemma_" + namer.GetName(b, "block_" + b.Label); } + private static Block GetCoalescedAfterBlock(Block b, IDictionary beforeToAfter, IDictionary CoalescedBlocksToTarget) + { + foreach (Block beforeBlockNew in beforeToAfter.Keys) //Get the Coalesced After Block + { + if (beforeToAfter[beforeBlockNew].UniqueId == CoalescedBlocksToTarget[b.UniqueId]) + { + return beforeToAfter[beforeBlockNew]; + } + } + return null; + } + } \ No newline at end of file diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 5ccdf615e..87a4e33e1 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -38,8 +38,7 @@ public class ProofGenerationLayer private static IDictionary beforeOptimizationsOrigBlock; private static IDictionary beforeDagOrigBlock; private static IDictionary beforeDagAfterDagBlock; - private static IDictionary beforeOptAfterOptBlock; - + private static CFGRepr beforeOptimizationsCFG; private static CFGRepr beforeDagCfg; @@ -733,7 +732,7 @@ from calls. new List { "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", - _proofGenConfig.GenerateBeforeAstCfgProg ? beforeAstToCfgProgAccess.TheoryName() : globalDataProgAccess.TheoryName() + _proofGenConfig.GenerateBeforeAstCfgProg ? beforeAstToCfgProgAccess.TheoryName() : "\"../"+globalDataProgAccess.TheoryName()+"\"" }, programDeclsUnoptimizedCfg); theories.Add(unoptimizedCfgProgTheory); @@ -989,7 +988,7 @@ out var endToEndLemmaPrelim // compute mapping between copied blocks (before opt -> after opt) var origToAfterOpt = beforeDagOrigBlock.InverseDict(); - beforeOptAfterOptBlock = DictionaryComposition(beforeOptimizationsOrigBlock, origToAfterOpt); + IDictionary beforeOptAfterOptBlock = DictionaryComposition(beforeOptimizationsOrigBlock, origToAfterOpt); var cfgOptimizationsProofTheory = CfgOptimizationsManager.CfgOptProof( @@ -998,7 +997,9 @@ out var endToEndLemmaPrelim beforeDagCfg, beforeOptAfterOptBlock, //not sure if this is correct unoptimizedCfgProgAccess, - beforeCfgToDagProgAccess); + beforeCfgToDagProgAccess, + afterPassificationImpl.ListCoalescedBlocks, + afterPassificationImpl.CoalescedBlocksToTarget); theories.Add(cfgOptimizationsProofTheory); #endregion From 9c8d1bf12839dec2b089ddf1714d07393e64195d Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Thu, 15 Jun 2023 11:54:04 +0200 Subject: [PATCH 046/123] Proof Generation for Loops finished (order of blocks still in progress) --- Source/Core/Absy.cs | 9 +- .../CFGOptimizationsLemmaManager.cs | 325 ++++++++++++++++-- .../CFGOptimizationsManager.cs | 105 +++++- .../CfgToDag/CfgToDagManager.cs | 5 +- .../ProofGeneration/ProofGenerationLayer.cs | 10 +- 5 files changed, 407 insertions(+), 47 deletions(-) diff --git a/Source/Core/Absy.cs b/Source/Core/Absy.cs index 49a058eca..df7c170d0 100644 --- a/Source/Core/Absy.cs +++ b/Source/Core/Absy.cs @@ -4116,11 +4116,16 @@ public List /*!*/ // Blocks before applying passification etc. // Both are used only when /inline is set. public List OriginalBlocks; - public IDictionary> ListCoalescedBlocks; - public IDictionary CoalescedBlocksToTarget; + public List OriginalLocVars; + public readonly ISet AssertionChecksums = new HashSet(ChecksumComparer.Default); + + #region ProofGen + public IDictionary> ListCoalescedBlocks; + public IDictionary CoalescedBlocksToTarget; + #endregion public sealed class ChecksumComparer : IEqualityComparer { diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index ee51c6615..1c5d2e69c 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -43,7 +43,8 @@ IDictionary beforeToAfterBlock public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable blocks where no coalescing happened Block beforeBlock, Block afterBlock, - string blockLemmaName) + string blockLemmaName, + IList Loops) { var proofMethods = new List { @@ -58,6 +59,12 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b "by simp" }; + var loopHeads = new List(); + foreach (Block loop in Loops) + { + loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); + } + var varContextName = "\\"; IList terms = new List(); terms.Add(IsaCommonTerms.TermIdentFromName("A")); @@ -69,7 +76,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.EmptySet); + terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); @@ -83,8 +90,16 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b public LemmaDecl GlobalBlockLemma( //normal global block lemma where the global block lemma needs to hold for all successors Block beforeBlock, Block afterBlock, - Func blockLemmaName) + Func blockLemmaName, + IDictionary> beforeOptBlockToLoops, + IList Loops) { + var loopHeads = new List(); + foreach (Block loop in Loops) + { + loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); + } + var function = new List(); foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) { @@ -100,13 +115,41 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", "apply simp" }; - if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1) + int countCases = 0; + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + { + if (isLoopHead(succ, beforeOptimizations, beforeOptBlockToLoops, beforeToAfterBlock) && Loops.Contains(succ)) + { + countCases = countCases + 1; + } + } + + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1 && beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() - countCases > 1) { proofMethods.Add("apply (intro conjI)"); } foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) { - proofMethods.Add("apply (rule " + blockLemmaName(succ) + ")"); + if (Loops.Count == 0) + { + proofMethods.Add("apply (rule " + blockLemmaName(succ) + ")"); + } + else if (isLoopHead(succ, beforeOptimizations, beforeOptBlockToLoops, beforeToAfterBlock) && Loops.Contains(succ)) + { + + } + else + { + var loopHeadsSucc = new List(); + foreach (Block loop in beforeOptBlockToLoops[succ]) + { + loopHeadsSucc.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); + } + proofMethods.Add("apply(rule exI[where ?x = \"{" + string.Join(",", loopHeadsSucc) + "}\"])"); + proofMethods.Add("apply simp"); + proofMethods.Add("apply (rule " +blockLemmaName(succ) + ")"); + } + } proofMethods.Add("apply simp"); if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 0) @@ -139,7 +182,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.EmptySet); + terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( @@ -152,8 +195,16 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b Block beforeBlock, Block afterBlock, Func GlobalblockLemmaName, - Func HybridblockLemmaName) + Func HybridblockLemmaName, + IDictionary> beforeOptBlockToLoops, + IList Loops) { + var loopHeads = new List(); + foreach (Block loop in Loops) + { + loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); + } + var function = new List(); foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) { @@ -163,25 +214,57 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b function.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[succ] + "," + afterOptProgAccess.BlockInfo().BlockIds[succAfter] + ")"); } } - + var proofMethods = new List { - + "apply (rule loopBlock_global_block_hybrid[where ?f = \"the ∘ map_of [" + string.Join(",", function) + "]\"])", "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", "apply simp" }; - if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1) + int countCases = 0; + + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + { + if (isLoopHead(succ, beforeOptimizations, beforeOptBlockToLoops, beforeToAfterBlock) && Loops.Contains(succ)) + { + countCases++; + } + } + + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1 && beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() - countCases > 0) { proofMethods.Add("apply (intro conjI)"); } foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) { - proofMethods.Add("apply (rule " + GlobalblockLemmaName(succ) + ")"); + if (Loops.Count == 0) + { + proofMethods.Add("apply (rule " + GlobalblockLemmaName(succ) + ")"); + } + else if (isLoopHead(succ, beforeOptimizations, beforeOptBlockToLoops, beforeToAfterBlock) && Loops.Contains(succ) && Loops.Contains(succ)) + { + + } + else + { + var loopHeadsSucc = new List(); + foreach (Block loop in beforeOptBlockToLoops[succ]) + { + loopHeadsSucc.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); + } + proofMethods.Add("apply(rule exI[where ?x = \"{" + string.Join(",", loopHeadsSucc) + "}\"])"); + proofMethods.Add("apply simp"); + proofMethods.Add("apply (rule " + GlobalblockLemmaName(succ) + ")"); + } + } + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 0) + { + proofMethods.Add("apply simp"); + proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.outEdges_" + + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); } - proofMethods.Add("apply simp"); - proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.outEdges_" + - afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); + proofMethods.Add("apply simp"); proofMethods.Add("apply (unfold p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + " block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock]+ "_def)"); proofMethods.Add("by simp"); @@ -198,7 +281,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); terms.Add(IsaCommonTerms.TermIdentFromName("block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); - terms.Add(IsaCommonTerms.EmptySet); + terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("hybrid_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( @@ -213,7 +296,8 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma Block afterBlock, Block succ, Func GlobalblockLemmaName, - Func HybridblockLemmaName) + Func HybridblockLemmaName, + IList Loops) { var proofMethods = new List { @@ -223,6 +307,12 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", "by simp" }; + + var loopHeads = new List(); + foreach (Block loop in Loops) + { + loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); + } List listCoalescedBlocks = new List(); Block curr = beforeBlock; @@ -246,8 +336,8 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.TermIdentFromName("(" + string.Join("@", listCoalescedBlocks) + ")")); //this is still missing - terms.Add(IsaCommonTerms.EmptySet); + terms.Add(IsaCommonTerms.TermIdentFromName("(" + string.Join("@", listCoalescedBlocks) + ")")); + terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("hybrid_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( @@ -261,7 +351,8 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma Block beforeBlock, Block afterBlock, Func GlobalblockLemmaName, - Func HybridblockLemmaName) + Func HybridblockLemmaName, + IList Loops) { var proofMethods = new List { @@ -286,6 +377,11 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma } proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + " p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def)"); proofMethods.Add("by simp"); + var loopHeads = new List(); + foreach (Block loop in Loops) + { + loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); + } var varContextName = "\\"; IList terms = new List(); terms.Add(IsaCommonTerms.TermIdentFromName("A")); @@ -297,7 +393,7 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.EmptySet); + terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( @@ -310,7 +406,8 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma public LemmaDecl HybridBlockLemmaPruning( //Pruning of unreachable blocks with block coalescing Block beforeBlock, Block afterBlock, - Func blockLemmaName) + Func blockLemmaName, + IList Loops) { var proofMethods = new List { @@ -322,6 +419,12 @@ public LemmaDecl HybridBlockLemmaPruning( //Pruning of unreachable blocks with b "apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def)", "by simp" }; + var loopHeads = new List(); + foreach (Block loop in Loops) + { + loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); + } + var varContextName = "\\"; IList terms = new List(); terms.Add(IsaCommonTerms.TermIdentFromName("A")); @@ -334,7 +437,7 @@ public LemmaDecl HybridBlockLemmaPruning( //Pruning of unreachable blocks with b terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); terms.Add(IsaCommonTerms.TermIdentFromName("block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); - terms.Add(IsaCommonTerms.EmptySet); + terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("hybrid_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( @@ -344,4 +447,182 @@ public LemmaDecl HybridBlockLemmaPruning( //Pruning of unreachable blocks with b return blockLemma; } + public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced + Block beforeBlock, + Block afterBlock, + Func blockLemmaName, + IDictionary> beforeOptBlockToLoops, + IList Loops) + { + + var loopHeads = new List(); + foreach (Block loop in Loops) + { + loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); + } + + var function = new List(); + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + { + if (beforeToAfterBlock.Keys.Contains(succ)) + { + Block succAfter = beforeToAfterBlock[succ]; + function.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[succ] + "," + afterOptProgAccess.BlockInfo().BlockIds[succAfter] + ")"); + } + } + var proofMethods = new List + { + "apply (rule loopHead_global_block[where ?f = \"the ∘ map_of [" + string.Join(",", function) + "]\"])", + "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply simp" + }; + + int countCases = 0; + + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + { + if (isLoopHead(succ, beforeOptimizations, beforeOptBlockToLoops, beforeToAfterBlock) && Loops.Contains(succ)) + { + countCases++; + } + } + + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1 && beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() - countCases > 0) + { + proofMethods.Add("apply (intro conjI)"); + } + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + { + if (isLoopHead(succ, beforeOptimizations, beforeOptBlockToLoops, beforeToAfterBlock) && Loops.Contains(succ)) + { + + } + else + { + var loopHeadsSucc = new List(); + foreach (Block loop in beforeOptBlockToLoops[succ]) + { + loopHeadsSucc.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); + } + proofMethods.Add("apply(rule exI[where ?x = \"{" + string.Join(",", loopHeadsSucc) + "}\"])"); + proofMethods.Add("apply simp"); + proofMethods.Add("apply (rule " + blockLemmaName(succ) + ")"); + } + + } + proofMethods.Add("apply simp"); + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 0) + { + proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.outEdges_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); + } + + + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1) + { + proofMethods.Add("apply (intro conjI)"); + } + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) + { + proofMethods.Add("apply simp"); + } + proofMethods.Add("apply (rule p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); + proofMethods.Add("apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")"); + proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def p_unoptimized_cfg_prog.block_" + + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + "_def)"); + proofMethods.Add("by simp"); + var varContextName = "\\"; + IList terms = new List(); + terms.Add(IsaCommonTerms.TermIdentFromName("A")); + terms.Add(IsaCommonTerms.TermIdentFromName("M")); + terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); + terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); + Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + + var blockLemma = new LemmaDecl( + blockLemmaName(beforeBlock), + conclusion, + new Proof(proofMethods)); + return blockLemma; + } + + public LemmaDecl LoopHeadCoalesced( //Loop Head coalesced + Block beforeBlock, + Block afterBlock, + Func GlobalblockLemmaName, + Func HybridblockLemmaName, + IList Loops) + { + var loopHeads = new List(); + foreach (Block loop in Loops) + { + loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); + } + + + + var proofMethods = new List + { + "apply (rule loopHead_global_block_hybrid)", + "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply simp", + "apply (rule " + HybridblockLemmaName(beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault()) + ")", + "apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply (rule p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + " )", + "apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] +"_def)", + "apply (unfold p_unoptimized_cfg_prog.block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] +"_def)", + "apply (unfold p_unoptimized_cfg_prog.block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault()] +"_def)", + "by simp" + }; + + List listCoalescedBlocks = new List(); + Block curr = beforeBlock; + listCoalescedBlocks.Add("block_" + beforeOptProgAccess.BlockInfo().BlockIds[curr]); + while ((beforeOptimizations.GetSuccessorBlocks(curr).Count() == 1 && + beforeOptimizations.GetSuccessorBlocks(curr).First().Predecessors.Count() == 1)) + { + curr = beforeOptimizations.GetSuccessorBlocks(curr).First(); + listCoalescedBlocks.Add("block_" + beforeOptProgAccess.BlockInfo().BlockIds[curr]); + + } + + var varContextName = "\\"; + IList terms = new List(); + terms.Add(IsaCommonTerms.TermIdentFromName("A")); + terms.Add(IsaCommonTerms.TermIdentFromName("M")); + terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); + terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); + Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + + var blockLemma = new LemmaDecl( + GlobalblockLemmaName(beforeBlock), + conclusion, + new Proof(proofMethods)); + return blockLemma; + } + + + private static bool isLoopHead(Block b, CFGRepr beforeOptimizations, IDictionary> beforeOptBlockToLoops, IDictionary beforeToAfter) + { + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(b)) + { + if (beforeOptBlockToLoops[b].Count < beforeOptBlockToLoops[succ].Count && beforeToAfter.ContainsKey(b)) + { + return true; + } + } + return false; + } + } \ No newline at end of file diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index d9c1bd8ed..078e61676 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -2,6 +2,7 @@ using ProofGeneration.BoogieIsaInterface; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using Isabelle.Ast; using Isabelle.Util; @@ -28,8 +29,45 @@ public static Theory CfgOptProof( IProgramAccessor beforeOptCfgProgAcccess, //before CFG optimizations IProgramAccessor afterOptCfgProgAccess, //after CFG optimizationsList<(Block, Block)> CoalescedBlocks IDictionary> ListCoalescedBlocks, //TODO: Optimize CFGOptimizationsLemmaManager by using this dictionary - IDictionary CoalescedBlocksToTarget) + IDictionary CoalescedBlocksToTarget, + IDictionary> beforeDagBlockToLoops) { + IDictionary afterToBefore = beforeToAfter.ToDictionary(x => x.Value, x => x.Key); + IDictionary> beforeOptBlockToLoops = new Dictionary>(); + Block coalescedAfterBlock = new Block(); + + foreach (Block beforeBlock in beforeOptimizations.GetBlocksForwards()) + { + if (beforeToAfter.ContainsKey(beforeBlock)) + { + IList temp = new List(); + foreach (Block loopHeader in beforeDagBlockToLoops[beforeToAfter[beforeBlock]]) + { + temp.Add(afterToBefore[loopHeader]); + } + beforeOptBlockToLoops.Add(beforeBlock, temp); + } + else if (CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) { + coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + List temp = new List(); + foreach (Block loopHeader in beforeDagBlockToLoops[coalescedAfterBlock]) + { + temp.Add(afterToBefore[loopHeader]); + } + + foreach (Block afterSucc in afterOptimizations.GetSuccessorBlocks( + GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget))) + { + if (beforeDagBlockToLoops[coalescedAfterBlock].Count < beforeDagBlockToLoops[afterSucc].Count) + { + temp.Add(afterToBefore[GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget)]); + break; + } + } + beforeOptBlockToLoops.Add(beforeBlock, temp); + } + } + var varContextName = "\\"; var varContextAbbrev = new AbbreviationDecl( @@ -53,49 +91,63 @@ public static Theory CfgOptProof( outerDecls.Add(varContextAbbrev); outerDecls.Add(new DeclareDecl("Nat.One_nat_def[simp del]")); - List proofMethods = new List(); - Block coalescedAfterBlock = new Block(); - //assumption: no loops + + foreach (Block beforeBlock in beforeOptimizations.GetBlocksForwards()) { - if (CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //in this case we have block coalescing + if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops, beforeToAfter) && CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //In this case we have a coalesced loop head { - if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //Pruning of Unreachable Blocks Coalesced + coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + var globalBlock = lemmaManager.LoopHeadCoalesced(beforeBlock, coalescedAfterBlock, + bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), + beforeOptBlockToLoops[beforeBlock]); + outerDecls.Add(globalBlock); + } + else if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops,beforeToAfter)) //normal Loop Head + { + var globalBlock = lemmaManager.LoopHeadNotCoalesced(beforeBlock, beforeToAfter[beforeBlock], bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); + outerDecls.Add(globalBlock); + } + else if (CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //in this case we have block coalescing + { + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //Pruning of Unreachable Blocks Coalesced DONE { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); var pruningCoalesced = lemmaManager.HybridBlockLemmaPruning(beforeBlock, coalescedAfterBlock, - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer)); + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(pruningCoalesced); } - else if (beforeToAfter.ContainsKey(beforeBlock)) //head + else if (beforeToAfter.ContainsKey(beforeBlock)) //head DONE { Block afterBlock = beforeToAfter[beforeBlock]; var head = lemmaManager.HybridBlockLemma(beforeBlock, afterBlock, beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault(), bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer)); + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(head); var convertGlobalBlock = lemmaManager.ConvertHybridToGlobal(beforeBlock, afterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer)); + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(convertGlobalBlock); } - else if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() != 1 || beforeOptimizations.GetSuccessorBlocks(beforeBlock).First().Predecessors.Count() != 1) //tail + else if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() != 1 || beforeOptimizations.GetSuccessorBlocks(beforeBlock).First().Predecessors.Count() != 1) //tail TODO: { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); var tail = lemmaManager.HybridBlockLemmaTail(beforeBlock, coalescedAfterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer)); + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), + beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(tail); } - else //in Between Block + else //in Between Block DONE { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); var inBetweenBlock = lemmaManager.HybridBlockLemma(beforeBlock, coalescedAfterBlock, beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault(), bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer)); + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(inBetweenBlock); } } @@ -104,24 +156,27 @@ public static Theory CfgOptProof( if (beforeToAfter.Keys.Contains(beforeBlock)) { Block afterBlock = beforeToAfter[beforeBlock]; - if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //If there is an assume or assert false statement in the block + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //If there is an assume or assert false statement in the block DONE { - var pruning = lemmaManager.GlobalBlockLemmaPruningNotCoalesced(beforeBlock, afterBlock, GetGlobalBlockLemmaName(beforeBlock, lemmaNamer)); + var pruning = lemmaManager.GlobalBlockLemmaPruningNotCoalesced(beforeBlock, afterBlock, GetGlobalBlockLemmaName(beforeBlock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(pruning); } - else //otherwhise we just need to apply the normal global block lemma. Assumption: Global Block Lemma holds for all successors + else //otherwhise we just need to apply the normal global block lemma. Assumption: Global Block Lemma holds for all successors DONE { - var globalBlock = lemmaManager.GlobalBlockLemma(beforeBlock, afterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer)); + var globalBlock = lemmaManager.GlobalBlockLemma(beforeBlock, afterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(globalBlock); + } } } } + + List importTheories = new List { - "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.CFGOptimizations", "Boogie_Lang.CFGOptimizationsLoop", + "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.CFGOptimizationsLoop", afterOptCfgProgAccess.TheoryName(), beforeOptCfgProgAcccess.TheoryName() }; @@ -154,6 +209,18 @@ private static Block GetCoalescedAfterBlock(Block b, IDictionary b } return null; } + + private static bool isLoopHead(Block b, CFGRepr beforeOptimizations, IDictionary> beforeOptBlockToLoops, IDictionary beforeToAfter) + { + foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(b)) + { + if (beforeOptBlockToLoops[b].Count < beforeOptBlockToLoops[succ].Count && beforeToAfter.ContainsKey(b)) + { + return true; + } + } + return false; + } } \ No newline at end of file diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs index 987e44234..5ccfe24b5 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs @@ -35,7 +35,8 @@ public static Theory CfgToDagProof( IDictionary beforeToAfter, IProgramAccessor beforeDagProgAccess, IProgramAccessor afterDagProgAccess, - IVariableTranslationFactory varFactory) + IVariableTranslationFactory varFactory, + out IDictionary> beforeDagBlockToLoops) { var afterToBefore = beforeToAfter.InverseDict(); @@ -64,6 +65,8 @@ public static Theory CfgToDagProof( blocksToLoops.Add(beforeBlock, loopsList); } + beforeDagBlockToLoops = blocksToLoops; + var varContextName = "\\1"; var varContextAbbrev = new AbbreviationDecl( varContextName, diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 87a4e33e1..35cf40b59 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -951,6 +951,8 @@ out var endToEndLemmaPrelim #endregion } + IDictionary> beforeDagBlocktoLoops = null; + if (_proofGenConfig.GenerateCfgDagProof) { #region cfg to dag @@ -975,7 +977,8 @@ out var endToEndLemmaPrelim beforeDagAfterDagBlock, beforeCfgToDagProgAccess, beforePassiveProgAccess, - afterOptimizationsVarTranslationFactory); + afterOptimizationsVarTranslationFactory, + out beforeDagBlocktoLoops); theories.Add(cfgToDagProofTheory); #endregion @@ -999,8 +1002,9 @@ out var endToEndLemmaPrelim unoptimizedCfgProgAccess, beforeCfgToDagProgAccess, afterPassificationImpl.ListCoalescedBlocks, - afterPassificationImpl.CoalescedBlocksToTarget); - theories.Add(cfgOptimizationsProofTheory); + afterPassificationImpl.CoalescedBlocksToTarget, + beforeDagBlocktoLoops); + theories.Add(cfgOptimizationsProofTheory); #endregion } From edf027ab4cef9ccf150b42b96f71e26b88eb592a Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Wed, 21 Jun 2023 10:58:05 +0200 Subject: [PATCH 047/123] Changed order in which lemmas are generated --- .../CFGOptimizationsLemmaManager.cs | 1 + .../CFGOptimizationsManager.cs | 137 ++++++++++++++++-- Source/ProofGeneration/CFGRepr/CFGRepr.cs | 100 ++++++++++++- 3 files changed, 227 insertions(+), 11 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index 1c5d2e69c..c765856d2 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -303,6 +303,7 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma { "apply (rule extend_hybrid_global_block_lemma_loop)", "apply (rule " + HybridblockLemmaName(succ) + ")", + //beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma() "apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] +")", "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", "by simp" diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index 078e61676..31f85486e 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -11,7 +11,7 @@ using ProofGeneration.BoogieIsaInterface.VariableTranslation; using ProofGeneration.CFGRepresentation; using ProofGeneration.Util; - +using ProofGenUtil; namespace ProofGeneration.CFGOptimizations; @@ -91,8 +91,98 @@ public static Theory CfgOptProof( outerDecls.Add(varContextAbbrev); outerDecls.Add(new DeclareDecl("Nat.One_nat_def[simp del]")); + //TODO: Check Dead Variables Elimination (Variables names change as well). See DeadVarElim.blp + //TODO: Check document names (not always p_before_cfg_to_dag_prog and p_unoptimized_cfg_prog) + + + CFGRepr beforeOptimizationsCopy = beforeOptimizations.Copy(); //TODO: extend it to deep copy, not sure how to do that + beforeOptimizationsCopy.DeleteBackedges(beforeOptBlockToLoops); + + for (int i = 0; i < beforeOptimizationsCopy.NumOfBlocks(); i++) + { + Block current = GetBlockWithoutSuccessor(beforeOptimizationsCopy); + Block beforeBlock = FindBlock(beforeOptimizations, current.UniqueId); + + if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops, beforeToAfter) && CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //In this case we have a coalesced loop head + { + coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + var globalBlock = lemmaManager.LoopHeadCoalesced(beforeBlock, coalescedAfterBlock, + bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), + beforeOptBlockToLoops[beforeBlock]); + outerDecls.Add(globalBlock); + } + else if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops,beforeToAfter)) //normal Loop Head + { + var globalBlock = lemmaManager.LoopHeadNotCoalesced(beforeBlock, beforeToAfter[beforeBlock], bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); + outerDecls.Add(globalBlock); + } + else if (CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //in this case we have block coalescing + { + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //Pruning of Unreachable Blocks Coalesced + { + coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + var pruningCoalesced = lemmaManager.HybridBlockLemmaPruning(beforeBlock, coalescedAfterBlock, + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); + outerDecls.Add(pruningCoalesced); + } + else if (beforeToAfter.ContainsKey(beforeBlock)) //Head of coalesced blocks + { + Block afterBlock = beforeToAfter[beforeBlock]; + var head = lemmaManager.HybridBlockLemma(beforeBlock, afterBlock, + beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault(), + bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); + outerDecls.Add(head); + var convertGlobalBlock = lemmaManager.ConvertHybridToGlobal(beforeBlock, afterBlock, + bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); + outerDecls.Add(convertGlobalBlock); + } + else if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() != 1 || beforeOptimizations.GetSuccessorBlocks(beforeBlock).First().Predecessors.Count() != 1) //tail of coalesced blocks + { + coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + + var tail = lemmaManager.HybridBlockLemmaTail(beforeBlock, coalescedAfterBlock, + bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), + beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); + outerDecls.Add(tail); + } + else //in Between Block + { + coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + var inBetweenBlock = lemmaManager.HybridBlockLemma(beforeBlock, coalescedAfterBlock, + beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault(), + bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); + outerDecls.Add(inBetweenBlock); + } + } + else //no block coalescing + { + if (beforeToAfter.Keys.Contains(beforeBlock)) + { + Block afterBlock = beforeToAfter[beforeBlock]; + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //If there is an assume or assert false statement in the block + { + var pruning = lemmaManager.GlobalBlockLemmaPruningNotCoalesced(beforeBlock, afterBlock, GetGlobalBlockLemmaName(beforeBlock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); + outerDecls.Add(pruning); + } + else //otherwhise we just need to apply the normal global block lemma. Assumption: Global Block Lemma holds for all successors + { + var globalBlock = lemmaManager.GlobalBlockLemma(beforeBlock, afterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); + outerDecls.Add(globalBlock); + } + } + } + beforeOptimizationsCopy.DeleteBlock(current); + } + + + /* foreach (Block beforeBlock in beforeOptimizations.GetBlocksForwards()) { if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops, beforeToAfter) && CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //In this case we have a coalesced loop head @@ -111,14 +201,14 @@ public static Theory CfgOptProof( } else if (CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //in this case we have block coalescing { - if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //Pruning of Unreachable Blocks Coalesced DONE + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //Pruning of Unreachable Blocks Coalesced { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); var pruningCoalesced = lemmaManager.HybridBlockLemmaPruning(beforeBlock, coalescedAfterBlock, bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(pruningCoalesced); } - else if (beforeToAfter.ContainsKey(beforeBlock)) //head DONE + else if (beforeToAfter.ContainsKey(beforeBlock)) //Loop head { Block afterBlock = beforeToAfter[beforeBlock]; var head = lemmaManager.HybridBlockLemma(beforeBlock, afterBlock, @@ -131,7 +221,7 @@ public static Theory CfgOptProof( bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(convertGlobalBlock); } - else if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() != 1 || beforeOptimizations.GetSuccessorBlocks(beforeBlock).First().Predecessors.Count() != 1) //tail TODO: + else if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() != 1 || beforeOptimizations.GetSuccessorBlocks(beforeBlock).First().Predecessors.Count() != 1) { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); @@ -141,7 +231,7 @@ public static Theory CfgOptProof( beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(tail); } - else //in Between Block DONE + else //in Between Block { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); var inBetweenBlock = lemmaManager.HybridBlockLemma(beforeBlock, coalescedAfterBlock, @@ -156,21 +246,21 @@ public static Theory CfgOptProof( if (beforeToAfter.Keys.Contains(beforeBlock)) { Block afterBlock = beforeToAfter[beforeBlock]; - if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //If there is an assume or assert false statement in the block DONE + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //If there is an assume or assert false statement in the block { var pruning = lemmaManager.GlobalBlockLemmaPruningNotCoalesced(beforeBlock, afterBlock, GetGlobalBlockLemmaName(beforeBlock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(pruning); } - else //otherwhise we just need to apply the normal global block lemma. Assumption: Global Block Lemma holds for all successors DONE + else //otherwhise we just need to apply the normal global block lemma. Assumption: Global Block Lemma holds for all successors { var globalBlock = lemmaManager.GlobalBlockLemma(beforeBlock, afterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(globalBlock); - } } } - } + */ + @@ -222,5 +312,34 @@ private static bool isLoopHead(Block b, CFGRepr beforeOptimizations, IDictionary return false; } + private static Block GetBlockWithoutSuccessor(CFGRepr cfg) + { + foreach (Block curr in cfg.GetBlocksForwards()) + { + if (cfg.GetSuccessorBlocks(curr).Count() == 0) + { + return curr; + } + } + return null; + } + + private static void RemoveBlock(CFGRepr cfg, Block remove) + { + + } + + private static Block FindBlock(CFGRepr cfg, int id) + { + foreach (Block curr in cfg.GetBlocksForwards()) + { + if (curr.UniqueId == id) + { + return curr; + } + } + return null; + } + } \ No newline at end of file diff --git a/Source/ProofGeneration/CFGRepr/CFGRepr.cs b/Source/ProofGeneration/CFGRepr/CFGRepr.cs index 4199ab844..7f3297825 100644 --- a/Source/ProofGeneration/CFGRepr/CFGRepr.cs +++ b/Source/ProofGeneration/CFGRepr/CFGRepr.cs @@ -1,13 +1,15 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; using Microsoft.Boogie; +using ProofGenUtil; namespace ProofGeneration.CFGRepresentation { public class CFGRepr { - private readonly Block[] blocks; + private Block[] blocks; //make sure that I can change that from readonly public readonly Block entry; private readonly IDictionary labeling; private readonly IDictionary> outgoingBlocks; @@ -75,5 +77,99 @@ public IEnumerable GetBlocksForwards() for (var i = blocks.Length - 1; i >= 0; i--) yield return blocks[i]; } + + + //TODO: Check if this is correct + public CFGRepr(CFGRepr other) + { + // Copy blocks array + blocks = new Block[other.blocks.Length]; + Array.Copy(other.blocks, blocks, other.blocks.Length); + + // Copy outgoingBlocks dictionary + outgoingBlocks = new Dictionary>(); + foreach (var kvp in other.outgoingBlocks) + { + outgoingBlocks.Add(kvp.Key, new List(kvp.Value)); + } + + + // Copy labeling dictionary + labeling = new Dictionary(); + foreach (var kvp in other.labeling) + { + labeling.Add(kvp.Key, kvp.Value); + } + + + // Copy entry block + entry = other.entry; + } + + public CFGRepr Copy() + { + return new CFGRepr(this); + } + + public void DeleteBlock(Block block) + { + if (!ContainsBlock(block)) + { + throw new ArgumentException("Block does not exist in the CFG."); + } + + // Remove block from the blocks array + int index = GetUniqueIntLabel(block); + + var blocks_new = new Block[blocks.Length - 1]; + + for (int i = 0, j = 0; i < blocks.Length; i++) + { + if (i == index) + { + continue; + } + blocks_new[j] = blocks[i]; + j++; + } + + blocks = blocks_new; + + // Remove block from the outgoingBlocks dictionary + outgoingBlocks.Remove(block); + + // Remove block from the labeling dictionary + labeling.Remove(block); + + // Remove block from the successors of other blocks + foreach (var kvp in outgoingBlocks) + { + kvp.Value.Remove(block); + } + } + + public void DeleteBackedges(IDictionary> BlockToLoops) + { + foreach (Block b in blocks) + { + List Backedges = new List(); + foreach (Block succ in GetSuccessorBlocks(b)) + { + if (BlockToLoops[b].Contains(succ)) + { + Backedges.Add(succ); + } + } + foreach (Block toRemove in Backedges) + { + outgoingBlocks[b].Remove(toRemove); + } + } + } + + + + + } } \ No newline at end of file From 5b7f2003f37b2871a0b4c6c19753a179056c8839 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 21 Jun 2023 11:18:34 +0200 Subject: [PATCH 048/123] set cfg_optimizations branch on .gitmodules --- .gitmodules | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitmodules b/.gitmodules index c3f8cfee6..892c2c7c4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "foundational_boogie"] path = foundational_boogie url = https://github.com/gauravpartha/foundational_boogie + branch = cfg_optimizations From 0cbf184998aaca1b41ead2cab3be41b2c0ee0721 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 21 Jun 2023 11:23:39 +0200 Subject: [PATCH 049/123] update submodule branch to matching cfg_optimizations --- foundational_boogie | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundational_boogie b/foundational_boogie index 58d1183fb..20d38f52e 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit 58d1183fbda06a6fea330b0b11717abd0bfdaa9f +Subproject commit 20d38f52e51ea3fae58dd1166ca637a512c45c18 From 0f1580e912ba577d074184f72c888ab38fa2085a Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Mon, 26 Jun 2023 17:12:28 +0200 Subject: [PATCH 050/123] Generation of End to End Lemma finished --- .../CFGOptimizationsEndToEnd.cs | 224 ++++++++++++++++++ .../CFGOptimizationsLemmaManager.cs | 208 ++++++++++------ .../CFGOptimizationsManager.cs | 116 +++++---- Source/ProofGeneration/CFGRepr/CFGRepr.cs | 37 --- .../ProofGeneration/ProofGenerationLayer.cs | 3 +- 5 files changed, 442 insertions(+), 146 deletions(-) create mode 100644 Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs new file mode 100644 index 000000000..d404f8ee2 --- /dev/null +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs @@ -0,0 +1,224 @@ +namespace ProofGeneration.CFGOptimizations; +using System; +using System.Collections.Generic; +using System.Text; +using Isabelle.Ast; +using Isabelle.Util; +using ProofGeneration.BoogieIsaInterface; +using ProofGeneration.CFGRepresentation; +using ProofGeneration.PhasesUtil; +using ProofGeneration.Util; + +public class CFGOptimizationsEndToEnd +{ + private readonly string axiomAssmName = "Axioms"; + private readonly string binderEmptyAssmName = "BinderNs"; + private readonly string closedAssmName = "Closed"; + private readonly string constsGlobalsAssmName = "ConstsGlobal"; + private readonly TermIdent finalNodeOrReturn = IsaCommonTerms.TermIdentFromName("m'"); + private readonly TermIdent finalState = IsaCommonTerms.TermIdentFromName("s'"); + private readonly string finterpAssmName = "FInterp"; + private readonly string nonEmptyTypesAssmName = "NonEmptyTypes"; + + private readonly TermIdent normalInitState = IsaCommonTerms.TermIdentFromName("ns"); + private readonly string oldGlobalAssmName = "OldGlobal"; + private readonly string paramsLocalsAssmName = "ParamsLocal"; + private readonly string preconditionsAssmName = "Precondition"; + + private readonly string redAssmName = "Red"; + private readonly string vcAssmName = "VC"; + private BoogieContextIsa boogieContext; + + private IProgramAccessor programAccessor; + + + private readonly string varContextName = "\\0"; + + + public IEnumerable EndToEndProof( + string entryBlockCfgOptLemma, + string cfgOptEndToEndLemma, + Term vcAssm, + IProgramAccessor beforeOptProgAccess, + IProgramAccessor afterOptProgAccess, + IProgramAccessor programAccessor, + CFGRepr afterOptCFG, + PhasesTheories phasesTheories) + { + this.programAccessor = programAccessor; + boogieContext = new BoogieContextIsa( + IsaCommonTerms.TermIdentFromName("A"), + IsaCommonTerms.TermIdentFromName("M"), + IsaCommonTerms.TermIdentFromName(varContextName), + IsaCommonTerms.TermIdentFromName("\\"), + IsaCommonTerms.EmptyList + ); + + var abbrev = new AbbreviationDecl( + varContextName, + new Tuple, Term>(new List(), + new TermTuple(afterOptProgAccess.ConstsAndGlobalsDecl(), afterOptProgAccess.ParamsAndLocalsDecl())) + ); + + var result = new List {abbrev}; + + var kStepRed = IsaBoogieTerm.RedCFGKStep( + BoogieContextIsa.CreateWithNewVarContext( + boogieContext, + new TermTuple(afterOptProgAccess.ConstsAndGlobalsDecl(), afterOptProgAccess.ParamsAndLocalsDecl()) + ), + beforeOptProgAccess.CfgDecl(), + IsaBoogieTerm.CFGConfigNode(new NatConst(afterOptCFG.GetUniqueIntLabel(afterOptCFG.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 " + entryBlockCfgOptLemma)); + proofSb.AppendLine("apply (rule Aux)"); + proofSb.AppendLine("apply (rule allI | rule impI)+"); + proofSb.AppendLine("apply (rule " + phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag) + ".end_to_end_theorem_aux)"); + proofSb.AppendLine("using assms"); + proofSb.AppendLine("by auto"); + proofSb.AppendLine("qed"); + + var helperLemmaName = "end_to_end_theorem_aux"; + + var helperLemma = + new LemmaDecl( + helperLemmaName, + LemmaContext(afterOptCFG, vcAssm, afterOptProgAccess), + CfgOptLemmaConclusion(boogieContext, afterOptProgAccess.PostconditionsDecl(), + finalNodeOrReturn, finalState), + new Proof(new List {proofSb.ToString()}) + ); + result.Add(helperLemma); + + var defProcWithoutDeadVar = new DefDecl("p_unoptimized_without_dead_vars", new Tuple, Term>(new List(), IsaCommonTerms.TermIdentFromName("proc ⦇ proc_body := (Some (" + afterOptProgAccess.BlockInfo().getTheoryName() + ".locals_vdecls," + beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body)) ⦈"))); + result.Add(defProcWithoutDeadVar); + + var endToEndLemma = + new LemmaDecl( + "end_to_end_theorem", + ContextElem.CreateWithAssumptions(new List {vcAssm}, new List {"VC"}), + ProcedureIsCorrect( + programAccessor.FunctionsDecl(), + IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), + IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()), + programAccessor.AxiomsDecl(), + programAccessor.ProcDecl()), + new Proof( + new List + { + ProofUtil.Apply(ProofUtil.Rule(ProofUtil.OF("end_to_end_util",helperLemmaName))), + ProofUtil.Apply("assumption"), + "using VC apply simp", + ProofUtil.Apply("assumption+"), + "apply (unfold p_unoptimized_without_dead_vars_def)", + "apply (simp add: " + afterOptProgAccess.BlockInfo().getTheoryName() + ".pres_def " + afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_def exprs_to_only_checked_spec_1)", + "apply (simp add: " + afterOptProgAccess.BlockInfo().getTheoryName() + ".post_def " + afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_def exprs_to_only_checked_spec_2)", + "apply simp", + "apply (simp add: " + afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_def)", + "apply (simp add: " + afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_def)", + "apply (simp add: " + afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_def)", + "apply (simp add: " + beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body_def)", + "done" + } + ) ); + + result.Add(endToEndLemma); + + + return result; + } + + + private ContextElem LemmaContext( + CFGRepr cfg, + Term vcAssm, + IProgramAccessor afterOptProgAccess + ) + { + var multiRed = IsaBoogieTerm.RedCFGMulti( + BoogieContextIsa.CreateWithNewVarContext( + boogieContext, + new TermTuple(afterOptProgAccess.ConstsAndGlobalsDecl(), afterOptProgAccess.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, afterOptProgAccess.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 + { + multiRed, vcAssm, closedAssm, nonEmptyTypesAssm, finterpAssm, axiomAssm, + presAssm, localsAssm, globalsAssm, oldGlobalStateAssm, binderEmptyAssm + }, + new List + { + redAssmName, vcAssmName, closedAssmName, nonEmptyTypesAssmName, finterpAssmName, axiomAssmName, + preconditionsAssmName, paramsLocalsAssmName, constsGlobalsAssmName, oldGlobalAssmName, + binderEmptyAssmName + } + ); + } + + public static Term CfgOptLemmaConclusion(BoogieContextIsa boogieContext, Term post, Term finalNode, + Term finalState) + { + return new TermApp( + IsaCommonTerms.TermIdentFromName("Semantics.valid_configuration"), + boogieContext.absValTyMap, + boogieContext.varContext, + boogieContext.funContext, + boogieContext.rtypeEnv, + post, + finalNode, + finalState); + } + + public static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term globalDecls, Term axioms, + Term procedure) + { + var typeInterpId = new SimpleIdentifier("A"); + return + TermQuantifier.MetaAll( + new List {typeInterpId}, + null, + new TermApp( + IsaCommonTerms.TermIdentFromName("Semantics.proc_is_correct"), + //TODO: here assuming that we use "'a" for the abstract value type carrier t --> make t a parameter somewhere + new TermWithExplicitType(new TermIdent(typeInterpId), + IsaBoogieType.AbstractValueTyFunType(new VarType("a"))), + funDecls, + constantDecls, + globalDecls, + axioms, + IsaCommonTerms.TermIdentFromName("p_unoptimized_without_dead_vars"), + IsaBoogieTerm.SematicsProcSpecSatisfied)); + } +} \ No newline at end of file diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index c765856d2..635a69eff 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using Isabelle.Ast; using Isabelle.Util; using Microsoft.Boogie; using ProofGeneration.BoogieIsaInterface; @@ -23,12 +22,14 @@ public class CFGOptimizationsLemmaManager private readonly CFGRepr afterOptimizations; private readonly string funContextWfName; private readonly IDictionary beforeToAfterBlock; + private readonly BoogieContextIsa boogieContext; public CFGOptimizationsLemmaManager( IProgramAccessor beforeOptProgAccess, IProgramAccessor afterOptProgAccess, CFGRepr beforeOptimizations, CFGRepr afterOptimizations, string funContextWfName, + BoogieContextIsa boogieContext, IDictionary beforeToAfterBlock ) { @@ -37,6 +38,7 @@ IDictionary beforeToAfterBlock this.beforeOptimizations = beforeOptimizations; this.afterOptimizations = afterOptimizations; this.funContextWfName = funContextWfName; + this.boogieContext = boogieContext; this.beforeToAfterBlock = beforeToAfterBlock; } @@ -46,16 +48,16 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b string blockLemmaName, IList Loops) { + var proofMethods = new List { - "apply (rule pruning_not_coalesced_loop)", - "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", - "apply (rule p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")", - "apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", - "apply (unfold p_unoptimized_cfg_prog.block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + "_def)", + "apply (rule " + beforeOptProgAccess.BlockInfo().OutEdgesMembershipLemma(beforeBlock) + ")", + "apply (rule " + afterOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(afterBlock) + ")", + "apply (rule " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + ")", + "apply (unfold " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock) + "_def)", "apply simp", - "apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def)", + "apply (unfold " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) + "_def)", "by simp" }; @@ -72,11 +74,12 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); @@ -94,6 +97,9 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b IDictionary> beforeOptBlockToLoops, IList Loops) { + + + var loopHeads = new List(); foreach (Block loop in Loops) { @@ -112,7 +118,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b var proofMethods = new List { "apply (rule loopBlock_global_block[where ?f = \"the ∘ map_of [" + string.Join(",", function) + "]\"])", - "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply (rule " + beforeOptProgAccess.BlockInfo().OutEdgesMembershipLemma(beforeBlock) + ")", "apply simp" }; int countCases = 0; @@ -154,7 +160,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b proofMethods.Add("apply simp"); if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 0) { - proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.outEdges_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); + proofMethods.Add("apply (unfold " + afterOptProgAccess.BlockInfo().OutEdgesMembershipLemma(afterBlock) + ")"); } @@ -166,10 +172,11 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b { proofMethods.Add("apply simp"); } - proofMethods.Add("apply (rule p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); - proofMethods.Add("apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")"); - proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def p_unoptimized_cfg_prog.block_" + - beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + "_def)"); + + proofMethods.Add("apply (rule " + afterOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(afterBlock) + ")"); + proofMethods.Add("apply (rule " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + ")"); + proofMethods.Add("apply (unfold " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) + "_def " + + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock) + "_def)"); proofMethods.Add("by simp"); var varContextName = "\\"; IList terms = new List(); @@ -178,11 +185,12 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( @@ -219,7 +227,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b { "apply (rule loopBlock_global_block_hybrid[where ?f = \"the ∘ map_of [" + string.Join(",", function) + "]\"])", - "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply (rule " + beforeOptProgAccess.BlockInfo().OutEdgesMembershipLemma(beforeBlock) + ")", "apply simp" }; int countCases = 0; @@ -261,12 +269,12 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 0) { proofMethods.Add("apply simp"); - proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.outEdges_" + - afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); + proofMethods.Add("apply (unfold " + afterOptProgAccess.BlockInfo().OutEdgesMembershipLemma(afterBlock) + ")"); } proofMethods.Add("apply simp"); - proofMethods.Add("apply (unfold p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + " block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock]+ "_def)"); + + proofMethods.Add("apply (unfold " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + " " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock) + "_def)"); proofMethods.Add("by simp"); var varContextName = "\\"; @@ -276,12 +284,13 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.TermIdentFromName("block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock))); terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("hybrid_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( @@ -304,8 +313,8 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma "apply (rule extend_hybrid_global_block_lemma_loop)", "apply (rule " + HybridblockLemmaName(succ) + ")", //beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma() - "apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] +")", - "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply (rule " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + ")", + "apply (rule " + beforeOptProgAccess.BlockInfo().OutEdgesMembershipLemma(beforeBlock) + ")", "by simp" }; @@ -317,12 +326,12 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma List listCoalescedBlocks = new List(); Block curr = beforeBlock; - listCoalescedBlocks.Add("block_" + beforeOptProgAccess.BlockInfo().BlockIds[curr]); + listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(curr)); while ((beforeOptimizations.GetSuccessorBlocks(curr).Count() == 1 && beforeOptimizations.GetSuccessorBlocks(curr).First().Predecessors.Count() == 1)) { curr = beforeOptimizations.GetSuccessorBlocks(curr).First(); - listCoalescedBlocks.Add("block_" + beforeOptProgAccess.BlockInfo().BlockIds[curr]); + listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(curr)); } @@ -333,12 +342,13 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); terms.Add(IsaCommonTerms.TermIdentFromName("(" + string.Join("@", listCoalescedBlocks) + ")")); terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("hybrid_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( @@ -363,12 +373,12 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma List listCoalescedBlocks = new List(); Block curr = beforeBlock; - listCoalescedBlocks.Add("block_" + beforeOptProgAccess.BlockInfo().BlockIds[curr]); + listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(curr)); while ((beforeOptimizations.GetSuccessorBlocks(curr).Count() == 1 && beforeOptimizations.GetSuccessorBlocks(curr).First().Predecessors.Count() == 1)) { curr = beforeOptimizations.GetSuccessorBlocks(curr).First(); - listCoalescedBlocks.Add("block_" + beforeOptProgAccess.BlockInfo().BlockIds[curr]); + listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(curr)); } @@ -376,7 +386,7 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma { proofMethods.Add("apply (unfold " + b + "_def)"); } - proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + " p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def)"); + proofMethods.Add("apply (unfold " + afterOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(afterBlock) + " " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) + "_def)"); proofMethods.Add("by simp"); var loopHeads = new List(); foreach (Block loop in Loops) @@ -390,11 +400,12 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( @@ -413,11 +424,12 @@ public LemmaDecl HybridBlockLemmaPruning( //Pruning of unreachable blocks with b var proofMethods = new List { "apply (rule pruning_coalesced_loop)", - "apply (rule p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")", - "apply (unfold p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + " p_unoptimized_cfg_prog.block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + "_def)", + "apply (rule " + afterOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(afterBlock) + ")", + "apply (unfold " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + ")", + "apply (unfold " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock) + "_def)", "apply simp", "apply simp", - "apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def)", + "apply (unfold " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) + "_def)", "by simp" }; var loopHeads = new List(); @@ -433,12 +445,13 @@ public LemmaDecl HybridBlockLemmaPruning( //Pruning of unreachable blocks with b terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.TermIdentFromName("block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock))); terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("hybrid_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( @@ -474,7 +487,7 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced var proofMethods = new List { "apply (rule loopHead_global_block[where ?f = \"the ∘ map_of [" + string.Join(",", function) + "]\"])", - "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply (rule " + beforeOptProgAccess.BlockInfo().OutEdgesMembershipLemma(beforeBlock) + ")", "apply simp" }; @@ -514,7 +527,7 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced proofMethods.Add("apply simp"); if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 0) { - proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.outEdges_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); + proofMethods.Add("apply (unfold " + afterOptProgAccess.BlockInfo().OutEdgesMembershipLemma(afterBlock) + ")"); } @@ -526,10 +539,9 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced { proofMethods.Add("apply simp"); } - proofMethods.Add("apply (rule p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + ")"); - proofMethods.Add("apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")"); - proofMethods.Add("apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + "_def p_unoptimized_cfg_prog.block_" + - beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + "_def)"); + proofMethods.Add("apply (rule " + afterOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(afterBlock) + ")"); + proofMethods.Add("apply (rule " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + ")"); + proofMethods.Add("apply (unfold "+ afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) + "_def " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock) + "_def)"); proofMethods.Add("by simp"); var varContextName = "\\"; IList terms = new List(); @@ -538,11 +550,12 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( @@ -570,27 +583,18 @@ public LemmaDecl LoopHeadCoalesced( //Loop Head coalesced var proofMethods = new List { "apply (rule loopHead_global_block_hybrid)", - "apply (rule p_unoptimized_cfg_prog.outEdges_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", + "apply (rule " + beforeOptProgAccess.BlockInfo().OutEdgesMembershipLemma(beforeBlock) + ")", "apply simp", "apply (rule " + HybridblockLemmaName(beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault()) + ")", - "apply (rule p_unoptimized_cfg_prog.node_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] + ")", - "apply (rule p_before_cfg_to_dag_prog.node_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] + " )", - "apply (unfold p_before_cfg_to_dag_prog.block_" + afterOptProgAccess.BlockInfo().BlockIds[afterBlock] +"_def)", - "apply (unfold p_unoptimized_cfg_prog.block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock] +"_def)", - "apply (unfold p_unoptimized_cfg_prog.block_" + beforeOptProgAccess.BlockInfo().BlockIds[beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault()] +"_def)", + "apply (rule " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + ")", + "apply (rule " + afterOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(afterBlock) + ")", + "apply (unfold " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) +"_def)", + "apply (unfold " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock) + "_def)", + "apply (unfold " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault()) + "_def)", "by simp" }; - List listCoalescedBlocks = new List(); - Block curr = beforeBlock; - listCoalescedBlocks.Add("block_" + beforeOptProgAccess.BlockInfo().BlockIds[curr]); - while ((beforeOptimizations.GetSuccessorBlocks(curr).Count() == 1 && - beforeOptimizations.GetSuccessorBlocks(curr).First().Predecessors.Count() == 1)) - { - curr = beforeOptimizations.GetSuccessorBlocks(curr).First(); - listCoalescedBlocks.Add("block_" + beforeOptProgAccess.BlockInfo().BlockIds[curr]); - - } + var varContextName = "\\"; IList terms = new List(); @@ -599,11 +603,12 @@ public LemmaDecl LoopHeadCoalesced( //Loop Head coalesced terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_unoptimized_cfg_prog.proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName("p_before_cfg_to_dag_prog.proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); + terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( @@ -613,6 +618,75 @@ public LemmaDecl LoopHeadCoalesced( //Loop Head coalesced return blockLemma; } + public LemmaDecl EntryLemma(string entryLemmaName, string globalBlockLemmaEntryBlockName, Block beforeEntryBlock, + Block afterEntryBlock) + { + Term numSteps = IsaCommonTerms.TermIdentFromName("j"); + Term normalInitState1 = IsaCommonTerms.TermIdentFromName("ns1"); + TermIdent finalNode = IsaCommonTerms.TermIdentFromName("m'"); + Term finalState = IsaCommonTerms.TermIdentFromName("s'"); + var redCfg = IsaBoogieTerm.RedCFGKStep( + boogieContext, + beforeOptProgAccess.CfgDecl(), + IsaBoogieTerm.CFGConfigNode(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeEntryBlock]), + IsaBoogieTerm.Normal(normalInitState1)), + numSteps, + IsaBoogieTerm.CFGConfig(finalNode, finalState)); + + var finalNodeId2 = new SimpleIdentifier("m2'"); + var finalStateId2 = new SimpleIdentifier("s2'"); + var tarVer = cfgOptTargetVerifies(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterEntryBlock]), + normalInitState1, finalNodeId2, finalStateId2); + + + var assumptions = new List {redCfg}; + assumptions.Add(tarVer); + + return new LemmaDecl( + entryLemmaName, + ContextElem.CreateWithAssumptions(assumptions), + CFGOptimizationsEndToEnd.CfgOptLemmaConclusion(boogieContext, afterOptProgAccess.PostconditionsDecl(), finalNode, finalState), + new Proof(new List + { + "using " + globalBlockLemmaEntryBlockName, + "unfolding global_block_lemma_loop_def", + "using assms(1) assms(2) by blast" + }) + ); + + } + + private Term cfgOptTargetVerifies( + Term initialStateNode, + Term initialNormalState, + Identifier finalNodeId2, + Identifier finalStateId2 + ) + { + Term finalNode2 = new TermIdent(finalNodeId2); + Term finalState2 = new TermIdent(finalStateId2); + + Func, IList, Term, TermQuantifier> forallConstructor; + Func impliesConstructor; + forallConstructor = TermQuantifier.ForAll; + impliesConstructor = TermBinary.Implies; + + return + forallConstructor( + new List {finalNodeId2, finalStateId2}, + null, + impliesConstructor( + IsaBoogieTerm.RedCFGMulti(boogieContext, + afterOptProgAccess.CfgDecl(), + IsaBoogieTerm.CFGConfigNode( + initialStateNode, IsaBoogieTerm.Normal(initialNormalState) + ), + IsaBoogieTerm.CFGConfig(finalNode2, finalState2) + ), + CFGOptimizationsEndToEnd.CfgOptLemmaConclusion(boogieContext, afterOptProgAccess.PostconditionsDecl(), finalNode2, finalState2)) + ); + } + private static bool isLoopHead(Block b, CFGRepr beforeOptimizations, IDictionary> beforeOptBlockToLoops, IDictionary beforeToAfter) { diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index 31f85486e..1b461e9d3 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -26,11 +26,12 @@ public static Theory CfgOptProof( CFGRepr beforeOptimizations, CFGRepr afterOptimizations, IDictionary beforeToAfter, // mapping from current block to target block - IProgramAccessor beforeOptCfgProgAcccess, //before CFG optimizations + IProgramAccessor beforeOptCfgProgAccess, //before CFG optimizations IProgramAccessor afterOptCfgProgAccess, //after CFG optimizationsList<(Block, Block)> CoalescedBlocks IDictionary> ListCoalescedBlocks, //TODO: Optimize CFGOptimizationsLemmaManager by using this dictionary IDictionary CoalescedBlocksToTarget, - IDictionary> beforeDagBlockToLoops) + IDictionary> beforeDagBlockToLoops, + Term vcAssm) { IDictionary afterToBefore = beforeToAfter.ToDictionary(x => x.Value, x => x.Key); IDictionary> beforeOptBlockToLoops = new Dictionary>(); @@ -70,39 +71,49 @@ public static Theory CfgOptProof( var varContextName = "\\"; - var varContextAbbrev = new AbbreviationDecl( - varContextName, - new Tuple, Term>(new List(), afterOptCfgProgAccess.VarContext())); - + var funContextWfName = "Wf_Fun"; + + var boogieContext = new BoogieContextIsa( + IsaCommonTerms.TermIdentFromName("A"), + IsaCommonTerms.TermIdentFromName("M"), + IsaCommonTerms.TermIdentFromName(varContextName), + IsaCommonTerms.TermIdentFromName("\\"), + IsaCommonTerms.TermIdentFromName("\\")); var lemmaManager = new CFGOptimizationsLemmaManager( - beforeOptCfgProgAcccess, + beforeOptCfgProgAccess, afterOptCfgProgAccess, beforeOptimizations, afterOptimizations, funContextWfName, - beforeToAfter); //TODO: Add necessary declarations + boogieContext, + beforeToAfter); var lemmaNamer = new IsaUniqueNamer(); var outerDecls = new List(); - outerDecls.Add(varContextAbbrev); outerDecls.Add(new DeclareDecl("Nat.One_nat_def[simp del]")); - //TODO: Check Dead Variables Elimination (Variables names change as well). See DeadVarElim.blp - //TODO: Check document names (not always p_before_cfg_to_dag_prog and p_unoptimized_cfg_prog) - - - CFGRepr beforeOptimizationsCopy = beforeOptimizations.Copy(); //TODO: extend it to deep copy, not sure how to do that + + + CFGRepr beforeOptimizationsCopy = beforeOptimizations.Copy(); beforeOptimizationsCopy.DeleteBackedges(beforeOptBlockToLoops); - for (int i = 0; i < beforeOptimizationsCopy.NumOfBlocks(); i++) + List topoOrder = new List(); + IDictionary visited = new Dictionary(); + foreach (var current in beforeOptimizationsCopy.GetBlocksForwards()) + { + if (!visited.ContainsKey(current)) + { + TopologicalOrder(current, topoOrder, visited, beforeOptimizationsCopy); + } + } + + foreach (var current in topoOrder) { - Block current = GetBlockWithoutSuccessor(beforeOptimizationsCopy); Block beforeBlock = FindBlock(beforeOptimizations, current.UniqueId); - if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops, beforeToAfter) && CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //In this case we have a coalesced loop head { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); @@ -176,15 +187,15 @@ public static Theory CfgOptProof( } } } - beforeOptimizationsCopy.DeleteBlock(current); } - - /* - foreach (Block beforeBlock in beforeOptimizations.GetBlocksForwards()) + for (int i = 0; i < beforeOptimizations.NumOfBlocks(); i++) { + Block current = GetBlockWithoutSuccessor(beforeOptimizationsCopy); + Block beforeBlock = FindBlock(beforeOptimizations, current.UniqueId); + if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops, beforeToAfter) && CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //In this case we have a coalesced loop head { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); @@ -208,7 +219,7 @@ public static Theory CfgOptProof( bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(pruningCoalesced); } - else if (beforeToAfter.ContainsKey(beforeBlock)) //Loop head + else if (beforeToAfter.ContainsKey(beforeBlock)) //Head of coalesced blocks { Block afterBlock = beforeToAfter[beforeBlock]; var head = lemmaManager.HybridBlockLemma(beforeBlock, afterBlock, @@ -221,7 +232,7 @@ public static Theory CfgOptProof( bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(convertGlobalBlock); } - else if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() != 1 || beforeOptimizations.GetSuccessorBlocks(beforeBlock).First().Predecessors.Count() != 1) + else if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() != 1 || beforeOptimizations.GetSuccessorBlocks(beforeBlock).First().Predecessors.Count() != 1) //tail of coalesced blocks { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); @@ -258,17 +269,37 @@ public static Theory CfgOptProof( } } } + beforeOptimizationsCopy.DeleteBlock(current); } */ - - - + + var entryLemma = lemmaManager.EntryLemma("entry_lemma", + GetGlobalBlockLemmaName(beforeOptimizations.entry, lemmaNamer), beforeOptimizations.entry, + afterOptimizations.entry); + outerDecls.Add(entryLemma); + + var endToEndManager = new CFGOptimizationsEndToEnd(); + var endToEndDecls = endToEndManager.EndToEndProof( + "entry_lemma", + "end_to_end", + vcAssm, + beforeOptCfgProgAccess, + afterOptCfgProgAccess, + beforeOptCfgProgAccess, + afterOptimizations, + phasesTheories + ); + outerDecls.AddRange(endToEndDecls); + + List importTheories = new List { "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.CFGOptimizationsLoop", afterOptCfgProgAccess.TheoryName(), - beforeOptCfgProgAcccess.TheoryName() + beforeOptCfgProgAccess.TheoryName(), + phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag) + }; return new Theory( @@ -311,34 +342,37 @@ private static bool isLoopHead(Block b, CFGRepr beforeOptimizations, IDictionary } return false; } - - private static Block GetBlockWithoutSuccessor(CFGRepr cfg) + + + + private static Block FindBlock(CFGRepr cfg, int id) { foreach (Block curr in cfg.GetBlocksForwards()) { - if (cfg.GetSuccessorBlocks(curr).Count() == 0) + if (curr.UniqueId == id) { return curr; } } return null; } - - private static void RemoveBlock(CFGRepr cfg, Block remove) - { - - } - - private static Block FindBlock(CFGRepr cfg, int id) + + private static void TopologicalOrder(Block current, List topoOrder, IDictionary visited, CFGRepr beforeOptimizationsCopy) { - foreach (Block curr in cfg.GetBlocksForwards()) + if (!visited.ContainsKey(current)) { - if (curr.UniqueId == id) + visited.Add(current, true); + } + + foreach (var succ in beforeOptimizationsCopy.GetSuccessorBlocks(current)) + { + if (!visited.ContainsKey(succ)) { - return curr; + TopologicalOrder(succ,topoOrder, visited, beforeOptimizationsCopy); } } - return null; + + topoOrder.Add(current); } diff --git a/Source/ProofGeneration/CFGRepr/CFGRepr.cs b/Source/ProofGeneration/CFGRepr/CFGRepr.cs index 7f3297825..da582c730 100644 --- a/Source/ProofGeneration/CFGRepr/CFGRepr.cs +++ b/Source/ProofGeneration/CFGRepr/CFGRepr.cs @@ -110,43 +110,6 @@ public CFGRepr Copy() { return new CFGRepr(this); } - - public void DeleteBlock(Block block) - { - if (!ContainsBlock(block)) - { - throw new ArgumentException("Block does not exist in the CFG."); - } - - // Remove block from the blocks array - int index = GetUniqueIntLabel(block); - - var blocks_new = new Block[blocks.Length - 1]; - - for (int i = 0, j = 0; i < blocks.Length; i++) - { - if (i == index) - { - continue; - } - blocks_new[j] = blocks[i]; - j++; - } - - blocks = blocks_new; - - // Remove block from the outgoingBlocks dictionary - outgoingBlocks.Remove(block); - - // Remove block from the labeling dictionary - labeling.Remove(block); - - // Remove block from the successors of other blocks - foreach (var kvp in outgoingBlocks) - { - kvp.Value.Remove(block); - } - } public void DeleteBackedges(IDictionary> BlockToLoops) { diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 35cf40b59..4426da815 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -1003,7 +1003,8 @@ out var endToEndLemmaPrelim beforeCfgToDagProgAccess, afterPassificationImpl.ListCoalescedBlocks, afterPassificationImpl.CoalescedBlocksToTarget, - beforeDagBlocktoLoops); + beforeDagBlocktoLoops, + vcAssm); theories.Add(cfgOptimizationsProofTheory); #endregion From 184f6447eb7a34df44d050700debd364498ba82a Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Wed, 28 Jun 2023 10:01:28 +0200 Subject: [PATCH 051/123] CFG Optimizations test files --- .../cfg_optimizations_tests/DeadVarElim.bpl | 14 +++++++ .../cfg_optimizations_tests/NestedLoop.bpl | 23 +++++++++++ .../block_coalescing.bpl | 22 +++++++++++ .../block_coalescing_new.bpl | 34 +++++++++++++++++ .../cfg_optimizations_tests/loop.bpl | 13 +++++++ .../cfg_optimizations_tests/loop_new.bpl | 15 ++++++++ .../testComplicatedAllCases.bpl | 38 +++++++++++++++++++ foundational_boogie | 2 +- 8 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/DeadVarElim.bpl create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/NestedLoop.bpl create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing.bpl create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_new.bpl create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/loop.bpl create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/loop_new.bpl create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/testComplicatedAllCases.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/DeadVarElim.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/DeadVarElim.bpl new file mode 100644 index 000000000..8387f0deb --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/DeadVarElim.bpl @@ -0,0 +1,14 @@ + +procedure p2(){ + var k: int; + var j: int; + var i: bool; + + i := true; + + goto T1; + + T1: + k := 0; + k := k + 1; +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/NestedLoop.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/NestedLoop.bpl new file mode 100644 index 000000000..df0b9d84b --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/NestedLoop.bpl @@ -0,0 +1,23 @@ +procedure p() { + var y: int; + var i: int; + + l1: + i := 0; + y := 0; + + + l2: + i := i+1; + + + l3: + while ( i <= 10 ){ + goto l2,l4; + l4: + i := i + 1; + y := y + i; + } + + assert y >= 0; +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing.bpl new file mode 100644 index 000000000..a604fb3a4 --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing.bpl @@ -0,0 +1,22 @@ +procedure p() { + var y: int; + + y := 1; + + y := y+1; + goto l1; + + l1: + y := y+2; + goto l2; + + l2: + y := y+3; + goto l3,l4; + + l3: + assert y >= 0; + + l4: + assert y >= 0; +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_new.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_new.bpl new file mode 100644 index 000000000..f7d7d6ea2 --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_new.bpl @@ -0,0 +1,34 @@ +procedure p() { + var y: int; + + y := 1; + + y := y+1; + goto l1; + + l1: + y := y+2; + goto l2, l7; + + l2: + y := y+3; + goto l3,l4; + + l3: + assert y >= 0; + + l4: + assert y >= 0; + goto l5; + + l5: + y:= y+5; + goto l6; + + l6: + assume false; + goto l7; + + l7: + y := y + 7; +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop.bpl new file mode 100644 index 000000000..254ea922f --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop.bpl @@ -0,0 +1,13 @@ +procedure p() { + var y: int; + var i: int; + i := 0; + y := 0; + + while ( i <= 10 ){ + y := y + i; + i := i + 1; + } + + assert y >= 0; +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_new.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_new.bpl new file mode 100644 index 000000000..2f2501ed2 --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_new.bpl @@ -0,0 +1,15 @@ +procedure p() { + var y: int; + var i: int; + i := 0; + y := 0; + + while ( i <= 10 ){ + y := y + i; + goto l1; + + l1: + i := i + 1; + } + +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/testComplicatedAllCases.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/testComplicatedAllCases.bpl new file mode 100644 index 000000000..9dfc22b0c --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/testComplicatedAllCases.bpl @@ -0,0 +1,38 @@ +procedure p() { + var y: int; + var i: int; + + l1: + i := 0; + y := 0; + goto l3, l5; + + + l2: + i := i+1; + + + l3: + while ( i <= 10 ){ + goto l2,l4, l6, l3; + l4: + i := i + 1; + y := y + i; + } + + assert y >= 0; + + + l5: + i := i + 10; + goto l6; + + + l6: + i := i + 10; + assume false; + goto l7; + + l7: + i := i + 1; +} \ No newline at end of file diff --git a/foundational_boogie b/foundational_boogie index 20d38f52e..58d1183fb 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit 20d38f52e51ea3fae58dd1166ca637a512c45c18 +Subproject commit 58d1183fbda06a6fea330b0b11717abd0bfdaa9f From 4a8d256a4785fd93ce3d4c223c28b244946a34a5 Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Wed, 28 Jun 2023 10:07:41 +0200 Subject: [PATCH 052/123] isLoopHead fix --- .../CFGOptimizationsLemmaManager.cs | 6 ++- .../CFGOptimizationsManager.cs | 6 ++- .../CfgToDag/CfgToDagManager.cs | 31 ++--------- .../ProofGeneration/ProofGenerationLayer.cs | 54 ++++++++++++++++--- 4 files changed, 61 insertions(+), 36 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index 635a69eff..830243d49 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -690,9 +690,13 @@ Identifier finalStateId2 private static bool isLoopHead(Block b, CFGRepr beforeOptimizations, IDictionary> beforeOptBlockToLoops, IDictionary beforeToAfter) { + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(b)) + { + return false; + } foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(b)) { - if (beforeOptBlockToLoops[b].Count < beforeOptBlockToLoops[succ].Count && beforeToAfter.ContainsKey(b)) + if (beforeToAfter.ContainsKey(b) && beforeOptBlockToLoops[b].Count < beforeOptBlockToLoops[succ].Count) { return true; } diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index 1b461e9d3..7454f3d04 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -333,9 +333,13 @@ private static Block GetCoalescedAfterBlock(Block b, IDictionary b private static bool isLoopHead(Block b, CFGRepr beforeOptimizations, IDictionary> beforeOptBlockToLoops, IDictionary beforeToAfter) { + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(b)) + { + return false; + } foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(b)) { - if (beforeOptBlockToLoops[b].Count < beforeOptBlockToLoops[succ].Count && beforeToAfter.ContainsKey(b)) + if (beforeToAfter.ContainsKey(b) && beforeOptBlockToLoops[b].Count < beforeOptBlockToLoops[succ].Count) { return true; } diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs index 5ccfe24b5..e138beedf 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs @@ -35,38 +35,13 @@ public static Theory CfgToDagProof( IDictionary beforeToAfter, IProgramAccessor beforeDagProgAccess, IProgramAccessor afterDagProgAccess, - IVariableTranslationFactory varFactory, - out IDictionary> beforeDagBlockToLoops) + 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> blocksToLoops = new Dictionary>(); - - foreach (var afterBlock in afterDagCfg.GetBlocksBackwards()) - if (afterToBefore.TryGetValue(afterBlock, out var beforeBlock)) - { - var loops = new HashSet(); - 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); - } - - beforeDagBlockToLoops = blocksToLoops; - + IDictionary> blocksToLoops = ProofGenerationLayer.getBeforeDagBlockToLoops(beforeToAfter, afterDagCfg, hintManager); + var varContextName = "\\1"; var varContextAbbrev = new AbbreviationDecl( varContextName, diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 4426da815..17948555c 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -926,6 +926,7 @@ out var endToEndLemmaPrelim Console.WriteLine("Passive prog mapping: " + fixedVarTranslation.OutputMapping()); Console.WriteLine("Before passive prog mapping: " + fixedVarTranslation2.OutputMapping()); */ + //TODO: do computation if (_proofGenConfig.GeneratePassifProof) { @@ -951,7 +952,7 @@ out var endToEndLemmaPrelim #endregion } - IDictionary> beforeDagBlocktoLoops = null; + if (_proofGenConfig.GenerateCfgDagProof) { @@ -977,8 +978,7 @@ out var endToEndLemmaPrelim beforeDagAfterDagBlock, beforeCfgToDagProgAccess, beforePassiveProgAccess, - afterOptimizationsVarTranslationFactory, - out beforeDagBlocktoLoops); + afterOptimizationsVarTranslationFactory); theories.Add(cfgToDagProofTheory); #endregion @@ -992,13 +992,12 @@ out var endToEndLemmaPrelim // compute mapping between copied blocks (before opt -> after opt) var origToAfterOpt = beforeDagOrigBlock.InverseDict(); IDictionary beforeOptAfterOptBlock = DictionaryComposition(beforeOptimizationsOrigBlock, origToAfterOpt); - - + IDictionary> beforeDagBlocktoLoops = getBeforeDagBlockToLoops(beforeDagAfterDagBlock, beforePassificationCfg, cfgToDagHintManager); var cfgOptimizationsProofTheory = CfgOptimizationsManager.CfgOptProof( phasesTheories, beforeOptimizationsCFG, beforeDagCfg, - beforeOptAfterOptBlock, //not sure if this is correct + beforeOptAfterOptBlock, unoptimizedCfgProgAccess, beforeCfgToDagProgAccess, afterPassificationImpl.ListCoalescedBlocks, @@ -1140,5 +1139,48 @@ public static BoogieIsaProgInterface BoogieIsaProgInterface() { return new BoogieIsaProgInterface(new Dictionary(procNameToTopLevelPrograms), globalDataProgAccess); } + + public static IDictionary> getBeforeDagBlockToLoops(IDictionary beforeToAfter, CFGRepr afterDagCfg, CfgToDagHintManager hintManager) + { + var afterToBefore = beforeToAfter.InverseDict(); + IDictionary> blocksToLoops = new Dictionary>(); + foreach (var afterBlock in afterDagCfg.GetBlocksBackwards()) + { + if (afterToBefore.TryGetValue(afterBlock, out var beforeBlock)) + { + var loops = new HashSet(); + 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); + } + } + return blocksToLoops; + } } } \ No newline at end of file From ebbd0be7a8091bc6a8960046bd97a251118c318a Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Thu, 29 Jun 2023 07:24:59 +0200 Subject: [PATCH 053/123] Changed some tests and changed the mapping from blocks to coalesced blocks --- .../more_procedures.bpl | 62 ++++++++ .../testComplicatedAllCases.bpl | 11 +- Source/Core/Absy.cs | 4 +- Source/Core/DeadVarElim.cs | 36 +++-- .../CFGOptimizationsEndToEnd.cs | 15 +- .../CFGOptimizationsLemmaManager.cs | 84 +++++++---- .../CFGOptimizationsManager.cs | 132 ++++-------------- .../CfgToDag/CfgToDagManager.cs | 5 +- .../ProofGeneration/ProofGenerationLayer.cs | 40 ++++-- 9 files changed, 219 insertions(+), 170 deletions(-) create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/more_procedures.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/more_procedures.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/more_procedures.bpl new file mode 100644 index 000000000..66727cd3b --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/more_procedures.bpl @@ -0,0 +1,62 @@ +procedure p() { + var y: int; + + y := 1; + + y := y+1; + goto l1; + + l1: + y := y+2; + goto l2; + + l2: + y := y+3; + goto l3,l4; + + l3: + assert y >= 0; + + l4: + assert y >= 0; +} + +procedure procedure_test() { + var y: int; + var i: int; + + l1: + i := 0; + y := 0; + goto l2; + + + l2: + i := i+1; + + + l3: + while ( i <= 10 ){ + i := i + 1; + goto l4, l2; + + l4: + y := y + i; + } + + assert true; + + + l5: + i := i + 10; + goto l6; + + + l6: + i := i + 10; + assume false; + goto l7; + + l7: + i := i + 1; +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/testComplicatedAllCases.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/testComplicatedAllCases.bpl index 9dfc22b0c..11546c2b4 100644 --- a/ProofGenerationBenchmarks/cfg_optimizations_tests/testComplicatedAllCases.bpl +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/testComplicatedAllCases.bpl @@ -1,11 +1,11 @@ -procedure p() { +procedure procedure_test() { var y: int; var i: int; l1: i := 0; y := 0; - goto l3, l5; + goto l2; l2: @@ -14,13 +14,14 @@ procedure p() { l3: while ( i <= 10 ){ - goto l2,l4, l6, l3; - l4: i := i + 1; + goto l4, l2; + + l4: y := y + i; } - assert y >= 0; + assert true; l5: diff --git a/Source/Core/Absy.cs b/Source/Core/Absy.cs index df7c170d0..d17cc1d7d 100644 --- a/Source/Core/Absy.cs +++ b/Source/Core/Absy.cs @@ -4123,8 +4123,8 @@ public List /*!*/ public readonly ISet AssertionChecksums = new HashSet(ChecksumComparer.Default); #region ProofGen - public IDictionary> ListCoalescedBlocks; - public IDictionary CoalescedBlocksToTarget; + public IDictionary CoalescedBlocksToTarget; + public IDictionary> ListCoalescedBlocks; #endregion public sealed class ChecksumComparer : IEqualityComparer diff --git a/Source/Core/DeadVarElim.cs b/Source/Core/DeadVarElim.cs index 66ba21e53..13b6f6991 100644 --- a/Source/Core/DeadVarElim.cs +++ b/Source/Core/DeadVarElim.cs @@ -484,9 +484,9 @@ public static void CoalesceBlocks(Program program) public override Implementation VisitImplementation(Implementation impl) { - - IDictionary CoalescedBlocksToTarget = new Dictionary(); - IDictionary> ListCoalescedBlocks = new Dictionary>(); + + IDictionary CoalescedBlocksToTarget = new Dictionary(); + IDictionary> ListCoalescedBlocks = new Dictionary>(); //Contract.Requires(impl != null); Contract.Ensures(Contract.Result() != null); @@ -533,20 +533,21 @@ public override Implementation VisitImplementation(Implementation impl) if (!multiPredBlocks.Contains(succ)) { - if (!ListCoalescedBlocks.ContainsKey(b.UniqueId)) + if (!ListCoalescedBlocks.ContainsKey(b)) { - List newList = new List(); - newList.Add(b.UniqueId); - ListCoalescedBlocks.Add(b.UniqueId, newList); + List newList = new List(); + newList.Add(b); + ListCoalescedBlocks.Add(b, newList); } - ListCoalescedBlocks[b.UniqueId].Add(succ.UniqueId); - if (!CoalescedBlocksToTarget.ContainsKey(succ.UniqueId)) + ListCoalescedBlocks[b].Add(succ); + + if (!CoalescedBlocksToTarget.ContainsKey(succ)) { - CoalescedBlocksToTarget.Add(succ.UniqueId, b.UniqueId); + CoalescedBlocksToTarget.Add(succ, b); } - if (!CoalescedBlocksToTarget.ContainsKey(b.UniqueId)) + if (!CoalescedBlocksToTarget.ContainsKey(b)) { - CoalescedBlocksToTarget.Add(b.UniqueId, b.UniqueId); + CoalescedBlocksToTarget.Add(b, b); } foreach (Cmd /*!*/ cmd in succ.Cmds) { @@ -600,6 +601,17 @@ public override Implementation VisitImplementation(Implementation impl) gotoCmd.labelNames.Add(succ.Label); } } + + var ListCoalescedBlocks_old = new Dictionary>(ListCoalescedBlocks); + foreach (var curr in ListCoalescedBlocks_old.Keys) + { + for (int i = 1; i < ListCoalescedBlocks[curr].Count; i++) + { + List temp = new List(ListCoalescedBlocks[curr]); + List subList = new List(temp.GetRange(i, temp.Count - i)); + ListCoalescedBlocks.Add(ListCoalescedBlocks[curr][i], subList); + } + } impl.CoalescedBlocksToTarget = CoalescedBlocksToTarget; impl.ListCoalescedBlocks = ListCoalescedBlocks; diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs index d404f8ee2..f0ac4cb02 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs @@ -43,7 +43,8 @@ public IEnumerable EndToEndProof( IProgramAccessor afterOptProgAccess, IProgramAccessor programAccessor, CFGRepr afterOptCFG, - PhasesTheories phasesTheories) + PhasesTheories phasesTheories, + string procedureName) { this.programAccessor = programAccessor; boogieContext = new BoogieContextIsa( @@ -98,10 +99,10 @@ public IEnumerable EndToEndProof( new Proof(new List {proofSb.ToString()}) ); result.Add(helperLemma); - - var defProcWithoutDeadVar = new DefDecl("p_unoptimized_without_dead_vars", new Tuple, Term>(new List(), IsaCommonTerms.TermIdentFromName("proc ⦇ proc_body := (Some (" + afterOptProgAccess.BlockInfo().getTheoryName() + ".locals_vdecls," + beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body)) ⦈"))); + var defProcWithoutDeadVar = new DefDecl(procedureName + "_unoptimized_without_dead_vars", new Tuple, Term>(new List(), IsaCommonTerms.TermIdentFromName("proc \\ proc_body := (Some (" + afterOptProgAccess.BlockInfo().getTheoryName() + ".locals_vdecls," + beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body)) \\"))); result.Add(defProcWithoutDeadVar); + var endToEndLemma = new LemmaDecl( "end_to_end_theorem", @@ -111,7 +112,7 @@ public IEnumerable EndToEndProof( IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()), programAccessor.AxiomsDecl(), - programAccessor.ProcDecl()), + defProcWithoutDeadVar.Name), new Proof( new List { @@ -119,7 +120,7 @@ public IEnumerable EndToEndProof( ProofUtil.Apply("assumption"), "using VC apply simp", ProofUtil.Apply("assumption+"), - "apply (unfold p_unoptimized_without_dead_vars_def)", + "apply (unfold " + defProcWithoutDeadVar.Name + "_def)", "apply (simp add: " + afterOptProgAccess.BlockInfo().getTheoryName() + ".pres_def " + afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_def exprs_to_only_checked_spec_1)", "apply (simp add: " + afterOptProgAccess.BlockInfo().getTheoryName() + ".post_def " + afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_def exprs_to_only_checked_spec_2)", "apply simp", @@ -202,7 +203,7 @@ public static Term CfgOptLemmaConclusion(BoogieContextIsa boogieContext, Term po } public static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term globalDecls, Term axioms, - Term procedure) + string name) { var typeInterpId = new SimpleIdentifier("A"); return @@ -218,7 +219,7 @@ public static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term gl constantDecls, globalDecls, axioms, - IsaCommonTerms.TermIdentFromName("p_unoptimized_without_dead_vars"), + IsaCommonTerms.TermIdentFromName(name), IsaBoogieTerm.SematicsProcSpecSatisfied)); } } \ No newline at end of file diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index 830243d49..daca361a4 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -58,8 +58,16 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b "apply (unfold " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock) + "_def)", "apply simp", "apply (unfold " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) + "_def)", - "by simp" + "apply simp" }; + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() == 0) + { + proofMethods.Add("by (rule " + afterOptProgAccess.BlockInfo().OutEdgesMembershipLemma(afterBlock) + ")"); + } + else + { + proofMethods.Add("by simp"); + } var loopHeads = new List(); foreach (Block loop in Loops) @@ -117,7 +125,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b } var proofMethods = new List { - "apply (rule loopBlock_global_block[where ?f = \"the ∘ map_of [" + string.Join(",", function) + "]\"])", + "apply (rule loopBlock_global_block[where ?f = \"the \\ map_of [" + string.Join(",", function) + "]\"])", "apply (rule " + beforeOptProgAccess.BlockInfo().OutEdgesMembershipLemma(beforeBlock) + ")", "apply simp" }; @@ -177,7 +185,15 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b proofMethods.Add("apply (rule " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + ")"); proofMethods.Add("apply (unfold " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) + "_def " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock) + "_def)"); - proofMethods.Add("by simp"); + proofMethods.Add("apply simp"); + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() == 0) + { + proofMethods.Add("by (rule " + afterOptProgAccess.BlockInfo().OutEdgesMembershipLemma(afterBlock) + ")"); + } + else + { + proofMethods.Add("by simp"); + } var varContextName = "\\"; IList terms = new List(); terms.Add(IsaCommonTerms.TermIdentFromName("A")); @@ -226,7 +242,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b var proofMethods = new List { - "apply (rule loopBlock_global_block_hybrid[where ?f = \"the ∘ map_of [" + string.Join(",", function) + "]\"])", + "apply (rule loopBlock_global_block_hybrid[where ?f = \"the \\ map_of [" + string.Join(",", function) + "]\"])", "apply (rule " + beforeOptProgAccess.BlockInfo().OutEdgesMembershipLemma(beforeBlock) + ")", "apply simp" }; @@ -275,7 +291,15 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b proofMethods.Add("apply simp"); proofMethods.Add("apply (unfold " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + " " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock) + "_def)"); - proofMethods.Add("by simp"); + proofMethods.Add("apply simp"); + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() == 0) + { + proofMethods.Add("by (rule " + afterOptProgAccess.BlockInfo().OutEdgesMembershipLemma(afterBlock) + ")"); + } + else + { + proofMethods.Add("by simp"); + } var varContextName = "\\"; IList terms = new List(); @@ -304,9 +328,9 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma Block beforeBlock, Block afterBlock, Block succ, - Func GlobalblockLemmaName, Func HybridblockLemmaName, - IList Loops) + IList Loops, + IDictionary> ListCoalescedBlocks) { var proofMethods = new List { @@ -325,16 +349,11 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma } List listCoalescedBlocks = new List(); - Block curr = beforeBlock; - listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(curr)); - while ((beforeOptimizations.GetSuccessorBlocks(curr).Count() == 1 && - beforeOptimizations.GetSuccessorBlocks(curr).First().Predecessors.Count() == 1)) + foreach (Block current in ListCoalescedBlocks[beforeBlock]) { - curr = beforeOptimizations.GetSuccessorBlocks(curr).First(); - listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(curr)); - + listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(current)); } - + var varContextName = "\\"; IList terms = new List(); terms.Add(IsaCommonTerms.TermIdentFromName("A")); @@ -363,7 +382,8 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma Block afterBlock, Func GlobalblockLemmaName, Func HybridblockLemmaName, - IList Loops) + IList Loops, + IDictionary> ListCoalescedBlocks) { var proofMethods = new List { @@ -372,15 +392,11 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma }; List listCoalescedBlocks = new List(); - Block curr = beforeBlock; - listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(curr)); - while ((beforeOptimizations.GetSuccessorBlocks(curr).Count() == 1 && - beforeOptimizations.GetSuccessorBlocks(curr).First().Predecessors.Count() == 1)) + foreach (Block current in ListCoalescedBlocks[beforeBlock]) { - curr = beforeOptimizations.GetSuccessorBlocks(curr).First(); - listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(curr)); - + listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(current)); } + foreach (string b in listCoalescedBlocks) { @@ -430,8 +446,16 @@ public LemmaDecl HybridBlockLemmaPruning( //Pruning of unreachable blocks with b "apply simp", "apply simp", "apply (unfold " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) + "_def)", - "by simp" + "apply simp" }; + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() == 0) + { + proofMethods.Add("by (rule " + afterOptProgAccess.BlockInfo().OutEdgesMembershipLemma(afterBlock) + ")"); + } + else + { + proofMethods.Add("by simp"); + } var loopHeads = new List(); foreach (Block loop in Loops) { @@ -486,7 +510,7 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced } var proofMethods = new List { - "apply (rule loopHead_global_block[where ?f = \"the ∘ map_of [" + string.Join(",", function) + "]\"])", + "apply (rule loopHead_global_block[where ?f = \"the \\ map_of [" + string.Join(",", function) + "]\"])", "apply (rule " + beforeOptProgAccess.BlockInfo().OutEdgesMembershipLemma(beforeBlock) + ")", "apply simp" }; @@ -542,7 +566,15 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced proofMethods.Add("apply (rule " + afterOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(afterBlock) + ")"); proofMethods.Add("apply (rule " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + ")"); proofMethods.Add("apply (unfold "+ afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) + "_def " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock) + "_def)"); - proofMethods.Add("by simp"); + proofMethods.Add("apply simp"); + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() == 0) + { + proofMethods.Add("by (rule " + afterOptProgAccess.BlockInfo().OutEdgesMembershipLemma(afterBlock) + ")"); + } + else + { + proofMethods.Add("by simp"); + } var varContextName = "\\"; IList terms = new List(); terms.Add(IsaCommonTerms.TermIdentFromName("A")); diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index 7454f3d04..678766d7d 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -28,10 +28,11 @@ public static Theory CfgOptProof( IDictionary beforeToAfter, // mapping from current block to target block IProgramAccessor beforeOptCfgProgAccess, //before CFG optimizations IProgramAccessor afterOptCfgProgAccess, //after CFG optimizationsList<(Block, Block)> CoalescedBlocks - IDictionary> ListCoalescedBlocks, //TODO: Optimize CFGOptimizationsLemmaManager by using this dictionary - IDictionary CoalescedBlocksToTarget, + IDictionary> ListCoalescedBlocks, //TODO: Optimize CFGOptimizationsLemmaManager by using this dictionary + IDictionary CoalescedBlocksToTarget, IDictionary> beforeDagBlockToLoops, - Term vcAssm) + Term vcAssm, + string procedureName) { IDictionary afterToBefore = beforeToAfter.ToDictionary(x => x.Value, x => x.Key); IDictionary> beforeOptBlockToLoops = new Dictionary>(); @@ -48,9 +49,10 @@ public static Theory CfgOptProof( } beforeOptBlockToLoops.Add(beforeBlock, temp); } - else if (CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) { - coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + else if (CoalescedBlocksToTarget.ContainsKey(beforeBlock)) { + coalescedAfterBlock = CoalescedBlocksToTarget[beforeBlock]; List temp = new List(); + bool test = beforeDagBlockToLoops.ContainsKey(coalescedAfterBlock); foreach (Block loopHeader in beforeDagBlockToLoops[coalescedAfterBlock]) { temp.Add(afterToBefore[loopHeader]); @@ -102,10 +104,10 @@ public static Theory CfgOptProof( beforeOptimizationsCopy.DeleteBackedges(beforeOptBlockToLoops); List topoOrder = new List(); - IDictionary visited = new Dictionary(); + HashSet visited = new HashSet(); foreach (var current in beforeOptimizationsCopy.GetBlocksForwards()) { - if (!visited.ContainsKey(current)) + if (!visited.Contains(current)) { TopologicalOrder(current, topoOrder, visited, beforeOptimizationsCopy); } @@ -114,7 +116,7 @@ public static Theory CfgOptProof( foreach (var current in topoOrder) { Block beforeBlock = FindBlock(beforeOptimizations, current.UniqueId); - if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops, beforeToAfter) && CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //In this case we have a coalesced loop head + if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops, beforeToAfter) && CoalescedBlocksToTarget.ContainsKey(beforeBlock)) //In this case we have a coalesced loop head { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); var globalBlock = lemmaManager.LoopHeadCoalesced(beforeBlock, coalescedAfterBlock, @@ -128,7 +130,7 @@ public static Theory CfgOptProof( var globalBlock = lemmaManager.LoopHeadNotCoalesced(beforeBlock, beforeToAfter[beforeBlock], bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(globalBlock); } - else if (CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //in this case we have block coalescing + else if (CoalescedBlocksToTarget.ContainsKey(beforeBlock)) //in this case we have block coalescing { if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //Pruning of Unreachable Blocks Coalesced { @@ -142,12 +144,13 @@ public static Theory CfgOptProof( Block afterBlock = beforeToAfter[beforeBlock]; var head = lemmaManager.HybridBlockLemma(beforeBlock, afterBlock, beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault(), - bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock], + ListCoalescedBlocks); outerDecls.Add(head); var convertGlobalBlock = lemmaManager.ConvertHybridToGlobal(beforeBlock, afterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock], + ListCoalescedBlocks); outerDecls.Add(convertGlobalBlock); } else if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() != 1 || beforeOptimizations.GetSuccessorBlocks(beforeBlock).First().Predecessors.Count() != 1) //tail of coalesced blocks @@ -165,90 +168,8 @@ public static Theory CfgOptProof( coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); var inBetweenBlock = lemmaManager.HybridBlockLemma(beforeBlock, coalescedAfterBlock, beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault(), - bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); - outerDecls.Add(inBetweenBlock); - } - } - else //no block coalescing - { - if (beforeToAfter.Keys.Contains(beforeBlock)) - { - Block afterBlock = beforeToAfter[beforeBlock]; - if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //If there is an assume or assert false statement in the block - { - var pruning = lemmaManager.GlobalBlockLemmaPruningNotCoalesced(beforeBlock, afterBlock, GetGlobalBlockLemmaName(beforeBlock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); - outerDecls.Add(pruning); - } - else //otherwhise we just need to apply the normal global block lemma. Assumption: Global Block Lemma holds for all successors - { - var globalBlock = lemmaManager.GlobalBlockLemma(beforeBlock, afterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); - outerDecls.Add(globalBlock); - } - } - } - } - - - /* - for (int i = 0; i < beforeOptimizations.NumOfBlocks(); i++) - { - Block current = GetBlockWithoutSuccessor(beforeOptimizationsCopy); - Block beforeBlock = FindBlock(beforeOptimizations, current.UniqueId); - - if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops, beforeToAfter) && CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //In this case we have a coalesced loop head - { - coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); - var globalBlock = lemmaManager.LoopHeadCoalesced(beforeBlock, coalescedAfterBlock, - bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), - beforeOptBlockToLoops[beforeBlock]); - outerDecls.Add(globalBlock); - } - else if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops,beforeToAfter)) //normal Loop Head - { - var globalBlock = lemmaManager.LoopHeadNotCoalesced(beforeBlock, beforeToAfter[beforeBlock], bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); - outerDecls.Add(globalBlock); - } - else if (CoalescedBlocksToTarget.ContainsKey(beforeBlock.UniqueId)) //in this case we have block coalescing - { - if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //Pruning of Unreachable Blocks Coalesced - { - coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); - var pruningCoalesced = lemmaManager.HybridBlockLemmaPruning(beforeBlock, coalescedAfterBlock, - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); - outerDecls.Add(pruningCoalesced); - } - else if (beforeToAfter.ContainsKey(beforeBlock)) //Head of coalesced blocks - { - Block afterBlock = beforeToAfter[beforeBlock]; - var head = lemmaManager.HybridBlockLemma(beforeBlock, afterBlock, - beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault(), - bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); - outerDecls.Add(head); - var convertGlobalBlock = lemmaManager.ConvertHybridToGlobal(beforeBlock, afterBlock, - bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); - outerDecls.Add(convertGlobalBlock); - } - else if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() != 1 || beforeOptimizations.GetSuccessorBlocks(beforeBlock).First().Predecessors.Count() != 1) //tail of coalesced blocks - { - coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); - - var tail = lemmaManager.HybridBlockLemmaTail(beforeBlock, coalescedAfterBlock, - bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), - beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); - outerDecls.Add(tail); - } - else //in Between Block - { - coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); - var inBetweenBlock = lemmaManager.HybridBlockLemma(beforeBlock, coalescedAfterBlock, - beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault(), - bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), - bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); + bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock], + ListCoalescedBlocks); outerDecls.Add(inBetweenBlock); } } @@ -269,9 +190,7 @@ public static Theory CfgOptProof( } } } - beforeOptimizationsCopy.DeleteBlock(current); } - */ var entryLemma = lemmaManager.EntryLemma("entry_lemma", GetGlobalBlockLemmaName(beforeOptimizations.entry, lemmaNamer), beforeOptimizations.entry, @@ -287,7 +206,8 @@ public static Theory CfgOptProof( afterOptCfgProgAccess, beforeOptCfgProgAccess, afterOptimizations, - phasesTheories + phasesTheories, + procedureName ); outerDecls.AddRange(endToEndDecls); @@ -319,11 +239,11 @@ private static string GetHybridBlockLemmaName(Block b, IsaUniqueNamer namer) return "hybrid_block_lemma_" + namer.GetName(b, "block_" + b.Label); } - private static Block GetCoalescedAfterBlock(Block b, IDictionary beforeToAfter, IDictionary CoalescedBlocksToTarget) + private static Block GetCoalescedAfterBlock(Block b, IDictionary beforeToAfter, IDictionary CoalescedBlocksToTarget) { foreach (Block beforeBlockNew in beforeToAfter.Keys) //Get the Coalesced After Block { - if (beforeToAfter[beforeBlockNew].UniqueId == CoalescedBlocksToTarget[b.UniqueId]) + if (beforeToAfter[beforeBlockNew] == CoalescedBlocksToTarget[b]) { return beforeToAfter[beforeBlockNew]; } @@ -349,7 +269,7 @@ private static bool isLoopHead(Block b, CFGRepr beforeOptimizations, IDictionary - private static Block FindBlock(CFGRepr cfg, int id) + public static Block FindBlock(CFGRepr cfg, int id) //TODO: remove { foreach (Block curr in cfg.GetBlocksForwards()) { @@ -361,16 +281,16 @@ private static Block FindBlock(CFGRepr cfg, int id) return null; } - private static void TopologicalOrder(Block current, List topoOrder, IDictionary visited, CFGRepr beforeOptimizationsCopy) + private static void TopologicalOrder(Block current, List topoOrder, HashSet visited, CFGRepr beforeOptimizationsCopy) { - if (!visited.ContainsKey(current)) + if (!visited.Contains(current)) { - visited.Add(current, true); + visited.Add(current); } foreach (var succ in beforeOptimizationsCopy.GetSuccessorBlocks(current)) { - if (!visited.ContainsKey(succ)) + if (!visited.Contains(current)) { TopologicalOrder(succ,topoOrder, visited, beforeOptimizationsCopy); } diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs index e138beedf..adbf4bd03 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs @@ -35,12 +35,13 @@ public static Theory CfgToDagProof( IDictionary beforeToAfter, IProgramAccessor beforeDagProgAccess, IProgramAccessor afterDagProgAccess, - IVariableTranslationFactory varFactory) + IVariableTranslationFactory varFactory, + IDictionary> blocksToLoops) { 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> blocksToLoops = ProofGenerationLayer.getBeforeDagBlockToLoops(beforeToAfter, afterDagCfg, hintManager); + var varContextName = "\\1"; var varContextAbbrev = new AbbreviationDecl( diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 17948555c..fdbf38bed 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; @@ -926,7 +927,6 @@ out var endToEndLemmaPrelim Console.WriteLine("Passive prog mapping: " + fixedVarTranslation.OutputMapping()); Console.WriteLine("Before passive prog mapping: " + fixedVarTranslation2.OutputMapping()); */ - //TODO: do computation if (_proofGenConfig.GeneratePassifProof) { @@ -948,11 +948,11 @@ out var endToEndLemmaPrelim varTranslationFactory ); theories.Add(passificationProofTheory); - + #endregion } - + IDictionary> beforeDagBlocktoLoops = null; if (_proofGenConfig.GenerateCfgDagProof) { @@ -962,8 +962,7 @@ out var endToEndLemmaPrelim uniqueExitBlockOrig != null ? beforePassiveOrigBlock.First(kv => kv.Value == uniqueExitBlockOrig).Key : null; - - + beforeDagBlocktoLoops = getBeforeDagBlockToLoops(beforeDagAfterDagBlock, beforePassificationCfg, cfgToDagHintManager); var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( phasesTheories, _proofGenConfig.GenerateCfgDagE2E, @@ -978,7 +977,8 @@ out var endToEndLemmaPrelim beforeDagAfterDagBlock, beforeCfgToDagProgAccess, beforePassiveProgAccess, - afterOptimizationsVarTranslationFactory); + afterOptimizationsVarTranslationFactory, + beforeDagBlocktoLoops); theories.Add(cfgToDagProofTheory); #endregion @@ -992,7 +992,26 @@ out var endToEndLemmaPrelim // compute mapping between copied blocks (before opt -> after opt) var origToAfterOpt = beforeDagOrigBlock.InverseDict(); IDictionary beforeOptAfterOptBlock = DictionaryComposition(beforeOptimizationsOrigBlock, origToAfterOpt); - IDictionary> beforeDagBlocktoLoops = getBeforeDagBlockToLoops(beforeDagAfterDagBlock, beforePassificationCfg, cfgToDagHintManager); + if (beforeDagBlocktoLoops == null) + { + beforeDagBlocktoLoops = getBeforeDagBlockToLoops(beforeDagAfterDagBlock, beforePassificationCfg, cfgToDagHintManager); + } + + IDictionary CoalescedBlocksToTarget = DictionaryComposition(afterPassificationImpl.CoalescedBlocksToTarget, origToAfterOpt); + CoalescedBlocksToTarget = DictionaryComposition(beforeOptimizationsOrigBlock, CoalescedBlocksToTarget); + + IDictionary> ListCoalescedBlocks = new Dictionary>(); + foreach (var curr in afterPassificationImpl.ListCoalescedBlocks.Keys) + { + List temp = new List(); + foreach (var next in afterPassificationImpl.ListCoalescedBlocks[curr]) + { + temp.Add(beforeOptimizationsOrigBlock.InverseDict()[next]); + } + ListCoalescedBlocks.Add(beforeOptimizationsOrigBlock.InverseDict()[curr], temp); + } + + var cfgOptimizationsProofTheory = CfgOptimizationsManager.CfgOptProof( phasesTheories, beforeOptimizationsCFG, @@ -1000,10 +1019,11 @@ out var endToEndLemmaPrelim beforeOptAfterOptBlock, unoptimizedCfgProgAccess, beforeCfgToDagProgAccess, - afterPassificationImpl.ListCoalescedBlocks, - afterPassificationImpl.CoalescedBlocksToTarget, + ListCoalescedBlocks, + CoalescedBlocksToTarget, beforeDagBlocktoLoops, - vcAssm); + vcAssm, + afterPassificationImpl.Name); theories.Add(cfgOptimizationsProofTheory); #endregion From 56cd3d8f98650da22bd0d0d75af6d1d19937a52b Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Thu, 29 Jun 2023 16:55:08 +0200 Subject: [PATCH 054/123] Changed Topological sort to an iterative approach --- .../CFGOptimizationsManager.cs | 53 +++++++++---------- Source/ProofGeneration/CFGRepr/CFGRepr.cs | 1 + 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index 678766d7d..9ed32615b 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -104,18 +104,12 @@ public static Theory CfgOptProof( beforeOptimizationsCopy.DeleteBackedges(beforeOptBlockToLoops); List topoOrder = new List(); - HashSet visited = new HashSet(); - foreach (var current in beforeOptimizationsCopy.GetBlocksForwards()) - { - if (!visited.Contains(current)) - { - TopologicalOrder(current, topoOrder, visited, beforeOptimizationsCopy); - } - } + TopologicalOrder(topoOrder, beforeOptimizationsCopy); + topoOrder.Reverse(); foreach (var current in topoOrder) { - Block beforeBlock = FindBlock(beforeOptimizations, current.UniqueId); + Block beforeBlock = current; if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops, beforeToAfter) && CoalescedBlocksToTarget.ContainsKey(beforeBlock)) //In this case we have a coalesced loop head { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); @@ -153,7 +147,7 @@ public static Theory CfgOptProof( ListCoalescedBlocks); outerDecls.Add(convertGlobalBlock); } - else if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() != 1 || beforeOptimizations.GetSuccessorBlocks(beforeBlock).First().Predecessors.Count() != 1) //tail of coalesced blocks + else if (ListCoalescedBlocks[beforeBlock].Count == 1) //tail of coalesced blocks { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); @@ -269,34 +263,39 @@ private static bool isLoopHead(Block b, CFGRepr beforeOptimizations, IDictionary - public static Block FindBlock(CFGRepr cfg, int id) //TODO: remove + + private static void TopologicalOrder(List topoOrder, CFGRepr beforeOptimizationsCopy) { - foreach (Block curr in cfg.GetBlocksForwards()) + Dictionary inDegree = new Dictionary(); + foreach (var b in beforeOptimizationsCopy.GetBlocksForwards()) { - if (curr.UniqueId == id) - { - return curr; - } + inDegree.Add(b, b.Predecessors.Count()); } - return null; - } - - private static void TopologicalOrder(Block current, List topoOrder, HashSet visited, CFGRepr beforeOptimizationsCopy) - { - if (!visited.Contains(current)) + + Queue q = new Queue(); + foreach (var b in beforeOptimizationsCopy.GetBlocksForwards()) { - visited.Add(current); + if (inDegree[b] == 0) + { + q.Enqueue(b); + } } - foreach (var succ in beforeOptimizationsCopy.GetSuccessorBlocks(current)) + while (q.Count > 0) { - if (!visited.Contains(current)) + Block u = q.Dequeue(); + topoOrder.Add(u); + foreach (var b in beforeOptimizationsCopy.GetSuccessorBlocks(u)) { - TopologicalOrder(succ,topoOrder, visited, beforeOptimizationsCopy); + if (--inDegree[b] == 0) + { + q.Enqueue(b); + } } + } - topoOrder.Add(current); + } diff --git a/Source/ProofGeneration/CFGRepr/CFGRepr.cs b/Source/ProofGeneration/CFGRepr/CFGRepr.cs index da582c730..2019c4a2b 100644 --- a/Source/ProofGeneration/CFGRepr/CFGRepr.cs +++ b/Source/ProofGeneration/CFGRepr/CFGRepr.cs @@ -125,6 +125,7 @@ public void DeleteBackedges(IDictionary> BlockToLoops) } foreach (Block toRemove in Backedges) { + toRemove.Predecessors.Remove(b); outgoingBlocks[b].Remove(toRemove); } } From 1cce2ef3b506bd8ebc79d19e5f1a5329eee94ba9 Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Mon, 3 Jul 2023 07:12:15 +0200 Subject: [PATCH 055/123] Changed tests and proof generation for new hybrid block lemmas --- ..._coalescing.bpl => block_coalescing_1.bpl} | 0 ...lescing_new.bpl => block_coalescing_2.bpl} | 0 .../{DeadVarElim.bpl => dead_var_elim.bpl} | 0 .../{loop_new.bpl => loop_coalesced.bpl} | 0 ...l => loop_pruning_coalescing_combined.bpl} | 0 .../{loop.bpl => loop_without_coalescing.bpl} | 0 .../{NestedLoop.bpl => nested_loop.bpl} | 0 .../cfg_optimizations_tests/pruning.bpl | 30 +++++++++++++++++++ ...more_procedures.bpl => two_procedures.bpl} | 0 .../CFGOptimizationsLemmaManager.cs | 12 +++----- Source/ProofGeneration/CFGRepr/CFGRepr.cs | 21 +++++++------ 11 files changed, 46 insertions(+), 17 deletions(-) rename ProofGenerationBenchmarks/cfg_optimizations_tests/{block_coalescing.bpl => block_coalescing_1.bpl} (100%) rename ProofGenerationBenchmarks/cfg_optimizations_tests/{block_coalescing_new.bpl => block_coalescing_2.bpl} (100%) rename ProofGenerationBenchmarks/cfg_optimizations_tests/{DeadVarElim.bpl => dead_var_elim.bpl} (100%) rename ProofGenerationBenchmarks/cfg_optimizations_tests/{loop_new.bpl => loop_coalesced.bpl} (100%) rename ProofGenerationBenchmarks/cfg_optimizations_tests/{testComplicatedAllCases.bpl => loop_pruning_coalescing_combined.bpl} (100%) rename ProofGenerationBenchmarks/cfg_optimizations_tests/{loop.bpl => loop_without_coalescing.bpl} (100%) rename ProofGenerationBenchmarks/cfg_optimizations_tests/{NestedLoop.bpl => nested_loop.bpl} (100%) create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/pruning.bpl rename ProofGenerationBenchmarks/cfg_optimizations_tests/{more_procedures.bpl => two_procedures.bpl} (100%) diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_1.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_1.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_new.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_2.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_new.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_2.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/DeadVarElim.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/dead_var_elim.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/DeadVarElim.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/dead_var_elim.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_new.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_coalesced.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/loop_new.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/loop_coalesced.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/testComplicatedAllCases.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_pruning_coalescing_combined.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/testComplicatedAllCases.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/loop_pruning_coalescing_combined.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalescing.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/loop.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalescing.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/NestedLoop.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/nested_loop.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/NestedLoop.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/nested_loop.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning.bpl new file mode 100644 index 000000000..c03f86b67 --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning.bpl @@ -0,0 +1,30 @@ +procedure p() { + var y: int; + var i: int; + + l1: + i := 0; + y := 0; + goto l2,l5; + + + l2: + i := i+1; + goto l3; + + l3: + assume false; + goto l4; + + l4: + i := i + 1; + goto l6; + + l5: + assume false; + goto l6; + + + l6: + assert true; +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/more_procedures.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/two_procedures.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/more_procedures.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/two_procedures.bpl diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index daca361a4..1f78d2e34 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -448,14 +448,10 @@ public LemmaDecl HybridBlockLemmaPruning( //Pruning of unreachable blocks with b "apply (unfold " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) + "_def)", "apply simp" }; - if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() == 0) - { - proofMethods.Add("by (rule " + afterOptProgAccess.BlockInfo().OutEdgesMembershipLemma(afterBlock) + ")"); - } - else - { - proofMethods.Add("by simp"); - } + proofMethods.Add("apply (unfold " + afterOptProgAccess.BlockInfo().OutEdgesMembershipLemma(afterBlock) + ")"); + proofMethods.Add("apply (unfold " + beforeOptProgAccess.BlockInfo().OutEdgesMembershipLemma(beforeBlock) + ")"); + proofMethods.Add("by simp"); + var loopHeads = new List(); foreach (Block loop in Loops) { diff --git a/Source/ProofGeneration/CFGRepr/CFGRepr.cs b/Source/ProofGeneration/CFGRepr/CFGRepr.cs index 2019c4a2b..a7cc1c128 100644 --- a/Source/ProofGeneration/CFGRepr/CFGRepr.cs +++ b/Source/ProofGeneration/CFGRepr/CFGRepr.cs @@ -116,17 +116,20 @@ public void DeleteBackedges(IDictionary> BlockToLoops) foreach (Block b in blocks) { List Backedges = new List(); - foreach (Block succ in GetSuccessorBlocks(b)) + if (BlockToLoops.ContainsKey(b)) { - if (BlockToLoops[b].Contains(succ)) + foreach (Block succ in GetSuccessorBlocks(b)) { - Backedges.Add(succ); - } - } - foreach (Block toRemove in Backedges) - { - toRemove.Predecessors.Remove(b); - outgoingBlocks[b].Remove(toRemove); + if (BlockToLoops[b].Contains(succ)) + { + Backedges.Add(succ); + } + } + foreach (Block toRemove in Backedges) + { + toRemove.Predecessors.Remove(b); + outgoingBlocks[b].Remove(toRemove); + } } } } From 530444f1e33ab9bd3e3c3edf22d496f074345dda Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Mon, 3 Jul 2023 07:42:37 +0200 Subject: [PATCH 056/123] Changed test such that it contains optimizations --- .../cfg_optimizations_tests/loop_without_coalescing.bpl | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalescing.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalescing.bpl index 254ea922f..7cf99ea85 100644 --- a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalescing.bpl +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalescing.bpl @@ -2,12 +2,17 @@ procedure p() { var y: int; var i: int; i := 0; + goto l1; + + l1: y := 0; + goto l2; + + l2: while ( i <= 10 ){ y := y + i; i := i + 1; } - assert y >= 0; } \ No newline at end of file From 3069bbf17a039879fbba598b4bab5fb8adef75e9 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 3 Jul 2023 17:33:58 +0200 Subject: [PATCH 057/123] add TODOs --- Source/Core/AbsyCmd.cs | 1 + Source/ProofGeneration/ProofGenerationLayer.cs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Source/Core/AbsyCmd.cs b/Source/Core/AbsyCmd.cs index 170b3b6c6..37c1a54c1 100644 --- a/Source/Core/AbsyCmd.cs +++ b/Source/Core/AbsyCmd.cs @@ -436,6 +436,7 @@ public List /*!*/ Blocks { get { + /** Gaurav: TODO move this part to unique caller, too brittle here */ #region proofgen AstToCfgProofGenInfo proofGenInfo = new AstToCfgProofGenInfo(); proofGenInfo.SetStmtList(stmtList); diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index f8ec7922b..45f4182ca 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -633,6 +633,8 @@ from calls. new DeBruijnFixedTVarTranslation(beforeOptimizationsData), boogieGlobalData); + /* Gaurav TODO: move later (see adjust_interface branch) in case not all data is initalized since options specify + * that proofs should not generated */ var afterOptimizationsVarTranslationFactory = new DeBruijnVarFactory( new DeBruijnFixedVarTranslation(afterOptimizationsData), From 9fb01ebf01677614e99f940517e73699d8e1bd5f Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 3 Jul 2023 19:53:47 +0200 Subject: [PATCH 058/123] get rid of RemoveApostrophe usage for axioms We should revisit the RemoveApostrophe with a different solution where terms are constructed via the AST instead of via strings. --- .../BoogieIsaInterface/IsaProgramGenerator.cs | 14 ++++---------- .../IsaProgramGeneratorForAst.cs | 9 +++++---- .../BoogieIsaInterface/MembershipLemmaManager.cs | 4 ++-- Source/ProofGeneration/Util/IsaUniqueNamer.cs | 5 ----- 4 files changed, 11 insertions(+), 21 deletions(-) diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs index 563770ecc..0b307faeb 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs @@ -180,8 +180,8 @@ public IProgramAccessor GetIsaProgram( if (config.generateAxioms) { - decls.Add(GetAxioms(methodData.Axioms, uniqueNamer)); - if(generateMembershipLemmas) membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms, uniqueNamer); + decls.Add(GetAxioms(methodData.Axioms)); + if(generateMembershipLemmas) membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms); } if (config.generateFunctions) @@ -212,23 +212,17 @@ public IProgramAccessor GetIsaProgram( return membershipLemmaManager; } - private DefDecl GetAxioms(IEnumerable axioms, IsaUniqueNamer uniqueNamer) + private DefDecl GetAxioms(IEnumerable axioms) { var axiomsExpr = new List(); foreach (var ax in axioms) { - string test1 = ax.Expr.ToString(); var axTerms = cmdIsaVisitor.Translate(ax.Expr); if (axTerms.Count != 1) throw new ProofGenUnexpectedStateException(GetType(), "axiom not translated into single term"); - if (axTerms.First().ToString().Contains("fun")) - { - string test = axTerms.First().ToString(); - } - - axiomsExpr.Add( IsaCommonTerms.TermIdentFromName(uniqueNamer.RemoveApostrophe(axTerms.First().ToString()) ) ); + axiomsExpr.Add(axTerms.First()); } var equation = new Tuple, Term>(new List(), new TermList(axiomsExpr)); diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs index 07ae00339..95b53d8cb 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs @@ -142,8 +142,8 @@ public IProgramAccessor GetIsaProgram( if (config.generateAxioms) { - decls.Add(GetAxioms(methodData.Axioms, uniqueNamer)); - if(generateMembershipLemmas) membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms, uniqueNamer); + decls.Add(GetAxioms(methodData.Axioms)); + if(generateMembershipLemmas) membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms); } if (config.generateFunctions) @@ -174,7 +174,7 @@ public IProgramAccessor GetIsaProgram( return membershipLemmaManager; } - private DefDecl GetAxioms(IEnumerable axioms, IsaUniqueNamer uniqueNamer) + private DefDecl GetAxioms(IEnumerable axioms) { var axiomsExpr = new List(); foreach (var ax in axioms) @@ -182,7 +182,8 @@ private DefDecl GetAxioms(IEnumerable axioms, IsaUniqueNamer uniqueNamer) var axTerms = cmdIsaVisitor.Translate(ax.Expr); if (axTerms.Count != 1) throw new ProofGenUnexpectedStateException(GetType(), "axiom not translated into single term"); - axiomsExpr.Add(IsaCommonTerms.TermIdentFromName(uniqueNamer.RemoveApostrophe(axTerms.First().ToString()))); + + axiomsExpr.Add(axTerms.First()); } var equation = new Tuple, Term>(new List(), new TermList(axiomsExpr)); diff --git a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs index 6cfdf8e92..277a68920 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs @@ -503,14 +503,14 @@ private void AddLookupVarDeclTyLemmas( } } - public void AddAxiomMembershipLemmas(IEnumerable axioms, IsaUniqueNamer uniqueNamer) + public void AddAxiomMembershipLemmas(IEnumerable axioms) { var axiomSet = IsaCommonTerms.SetOfList(IsaCommonTerms.TermIdentFromName(isaProgramRepr.GlobalProgramRepr.axiomsDeclDef)); var id = 0; foreach (var axiom in axioms) { var axiomTerm = basicCmdIsaVisitor.Translate(axiom.Expr); - var elemAssm = IsaCommonTerms.Elem(IsaCommonTerms.TermIdentFromName(uniqueNamer.RemoveApostrophe(axiomTerm.ToString())), axiomSet); + var elemAssm = IsaCommonTerms.Elem(axiomTerm, axiomSet); var proof = new Proof(new List {"by (simp add: " + isaProgramRepr.GlobalProgramRepr.axiomsDeclDef+ "_def)"}); membershipLemmas.Add(axiom, new LemmaDecl(MembershipName(axiom, id), elemAssm, proof)); diff --git a/Source/ProofGeneration/Util/IsaUniqueNamer.cs b/Source/ProofGeneration/Util/IsaUniqueNamer.cs index c214fa9ac..8fb1b50e8 100644 --- a/Source/ProofGeneration/Util/IsaUniqueNamer.cs +++ b/Source/ProofGeneration/Util/IsaUniqueNamer.cs @@ -44,11 +44,6 @@ public string GetName(string preferredName) return GetName(preferredName, preferredName); } - public string RemoveApostrophe(string preferredName) - { - return RemoveApostrophe(preferredName, preferredName); - } - public string RemoveApostropheInFunc(string preferredName) { return RemoveApostropheInFunc(preferredName, preferredName); From b0743e934f00cd28e798f7060011a49dc6ef6898 Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Wed, 5 Jul 2023 13:22:25 +0200 Subject: [PATCH 059/123] Added new tests for cgf optimizations --- .../block_coalescing_2.bpl | 8 +- .../block_coalescing_3.bpl | 36 +++ ...=> loop_pruning_coalescing_combined_1.bpl} | 0 .../loop_with_coalesced_body_1.bpl | 40 ++++ .../loop_with_coalesced_body_2.bpl | 39 +++ ....bpl => loop_without_coalesced_body_1.bpl} | 4 + .../loop_without_coalesced_body_2.bpl | 28 +++ ... loop_without_coalesced_body_3 - Copy.bpl} | 0 .../no_optimization.bpl | 8 + .../{pruning.bpl => pruning_1.bpl} | 0 .../{loop_coalesced.bpl => pruning_2.bpl} | 16 +- .../cfg_optimizations_tests/pruning_3.bpl | 36 +++ .../cfg_optimizations_tests/pruning_4.bpl | 40 ++++ ...wo_procedures.bpl => two_procedures_1.bpl} | 0 .../two_procedures_2.bpl | 80 +++++++ .../CFGOptimizationsLemmaManager.cs | 222 +++++++----------- .../CFGOptimizationsManager.cs | 35 +-- Source/ProofGeneration/CFGRepr/CFGRepr.cs | 28 ++- 18 files changed, 444 insertions(+), 176 deletions(-) create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_3.bpl rename ProofGenerationBenchmarks/cfg_optimizations_tests/{loop_pruning_coalescing_combined.bpl => loop_pruning_coalescing_combined_1.bpl} (100%) create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/loop_with_coalesced_body_1.bpl create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/loop_with_coalesced_body_2.bpl rename ProofGenerationBenchmarks/cfg_optimizations_tests/{loop_without_coalescing.bpl => loop_without_coalesced_body_1.bpl} (84%) create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_2.bpl rename ProofGenerationBenchmarks/cfg_optimizations_tests/{nested_loop.bpl => loop_without_coalesced_body_3 - Copy.bpl} (100%) create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/no_optimization.bpl rename ProofGenerationBenchmarks/cfg_optimizations_tests/{pruning.bpl => pruning_1.bpl} (100%) rename ProofGenerationBenchmarks/cfg_optimizations_tests/{loop_coalesced.bpl => pruning_2.bpl} (51%) create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_3.bpl create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_4.bpl rename ProofGenerationBenchmarks/cfg_optimizations_tests/{two_procedures.bpl => two_procedures_1.bpl} (100%) create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/two_procedures_2.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_2.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_2.bpl index f7d7d6ea2..36f472ffb 100644 --- a/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_2.bpl +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_2.bpl @@ -1,4 +1,4 @@ -procedure p() { +procedure proecdure_1() { var y: int; y := 1; @@ -16,6 +16,7 @@ procedure p() { l3: assert y >= 0; + goto l4, l5; l4: assert y >= 0; @@ -31,4 +32,9 @@ procedure p() { l7: y := y + 7; + assume false; + goto l8; + + l8: + y := y + 8; } \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_3.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_3.bpl new file mode 100644 index 000000000..cc1f69101 --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_3.bpl @@ -0,0 +1,36 @@ +procedure proecdure_1() { + var y: int; + var i: int; + + i := 0; + y := 0; + + goto l1, l2; + + l1: + i := i + 5; + goto l3; + + l3: + i := i + 1; + y := y + i; + goto l4; + + l4: + y := y + 1; + goto l2; + + + l2: + if (i>y){ + y := i; + goto l5; + + l5: + y := i + 1; + } + assume false; + i := i + 1; + y := i + 1; + +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_pruning_coalescing_combined.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_pruning_coalescing_combined_1.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/loop_pruning_coalescing_combined.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/loop_pruning_coalescing_combined_1.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_with_coalesced_body_1.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_with_coalesced_body_1.bpl new file mode 100644 index 000000000..667d5e4c8 --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_with_coalesced_body_1.bpl @@ -0,0 +1,40 @@ +procedure p() { + var y: int; + var i: int; + i := 0; + y := 0; + l10: + + while ( i <= 10 ){ + y := y + i; + goto l1; + + l1: + i := i + 1; + } + + i := i + 1; + if (y <= 1000){ + goto l10; + } + else{ + goto l2; + } + + l2: + i := i + 1; + goto l3; + + l3: + i := i + 1; + goto l4; + + l4: + i := i + 1; + goto l5; + + l5: + i := i + 1; + + +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_with_coalesced_body_2.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_with_coalesced_body_2.bpl new file mode 100644 index 000000000..726795b2e --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_with_coalesced_body_2.bpl @@ -0,0 +1,39 @@ +procedure p() { + var y: int; + var i: int; + i := 0; + y := 0; + l10: + while (y<=1000){ + i := 0; + while ( i <= 10 ){ + y := y + i; + goto l1; + + l1: + i := i + 1; + } + } + + + i := i + 1; + if (y <= 1000){ + goto l10; + } + else{ + goto l2, l3; + } + + + l2: + while (i <= 1000){ + i := i + 1; + assume false; + i := i + 1; + } + + l3: + y := 1000; + + +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalescing.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_1.bpl similarity index 84% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalescing.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_1.bpl index 7cf99ea85..03f6313a3 100644 --- a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalescing.bpl +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_1.bpl @@ -15,4 +15,8 @@ procedure p() { i := i + 1; } + + i := i + 1; + assume true; + } \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_2.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_2.bpl new file mode 100644 index 000000000..041012eed --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_2.bpl @@ -0,0 +1,28 @@ +procedure p() { + var y: int; + var i: int; + i := 0; + goto l1; + + l1: + y := 0; + goto l2; + + + l2: + while (y <= 1000){ + i := 0; + while ( i <= 10 ){ + y := y + i; + i := i + 1; + goto l1, l3; + } + goto l3; + } + + + l3: + i := i + 1; + assume true; + +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/nested_loop.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_3 - Copy.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/nested_loop.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_3 - Copy.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/no_optimization.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/no_optimization.bpl new file mode 100644 index 000000000..0ea446578 --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/no_optimization.bpl @@ -0,0 +1,8 @@ +procedure proecdure_1() { + var i: int; + i := 0; + + while(i <= 10){ + i := i + 1; + } +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_1.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/pruning.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_1.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_coalesced.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_2.bpl similarity index 51% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/loop_coalesced.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_2.bpl index 2f2501ed2..0157aa05b 100644 --- a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_coalesced.bpl +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_2.bpl @@ -1,15 +1,23 @@ procedure p() { var y: int; var i: int; + + l1: i := 0; y := 0; + + + l2: + i := i+1; + + l3: while ( i <= 10 ){ + goto l2,l4; + l4: + assume false; y := y + i; - goto l1; - - l1: - i := i + 1; } + assert y >= 0; } \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_3.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_3.bpl new file mode 100644 index 000000000..27fed560a --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_3.bpl @@ -0,0 +1,36 @@ +procedure proecdure_1() { + var y: int; + var i: int; + + i := 0; + y := 0; + + goto l1, l2; + + l1: + i := i + 5; + goto l3; + + l3: + i := i + 1; + y := y + i; + goto l4; + + l4: + y := y + 1; + goto l2; + + + l2: + if (i>y){ + y := i; + goto l5; + + l5: + assume false; + } + assume false; + i := i + 1; + y := i + 1; + +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_4.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_4.bpl new file mode 100644 index 000000000..46d7f3296 --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_4.bpl @@ -0,0 +1,40 @@ +procedure p() { + var y: int; + var i: int; + i := 0; + y := 0; + l10: + + while ( i <= 10 ){ + y := y + i; + goto l1; + + l1: + i := i + 1; + } + + i := i + 1; + if (y <= 1000){ + goto l10; + } + else{ + goto l2; + } + + l2: + i := i + 1; + goto l3; + + l3: + i := i + 1; + goto l4; + + l4: + assume false; + goto l5; + + l5: + i := i + 1; + + +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/two_procedures.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/two_procedures_1.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/two_procedures.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/two_procedures_1.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/two_procedures_2.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/two_procedures_2.bpl new file mode 100644 index 000000000..a98aef8e4 --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/two_procedures_2.bpl @@ -0,0 +1,80 @@ +procedure p() { + var y: int; + var i: int; + i := 0; + y := 0; + l10: + + while ( i <= 10 ){ + y := y + i; + goto l1; + + l1: + i := i + 1; + } + + i := i + 1; + if (y <= 1000){ + goto l10; + } + else{ + goto l2; + } + + l2: + i := i + 1; + goto l3; + + l3: + i := i + 1; + goto l4; + + l4: + assume false; + goto l5; + + l5: + i := i + 1; + + +} + +procedure p_new() { + var y: int; + var i: int; + i := 0; + y := 0; + l10: + while (y<=1000){ + i := 0; + while ( i <= 10 ){ + y := y + i; + goto l1; + + l1: + i := i + 1; + } + } + + + i := i + 1; + if (y <= 1000){ + goto l10; + } + else{ + goto l2, l3; + } + + + l2: + while (i <= 1000){ + i := i + 1; + assume false; + i := i + 1; + } + + l3: + y := 1000; + + +} \ No newline at end of file diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index 1f78d2e34..3a6719df8 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -74,21 +74,9 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b { loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); } - - var varContextName = "\\"; - IList terms = new List(); - terms.Add(IsaCommonTerms.TermIdentFromName("A")); - terms.Add(IsaCommonTerms.TermIdentFromName("M")); - terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); - terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); - Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + + Term conclusion = getConclusion(loopHeads, "global_block_lemma_loop", beforeBlock, afterBlock, beforeOptProgAccess, + afterOptProgAccess, false, null); var blockLemma = new LemmaDecl( @@ -103,7 +91,8 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b Block afterBlock, Func blockLemmaName, IDictionary> beforeOptBlockToLoops, - IList Loops) + IList Loops, + ISet loopHeadsSet) { @@ -132,7 +121,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b int countCases = 0; foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) { - if (isLoopHead(succ, beforeOptimizations, beforeOptBlockToLoops, beforeToAfterBlock) && Loops.Contains(succ)) + if (loopHeadsSet.Contains(succ) && Loops.Contains(succ)) { countCases = countCases + 1; } @@ -148,7 +137,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b { proofMethods.Add("apply (rule " + blockLemmaName(succ) + ")"); } - else if (isLoopHead(succ, beforeOptimizations, beforeOptBlockToLoops, beforeToAfterBlock) && Loops.Contains(succ)) + else if (loopHeadsSet.Contains(succ) && Loops.Contains(succ)) { } @@ -194,20 +183,9 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b { proofMethods.Add("by simp"); } - var varContextName = "\\"; - IList terms = new List(); - terms.Add(IsaCommonTerms.TermIdentFromName("A")); - terms.Add(IsaCommonTerms.TermIdentFromName("M")); - terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); - terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); - Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + + Term conclusion = getConclusion(loopHeads, "global_block_lemma_loop", beforeBlock, afterBlock, beforeOptProgAccess, + afterOptProgAccess, false, null); var blockLemma = new LemmaDecl( blockLemmaName(beforeBlock), @@ -221,7 +199,8 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b Func GlobalblockLemmaName, Func HybridblockLemmaName, IDictionary> beforeOptBlockToLoops, - IList Loops) + IList Loops, + ISet loopHeadsSet) { var loopHeads = new List(); foreach (Block loop in Loops) @@ -250,7 +229,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) { - if (isLoopHead(succ, beforeOptimizations, beforeOptBlockToLoops, beforeToAfterBlock) && Loops.Contains(succ)) + if (loopHeadsSet.Contains(succ) && Loops.Contains(succ)) { countCases++; } @@ -266,7 +245,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b { proofMethods.Add("apply (rule " + GlobalblockLemmaName(succ) + ")"); } - else if (isLoopHead(succ, beforeOptimizations, beforeOptBlockToLoops, beforeToAfterBlock) && Loops.Contains(succ) && Loops.Contains(succ)) + else if (loopHeadsSet.Contains(succ) && Loops.Contains(succ)) { } @@ -300,22 +279,13 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b { proofMethods.Add("by simp"); } + List listCoalescedBlocks = new List(); + listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock)); + + + Term conclusion = getConclusion(loopHeads, "hybrid_block_lemma_loop", beforeBlock, afterBlock, beforeOptProgAccess, + afterOptProgAccess, true, listCoalescedBlocks); - var varContextName = "\\"; - IList terms = new List(); - terms.Add(IsaCommonTerms.TermIdentFromName("A")); - terms.Add(IsaCommonTerms.TermIdentFromName("M")); - terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); - terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock))); - terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); - Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("hybrid_block_lemma_loop"), terms); var blockLemma = new LemmaDecl( HybridblockLemmaName(beforeBlock), @@ -354,21 +324,10 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(current)); } - var varContextName = "\\"; - IList terms = new List(); - terms.Add(IsaCommonTerms.TermIdentFromName("A")); - terms.Add(IsaCommonTerms.TermIdentFromName("M")); - terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); - terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.TermIdentFromName("(" + string.Join("@", listCoalescedBlocks) + ")")); - terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); - Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("hybrid_block_lemma_loop"), terms); + + + Term conclusion = getConclusion(loopHeads, "hybrid_block_lemma_loop", beforeBlock, afterBlock, beforeOptProgAccess, + afterOptProgAccess, true, listCoalescedBlocks); var blockLemma = new LemmaDecl( HybridblockLemmaName(beforeBlock), @@ -409,20 +368,10 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma { loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); } - var varContextName = "\\"; - IList terms = new List(); - terms.Add(IsaCommonTerms.TermIdentFromName("A")); - terms.Add(IsaCommonTerms.TermIdentFromName("M")); - terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); - terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); - Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + + + Term conclusion = getConclusion(loopHeads, "global_block_lemma_loop", beforeBlock, afterBlock, beforeOptProgAccess, + afterOptProgAccess, false, null); var blockLemma = new LemmaDecl( GlobalblockLemmaName(beforeBlock), @@ -458,21 +407,12 @@ public LemmaDecl HybridBlockLemmaPruning( //Pruning of unreachable blocks with b loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); } - var varContextName = "\\"; - IList terms = new List(); - terms.Add(IsaCommonTerms.TermIdentFromName("A")); - terms.Add(IsaCommonTerms.TermIdentFromName("M")); - terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); - terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock))); - terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); - Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("hybrid_block_lemma_loop"), terms); + + List listCoalescedBlocks = new List(); + listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock)); + + Term conclusion = getConclusion(loopHeads, "hybrid_block_lemma_loop", beforeBlock, afterBlock, beforeOptProgAccess, + afterOptProgAccess, true, listCoalescedBlocks); var blockLemma = new LemmaDecl( blockLemmaName(beforeBlock), @@ -486,7 +426,8 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced Block afterBlock, Func blockLemmaName, IDictionary> beforeOptBlockToLoops, - IList Loops) + IList Loops, + ISet loopHeadsSet) { var loopHeads = new List(); @@ -515,7 +456,7 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) { - if (isLoopHead(succ, beforeOptimizations, beforeOptBlockToLoops, beforeToAfterBlock) && Loops.Contains(succ)) + if (loopHeadsSet.Contains(succ) && Loops.Contains(succ)) { countCases++; } @@ -527,7 +468,7 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced } foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) { - if (isLoopHead(succ, beforeOptimizations, beforeOptBlockToLoops, beforeToAfterBlock) && Loops.Contains(succ)) + if (loopHeadsSet.Contains(succ) && Loops.Contains(succ)) { } @@ -571,20 +512,9 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced { proofMethods.Add("by simp"); } - var varContextName = "\\"; - IList terms = new List(); - terms.Add(IsaCommonTerms.TermIdentFromName("A")); - terms.Add(IsaCommonTerms.TermIdentFromName("M")); - terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); - terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); - Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + + Term conclusion = getConclusion(loopHeads, "global_block_lemma_loop", beforeBlock, afterBlock, beforeOptProgAccess, + afterOptProgAccess, false, null); var blockLemma = new LemmaDecl( blockLemmaName(beforeBlock), @@ -598,13 +528,20 @@ public LemmaDecl LoopHeadCoalesced( //Loop Head coalesced Block afterBlock, Func GlobalblockLemmaName, Func HybridblockLemmaName, - IList Loops) + IList Loops, + IDictionary> ListCoalescedBlocks) { var loopHeads = new List(); foreach (Block loop in Loops) { loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); } + + + foreach (Block current in ListCoalescedBlocks[beforeBlock]) + { + + } @@ -616,28 +553,18 @@ public LemmaDecl LoopHeadCoalesced( //Loop Head coalesced "apply (rule " + HybridblockLemmaName(beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault()) + ")", "apply (rule " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + ")", "apply (rule " + afterOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(afterBlock) + ")", - "apply (unfold " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) +"_def)", - "apply (unfold " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeBlock) + "_def)", - "apply (unfold " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault()) + "_def)", - "by simp" + "apply (unfold " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) +"_def)" }; + foreach (Block current in ListCoalescedBlocks[beforeBlock]) + { + proofMethods.Add("apply (unfold " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(current) + "_def)"); + } + proofMethods.Add("by simp"); - var varContextName = "\\"; - IList terms = new List(); - terms.Add(IsaCommonTerms.TermIdentFromName("A")); - terms.Add(IsaCommonTerms.TermIdentFromName("M")); - terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName("\\")); - terms.Add(IsaCommonTerms.TermIdentFromName(beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_body")); - terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); - terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); - terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); - terms.Add(IsaCommonTerms.TermIdentFromName(afterOptProgAccess.BlockInfo().getTheoryName() + ".post")); - Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName("global_block_lemma_loop"), terms); + Term conclusion = getConclusion(loopHeads, "global_block_lemma_loop", beforeBlock, afterBlock, beforeOptProgAccess, + afterOptProgAccess, false, null); var blockLemma = new LemmaDecl( GlobalblockLemmaName(beforeBlock), @@ -716,20 +643,31 @@ Identifier finalStateId2 } - private static bool isLoopHead(Block b, CFGRepr beforeOptimizations, IDictionary> beforeOptBlockToLoops, IDictionary beforeToAfter) + + + + public static Term getConclusion(List loopHeads, string name, Block beforeBlock, Block afterBlock, IProgramAccessor beforeOptProgAccess, IProgramAccessor afterOptProgAccess, bool isHybridBlock, List listCoalescedBlocks) { - if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(b)) - { - return false; - } - foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(b)) + var varContextName = "\\"; + IList terms = new List(); + terms.Add(IsaCommonTerms.TermIdentFromName("A")); + terms.Add(IsaCommonTerms.TermIdentFromName("M")); + terms.Add(IsaCommonTerms.TermIdentFromName(varContextName)); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(IsaCommonTerms.TermIdentFromName("\\")); + terms.Add(beforeOptProgAccess.CfgDecl()); + terms.Add(afterOptProgAccess.CfgDecl()); + terms.Add(new NatConst(beforeOptProgAccess.BlockInfo().BlockIds[beforeBlock])); + terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); + if (isHybridBlock) { - if (beforeToAfter.ContainsKey(b) && beforeOptBlockToLoops[b].Count < beforeOptBlockToLoops[succ].Count) - { - return true; - } + terms.Add(IsaCommonTerms.TermIdentFromName("(" + string.Join("@", listCoalescedBlocks) + ")")); } - return false; + terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); + terms.Add(afterOptProgAccess.PostconditionsDecl()); + Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName(name), terms); + return conclusion; } -} \ No newline at end of file +} + diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index 9ed32615b..bd63b881c 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -28,7 +28,7 @@ public static Theory CfgOptProof( IDictionary beforeToAfter, // mapping from current block to target block IProgramAccessor beforeOptCfgProgAccess, //before CFG optimizations IProgramAccessor afterOptCfgProgAccess, //after CFG optimizationsList<(Block, Block)> CoalescedBlocks - IDictionary> ListCoalescedBlocks, //TODO: Optimize CFGOptimizationsLemmaManager by using this dictionary + IDictionary> ListCoalescedBlocks, IDictionary CoalescedBlocksToTarget, IDictionary> beforeDagBlockToLoops, Term vcAssm, @@ -37,6 +37,7 @@ public static Theory CfgOptProof( IDictionary afterToBefore = beforeToAfter.ToDictionary(x => x.Value, x => x.Key); IDictionary> beforeOptBlockToLoops = new Dictionary>(); Block coalescedAfterBlock = new Block(); + ISet loopHeadsSet = new HashSet(); foreach (Block beforeBlock in beforeOptimizations.GetBlocksForwards()) { @@ -46,16 +47,17 @@ public static Theory CfgOptProof( foreach (Block loopHeader in beforeDagBlockToLoops[beforeToAfter[beforeBlock]]) { temp.Add(afterToBefore[loopHeader]); + loopHeadsSet.Add(afterToBefore[loopHeader]); } beforeOptBlockToLoops.Add(beforeBlock, temp); } else if (CoalescedBlocksToTarget.ContainsKey(beforeBlock)) { coalescedAfterBlock = CoalescedBlocksToTarget[beforeBlock]; List temp = new List(); - bool test = beforeDagBlockToLoops.ContainsKey(coalescedAfterBlock); foreach (Block loopHeader in beforeDagBlockToLoops[coalescedAfterBlock]) { temp.Add(afterToBefore[loopHeader]); + loopHeadsSet.Add(afterToBefore[loopHeader]); } foreach (Block afterSucc in afterOptimizations.GetSuccessorBlocks( @@ -64,6 +66,7 @@ public static Theory CfgOptProof( if (beforeDagBlockToLoops[coalescedAfterBlock].Count < beforeDagBlockToLoops[afterSucc].Count) { temp.Add(afterToBefore[GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget)]); + loopHeadsSet.Add(afterToBefore[GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget)]); break; } } @@ -110,18 +113,18 @@ public static Theory CfgOptProof( foreach (var current in topoOrder) { Block beforeBlock = current; - if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops, beforeToAfter) && CoalescedBlocksToTarget.ContainsKey(beforeBlock)) //In this case we have a coalesced loop head + if (loopHeadsSet.Contains(beforeBlock) && CoalescedBlocksToTarget.ContainsKey(beforeBlock)) //In this case we have a coalesced loop head { coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); var globalBlock = lemmaManager.LoopHeadCoalesced(beforeBlock, coalescedAfterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), - beforeOptBlockToLoops[beforeBlock]); + beforeOptBlockToLoops[beforeBlock], ListCoalescedBlocks); outerDecls.Add(globalBlock); } - else if (isLoopHead(beforeBlock, beforeOptimizations, beforeOptBlockToLoops,beforeToAfter)) //normal Loop Head + else if (loopHeadsSet.Contains(beforeBlock)) //normal Loop Head { - var globalBlock = lemmaManager.LoopHeadNotCoalesced(beforeBlock, beforeToAfter[beforeBlock], bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); + var globalBlock = lemmaManager.LoopHeadNotCoalesced(beforeBlock, beforeToAfter[beforeBlock], bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock], loopHeadsSet); outerDecls.Add(globalBlock); } else if (CoalescedBlocksToTarget.ContainsKey(beforeBlock)) //in this case we have block coalescing @@ -154,7 +157,7 @@ public static Theory CfgOptProof( var tail = lemmaManager.HybridBlockLemmaTail(beforeBlock, coalescedAfterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), - beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); + beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock], loopHeadsSet); outerDecls.Add(tail); } else //in Between Block @@ -179,7 +182,7 @@ public static Theory CfgOptProof( } else //otherwhise we just need to apply the normal global block lemma. Assumption: Global Block Lemma holds for all successors { - var globalBlock = lemmaManager.GlobalBlockLemma(beforeBlock, afterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock]); + var globalBlock = lemmaManager.GlobalBlockLemma(beforeBlock, afterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops, beforeOptBlockToLoops[beforeBlock], loopHeadsSet); outerDecls.Add(globalBlock); } } @@ -245,21 +248,7 @@ private static Block GetCoalescedAfterBlock(Block b, IDictionary b return null; } - private static bool isLoopHead(Block b, CFGRepr beforeOptimizations, IDictionary> beforeOptBlockToLoops, IDictionary beforeToAfter) - { - if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(b)) - { - return false; - } - foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(b)) - { - if (beforeToAfter.ContainsKey(b) && beforeOptBlockToLoops[b].Count < beforeOptBlockToLoops[succ].Count) - { - return true; - } - } - return false; - } + diff --git a/Source/ProofGeneration/CFGRepr/CFGRepr.cs b/Source/ProofGeneration/CFGRepr/CFGRepr.cs index a7cc1c128..c770b23cc 100644 --- a/Source/ProofGeneration/CFGRepr/CFGRepr.cs +++ b/Source/ProofGeneration/CFGRepr/CFGRepr.cs @@ -118,18 +118,34 @@ public void DeleteBackedges(IDictionary> BlockToLoops) List Backedges = new List(); if (BlockToLoops.ContainsKey(b)) { - foreach (Block succ in GetSuccessorBlocks(b)) + if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(b)) { - if (BlockToLoops[b].Contains(succ)) + foreach (Block succ in GetSuccessorBlocks(b)) { Backedges.Add(succ); - } + } + foreach (Block toRemove in Backedges) + { + toRemove.Predecessors.Remove(b); + outgoingBlocks[b].Remove(toRemove); + } } - foreach (Block toRemove in Backedges) + else { - toRemove.Predecessors.Remove(b); - outgoingBlocks[b].Remove(toRemove); + foreach (Block succ in GetSuccessorBlocks(b)) + { + if (BlockToLoops[b].Contains(succ)) + { + Backedges.Add(succ); + } + } + foreach (Block toRemove in Backedges) + { + toRemove.Predecessors.Remove(b); + outgoingBlocks[b].Remove(toRemove); + } } + } } } From 0cd8c1bd7ec72aff8a9be7c1fc8218c193c3c308 Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Wed, 5 Jul 2023 13:41:10 +0200 Subject: [PATCH 060/123] renamed test --- ...lesced_body_3 - Copy.bpl => loop_without_coalesced_body_3.bpl} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ProofGenerationBenchmarks/cfg_optimizations_tests/{loop_without_coalesced_body_3 - Copy.bpl => loop_without_coalesced_body_3.bpl} (100%) diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_3 - Copy.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_3.bpl similarity index 100% rename from ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_3 - Copy.bpl rename to ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_3.bpl From cd64f33318352e7ea7e2de85305ef16c2bc4fee1 Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Wed, 5 Jul 2023 14:16:35 +0200 Subject: [PATCH 061/123] Added flag for End to End Lemma in CFG optimizations --- .../CFGOptimizationsManager.cs | 34 +++++++++++-------- .../ProofGeneration/ProofGenerationLayer.cs | 3 +- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index bd63b881c..8d642cce8 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -32,7 +32,8 @@ public static Theory CfgOptProof( IDictionary CoalescedBlocksToTarget, IDictionary> beforeDagBlockToLoops, Term vcAssm, - string procedureName) + string procedureName, + bool generateEnd2EndLemma) { IDictionary afterToBefore = beforeToAfter.ToDictionary(x => x.Value, x => x.Key); IDictionary> beforeOptBlockToLoops = new Dictionary>(); @@ -193,20 +194,23 @@ public static Theory CfgOptProof( GetGlobalBlockLemmaName(beforeOptimizations.entry, lemmaNamer), beforeOptimizations.entry, afterOptimizations.entry); outerDecls.Add(entryLemma); - - var endToEndManager = new CFGOptimizationsEndToEnd(); - var endToEndDecls = endToEndManager.EndToEndProof( - "entry_lemma", - "end_to_end", - vcAssm, - beforeOptCfgProgAccess, - afterOptCfgProgAccess, - beforeOptCfgProgAccess, - afterOptimizations, - phasesTheories, - procedureName - ); - outerDecls.AddRange(endToEndDecls); + if (generateEnd2EndLemma) + { + var endToEndManager = new CFGOptimizationsEndToEnd(); + var endToEndDecls = endToEndManager.EndToEndProof( + "entry_lemma", + "end_to_end", + vcAssm, + beforeOptCfgProgAccess, + afterOptCfgProgAccess, + beforeOptCfgProgAccess, + afterOptimizations, + phasesTheories, + procedureName + ); + outerDecls.AddRange(endToEndDecls); + } + diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index fdbf38bed..aa007215d 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -1023,7 +1023,8 @@ out var endToEndLemmaPrelim CoalescedBlocksToTarget, beforeDagBlocktoLoops, vcAssm, - afterPassificationImpl.Name); + afterPassificationImpl.Name, + _proofGenConfig.GenerateCfgDagE2E); theories.Add(cfgOptimizationsProofTheory); #endregion From 705c299b508ed751f6feb43d5d42e016599958da Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Wed, 5 Jul 2023 14:39:16 +0200 Subject: [PATCH 062/123] corrected method where backedges are removed --- .../CFGOptimizationsLemmaManager.cs | 30 ++++--------------- 1 file changed, 5 insertions(+), 25 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index 3a6719df8..e6532c883 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -137,11 +137,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b { proofMethods.Add("apply (rule " + blockLemmaName(succ) + ")"); } - else if (loopHeadsSet.Contains(succ) && Loops.Contains(succ)) - { - - } - else + else if (!(loopHeadsSet.Contains(succ) && Loops.Contains(succ))) { var loopHeadsSucc = new List(); foreach (Block loop in beforeOptBlockToLoops[succ]) @@ -153,6 +149,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b proofMethods.Add("apply (rule " +blockLemmaName(succ) + ")"); } + } proofMethods.Add("apply simp"); if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 0) @@ -245,11 +242,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b { proofMethods.Add("apply (rule " + GlobalblockLemmaName(succ) + ")"); } - else if (loopHeadsSet.Contains(succ) && Loops.Contains(succ)) - { - - } - else + else if (!(loopHeadsSet.Contains(succ) && Loops.Contains(succ))) { var loopHeadsSucc = new List(); foreach (Block loop in beforeOptBlockToLoops[succ]) @@ -306,7 +299,6 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma { "apply (rule extend_hybrid_global_block_lemma_loop)", "apply (rule " + HybridblockLemmaName(succ) + ")", - //beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma() "apply (rule " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + ")", "apply (rule " + beforeOptProgAccess.BlockInfo().OutEdgesMembershipLemma(beforeBlock) + ")", "by simp" @@ -468,11 +460,7 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced } foreach (Block succ in beforeOptimizations.GetSuccessorBlocks(beforeBlock)) { - if (loopHeadsSet.Contains(succ) && Loops.Contains(succ)) - { - - } - else + if (!(loopHeadsSet.Contains(succ) && Loops.Contains(succ))) { var loopHeadsSucc = new List(); foreach (Block loop in beforeOptBlockToLoops[succ]) @@ -483,7 +471,7 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced proofMethods.Add("apply simp"); proofMethods.Add("apply (rule " + blockLemmaName(succ) + ")"); } - + } proofMethods.Add("apply simp"); if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 0) @@ -536,15 +524,7 @@ public LemmaDecl LoopHeadCoalesced( //Loop Head coalesced { loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); } - - - foreach (Block current in ListCoalescedBlocks[beforeBlock]) - { - - } - - var proofMethods = new List { "apply (rule loopHead_global_block_hybrid)", From f807d424e8b4eb27c2c7c1ed052c40038727813a Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 10 Jul 2023 19:51:58 +0200 Subject: [PATCH 063/123] add AllOptionsDisabeld method to ProofGenConfig --- Source/ProofGeneration/ProofGenConfig.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Source/ProofGeneration/ProofGenConfig.cs b/Source/ProofGeneration/ProofGenConfig.cs index 2c659a9ed..86deb8e21 100644 --- a/Source/ProofGeneration/ProofGenConfig.cs +++ b/Source/ProofGeneration/ProofGenConfig.cs @@ -27,6 +27,19 @@ public ProofGenConfig AllOptionsEnabled() return this; } + public ProofGenConfig AllOptionsDisabled() + { + _generateAstCfgE2E = false; + _generateCfgDagE2E = false; + _generatePassifE2E = false; + _generateVcE2E = false; + _generateAstCfgProof = false; + _generateCfgDagProof = false; + _generatePassifProof = false; + _generateVcProof = false; + return this; + } + /* _proofGenConfig.GeneratePassifE2E = _proofGenConfig.GenerateVcProof && _proofGenConfig.GenerateVcE2E && _proofGenConfig.GeneratePassifProof; _proofGenConfig.GenerateCfgDagE2E = _proofGenConfig.GeneratePassifE2E && _proofGenConfig.GenerateCfgDagProof; From d5b79c2ad946aba0aa5d61d1106946e596abc9a2 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 10 Jul 2023 21:38:32 +0200 Subject: [PATCH 064/123] refactor ProofGenConfig and change logic for generating end-to-end lemma in CFG-to-DAG phase --- .../CfgToDag/CfgToDagEndToEnd.cs | 66 +++--- .../CfgToDag/CfgToDagManager.cs | 12 +- Source/ProofGeneration/ProofGenConfig.cs | 215 +++++++++--------- .../ProofGeneration/ProofGenerationLayer.cs | 22 +- 4 files changed, 165 insertions(+), 150 deletions(-) diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs index 2455d1e29..15f218e93 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs @@ -35,6 +35,7 @@ public class CfgToDagEndToEnd private readonly string varContextName = "\\0"; public IEnumerable EndToEndProof( + bool lemmaForProcedure, string entryCfgLemma, string passificationEndToEndLemma, Term vcAssm, @@ -118,41 +119,44 @@ public IEnumerable EndToEndProof( result.Add(helperLemma); //transform end to end theorem to a compact representation - var endToEndLemma = + if (lemmaForProcedure) + { + var endToEndLemma = new LemmaDecl( - "end_to_end_theorem", - ContextElem.CreateWithAssumptions(new List {vcAssm}, new List {"VC"}), - ProcedureIsCorrect( - programAccessor.FunctionsDecl(), - IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), - IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()), - programAccessor.AxiomsDecl(), - programAccessor.ProcDecl()), - new Proof( - new List - { - 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 " + - programAccessor.PreconditionsDeclName() + "_def " + programAccessor.PostconditionsDeclName() + "_def " + - programAccessor.ParamsDecl() + "_def " + programAccessor.LocalsDecl() + "_def " + - programAccessor.PreconditionsDeclName() + "_def " + programAccessor.PostconditionsDeclName() + "_def " + - programAccessor.ParamsDecl() + "_def " + programAccessor.LocalsDecl() + "_def " + - - programAccessor.FunctionsDecl() + "_def " + programAccessor.FunctionsDecl() + "_def " + - programAccessor.AxiomsDecl() + "_def " + programAccessor.AxiomsDecl() + "_def " + - programAccessor.ConstsDecl() + "_def " + programAccessor.ConstsDecl() + "_def " + - programAccessor.GlobalsDecl() + "_def " + programAccessor.GlobalsDecl() + "_def " + - "exprs_to_only_checked_spec_def") - } - ) ); + "end_to_end_theorem", + ContextElem.CreateWithAssumptions(new List { vcAssm }, new List { "VC" }), + ProcedureIsCorrect( + programAccessor.FunctionsDecl(), + IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), + IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()), + programAccessor.AxiomsDecl(), + programAccessor.ProcDecl()), + new Proof( + new List + { + 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 " + + programAccessor.PreconditionsDeclName() + "_def " + + programAccessor.PostconditionsDeclName() + "_def " + + programAccessor.ParamsDecl() + "_def " + programAccessor.LocalsDecl() + "_def " + + programAccessor.PreconditionsDeclName() + "_def " + + programAccessor.PostconditionsDeclName() + "_def " + + programAccessor.ParamsDecl() + "_def " + programAccessor.LocalsDecl() + "_def " + + + programAccessor.FunctionsDecl() + "_def " + programAccessor.FunctionsDecl() + + "_def " + + programAccessor.AxiomsDecl() + "_def " + programAccessor.AxiomsDecl() + "_def " + + programAccessor.ConstsDecl() + "_def " + programAccessor.ConstsDecl() + "_def " + + programAccessor.GlobalsDecl() + "_def " + programAccessor.GlobalsDecl() + "_def " + + "exprs_to_only_checked_spec_def") + } + )); - if (!ProofGenerationLayer.GenerateAstCfgE2E()) - { result.Add(endToEndLemma); } - + return result; } diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs index adbf4bd03..ac6684a1c 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs @@ -11,6 +11,13 @@ namespace ProofGeneration.CfgToDag { + public enum CfgToDagEndToEndLemma + { + DoNotGenerate, + GenerateForProcedure, + GenerateForEntryBlock + } + public class CfgToDagManager { /** @@ -23,7 +30,7 @@ public class CfgToDagManager */ public static Theory CfgToDagProof( PhasesTheories phasesTheories, - bool generateEndToEndLemma, + CfgToDagEndToEndLemma generateEndToEndLemma, bool generatePassificationProof, bool generateVcProof, Term vcAssm, @@ -181,10 +188,11 @@ public static Theory CfgToDagProof( var theoryOuterDecls = new List(); theoryOuterDecls.Add(cfgToDagLemmasLocale); - if (generateEndToEndLemma) + if (generateEndToEndLemma != CfgToDagEndToEndLemma.DoNotGenerate) { var endToEndManager = new CfgToDagEndToEnd(); var endToEndDecls = endToEndManager.EndToEndProof( + generateEndToEndLemma == CfgToDagEndToEndLemma.GenerateForProcedure, cfgToDagLemmasLocale.Name + "." + entryLemma.Name, phasesTheories.EndToEndLemmaName(PhasesTheories.Phase.Passification, true), vcAssm, diff --git a/Source/ProofGeneration/ProofGenConfig.cs b/Source/ProofGeneration/ProofGenConfig.cs index 86deb8e21..137f0b348 100644 --- a/Source/ProofGeneration/ProofGenConfig.cs +++ b/Source/ProofGeneration/ProofGenConfig.cs @@ -1,132 +1,133 @@ -namespace ProofGeneration +using System; +using System.Collections.Generic; + +namespace ProofGeneration { /// /// Used to indicate which proofs should be generated. /// public class ProofGenConfig { - private bool _generateAstCfgE2E; - private bool _generateCfgDagE2E; - private bool _generatePassifE2E; - private bool _generateVcE2E; - private bool _generateAstCfgProof; - private bool _generateCfgDagProof; - private bool _generatePassifProof; - private bool _generateVcProof; - - public ProofGenConfig AllOptionsEnabled() + + private IDictionary generatePhaseProof; + + private List phases = new List + { + PhasesTheories.Phase.AstToCfg, + PhasesTheories.Phase.CfgOptimizations, + PhasesTheories.Phase.CfgToDag, + PhasesTheories.Phase.Passification, + PhasesTheories.Phase.Vc + }; + + private void UpdatePhaseDict(IDictionary dict, PhasesTheories.Phase key, V value) + { + if (!phases.Contains(key)) { - _generateAstCfgE2E = true; - _generateCfgDagE2E = true; - _generatePassifE2E = true; - _generateVcE2E = true; - _generateAstCfgProof = true; - _generateCfgDagProof = true; - _generatePassifProof = true; - _generateVcProof = true; - return this; + throw new ArgumentException("Unexpected phase " + key); } - - public ProofGenConfig AllOptionsDisabled() + + dict[key] = value; + } + + private void UpdatePhaseProofFlag(PhasesTheories.Phase phase, bool flag) + { + UpdatePhaseDict(generatePhaseProof, phase, flag); + } + + private bool GetPhaseProofFlag(PhasesTheories.Phase phase) + { + return generatePhaseProof[phase]; + } + + private ProofGenConfig AllOptions(bool enabled) + { + generatePhaseProof = new Dictionary(); + + foreach (var phase in phases) { - _generateAstCfgE2E = false; - _generateCfgDagE2E = false; - _generatePassifE2E = false; - _generateVcE2E = false; - _generateAstCfgProof = false; - _generateCfgDagProof = false; - _generatePassifProof = false; - _generateVcProof = false; - return this; + generatePhaseProof.Add(phase, enabled); } - /* - _proofGenConfig.GeneratePassifE2E = _proofGenConfig.GenerateVcProof && _proofGenConfig.GenerateVcE2E && _proofGenConfig.GeneratePassifProof; - _proofGenConfig.GenerateCfgDagE2E = _proofGenConfig.GeneratePassifE2E && _proofGenConfig.GenerateCfgDagProof; - _proofGenConfig.GenerateAstCfgE2E = _proofGenConfig.GenerateCfgDagE2E && _proofGenConfig.GenerateAstCfgProof; - - _proofGenConfig.GenerateBeforeAstCfgProg = _proofGenConfig.GenerateAstCfgProof; - _proofGenConfig.GenerateUnoptimizedCfgProg = proofGenInfo.GetOptimizationsFlag() && _proofGenConfig.GenerateAstCfgProof; - _proofGenConfig.GenerateBeforeCfgDagProg = (proofGenInfo.GetOptimizationsFlag() && _proofGenConfig.GenerateCfgDagProof) || - (!proofGenInfo.GetOptimizationsFlag() && (_proofGenConfig.GenerateAstCfgProof || _proofGenConfig.GenerateCfgDagProof)); - _proofGenConfig.GenerateBeforePassifProg = _proofGenConfig.GenerateCfgDagProof || _proofGenConfig.GeneratePassifProof; - _proofGenConfig.GeneratePassifiedProg = _proofGenConfig.GeneratePassifProof || _proofGenConfig.GenerateVcProof; - */ - public bool GenerateAstCfgE2E => _generateAstCfgE2E && GenerateAstCfgProof; - - public ProofGenConfig SetAstCfgE2E(bool flag) - { - _generateAstCfgE2E = flag; - return this; - } + return this; + } + + public ProofGenConfig AllOptionsEnabled() + { + return AllOptions(true); + } + + public ProofGenConfig AllOptionsDisabled() + { + return AllOptions(false); + } + + public bool GenerateAstCfgE2E(bool optimizationsHaveAnEffect) => + GenerateAstCfgProof && (!optimizationsHaveAnEffect && GenerateCfgDagE2E); //currently do not produce E2E if optimizations have an effect - public bool GenerateCfgDagE2E => _generateCfgDagE2E && GenerateCfgDagProof; - public ProofGenConfig SetCfgDagE2E(bool flag) - { - _generateCfgDagE2E = flag; - return this; - } + public bool GenerateCfgDagE2E => GenerateCfgDagProof && GeneratePassifE2E; - public bool GeneratePassifE2E => _generatePassifE2E && GeneratePassifProof && GenerateVcE2E; + public bool GeneratePassifE2E => GeneratePassifProof && GenerateVcE2E; - public ProofGenConfig SetPassifE2E(bool flag) - { - _generatePassifE2E = flag; - return this; - } + public bool GenerateVcE2E => GenerateVcProof; - public bool GenerateVcE2E => _generateVcE2E && GenerateVcProof; - - public ProofGenConfig SetVcE2E(bool flag) - { - _generateVcE2E = flag; - return this; - } + public bool GenerateAstCfgProof => GetPhaseProofFlag(PhasesTheories.Phase.AstToCfg); + public ProofGenConfig SetAstCfgProof(bool flag) + { + UpdatePhaseProofFlag(PhasesTheories.Phase.AstToCfg, flag); + return this; + } - public bool GenerateAstCfgProof => _generateAstCfgProof; - public ProofGenConfig SetAstCfgProof(bool flag) - { - _generateAstCfgProof = flag; - return this; - } + public bool GenerateCfgOptProof(bool optimizationsHaveAnEffect) => + optimizationsHaveAnEffect && GetPhaseProofFlag(PhasesTheories.Phase.CfgOptimizations); - public bool GenerateCfgDagProof => _generateCfgDagProof; - public ProofGenConfig SetCfgDagProof(bool flag) - { - _generateCfgDagProof = flag; - return this; - } + public ProofGenConfig SetCfgOptProof(bool flag) + { + UpdatePhaseProofFlag(PhasesTheories.Phase.CfgOptimizations, flag); + return this; + } - public bool GeneratePassifProof => _generatePassifProof; - public ProofGenConfig SetPassifProof(bool flag) - { - _generatePassifProof = flag; - return this; - } + public bool GenerateCfgDagProof => GetPhaseProofFlag(PhasesTheories.Phase.CfgToDag); + public ProofGenConfig SetCfgDagProof(bool flag) + { + UpdatePhaseProofFlag(PhasesTheories.Phase.CfgToDag, flag); + return this; + } - public bool GenerateVcProof => _generateVcProof; - - public ProofGenConfig SetVcProof(bool flag) - { - _generateVcProof = flag; - return this; - } + public bool GeneratePassifProof => GetPhaseProofFlag(PhasesTheories.Phase.Passification); + public ProofGenConfig SetPassifProof(bool flag) + { + UpdatePhaseProofFlag(PhasesTheories.Phase.Passification, flag); + return this; + } - /** Program Generation Getters */ - - public bool GenerateBeforeAstCfgProg => GenerateAstCfgProof; + public bool GenerateVcProof => GetPhaseProofFlag(PhasesTheories.Phase.Vc); + + public ProofGenConfig SetVcProof(bool flag) + { + UpdatePhaseProofFlag(PhasesTheories.Phase.Vc, flag); + return this; + } - public bool GenerateUnoptimizedCfgProg(bool optimizationsHaveAnEffect) - { - return optimizationsHaveAnEffect; - } + /** Program Generation Getters */ + + public bool GenerateBeforeAstCfgProg => GenerateAstCfgProof; - public bool GenerateBeforeCfgDagProg(bool optimizationsHaveAnEffect) - { - return GenerateCfgDagProof || (optimizationsHaveAnEffect && GenerateAstCfgProof); - } + public bool GenerateUnoptimizedCfgProg(bool optimizationsHaveAnEffect) + { + return optimizationsHaveAnEffect && GenerateAstCfgProof || + GenerateCfgOptProof(optimizationsHaveAnEffect); + } + + public bool GenerateBeforeCfgDagProg(bool optimizationsHaveAnEffect) + { + return (!optimizationsHaveAnEffect && GenerateAstCfgProof) || //directly connect AST to CFG before CfgToDag if there are no optimizations + GenerateCfgOptProof(optimizationsHaveAnEffect) || + GenerateCfgDagProof; + } - public bool GenerateBeforePassiveProg => GenerateCfgDagProof || GeneratePassifProof; - public bool GeneratePassifiedProg => GeneratePassifProof || GenerateVcProof; + public bool GenerateBeforePassiveProg => GenerateCfgDagProof || GeneratePassifProof; + public bool GeneratePassifiedProg => GeneratePassifProof || GenerateVcProof; + } } \ No newline at end of file diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index aa007215d..fc7df9f40 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -80,6 +80,7 @@ public class ProofGenerationLayer //private static Block uniqueExitBlockOrigBeforeOptimizations; private static Block uniqueExitBlockOrig; + //new ProofGenConfig().AllOptionsDisabled().SetCfgOptProof(true); private static ProofGenConfig _proofGenConfig = new ProofGenConfig().AllOptionsEnabled(); private static IProgramAccessor globalDataProgAccess; @@ -543,11 +544,6 @@ private static void DesugarCmdsInBigBlock(BigBlock b) } } - public static bool GenerateAstCfgE2E() - { - return _proofGenConfig.GenerateAstCfgE2E; - } - /// /// Generate all proofs for the current procedure. /// @@ -741,6 +737,10 @@ from calls. #endregion } + var generateProcForBeforeCfgToDag = + _proofGenConfig.GenerateAstCfgE2E(proofGenInfo.GetOptimizationsFlag()) && + proofGenInfo.GetOptimizationsFlag(); + if (_proofGenConfig.GenerateBeforeCfgDagProg(proofGenInfo.GetOptimizationsFlag())) { #region before cfg to dag program @@ -753,7 +753,8 @@ from calls. false, false, parentAccessorForBeforeCfgToDag == null || proofGenInfo.GetOptimizationsFlag(), - parentAccessorForBeforeCfgToDag != null ? SpecsConfig.None : specsConfigDefault, + //do not generate separate procedure if AST is going to connect directly to the CFG before the DAG + generateProcForBeforeCfgToDag ? specsConfigDefault : SpecsConfig.None, parentAccessorForBeforeCfgToDag == null || proofGenInfo.GetOptimizationsFlag()); beforeCfgToDagProgAccess = new IsaProgramGenerator().GetIsaProgram( @@ -965,7 +966,9 @@ out var endToEndLemmaPrelim beforeDagBlocktoLoops = getBeforeDagBlockToLoops(beforeDagAfterDagBlock, beforePassificationCfg, cfgToDagHintManager); var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( phasesTheories, - _proofGenConfig.GenerateCfgDagE2E, + //hacky: find better solution + _proofGenConfig.GenerateCfgDagE2E ? (generateProcForBeforeCfgToDag ? CfgToDagEndToEndLemma.GenerateForProcedure : CfgToDagEndToEndLemma.GenerateForEntryBlock) + : CfgToDagEndToEndLemma.DoNotGenerate, _proofGenConfig.GeneratePassifProof, _proofGenConfig.GenerateVcProof, vcAssm, @@ -984,8 +987,7 @@ out var endToEndLemmaPrelim #endregion } - //TODO: change flag to proof flag - if (_proofGenConfig.GenerateUnoptimizedCfgProg(proofGenInfo.GetOptimizationsFlag())) + if (_proofGenConfig.GenerateCfgOptProof(proofGenInfo.GetOptimizationsFlag())) { #region cfg optimizations @@ -1087,7 +1089,7 @@ out var endToEndLemmaPrelim var astToCfgProofTheory = AstToCfgManager.AstToCfgProof( phasesTheories.TheoryName(PhasesTheories.Phase.AstToCfg), phasesTheories, - _proofGenConfig.GenerateAstCfgE2E, + _proofGenConfig.GenerateAstCfgE2E(proofGenInfo.GetOptimizationsFlag()), _proofGenConfig, vcAssm, proofGenInfo, From 3fa68eb24bbccaeb2d983a0ca55cacaa0ac91b6f Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 10 Jul 2023 21:50:02 +0200 Subject: [PATCH 065/123] minor fix --- Source/ProofGeneration/ProofGenerationLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index fc7df9f40..690465d87 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -754,7 +754,7 @@ from calls. false, parentAccessorForBeforeCfgToDag == null || proofGenInfo.GetOptimizationsFlag(), //do not generate separate procedure if AST is going to connect directly to the CFG before the DAG - generateProcForBeforeCfgToDag ? specsConfigDefault : SpecsConfig.None, + parentAccessorForBeforeCfgToDag == null || generateProcForBeforeCfgToDag ? specsConfigDefault : SpecsConfig.None, parentAccessorForBeforeCfgToDag == null || proofGenInfo.GetOptimizationsFlag()); beforeCfgToDagProgAccess = new IsaProgramGenerator().GetIsaProgram( From 011c399b319bbe9959ea4ba2e4ebb0917c3b20a7 Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Tue, 11 Jul 2023 08:20:39 +0200 Subject: [PATCH 066/123] Added flag for CFG to DAG proof --- .../CFGOptimizations/CFGOptimizationsManager.cs | 14 ++++++++------ Source/ProofGeneration/ProofGenerationLayer.cs | 4 +++- foundational_boogie | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index 8d642cce8..bc065c3db 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -33,7 +33,8 @@ public static Theory CfgOptProof( IDictionary> beforeDagBlockToLoops, Term vcAssm, string procedureName, - bool generateEnd2EndLemma) + bool generateEnd2EndLemma, + bool generateCfgDagProof) { IDictionary afterToBefore = beforeToAfter.ToDictionary(x => x.Value, x => x.Key); IDictionary> beforeOptBlockToLoops = new Dictionary>(); @@ -210,18 +211,19 @@ public static Theory CfgOptProof( ); outerDecls.AddRange(endToEndDecls); } - - List importTheories = new List { "Boogie_Lang.Semantics", "Boogie_Lang.Util", "Boogie_Lang.CFGOptimizationsLoop", afterOptCfgProgAccess.TheoryName(), - beforeOptCfgProgAccess.TheoryName(), - phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag) - + beforeOptCfgProgAccess.TheoryName() }; + if (generateCfgDagProof) + { + importTheories.Add(phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag)); + } + return new Theory( phasesTheories.TheoryName(PhasesTheories.Phase.CfgOptimizations), diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 690465d87..6c743c423 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -82,6 +82,7 @@ public class ProofGenerationLayer //new ProofGenConfig().AllOptionsDisabled().SetCfgOptProof(true); private static ProofGenConfig _proofGenConfig = new ProofGenConfig().AllOptionsEnabled(); + //private static ProofGenConfig _proofGenConfig = new ProofGenConfig().AllOptionsDisabled().SetCfgOptProof(true); private static IProgramAccessor globalDataProgAccess; @@ -1026,7 +1027,8 @@ out var endToEndLemmaPrelim beforeDagBlocktoLoops, vcAssm, afterPassificationImpl.Name, - _proofGenConfig.GenerateCfgDagE2E); + _proofGenConfig.GenerateCfgDagE2E, + _proofGenConfig.GenerateCfgDagProof); theories.Add(cfgOptimizationsProofTheory); #endregion diff --git a/foundational_boogie b/foundational_boogie index 78ee660eb..58d1183fb 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit 78ee660ebcab3e7d942a459de569f5122f9ed4e8 +Subproject commit 58d1183fbda06a6fea330b0b11717abd0bfdaa9f From 3b3d6ec0338c55043ee69b461a4f4c6ac281f58b Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Tue, 11 Jul 2023 16:39:50 +0200 Subject: [PATCH 067/123] Minor Change generate proc for CFG to DAG --- Source/ProofGeneration/ProofGenerationLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 6c743c423..dbc105069 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -739,7 +739,7 @@ from calls. } var generateProcForBeforeCfgToDag = - _proofGenConfig.GenerateAstCfgE2E(proofGenInfo.GetOptimizationsFlag()) && + //_proofGenConfig.GenerateAstCfgE2E(proofGenInfo.GetOptimizationsFlag()) && proofGenInfo.GetOptimizationsFlag(); if (_proofGenConfig.GenerateBeforeCfgDagProg(proofGenInfo.GetOptimizationsFlag())) From 1a0be6ab7707bc8259de36a2e02a4bd5de7b60f7 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 11 Jul 2023 20:23:29 +0200 Subject: [PATCH 068/123] Merge branch 'cfg_optimizations' of https://github.com/gauravpartha/boogie_proofgen into cfg_optimizations # Conflicts: # foundational_boogie --- foundational_boogie | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundational_boogie b/foundational_boogie index 58d1183fb..e87d56f0c 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit 58d1183fbda06a6fea330b0b11717abd0bfdaa9f +Subproject commit e87d56f0ce3ab93a23f3667ddc706d6151929b0a From 00bb4e5530bf9f7aae7625be345ff1c4b8edf36a Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 11 Jul 2023 20:33:15 +0200 Subject: [PATCH 069/123] update submodule --- foundational_boogie | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundational_boogie b/foundational_boogie index e87d56f0c..832b1e7a7 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit e87d56f0ce3ab93a23f3667ddc706d6151929b0a +Subproject commit 832b1e7a72beef9349ed91daad1e8b3fe0cf0b2f From 855537169bc03f782b5388bbdbbe4ec71b5de3ea Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Wed, 12 Jul 2023 15:08:01 +0200 Subject: [PATCH 070/123] Fixed problem with self loops --- .../CFGOptimizationsLemmaManager.cs | 4 ++-- .../CFGOptimizationsManager.cs | 18 ++++++++++++++++-- Source/ProofGeneration/CFGRepr/CFGRepr.cs | 11 +++++++++-- Source/ProofGeneration/ProofGenerationLayer.cs | 18 +++++++++++++----- 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index e6532c883..65f76c468 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -232,7 +232,7 @@ public LemmaDecl GlobalBlockLemmaPruningNotCoalesced( //Pruning of unreachable b } } - if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1 && beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() - countCases > 0) + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1 && beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() - countCases > 1) { proofMethods.Add("apply (intro conjI)"); } @@ -454,7 +454,7 @@ public LemmaDecl LoopHeadNotCoalesced( //Loop Head uncoalesced } } - if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1 && beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() - countCases > 0) + if (beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() > 1 && beforeOptimizations.GetSuccessorBlocks(beforeBlock).Count() - countCases > 1) { proofMethods.Add("apply (intro conjI)"); } diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index bc065c3db..120f16437 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -34,12 +34,15 @@ public static Theory CfgOptProof( Term vcAssm, string procedureName, bool generateEnd2EndLemma, - bool generateCfgDagProof) + bool generateCfgDagProof, + IDictionary selfLoops) { IDictionary afterToBefore = beforeToAfter.ToDictionary(x => x.Value, x => x.Key); IDictionary> beforeOptBlockToLoops = new Dictionary>(); Block coalescedAfterBlock = new Block(); ISet loopHeadsSet = new HashSet(); + IDictionary selfLoopsNew = new Dictionary(); + foreach (Block beforeBlock in beforeOptimizations.GetBlocksForwards()) { @@ -52,6 +55,11 @@ public static Theory CfgOptProof( loopHeadsSet.Add(afterToBefore[loopHeader]); } beforeOptBlockToLoops.Add(beforeBlock, temp); + if (selfLoops.ContainsKey(beforeToAfter[beforeBlock])) + { + selfLoopsNew.Add(beforeBlock, beforeBlock); + loopHeadsSet.Add(beforeBlock); + } } else if (CoalescedBlocksToTarget.ContainsKey(beforeBlock)) { coalescedAfterBlock = CoalescedBlocksToTarget[beforeBlock]; @@ -72,7 +80,13 @@ public static Theory CfgOptProof( break; } } + if (selfLoops.ContainsKey(coalescedAfterBlock)) + { + temp.Add(afterToBefore[coalescedAfterBlock]); + loopHeadsSet.Add(afterToBefore[coalescedAfterBlock]); + } beforeOptBlockToLoops.Add(beforeBlock, temp); + } } @@ -106,7 +120,7 @@ public static Theory CfgOptProof( CFGRepr beforeOptimizationsCopy = beforeOptimizations.Copy(); - beforeOptimizationsCopy.DeleteBackedges(beforeOptBlockToLoops); + beforeOptimizationsCopy.DeleteBackedges(beforeOptBlockToLoops, selfLoopsNew); List topoOrder = new List(); TopologicalOrder(topoOrder, beforeOptimizationsCopy); diff --git a/Source/ProofGeneration/CFGRepr/CFGRepr.cs b/Source/ProofGeneration/CFGRepr/CFGRepr.cs index c770b23cc..efaf91155 100644 --- a/Source/ProofGeneration/CFGRepr/CFGRepr.cs +++ b/Source/ProofGeneration/CFGRepr/CFGRepr.cs @@ -111,7 +111,7 @@ public CFGRepr Copy() return new CFGRepr(this); } - public void DeleteBackedges(IDictionary> BlockToLoops) + public void DeleteBackedges(IDictionary> BlockToLoops, IDictionary selfLoops) { foreach (Block b in blocks) { @@ -144,8 +144,15 @@ public void DeleteBackedges(IDictionary> BlockToLoops) toRemove.Predecessors.Remove(b); outgoingBlocks[b].Remove(toRemove); } + } - + + } + + if (selfLoops.ContainsKey(b)) + { + outgoingBlocks[b].Remove(b); + b.Predecessors.Remove(b); } } } diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index dbc105069..5d23f2659 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -955,7 +955,7 @@ out var endToEndLemmaPrelim } IDictionary> beforeDagBlocktoLoops = null; - + IDictionary selfLoops = null; if (_proofGenConfig.GenerateCfgDagProof) { #region cfg to dag @@ -964,7 +964,7 @@ out var endToEndLemmaPrelim uniqueExitBlockOrig != null ? beforePassiveOrigBlock.First(kv => kv.Value == uniqueExitBlockOrig).Key : null; - beforeDagBlocktoLoops = getBeforeDagBlockToLoops(beforeDagAfterDagBlock, beforePassificationCfg, cfgToDagHintManager); + beforeDagBlocktoLoops = getBeforeDagBlockToLoops(beforeDagAfterDagBlock, beforePassificationCfg, cfgToDagHintManager, out selfLoops); var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( phasesTheories, //hacky: find better solution @@ -997,9 +997,11 @@ out var endToEndLemmaPrelim IDictionary beforeOptAfterOptBlock = DictionaryComposition(beforeOptimizationsOrigBlock, origToAfterOpt); if (beforeDagBlocktoLoops == null) { - beforeDagBlocktoLoops = getBeforeDagBlockToLoops(beforeDagAfterDagBlock, beforePassificationCfg, cfgToDagHintManager); + beforeDagBlocktoLoops = getBeforeDagBlockToLoops(beforeDagAfterDagBlock, beforePassificationCfg, cfgToDagHintManager, out selfLoops); } + + IDictionary CoalescedBlocksToTarget = DictionaryComposition(afterPassificationImpl.CoalescedBlocksToTarget, origToAfterOpt); CoalescedBlocksToTarget = DictionaryComposition(beforeOptimizationsOrigBlock, CoalescedBlocksToTarget); @@ -1028,7 +1030,8 @@ out var endToEndLemmaPrelim vcAssm, afterPassificationImpl.Name, _proofGenConfig.GenerateCfgDagE2E, - _proofGenConfig.GenerateCfgDagProof); + _proofGenConfig.GenerateCfgDagProof, + selfLoops); theories.Add(cfgOptimizationsProofTheory); #endregion @@ -1165,8 +1168,9 @@ public static BoogieIsaProgInterface BoogieIsaProgInterface() return new BoogieIsaProgInterface(new Dictionary(procNameToTopLevelPrograms), globalDataProgAccess); } - public static IDictionary> getBeforeDagBlockToLoops(IDictionary beforeToAfter, CFGRepr afterDagCfg, CfgToDagHintManager hintManager) + public static IDictionary> getBeforeDagBlockToLoops(IDictionary beforeToAfter, CFGRepr afterDagCfg, CfgToDagHintManager hintManager, out IDictionary selfLoops) { + selfLoops = new Dictionary(); var afterToBefore = beforeToAfter.InverseDict(); IDictionary> blocksToLoops = new Dictionary>(); foreach (var afterBlock in afterDagCfg.GetBlocksBackwards()) @@ -1199,6 +1203,10 @@ public static IDictionary> getBeforeDagBlockToLoops(IDiction { loops.Add(backedgeLoop); } + else + { + selfLoops.Add(beforeBlock, backedgeLoop); + } } } var loopsList = loops.ToList(); From b51737653920409278be018bcb55ac0b2e5fed27 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 12 Jul 2023 17:51:58 +0200 Subject: [PATCH 071/123] update submodule --- foundational_boogie | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundational_boogie b/foundational_boogie index 832b1e7a7..6254cd790 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit 832b1e7a72beef9349ed91daad1e8b3fe0cf0b2f +Subproject commit 6254cd7904468f3d7fece22c16ea6414f2924c1e From fcf8c6e6502e6b8b299cd00487c8f51a4a07be2f Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Thu, 13 Jul 2023 14:11:49 +0200 Subject: [PATCH 072/123] Minor Change --- .../CFGOptimizationsManager.cs | 32 ++++++------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index 120f16437..ecae962a1 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -18,16 +18,14 @@ namespace ProofGeneration.CFGOptimizations; public class CfgOptimizationsManager { - - //string uniqueTheoryName, - //PhasesTheories phasesTheories, + public static Theory CfgOptProof( PhasesTheories phasesTheories, CFGRepr beforeOptimizations, CFGRepr afterOptimizations, IDictionary beforeToAfter, // mapping from current block to target block IProgramAccessor beforeOptCfgProgAccess, //before CFG optimizations - IProgramAccessor afterOptCfgProgAccess, //after CFG optimizationsList<(Block, Block)> CoalescedBlocks + IProgramAccessor afterOptCfgProgAccess, //after CFG optimizationsList IDictionary> ListCoalescedBlocks, IDictionary CoalescedBlocksToTarget, IDictionary> beforeDagBlockToLoops, @@ -71,12 +69,12 @@ public static Theory CfgOptProof( } foreach (Block afterSucc in afterOptimizations.GetSuccessorBlocks( - GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget))) + CoalescedBlocksToTarget[beforeBlock])) { if (beforeDagBlockToLoops[coalescedAfterBlock].Count < beforeDagBlockToLoops[afterSucc].Count) { - temp.Add(afterToBefore[GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget)]); - loopHeadsSet.Add(afterToBefore[GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget)]); + temp.Add(afterToBefore[CoalescedBlocksToTarget[beforeBlock]]); + loopHeadsSet.Add(afterToBefore[CoalescedBlocksToTarget[beforeBlock]]); break; } } @@ -131,7 +129,7 @@ public static Theory CfgOptProof( Block beforeBlock = current; if (loopHeadsSet.Contains(beforeBlock) && CoalescedBlocksToTarget.ContainsKey(beforeBlock)) //In this case we have a coalesced loop head { - coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + coalescedAfterBlock = CoalescedBlocksToTarget[beforeBlock]; var globalBlock = lemmaManager.LoopHeadCoalesced(beforeBlock, coalescedAfterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), @@ -147,7 +145,7 @@ public static Theory CfgOptProof( { if (ProgramToVCProof.LemmaHelper.FinalStateIsMagic(beforeBlock)) //Pruning of Unreachable Blocks Coalesced { - coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + coalescedAfterBlock = CoalescedBlocksToTarget[beforeBlock]; var pruningCoalesced = lemmaManager.HybridBlockLemmaPruning(beforeBlock, coalescedAfterBlock, bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock]); outerDecls.Add(pruningCoalesced); @@ -168,7 +166,7 @@ public static Theory CfgOptProof( } else if (ListCoalescedBlocks[beforeBlock].Count == 1) //tail of coalesced blocks { - coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + coalescedAfterBlock = CoalescedBlocksToTarget[beforeBlock]; var tail = lemmaManager.HybridBlockLemmaTail(beforeBlock, coalescedAfterBlock, bigblock => GetGlobalBlockLemmaName(bigblock, lemmaNamer), @@ -178,7 +176,7 @@ public static Theory CfgOptProof( } else //in Between Block { - coalescedAfterBlock = GetCoalescedAfterBlock(beforeBlock, beforeToAfter, CoalescedBlocksToTarget); + coalescedAfterBlock = CoalescedBlocksToTarget[beforeBlock]; var inBetweenBlock = lemmaManager.HybridBlockLemma(beforeBlock, coalescedAfterBlock, beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault(), bigblock => GetHybridBlockLemmaName(bigblock, lemmaNamer), beforeOptBlockToLoops[beforeBlock], @@ -256,17 +254,7 @@ private static string GetHybridBlockLemmaName(Block b, IsaUniqueNamer namer) return "hybrid_block_lemma_" + namer.GetName(b, "block_" + b.Label); } - private static Block GetCoalescedAfterBlock(Block b, IDictionary beforeToAfter, IDictionary CoalescedBlocksToTarget) - { - foreach (Block beforeBlockNew in beforeToAfter.Keys) //Get the Coalesced After Block - { - if (beforeToAfter[beforeBlockNew] == CoalescedBlocksToTarget[b]) - { - return beforeToAfter[beforeBlockNew]; - } - } - return null; - } + From d8bd04625926c64b295b7e09620756864e2658ba Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Tue, 18 Jul 2023 10:30:03 +0200 Subject: [PATCH 073/123] Added new cfg optimizations tests --- .../cfg_optimizations_tests/big_program_1.bpl | 424 ++++++++++++++++++ .../cfg_optimizations_tests/big_program_2.bpl | 310 +++++++++++++ .../coalesced_loop_head.bpl | 36 ++ 3 files changed, 770 insertions(+) create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/big_program_1.bpl create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/big_program_2.bpl create mode 100644 ProofGenerationBenchmarks/cfg_optimizations_tests/coalesced_loop_head.bpl diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/big_program_1.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/big_program_1.bpl new file mode 100644 index 000000000..2e1140fd3 --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/big_program_1.bpl @@ -0,0 +1,424 @@ +procedure p() { + var x: int; + var y: int; + var i: int; + var z: int; + var a: int; + var b: int; + var c: int; + x := 0; + y := 0; + i := 0; + z := 0; + a := 0; + b := 0; + c := 0; + loop: + while (i <= 100){ + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto b1; + + b1: + y := y + 1; + goto b2; + + b2: + x := x + 1; + goto b3; + + b3: + z := z + 1; + goto b4; + + b4: + a := a + 1; + goto b5; + + b5: + b := b + 1; + goto b6; + + b6: + c := c + 1; + + + } + + + b7: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto b8; + + b8: + y := y + 1; + goto b9; + + b9: + x := x + 1; + goto b10; + + b10: + z := z + 1; + goto b11; + + b11: + a := a + 1; + goto b12; + + b12: + b := b + 1; + goto b13; + + b13: + c := c + 1; + + x := 0; + y := 0; + i := 0; + z := 0; + a := 0; + b := 0; + c := 0; + + loop2: + while (i <= 100){ + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto c1; + + c1: + y := y + 1; + goto c2; + + c2: + x := x + 1; + goto c3; + + c3: + z := z + 1; + goto c4; + + c4: + a := a + 1; + goto c5; + + c5: + b := b + 1; + goto c6; + + c6: + c := c + 1; + + + } + + + c7: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto c8; + + c8: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto c9; + + c9: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto c10; + + c10: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto c11; + + c11: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto c12; + + c12: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto c13; + + c13: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto d7; + + + d7: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto d8; + + d8: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto d9; + + d9: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto d10; + + d10: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto d11; + + d11: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto d12; + + d12: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto d13; + + d13: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto e7; + + e7: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto e8; + + e8: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto e9; + + e9: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto e10; + + e10: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto e11; + + e11: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto e12; + + e12: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto e13; + + e13: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto f7; + + + f7: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto f8; + + f8: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto f9; + + f9: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto f10; + + f10: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto f11; + + f11: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto f12; + + f12: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + goto f13; + + f13: + x := x + 1; + y := y + 1; + i := i + 1; + z := z + 1; + a := a + 1; + b := b + 1; + c := c + 1; + + + + + + + + + + + +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/big_program_2.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/big_program_2.bpl new file mode 100644 index 000000000..56885e12c --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/big_program_2.bpl @@ -0,0 +1,310 @@ +procedure p() { + var x: int; + var y: int; + var i: int; + var z: int; + var a: int; + var b: int; + var c: int; + x := 0; + z := 0; + + b1: + x := x + 1; + z := z + 1; + i := 0; + y := 0; + while (y<=1000){ + i := 0; + while ( i <= 10 ){ + x := x + 1; + z := z + 1; + y := y + i; + goto l1; + + l1: + x := x + 1; + z := z + 1; + i := i + 1; + } + } + i := i + 1; + if (y <= 1000){ + goto b1; + } + + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + + b2: + x := x + 1; + z := z + 1; + i := 0; + y := 0; + while (y<=1000){ + i := 0; + while ( i <= 10 ){ + x := x + 1; + z := z + 1; + y := y + i; + goto l2; + + l2: + x := x + 1; + z := z + 1; + i := i + 1; + } + } + i := i + 1; + if (y <= 1000){ + goto b2; + } + + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + + b3: + x := x + 1; + z := z + 1; + i := 0; + y := 0; + while (y<=1000){ + i := 0; + while ( i <= 10 ){ + x := x + 1; + z := z + 1; + y := y + i; + goto l3; + + l3: + x := x + 1; + z := z + 1; + i := i + 1; + } + } + i := i + 1; + if (y <= 1000){ + goto b3; + } + + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + + + + i := 0; + y := 0; + b4: + + while ( i <= 10 ){ + y := y + i; + goto b5; + + b5: + i := i + 1; + } + + i := i + 1; + if (y <= 1000){ + goto b4; + } + else{ + goto b6; + } + + b6: + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + i := i + 1; + goto b7; + + b7: + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + i := i + 1; + goto b8; + + b8: + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + i := i + 1; + goto b9; + + b9: + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + i := i + 1; + + b10: + x := x + 1; + z := z + 1; + i := 0; + y := 0; + while (y<=1000){ + i := 0; + while ( i <= 10 ){ + x := x + 1; + z := z + 1; + y := y + i; + goto b11; + + b11: + x := x + 1; + z := z + 1; + i := i + 1; + } + } + i := i + 1; + if (y <= 1000){ + goto b10; + } + + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + + b12: + x := x + 1; + z := z + 1; + i := 0; + y := 0; + while (y<=1000){ + i := 0; + while ( i <= 10 ){ + x := x + 1; + z := z + 1; + y := y + i; + goto b13; + + b13: + x := x + 1; + z := z + 1; + i := i + 1; + } + } + i := i + 1; + if (y <= 1000){ + goto b12; + } + + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + + b14: + x := x + 1; + z := z + 1; + i := 0; + y := 0; + while (y<=1000){ + i := 0; + while ( i <= 10 ){ + x := x + 1; + z := z + 1; + y := y + i; + goto b15; + + b15: + x := x + 1; + z := z + 1; + i := i + 1; + } + } + i := i + 1; + if (y <= 1000){ + goto b14; + } + + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + + + + i := 0; + y := 0; + b16: + + while ( i <= 10 ){ + y := y + i; + goto b17; + + b17: + i := i + 1; + } + + i := i + 1; + if (y <= 1000){ + goto b16; + } + else{ + goto b18; + } + + b18: + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + i := i + 1; + goto b19; + + b19: + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + i := i + 1; + goto b20; + + b20: + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + i := i + 1; + goto b21; + + b21: + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + x := x + 1; + z := z + 1; + i := i + 1; + + + + + + + + + + + +} \ No newline at end of file diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/coalesced_loop_head.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/coalesced_loop_head.bpl new file mode 100644 index 000000000..5c024ea10 --- /dev/null +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/coalesced_loop_head.bpl @@ -0,0 +1,36 @@ +procedure proecdure_1() { + var y: int; + var i: int; + + i := 0; + y := 0; + + goto l1, l2; + + l1: + i := i + 5; + goto l3; + + l3: + i := i + 1; + y := y + i; + goto l4; + + l4: + y := y + 1; + goto l1, l2; + + + l2: + if (i>y){ + y := i; + goto l5; + + l5: + y := i + 1; + } + assume false; + i := i + 1; + y := i + 1; + +} \ No newline at end of file From a86d7679d35320a12c62ec1e971e5d70c0934b1e Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Fri, 28 Jul 2023 08:39:47 +0200 Subject: [PATCH 074/123] Changed ListCoalescedBlocks datastructure --- Source/Core/Absy.cs | 2 +- Source/Core/DeadVarElim.cs | 35 +++++++++++-------- .../CFGOptimizationsLemmaManager.cs | 19 ++++++---- .../CFGOptimizationsManager.cs | 8 ++--- .../ProofGeneration/ProofGenerationLayer.cs | 9 +++-- 5 files changed, 45 insertions(+), 28 deletions(-) diff --git a/Source/Core/Absy.cs b/Source/Core/Absy.cs index d17cc1d7d..6aecce831 100644 --- a/Source/Core/Absy.cs +++ b/Source/Core/Absy.cs @@ -4124,7 +4124,7 @@ public List /*!*/ #region ProofGen public IDictionary CoalescedBlocksToTarget; - public IDictionary> ListCoalescedBlocks; + public IDictionary ListCoalescedBlocks; #endregion public sealed class ChecksumComparer : IEqualityComparer diff --git a/Source/Core/DeadVarElim.cs b/Source/Core/DeadVarElim.cs index 13b6f6991..b5cecf87f 100644 --- a/Source/Core/DeadVarElim.cs +++ b/Source/Core/DeadVarElim.cs @@ -486,7 +486,7 @@ public override Implementation VisitImplementation(Implementation impl) { IDictionary CoalescedBlocksToTarget = new Dictionary(); - IDictionary> ListCoalescedBlocks = new Dictionary>(); + IDictionary ListCoalescedBlocks = new Dictionary(); //Contract.Requires(impl != null); Contract.Ensures(Contract.Result() != null); @@ -537,9 +537,13 @@ public override Implementation VisitImplementation(Implementation impl) { List newList = new List(); newList.Add(b); - ListCoalescedBlocks.Add(b, newList); + BlockCoalescingInfo coalescedHead = new BlockCoalescingInfo(newList, 0); + ListCoalescedBlocks.Add(b, coalescedHead); } - ListCoalescedBlocks[b].Add(succ); + ListCoalescedBlocks[b].coalescedBlocks.Add(succ); + + BlockCoalescingInfo curr = new BlockCoalescingInfo(ListCoalescedBlocks[b].coalescedBlocks, ListCoalescedBlocks[b].coalescedBlocks.Count - 1); + ListCoalescedBlocks.Add(succ, curr); if (!CoalescedBlocksToTarget.ContainsKey(succ)) { @@ -601,17 +605,6 @@ public override Implementation VisitImplementation(Implementation impl) gotoCmd.labelNames.Add(succ.Label); } } - - var ListCoalescedBlocks_old = new Dictionary>(ListCoalescedBlocks); - foreach (var curr in ListCoalescedBlocks_old.Keys) - { - for (int i = 1; i < ListCoalescedBlocks[curr].Count; i++) - { - List temp = new List(ListCoalescedBlocks[curr]); - List subList = new List(temp.GetRange(i, temp.Count - i)); - ListCoalescedBlocks.Add(ListCoalescedBlocks[curr][i], subList); - } - } impl.CoalescedBlocksToTarget = CoalescedBlocksToTarget; impl.ListCoalescedBlocks = ListCoalescedBlocks; @@ -2352,4 +2345,18 @@ public override Block VisitBlock(Block node) return base.VisitBlock(node); } } + #region proofgen + public class BlockCoalescingInfo + { + + public List coalescedBlocks; + public int idx; + + public BlockCoalescingInfo(List coalescedBlocks, int idx) + { + this.coalescedBlocks = coalescedBlocks; + this.idx = idx; + } + } + #endregion } \ No newline at end of file diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index 65f76c468..1610d132f 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -293,7 +293,7 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma Block succ, Func HybridblockLemmaName, IList Loops, - IDictionary> ListCoalescedBlocks) + IDictionary ListCoalescedBlocks) { var proofMethods = new List { @@ -309,9 +309,11 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma { loopHeads.Add("(" + beforeOptProgAccess.BlockInfo().BlockIds[loop] + "," + afterOptProgAccess.BlockInfo().BlockIds[beforeToAfterBlock[loop]] + ")"); } + int i = ListCoalescedBlocks[beforeBlock].idx; + List coalescedBlocks = ListCoalescedBlocks[beforeBlock].coalescedBlocks; List listCoalescedBlocks = new List(); - foreach (Block current in ListCoalescedBlocks[beforeBlock]) + foreach (Block current in coalescedBlocks.GetRange(i, coalescedBlocks.Count - i)) { listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(current)); } @@ -334,7 +336,7 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma Func GlobalblockLemmaName, Func HybridblockLemmaName, IList Loops, - IDictionary> ListCoalescedBlocks) + IDictionary ListCoalescedBlocks) { var proofMethods = new List { @@ -342,8 +344,10 @@ public LemmaDecl HybridBlockLemma( //extend hybrid block lemma "apply (rule " + HybridblockLemmaName(beforeBlock) + ")" }; + int i = ListCoalescedBlocks[beforeBlock].idx; + List coalescedBlocks = ListCoalescedBlocks[beforeBlock].coalescedBlocks; List listCoalescedBlocks = new List(); - foreach (Block current in ListCoalescedBlocks[beforeBlock]) + foreach (Block current in coalescedBlocks.GetRange(i, coalescedBlocks.Count - i)) { listCoalescedBlocks.Add(beforeOptProgAccess.BlockInfo().CmdsQualifiedName(current)); } @@ -517,7 +521,7 @@ public LemmaDecl LoopHeadCoalesced( //Loop Head coalesced Func GlobalblockLemmaName, Func HybridblockLemmaName, IList Loops, - IDictionary> ListCoalescedBlocks) + IDictionary ListCoalescedBlocks) { var loopHeads = new List(); foreach (Block loop in Loops) @@ -535,7 +539,10 @@ public LemmaDecl LoopHeadCoalesced( //Loop Head coalesced "apply (rule " + afterOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(afterBlock) + ")", "apply (unfold " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) +"_def)" }; - foreach (Block current in ListCoalescedBlocks[beforeBlock]) + + int i = ListCoalescedBlocks[beforeBlock].idx; + List coalescedBlocks = ListCoalescedBlocks[beforeBlock].coalescedBlocks; + foreach (Block current in coalescedBlocks.GetRange(i, coalescedBlocks.Count - i)) { proofMethods.Add("apply (unfold " + beforeOptProgAccess.BlockInfo().CmdsQualifiedName(current) + "_def)"); } diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index ecae962a1..0a11116b5 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -26,7 +26,7 @@ public static Theory CfgOptProof( IDictionary beforeToAfter, // mapping from current block to target block IProgramAccessor beforeOptCfgProgAccess, //before CFG optimizations IProgramAccessor afterOptCfgProgAccess, //after CFG optimizationsList - IDictionary> ListCoalescedBlocks, + IDictionary ListCoalescedBlocks, IDictionary CoalescedBlocksToTarget, IDictionary> beforeDagBlockToLoops, Term vcAssm, @@ -124,9 +124,9 @@ public static Theory CfgOptProof( TopologicalOrder(topoOrder, beforeOptimizationsCopy); topoOrder.Reverse(); - foreach (var current in topoOrder) + foreach (var beforeBlock in topoOrder) { - Block beforeBlock = current; + if (loopHeadsSet.Contains(beforeBlock) && CoalescedBlocksToTarget.ContainsKey(beforeBlock)) //In this case we have a coalesced loop head { coalescedAfterBlock = CoalescedBlocksToTarget[beforeBlock]; @@ -164,7 +164,7 @@ public static Theory CfgOptProof( ListCoalescedBlocks); outerDecls.Add(convertGlobalBlock); } - else if (ListCoalescedBlocks[beforeBlock].Count == 1) //tail of coalesced blocks + else if (ListCoalescedBlocks[beforeBlock].coalescedBlocks.Count == ListCoalescedBlocks[beforeBlock].idx + 1) //tail of coalesced blocks { coalescedAfterBlock = CoalescedBlocksToTarget[beforeBlock]; diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 5d23f2659..d06b1ca95 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -1005,15 +1005,18 @@ out var endToEndLemmaPrelim IDictionary CoalescedBlocksToTarget = DictionaryComposition(afterPassificationImpl.CoalescedBlocksToTarget, origToAfterOpt); CoalescedBlocksToTarget = DictionaryComposition(beforeOptimizationsOrigBlock, CoalescedBlocksToTarget); - IDictionary> ListCoalescedBlocks = new Dictionary>(); + IDictionary ListCoalescedBlocks = new Dictionary(); foreach (var curr in afterPassificationImpl.ListCoalescedBlocks.Keys) { List temp = new List(); - foreach (var next in afterPassificationImpl.ListCoalescedBlocks[curr]) + foreach (var next in afterPassificationImpl.ListCoalescedBlocks[curr].coalescedBlocks) { temp.Add(beforeOptimizationsOrigBlock.InverseDict()[next]); } - ListCoalescedBlocks.Add(beforeOptimizationsOrigBlock.InverseDict()[curr], temp); + + BlockCoalescingInfo currInfo = + new BlockCoalescingInfo(temp, afterPassificationImpl.ListCoalescedBlocks[curr].idx); + ListCoalescedBlocks.Add(beforeOptimizationsOrigBlock.InverseDict()[curr], currInfo); } From f1222bc71faf06c6132b4e70bc1876203b0b89cc Mon Sep 17 00:00:00 2001 From: lukashimmelreich Date: Fri, 28 Jul 2023 08:41:03 +0200 Subject: [PATCH 075/123] Changed test --- .../cfg_optimizations_tests/loop_without_coalesced_body_3.bpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_3.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_3.bpl index df0b9d84b..c8eccd22c 100644 --- a/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_3.bpl +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/loop_without_coalesced_body_3.bpl @@ -19,5 +19,5 @@ procedure p() { y := y + i; } - assert y >= 0; + assert true; } \ No newline at end of file From d652f8f4bd9b1f970996c1923abc35b220a7578c Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 22 Aug 2023 11:28:42 +0200 Subject: [PATCH 076/123] add out parameters to in parameters --- Source/ProofGeneration/ProofGenerationLayer.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 962a7793d..67bdc45ee 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -250,8 +250,7 @@ private static BoogieMethodData MethodDataFromImpl( List overrideLocals = null ) { - //add out params to local variables for now - var locals = new List(overrideLocals ?? impl.LocVars).Union(impl.OutParams); + IEnumerable locals = (overrideLocals ?? impl.LocVars); if (extraLocalVariables != null) locals = locals.Union(extraLocalVariables); @@ -278,9 +277,10 @@ private static BoogieMethodData MethodDataFromImpl( return new BoogieMethodData( globalData, new List(impl.TypeParameters), - new List(impl.InParams), + new List(impl.InParams).Union(impl.OutParams), //add out parameters to in parameters for now locals, - null, + new List(), + //new List(impl.OutParams), new List(impl.Proc.Modifies), preconditions, postconditions); From f84cf82c0fc4d03d66ca905a7194899caf8959cc Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Sun, 22 Oct 2023 21:22:32 +0200 Subject: [PATCH 077/123] support unique constants in procedure correctness definition proof generation has not yet been adjusted to support unique constants --- .../BoogieIsaInterface/BoogieGlobalData.cs | 6 ++--- .../BoogieIsaInterface/BoogieMethodData.cs | 2 +- .../BoogieIsaInterface/IsaProgramGenerator.cs | 26 +++++++++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Source/ProofGeneration/BoogieIsaInterface/BoogieGlobalData.cs b/Source/ProofGeneration/BoogieIsaInterface/BoogieGlobalData.cs index 26cd9dffc..078634033 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/BoogieGlobalData.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/BoogieGlobalData.cs @@ -6,7 +6,7 @@ namespace ProofGeneration.BoogieIsaInterface public class BoogieGlobalData { public BoogieGlobalData(IEnumerable functions, IEnumerable axioms, - IEnumerable globalVars, IEnumerable constants) + IEnumerable globalVars, IEnumerable constants) { Functions = functions; Axioms = axioms; @@ -17,12 +17,12 @@ public BoogieGlobalData(IEnumerable functions, IEnumerable axio public IEnumerable Functions { get; } public IEnumerable Axioms { get; } public IEnumerable GlobalVars { get; } - public IEnumerable Constants { get; } + public IEnumerable Constants { get; } public static BoogieGlobalData CreateEmpty() { return new BoogieGlobalData(new List(), new List(), new List(), - new List()); + new List()); } } } \ No newline at end of file diff --git a/Source/ProofGeneration/BoogieIsaInterface/BoogieMethodData.cs b/Source/ProofGeneration/BoogieIsaInterface/BoogieMethodData.cs index c628b8dc2..1ce4d5f32 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/BoogieMethodData.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/BoogieMethodData.cs @@ -32,7 +32,7 @@ public BoogieMethodData( public IEnumerable Functions => globalData.Functions; public IEnumerable Axioms => globalData.Axioms; public IEnumerable GlobalVars => globalData.GlobalVars; - public IEnumerable Constants => globalData.Constants; + public IEnumerable Constants => globalData.Constants; public IEnumerable TypeParams { get; } public IEnumerable InParams { get; } diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs index 0b307faeb..694e0fbad 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs @@ -194,6 +194,7 @@ public IProgramAccessor GetIsaProgram( { decls.Add(GetVariableDeclarationsIsa("globals", methodData.GlobalVars)); decls.Add(GetVariableDeclarationsIsa("constants", methodData.Constants)); + decls.Add(GetUniqueConstants("unique_consts", methodData.Constants)); } if (generateMembershipLemmas) @@ -414,6 +415,31 @@ private DefDecl GetVariableDeclarationsIsa(string varKind, IEnumerable equation); } + private DefDecl GetUniqueConstants(String defName, IEnumerable constants) + { + var uniqueConstNames = new List(); + + foreach (var c in constants) + { + if (!c.Unique) + { + continue; + } + + if (varTranslation.VarTranslation.TryTranslateVariableId(c, out var resId, out _)) + { + uniqueConstNames.Add(resId); + } + else + { + throw new ProofGenUnexpectedStateException(GetType(), "Cannot translate constant " + c.Name); + } + } + + var equation = new Tuple, Term>(new List(), new TermList(uniqueConstNames)); + return new DefDecl(defName, IsaCommonTypes.GetListType(IsaBoogieType.VnameType()), equation); + } + private string VariableDeclarationsName(string varKind) { return varKind + "_vdecls"; From bb8b56b6657d6d7b28023b42ab561b3f271a77d9 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 31 Oct 2023 17:14:51 +0100 Subject: [PATCH 078/123] suppport int to real arithmetic conversion in programs (proof generation itself is not yet supported) --- .../ApplicableIsaVisitor.cs | 14 +++++- .../BoogieIsaInterface/IsaBoogieTerm.cs | 48 ++++++++++++------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/Source/ProofGeneration/BoogieIsaInterface/ApplicableIsaVisitor.cs b/Source/ProofGeneration/BoogieIsaInterface/ApplicableIsaVisitor.cs index 621881f3b..72578dbaa 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/ApplicableIsaVisitor.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/ApplicableIsaVisitor.cs @@ -68,10 +68,22 @@ public Term Visit(MapStore mapStore) { throw new NotImplementedException(); } - + public Term Visit(ArithmeticCoercion arithCoercion) { + if (_args.Count != 1) + { + throw new ExprArgException(); + } + + if(arithCoercion.Coercion == ArithmeticCoercion.CoercionType.ToReal) + { + return IsaBoogieTerm.IntToReal(_args[0]); + } + else + { throw new NotImplementedException(); + } } public Term Visit(IfThenElse ifThenElse) diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs index e7b09c7a2..f16ef138c 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs @@ -23,6 +23,8 @@ public static class IsaBoogieTerm private static readonly TermIdent boolLitId = IsaCommonTerms.TermIdentFromName("LBool"); private static readonly TermIdent realLitId = IsaCommonTerms.TermIdentFromName("LReal"); + private static readonly TermIdent intToRealId = IsaCommonTerms.TermIdentFromName("IntToReal"); + private static readonly TermIdent varId = IsaCommonTerms.TermIdentFromName("Var"); private static readonly TermIdent bvarId = IsaCommonTerms.TermIdentFromName("BVar"); private static readonly TermIdent oldVarId = IsaCommonTerms.TermIdentFromName("Old"); @@ -115,12 +117,12 @@ public static Term BVar(int i) Term natConst = new NatConst(i); return new TermApp(bvarId, natConst); } - + public static Term Old(Term body) { return new TermApp(oldVarId, body); } - + public static Term CondExp(Term cond, Term thn, Term els) { return new TermApp(condExpId, cond, thn, els); @@ -329,27 +331,37 @@ public static Term Binop(BinaryOperator.Opcode opcode, Term arg1, Term arg2) var list = new List {arg1, IsaCommonTerms.TermIdentFromName(bopIsa), arg2}; return new TermApp(IsaCommonTerms.TermIdentFromName("BinOp"), list); } + + private static Term Unop(Term unop, Term arg) + { + var list = new List {unop, arg}; + return new TermApp(IsaCommonTerms.TermIdentFromName("UnOp"), list); + } public static Term Unop(UnaryOperator.Opcode opcode, Term arg) { - string uopIsa; - - switch (opcode) - { - case UnaryOperator.Opcode.Not: - uopIsa = "Not"; - break; - case UnaryOperator.Opcode.Neg: - uopIsa = "UMinus"; - break; - default: - throw new NotImplementedException(); - } + string uopIsa; - var list = new List {IsaCommonTerms.TermIdentFromName(uopIsa), arg}; - return new TermApp(IsaCommonTerms.TermIdentFromName("UnOp"), list); + switch (opcode) + { + case UnaryOperator.Opcode.Not: + uopIsa = "Not"; + break; + case UnaryOperator.Opcode.Neg: + uopIsa = "UMinus"; + break; + default: + throw new NotImplementedException(); + } + + return Unop(IsaCommonTerms.TermIdentFromName(uopIsa), arg); } - + + public static Term IntToReal(Term intTerm) + { + return Unop(intToRealId, intTerm); + } + //value quantification /* From 7fe5a386dbbc42b850b6a60715facd95ef597783 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 31 Oct 2023 17:15:04 +0100 Subject: [PATCH 079/123] more efficient disjointness check --- .../BoogieIsaInterface/MembershipLemmaManager.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs index 1f4c769b3..651ed2c28 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs @@ -634,8 +634,8 @@ private void AddDisjointnessLemmas(int globalsMax, int localsMin) else proofMethods = new List { - "using " + LocalsAtLeastMin() + " " + GlobalsAtMostMax(), - "by fastforce" + "using " + ProofUtil.OF("max_min_disjoint_2", GlobalsAtMostMax(), LocalsAtLeastMin()), + "by linarith" }; helperLemmas.Add( new LemmaDecl(globalsLocalsDisjName, statement, new Proof(proofMethods)) From ad46066e9fa679a15c55f721d0a4a508f53193b2 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 31 Oct 2023 17:16:10 +0100 Subject: [PATCH 080/123] adjust foundational_boogie submodule --- foundational_boogie | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundational_boogie b/foundational_boogie index 5cfb4563b..26871a864 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit 5cfb4563b73e0b9706740431108367df80dda328 +Subproject commit 26871a8645e4e21690620753a0a787e026993bbd From 2155df6b75fd2372141e4bf6c2edbbbc74c17459 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Fri, 1 Dec 2023 15:41:36 +0100 Subject: [PATCH 081/123] Create membership lemma configuration for more fine-grained membership lemma options Do not emit axiom membership lemmas when no Boogie phase proofs are generated, since they are not required in such a case. --- Source/Core/CommandLineOptions.cs | 7 ----- .../BoogieIsaInterface/IsaProgramGenerator.cs | 16 +++++++---- .../IsaProgramGeneratorForAst.cs | 16 +++++++---- .../ProofGeneration/MembershipLemmaConfig.cs | 28 +++++++++++++++++++ .../ProofGeneration/ProofGenerationLayer.cs | 25 +++++++++++++---- 5 files changed, 69 insertions(+), 23 deletions(-) create mode 100644 Source/ProofGeneration/MembershipLemmaConfig.cs diff --git a/Source/Core/CommandLineOptions.cs b/Source/Core/CommandLineOptions.cs index d07ad8dcb..d4d5c435e 100644 --- a/Source/Core/CommandLineOptions.cs +++ b/Source/Core/CommandLineOptions.cs @@ -1061,13 +1061,6 @@ public bool OnlyGenerateInitialProgramIsa() { return GenerateIsaProgNoProofs != 0; } - - public bool GenerateMembershipLemmas() - { - return GenerateIsaProgNoProofs <= 1; - } - - public bool DesugarMaps = false; #endregion diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs index 694e0fbad..5f437328f 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs @@ -65,7 +65,7 @@ public IProgramAccessor GetIsaProgram( CFGRepr cfg, IsaUniqueNamer uniqueNamer, out IList decls, - bool generateMembershipLemmas, + MembershipLemmaConfig membershipLemmaConfig, bool onlyGlobalData = false ) { @@ -171,7 +171,7 @@ public IProgramAccessor GetIsaProgram( /* 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) + if (membershipLemmaConfig.GenerateVariableMembershipLemmas) { membershipLemmaManager.AddVariableMembershipLemmas(methodData.InParams, VarKind.ParamOrLocal); membershipLemmaManager.AddVariableMembershipLemmas(methodData.Locals, VarKind.ParamOrLocal); @@ -181,13 +181,19 @@ public IProgramAccessor GetIsaProgram( if (config.generateAxioms) { decls.Add(GetAxioms(methodData.Axioms)); - if(generateMembershipLemmas) membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms); + if (membershipLemmaConfig.GenerateAxiomMembershipLemmas) + { + membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms); + } } if (config.generateFunctions) { decls.Add(GetFunctionDeclarationsIsa(methodData.Functions, uniqueNamer)); - if(generateMembershipLemmas) membershipLemmaManager.AddFunctionMembershipLemmas(methodData.Functions, uniqueNamer); + if (membershipLemmaConfig.GenerateFunctionMembershipLemmas) + { + membershipLemmaManager.AddFunctionMembershipLemmas(methodData.Functions, uniqueNamer); + } } if (config.generateGlobalsAndConstants) @@ -197,7 +203,7 @@ public IProgramAccessor GetIsaProgram( decls.Add(GetUniqueConstants("unique_consts", methodData.Constants)); } - if (generateMembershipLemmas) + if (membershipLemmaConfig.GenerateVariableMembershipLemmas) { membershipLemmaManager.AddVariableMembershipLemmas(methodData.GlobalVars, VarKind.Global); membershipLemmaManager.AddVariableMembershipLemmas(methodData.Constants, VarKind.Constant); diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs index 95b53d8cb..4d7722b06 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs @@ -35,7 +35,7 @@ public IProgramAccessor GetIsaProgram( AstToCfgProofGenInfo proofGenInfo, IsaUniqueNamer uniqueNamer, out IList decls, - bool generateMembershipLemmas, + MembershipLemmaConfig membershipLemmaConfig, bool onlyGlobalData = false ) { @@ -133,7 +133,7 @@ public IProgramAccessor GetIsaProgram( /* 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) + if (membershipLemmaConfig.GenerateVariableMembershipLemmas) { membershipLemmaManager.AddVariableMembershipLemmas(methodData.InParams, VarKind.ParamOrLocal); membershipLemmaManager.AddVariableMembershipLemmas(methodData.Locals, VarKind.ParamOrLocal); @@ -143,13 +143,19 @@ public IProgramAccessor GetIsaProgram( if (config.generateAxioms) { decls.Add(GetAxioms(methodData.Axioms)); - if(generateMembershipLemmas) membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms); + if (membershipLemmaConfig.GenerateAxiomMembershipLemmas) + { + membershipLemmaManager.AddAxiomMembershipLemmas(methodData.Axioms); + } } if (config.generateFunctions) { decls.Add(GetFunctionDeclarationsIsa(methodData.Functions, uniqueNamer)); - if(generateMembershipLemmas) membershipLemmaManager.AddFunctionMembershipLemmas(methodData.Functions, uniqueNamer); + if (membershipLemmaConfig.GenerateFunctionMembershipLemmas) + { + membershipLemmaManager.AddFunctionMembershipLemmas(methodData.Functions, uniqueNamer); + } } if (config.generateGlobalsAndConstants) @@ -158,7 +164,7 @@ public IProgramAccessor GetIsaProgram( decls.Add(GetVariableDeclarationsIsa("constants", methodData.Constants)); } - if (generateMembershipLemmas) + if (membershipLemmaConfig.GenerateVariableMembershipLemmas) { membershipLemmaManager.AddVariableMembershipLemmas(methodData.GlobalVars, VarKind.Global); membershipLemmaManager.AddVariableMembershipLemmas(methodData.Constants, VarKind.Constant); diff --git a/Source/ProofGeneration/MembershipLemmaConfig.cs b/Source/ProofGeneration/MembershipLemmaConfig.cs new file mode 100644 index 000000000..b59a878bc --- /dev/null +++ b/Source/ProofGeneration/MembershipLemmaConfig.cs @@ -0,0 +1,28 @@ +namespace ProofGeneration; + +public class MembershipLemmaConfig +{ + + public bool GenerateAxiomMembershipLemmas + { + get; + } + + public bool GenerateFunctionMembershipLemmas + { + get; + } + + public bool GenerateVariableMembershipLemmas + { + get; + } + + public MembershipLemmaConfig(bool generateAxiomMembershipLemmas, bool generateFunctionMembershipLemmas, bool generateVariableMembershipLemmas) + { + GenerateAxiomMembershipLemmas = generateAxiomMembershipLemmas; + GenerateFunctionMembershipLemmas = generateFunctionMembershipLemmas; + GenerateVariableMembershipLemmas = generateVariableMembershipLemmas; + } + +} \ No newline at end of file diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 67bdc45ee..4748fe0f8 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -85,6 +85,17 @@ public class ProofGenerationLayer private static IsaUniqueNamer uniqueNamer; private static IDictionary procNameToTopLevelPrograms = new Dictionary(); + + private static MembershipLemmaConfig MembershipLemmaConfig() + { + switch (CommandLineOptions.Clo.GenerateIsaProgNoProofs) + { + case 0: return new MembershipLemmaConfig(true, true, true); + // axiom membership lemmas are required only if proofs are generated for the Boogie program + case 1: return new MembershipLemmaConfig(false, true, true); + default: return new MembershipLemmaConfig(false, false, false); + } + } /// /// Provide program for the next procedure (for the global declarations). @@ -120,7 +131,7 @@ public static void Program(Program p) null, uniqueNamer, out var declsGlobalData, - CommandLineOptions.Clo.GenerateMembershipLemmas(), + MembershipLemmaConfig(), true ); @@ -647,6 +658,8 @@ from calls. ? SpecsConfig.All : SpecsConfig.AllPreCheckedPost; + var membershipLemmaConfig = MembershipLemmaConfig(); + if (_proofGenConfig.GenerateBeforeAstCfgProg || CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) { #region before ast to cfg program @@ -673,7 +686,7 @@ from calls. proofGenInfo, uniqueNamer, out var programDeclsBeforeAstToCfg, - CommandLineOptions.Clo.GenerateMembershipLemmas()); + membershipLemmaConfig); procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "ast", beforeAstToCfgProgAccess); var beforeAstToCfgProgTheory = new Theory(beforeAstToCfgTheoryName, @@ -718,7 +731,7 @@ from calls. beforeOptimizationsCFG, uniqueNamer, out var programDeclsUnoptimizedCfg, - CommandLineOptions.Clo.GenerateMembershipLemmas()); + membershipLemmaConfig); procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "unoptimized", unoptimizedCfgProgAccess); @@ -767,7 +780,7 @@ afterOptimizationsData may not be correctly initialized beforeDagCfg, uniqueNamer, out var programDeclsBeforeCfgToDag, - CommandLineOptions.Clo.GenerateMembershipLemmas()); + membershipLemmaConfig); procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name, beforeCfgToDagProgAccess); var beforeCfgToDagProgTheory = new Theory(beforeCfgToDagTheoryName, @@ -801,7 +814,7 @@ afterOptimizationsData may not be correctly initialized beforePassificationCfg, uniqueNamer, out var programDeclsBeforePassive, - CommandLineOptions.Clo.GenerateMembershipLemmas()); + membershipLemmaConfig); var beforePassificationProgTheory = new Theory(beforePassiveProgTheoryName, new List {"Boogie_Lang.Semantics", "Boogie_Lang.Util", @@ -842,7 +855,7 @@ afterOptimizationsData may not be correctly initialized afterPassificationCfg, uniqueNamer, out var programDecls, - CommandLineOptions.Clo.GenerateMembershipLemmas()); + membershipLemmaConfig); var afterPassificationProgTheory = new Theory(finalProgTheoryName, From 22e39af68850f26c1949131f79d4c43aa64a935f Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Sat, 10 Feb 2024 20:45:06 +0100 Subject: [PATCH 082/123] update foundational_boogie submodule to commit that merged adjust_interface changes --- foundational_boogie | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundational_boogie b/foundational_boogie index 6254cd790..a12fd2c4a 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit 6254cd7904468f3d7fece22c16ea6414f2924c1e +Subproject commit a12fd2c4ad4324b55db1dddf6cea5be80c5e8263 From c2442de33414e905dbd674f690f3a518ffc40130 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Sat, 10 Feb 2024 21:03:07 +0100 Subject: [PATCH 083/123] remove duplicate method --- Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs index fc805654b..9c063dd22 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs @@ -122,11 +122,6 @@ public static Term Old(Term body) { return new TermApp(oldVarId, body); } - - public static Term CondExp(Term cond, Term thn, Term els) - { - return new TermApp(condExpId, cond, thn, els); - } public static Term CondExp(Term cond, Term thn, Term els) { From ea0ad07a701b449a442035aac3fd6a0c8bc86e46 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Sat, 10 Feb 2024 21:44:43 +0100 Subject: [PATCH 084/123] start incorporating unique constants into proof works for programs that don't have unique constants (use adjusted procedure correctness definition) --- .../AstToCfg/AstToCfgEndToEnd.cs | 4 ++- .../BoogieIsaInterface/IProgramAccessor.cs | 1 + .../BoogieIsaInterface/IsaBoogieTerm.cs | 23 +++++++++++++++++ .../BoogieIsaInterface/IsaProgramGenerator.cs | 13 +++++++--- .../IsaProgramGeneratorForAst.cs | 3 ++- .../BoogieIsaInterface/IsaProgramRepr.cs | 5 +++- .../MembershipLemmaManager.cs | 10 ++++++++ .../CFGOptimizationsEndToEnd.cs | 25 +++---------------- .../CfgToDag/CfgToDagEndToEnd.cs | 23 ++--------------- 9 files changed, 57 insertions(+), 50 deletions(-) diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs b/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs index 33eb85c90..070f94436 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs @@ -228,6 +228,7 @@ public IEnumerable EndToEndProof( ProcedureIsCorrect( beforeCfgProgramAccessor.FunctionsDecl(), IsaCommonTerms.TermIdentFromName(beforeCfgProgramAccessor.ConstsDecl()), + IsaCommonTerms.TermIdentFromName(beforeCfgProgramAccessor.UniqueConstsDecl()), IsaCommonTerms.TermIdentFromName(beforeCfgProgramAccessor.GlobalsDecl()), beforeCfgProgramAccessor.AxiomsDecl(), beforeCfgProgramAccessor.ProcDecl()), @@ -300,7 +301,7 @@ AstToCfgProofGenInfo proofGenInfo ); } - private static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term globalDecls, Term axioms, + private static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term uniqueConstantDecls, Term globalDecls, Term axioms, Term procedure) { var typeInterpId = new SimpleIdentifier("A"); @@ -313,6 +314,7 @@ private static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term g new TermWithExplicitType(new TermIdent(typeInterpId), IsaBoogieType.AbstractValueTyFunType(new VarType("a"))), funDecls, constantDecls, + uniqueConstantDecls, globalDecls, axioms, procedure, diff --git a/Source/ProofGeneration/BoogieIsaInterface/IProgramAccessor.cs b/Source/ProofGeneration/BoogieIsaInterface/IProgramAccessor.cs index 1a363607c..c6935d3cf 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IProgramAccessor.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IProgramAccessor.cs @@ -11,6 +11,7 @@ public interface IGlobalProgramAccessor public Term AxiomsDecl(); public Term ConstsAndGlobalsDecl(); public string ConstsDecl(); + public string UniqueConstsDecl(); public string GlobalsDecl(); /// diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs index 9c063dd22..e1968d6ad 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaBoogieTerm.cs @@ -850,5 +850,28 @@ public static Term InstantiateType(Term rtypeEnv, Term ty) { return new TermApp(instTypeId, rtypeEnv, ty); } + + public static Term ProcedureIsCorrectCfg(Term funDecls, Term constantDecls, Term uniqueConstants, Term globalDecls, Term axioms, + Term procedure) + { + var typeInterpId = new SimpleIdentifier("A"); + return + TermQuantifier.MetaAll( + new List {typeInterpId}, + null, + new TermApp( + IsaCommonTerms.TermIdentFromName("Semantics.proc_is_correct"), + //TODO: here assuming that we use "'a" for the abstract value type carrier t --> make t a parameter somewhere + new TermWithExplicitType(new TermIdent(typeInterpId), + IsaBoogieType.AbstractValueTyFunType(new VarType("a"))), + funDecls, + constantDecls, + uniqueConstants, + globalDecls, + axioms, + procedure, + IsaBoogieTerm.SematicsProcSpecSatisfied)); + } + } } \ No newline at end of file diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs index 5f437328f..4792f884a 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs @@ -92,8 +92,9 @@ public IProgramAccessor GetIsaProgram( var isaGlobalProgramRepr = new IsaGlobalProgramRepr( FunctionDeclarationsName(), AxiomDeclarationsName(), - VariableDeclarationsName("globals"), - VariableDeclarationsName("constants") + VariableDeclarationsName(globalsName), + VariableDeclarationsName(constantsName), + uniqueConstantsName ); var globalsMax = methodData.Constants.Count() + methodData.GlobalVars.Count() - 1; // assume single versioning and order on constants, globals, params, locals @@ -199,8 +200,8 @@ public IProgramAccessor GetIsaProgram( if (config.generateGlobalsAndConstants) { decls.Add(GetVariableDeclarationsIsa("globals", methodData.GlobalVars)); - decls.Add(GetVariableDeclarationsIsa("constants", methodData.Constants)); - decls.Add(GetUniqueConstants("unique_consts", methodData.Constants)); + decls.Add(GetVariableDeclarationsIsa(constantsName, methodData.Constants)); + decls.Add(GetUniqueConstants(uniqueConstantsName, methodData.Constants)); } if (membershipLemmaConfig.GenerateVariableMembershipLemmas) @@ -398,6 +399,10 @@ private string PostconditionDeclarationName() return "post"; } + private string globalsName = "globals"; + private string constantsName = "constants"; + private string uniqueConstantsName = "unique_consts"; + private DefDecl GetVariableDeclarationsIsa(string varKind, IEnumerable variables) { var typeIsaVisitor = new TypeIsaVisitor(varTranslation.TypeVarTranslation); diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs index 4d7722b06..fd103fcc0 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGeneratorForAst.cs @@ -48,7 +48,8 @@ public IProgramAccessor GetIsaProgram( FunctionDeclarationsName(), AxiomDeclarationsName(), VariableDeclarationsName("globals"), - VariableDeclarationsName("constants") + VariableDeclarationsName("constants"), + "unique_consts" ); var globalsMax = methodData.Constants.Count() + methodData.GlobalVars.Count() - 1; // assume single versioning and order on constants, globals, params, locals diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramRepr.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramRepr.cs index 36a88721d..e1781da79 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramRepr.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramRepr.cs @@ -4,6 +4,7 @@ public class IsaGlobalProgramRepr { public readonly string axiomsDeclDef; public readonly string constantsDeclDef; + public readonly string uniqueConstantsDeclDef; public readonly string funcsDeclDef; public readonly string globalsDeclDef; @@ -11,12 +12,14 @@ public IsaGlobalProgramRepr( string funcsDeclDef, string axiomsDeclDef, string globalsDeclDef, - string constantsDeclDef) + string constantsDeclDef, + string uniqueConstsDeclDef) { this.funcsDeclDef = funcsDeclDef; this.axiomsDeclDef = axiomsDeclDef; this.globalsDeclDef = globalsDeclDef; this.constantsDeclDef = constantsDeclDef; + this.uniqueConstantsDeclDef = uniqueConstsDeclDef; } } diff --git a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs index 651ed2c28..e22a68263 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/MembershipLemmaManager.cs @@ -28,6 +28,7 @@ public class MembershipLemmaManager : IProgramAccessor new Dictionary(); private readonly string consts; + private readonly string uniqueConsts; private readonly string[] constsAndGlobalsDefs; private readonly Term constsAndGlobalsList; private readonly string constsWfName = "consts_wf"; @@ -98,6 +99,7 @@ public MembershipLemmaManager ( config = new IsaProgramGeneratorConfig(null, true, true, true, false, SpecsConfig.None, false); consts = QualifyAccessName(isaProgramRepr.GlobalProgramRepr.constantsDeclDef); + uniqueConsts = QualifyAccessName(isaProgramRepr.GlobalProgramRepr.uniqueConstantsDeclDef); globals = QualifyAccessName(isaProgramRepr.GlobalProgramRepr.globalsDeclDef); constsAndGlobalsDefs = @@ -145,6 +147,9 @@ string theoryName consts = config.generateGlobalsAndConstants ? QualifyAccessName(isaProgramRepr.GlobalProgramRepr.constantsDeclDef) : parent.ConstsDecl(); + uniqueConsts = config.generateGlobalsAndConstants + ? QualifyAccessName(isaProgramRepr.GlobalProgramRepr.uniqueConstantsDeclDef) + : parent.UniqueConstsDecl(); globals = config.generateGlobalsAndConstants ? QualifyAccessName(isaProgramRepr.GlobalProgramRepr.globalsDeclDef) : parent.GlobalsDecl(); @@ -256,6 +261,11 @@ public string ConstsDecl() return consts; } + public string UniqueConstsDecl() + { + return uniqueConsts; + } + public string GlobalsDecl() { return globals; diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs index f0ac4cb02..58465c3fd 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs @@ -107,12 +107,13 @@ public IEnumerable EndToEndProof( new LemmaDecl( "end_to_end_theorem", ContextElem.CreateWithAssumptions(new List {vcAssm}, new List {"VC"}), - ProcedureIsCorrect( + IsaBoogieTerm.ProcedureIsCorrectCfg( programAccessor.FunctionsDecl(), IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), + IsaCommonTerms.TermIdentFromName(programAccessor.UniqueConstsDecl()), IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()), programAccessor.AxiomsDecl(), - defProcWithoutDeadVar.Name), + IsaCommonTerms.TermIdentFromName(defProcWithoutDeadVar.Name)), new Proof( new List { @@ -202,24 +203,4 @@ public static Term CfgOptLemmaConclusion(BoogieContextIsa boogieContext, Term po finalState); } - public static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term globalDecls, Term axioms, - string name) - { - var typeInterpId = new SimpleIdentifier("A"); - return - TermQuantifier.MetaAll( - new List {typeInterpId}, - null, - new TermApp( - IsaCommonTerms.TermIdentFromName("Semantics.proc_is_correct"), - //TODO: here assuming that we use "'a" for the abstract value type carrier t --> make t a parameter somewhere - new TermWithExplicitType(new TermIdent(typeInterpId), - IsaBoogieType.AbstractValueTyFunType(new VarType("a"))), - funDecls, - constantDecls, - globalDecls, - axioms, - IsaCommonTerms.TermIdentFromName(name), - IsaBoogieTerm.SematicsProcSpecSatisfied)); - } } \ No newline at end of file diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs index 15f218e93..d799045fb 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagEndToEnd.cs @@ -125,9 +125,10 @@ public IEnumerable EndToEndProof( new LemmaDecl( "end_to_end_theorem", ContextElem.CreateWithAssumptions(new List { vcAssm }, new List { "VC" }), - ProcedureIsCorrect( + IsaBoogieTerm.ProcedureIsCorrectCfg( programAccessor.FunctionsDecl(), IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), + IsaCommonTerms.TermIdentFromName(programAccessor.UniqueConstsDecl()), IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()), programAccessor.AxiomsDecl(), programAccessor.ProcDecl()), @@ -208,25 +209,5 @@ Term vcAssm ); } - public static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term globalDecls, Term axioms, - Term procedure) - { - var typeInterpId = new SimpleIdentifier("A"); - return - TermQuantifier.MetaAll( - new List {typeInterpId}, - null, - new TermApp( - IsaCommonTerms.TermIdentFromName("Semantics.proc_is_correct"), - //TODO: here assuming that we use "'a" for the abstract value type carrier t --> make t a parameter somewhere - new TermWithExplicitType(new TermIdent(typeInterpId), - IsaBoogieType.AbstractValueTyFunType(new VarType("a"))), - funDecls, - constantDecls, - globalDecls, - axioms, - procedure, - IsaBoogieTerm.SematicsProcSpecSatisfied)); - } } } \ No newline at end of file From 7af2dba72e2860afeda5ca75f2e4e636168af83c Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 15 Apr 2024 19:40:03 +0200 Subject: [PATCH 085/123] fix typos --- .../cfg_optimizations_tests/block_coalescing_2.bpl | 2 +- .../cfg_optimizations_tests/block_coalescing_3.bpl | 2 +- .../cfg_optimizations_tests/coalesced_loop_head.bpl | 2 +- .../cfg_optimizations_tests/no_optimization.bpl | 2 +- ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_3.bpl | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_2.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_2.bpl index 36f472ffb..321bf38e6 100644 --- a/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_2.bpl +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_2.bpl @@ -1,4 +1,4 @@ -procedure proecdure_1() { +procedure procedure_1() { var y: int; y := 1; diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_3.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_3.bpl index cc1f69101..ae7a142c2 100644 --- a/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_3.bpl +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/block_coalescing_3.bpl @@ -1,4 +1,4 @@ -procedure proecdure_1() { +procedure procedure_1() { var y: int; var i: int; diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/coalesced_loop_head.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/coalesced_loop_head.bpl index 5c024ea10..4f10149c6 100644 --- a/ProofGenerationBenchmarks/cfg_optimizations_tests/coalesced_loop_head.bpl +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/coalesced_loop_head.bpl @@ -1,4 +1,4 @@ -procedure proecdure_1() { +procedure procedure_1() { var y: int; var i: int; diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/no_optimization.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/no_optimization.bpl index 0ea446578..2e024b268 100644 --- a/ProofGenerationBenchmarks/cfg_optimizations_tests/no_optimization.bpl +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/no_optimization.bpl @@ -1,4 +1,4 @@ -procedure proecdure_1() { +procedure procedure_1() { var i: int; i := 0; diff --git a/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_3.bpl b/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_3.bpl index 27fed560a..ef7795ebd 100644 --- a/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_3.bpl +++ b/ProofGenerationBenchmarks/cfg_optimizations_tests/pruning_3.bpl @@ -1,4 +1,4 @@ -procedure proecdure_1() { +procedure procedure_1() { var y: int; var i: int; From 5556d1633bd91cfb7f6e00519677866e5c8bf595 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 16 Apr 2024 10:03:35 +0200 Subject: [PATCH 086/123] removed redundant code --- Source/ProofGeneration/ProofGenerationLayer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index e4eacefaa..0e923f71e 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -583,8 +583,6 @@ public static void VCGenerateAllProofs( } IList unoptimizedCfgBlocks = proofGenInfo.GetUnoptimizedBlocks(); - var newToOldInternal = new Dictionary(); - unoptimizedCfgBlocks.ZipDo(afterPassificationImpl.Blocks, (bNew, bOld) => newToOldInternal.Add(bNew, bOld)); IDictionary mappingOrigBlockToUnoptimizedCopy = proofGenInfo.GetMappingOrigBlockToUnoptimizedCopy(); IDictionary mappingUnoptimizedCopyToOrigBlock = From e3af2d2ecc4c48051defd51125a2c48220a4b7a6 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 16 Apr 2024 10:12:58 +0200 Subject: [PATCH 087/123] clean up --- Source/ProofGeneration/ProofGenerationLayer.cs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 0e923f71e..035b8bb7a 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -924,11 +924,6 @@ out var endToEndLemmaPrelim #endregion } - - /* - Console.WriteLine("Passive prog mapping: " + fixedVarTranslation.OutputMapping()); - Console.WriteLine("Before passive prog mapping: " + fixedVarTranslation2.OutputMapping()); - */ if (_proofGenConfig.GeneratePassifProof) { @@ -1000,8 +995,6 @@ out var endToEndLemmaPrelim beforeDagBlocktoLoops = getBeforeDagBlockToLoops(beforeDagAfterDagBlock, beforePassificationCfg, cfgToDagHintManager, out selfLoops); } - - IDictionary CoalescedBlocksToTarget = DictionaryComposition(afterPassificationImpl.CoalescedBlocksToTarget, origToAfterOpt); CoalescedBlocksToTarget = DictionaryComposition(beforeOptimizationsOrigBlock, CoalescedBlocksToTarget); From c53dc16315c21ee39e183e4832ebccc5759f2d76 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 16 Apr 2024 10:15:09 +0200 Subject: [PATCH 088/123] remove redundant parameter --- Source/ProofGeneration/Passification/PassificationManager.cs | 1 - Source/ProofGeneration/ProofGenerationLayer.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/Source/ProofGeneration/Passification/PassificationManager.cs b/Source/ProofGeneration/Passification/PassificationManager.cs index 006d36dae..2c782bd08 100644 --- a/Source/ProofGeneration/Passification/PassificationManager.cs +++ b/Source/ProofGeneration/Passification/PassificationManager.cs @@ -36,7 +36,6 @@ public static Theory PassificationProof( PassiveRelationGen relationGen, IProgramAccessor beforePassiveProgAccess, IProgramAccessor passiveProgAccess, - BoogieMethodData beforePassiveData, IVariableTranslationFactory beforePassiveFactory, IVariableTranslationFactory passiveFactory) { diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 035b8bb7a..5a131f37e 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -940,7 +940,6 @@ out var endToEndLemmaPrelim passiveRelationGen, beforePassiveProgAccess, passiveProgAccess, - afterOptimizationsData, afterOptimizationsVarTranslationFactory, varTranslationFactory ); From d3326b53d0646384bab114404976ddf2dab7d47b Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 17 Apr 2024 21:31:39 +0200 Subject: [PATCH 089/123] if dead variable elimination has an effect, then use two representations for unoptimized CFG --- .../BoogieIsaInterface/IsaProgramGenerator.cs | 13 +- .../CFGOptimizationsEndToEnd.cs | 25 ++-- .../ProofGeneration/ProofGenerationLayer.cs | 138 ++++++++++++------ 3 files changed, 119 insertions(+), 57 deletions(-) diff --git a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs index 0b307faeb..b708b7dcc 100644 --- a/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs +++ b/Source/ProofGeneration/BoogieIsaInterface/IsaProgramGenerator.cs @@ -203,8 +203,11 @@ public IProgramAccessor GetIsaProgram( decls.AddRange(membershipLemmaManager.OuterDecls()); } - if (config.specsConfig != SpecsConfig.None) - { + /* always add procedure definition even if it is potentially not used + (easier than having conditions here, especially since cost is small) + */ + if (!onlyGlobalData) + { DefDecl methodDef = MethodDefinition(membershipLemmaManager, methodData, config.specsConfig); decls.Add(methodDef); } @@ -258,8 +261,10 @@ private DefDecl MethodDefinition(IProgramAccessor programAccessor, BoogieMethodD //TODO: incorporate return values and modified variables Tuple.Create("proc_rets", (Term) IsaCommonTerms.EmptyList), Tuple.Create("proc_modifs", (Term) modifiedVarsTerm), - Tuple.Create("proc_pres", specConfig == SpecsConfig.All ? programAccessor.PreconditionsDecl() : IsaBoogieTerm.LiftExprsToCheckedSpecs(programAccessor.PreconditionsDecl())), - Tuple.Create("proc_posts", specConfig == SpecsConfig.All ? programAccessor.PostconditionsDecl() : IsaBoogieTerm.LiftExprsToCheckedSpecs(programAccessor.PostconditionsDecl())), + Tuple.Create("proc_pres", specConfig == SpecsConfig.All ? + programAccessor.PreconditionsDecl() : IsaBoogieTerm.LiftExprsToCheckedSpecs(programAccessor.PreconditionsDecl())), + Tuple.Create("proc_posts", specConfig == SpecsConfig.All ? + programAccessor.PostconditionsDecl() : IsaBoogieTerm.LiftExprsToCheckedSpecs(programAccessor.PostconditionsDecl())), //TODO: support abstract procedures Tuple.Create("proc_body", IsaCommonTerms.SomeOption(new TermTuple(IsaCommonTerms.TermIdentFromName(programAccessor.LocalsDecl()), programAccessor.CfgDecl()))) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs index f0ac4cb02..174facd82 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs @@ -99,9 +99,6 @@ public IEnumerable EndToEndProof( new Proof(new List {proofSb.ToString()}) ); result.Add(helperLemma); - var defProcWithoutDeadVar = new DefDecl(procedureName + "_unoptimized_without_dead_vars", new Tuple, Term>(new List(), IsaCommonTerms.TermIdentFromName("proc \\ proc_body := (Some (" + afterOptProgAccess.BlockInfo().getTheoryName() + ".locals_vdecls," + beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body)) \\"))); - result.Add(defProcWithoutDeadVar); - var endToEndLemma = new LemmaDecl( @@ -112,7 +109,7 @@ public IEnumerable EndToEndProof( IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()), programAccessor.AxiomsDecl(), - defProcWithoutDeadVar.Name), + programAccessor.ProcDeclName()), new Proof( new List { @@ -120,14 +117,18 @@ public IEnumerable EndToEndProof( ProofUtil.Apply("assumption"), "using VC apply simp", ProofUtil.Apply("assumption+"), - "apply (unfold " + defProcWithoutDeadVar.Name + "_def)", - "apply (simp add: " + afterOptProgAccess.BlockInfo().getTheoryName() + ".pres_def " + afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_def exprs_to_only_checked_spec_1)", - "apply (simp add: " + afterOptProgAccess.BlockInfo().getTheoryName() + ".post_def " + afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_def exprs_to_only_checked_spec_2)", - "apply simp", - "apply (simp add: " + afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_def)", - "apply (simp add: " + afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_def)", - "apply (simp add: " + afterOptProgAccess.BlockInfo().getTheoryName() + ".proc_def)", - "apply (simp add: " + beforeOptProgAccess.BlockInfo().getTheoryName() + ".proc_body_def)", + ProofUtil.Apply($"unfold {programAccessor.ProcDeclName()}_def"), + ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.PreconditionsDeclName()+"_def", + beforeOptProgAccess.ProcDeclName()+"_def", + "exprs_to_only_checked_spec_1")), + ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.PostconditionsDeclName()+"_def ", + beforeOptProgAccess.ProcDeclName()+"_def", + "exprs_to_only_checked_spec_2")), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.ProcDeclName() + "_def")), + ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.ProcDeclName() + "_def")), + ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.ProcDeclName() + "_def")), + ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.CfgDeclName() + "_def")), "done" } ) ); diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 5a131f37e..30b67f1ea 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -646,7 +646,8 @@ from calls. cmdIsaVisitor = new MultiCmdIsaVisitor(afterOptimizationsVarTranslationFactory); IProgramAccessor beforeAstToCfgProgAccess = null; - IProgramAccessor unoptimizedCfgProgAccess = null; + IProgramAccessor unoptimizedCfgProgAccess = null; //unoptimized CFG with original variable declarations + IProgramAccessor unoptimizedCfgOptVarProgAccess = null; //unoptimized CFG where dead variables are eliminated IProgramAccessor beforeCfgToDagProgAccess = null; IProgramAccessor beforePassiveProgAccess = null; IProgramAccessor passiveProgAccess = null; @@ -702,60 +703,121 @@ from calls. { #region unoptimized cfg program - var unoptimizedCfgTheoryName = - uniqueNamer.GetName(afterPassificationImpl.Name + "_unoptimized_cfg_prog"); var parentAccessorForUnoptimizedCfg = beforeAstToCfgProgAccess; - var unoptimizedCfgConfig = + + Func getUnoptimizedCfgConfig = generateLocalsAndParams => new IsaProgramGeneratorConfig( parentAccessorForUnoptimizedCfg ?? globalDataProgAccess, false, false, false, - parentAccessorForUnoptimizedCfg == null, - parentAccessorForUnoptimizedCfg != null ? SpecsConfig.None : specsConfigDefault, + generateLocalsAndParams, + /* if generate locals and params, then encoding of output variables may change, thus should generate + pre- and postconditions in such a case*/ + parentAccessorForUnoptimizedCfg != null && !generateLocalsAndParams ? SpecsConfig.None : specsConfigDefault, !_proofGenConfig.GenerateBeforeAstCfgProg); - - unoptimizedCfgProgAccess = new IsaProgramGenerator().GetIsaProgram( - unoptimizedCfgTheoryName, - afterPassificationImpl.Name, - beforeOptimizationsData, unoptimizedCfgConfig, beforeOptimizationsVarTranslationFactory, - beforeOptimizationsCFG, - uniqueNamer, - out var programDeclsUnoptimizedCfg, - !CommandLineOptions.Clo.GenerateIsaProgNoProofs); - procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "unoptimized", - unoptimizedCfgProgAccess); - - var unoptimizedCfgProgTheory = new Theory(unoptimizedCfgTheoryName, - new List - { - "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", - _proofGenConfig.GenerateBeforeAstCfgProg ? beforeAstToCfgProgAccess.TheoryName() : "\"../"+globalDataProgAccess.TheoryName()+"\"" - }, - programDeclsUnoptimizedCfg); - theories.Add(unoptimizedCfgProgTheory); + + Func>> getUnoptimizedCfgAccess = + (theoryName, config, methodData, factory) => + { var accessor = + new IsaProgramGenerator().GetIsaProgram( + theoryName, + afterPassificationImpl.Name, + /* pick data after optimizations (allows connecting to CFG-to-DAG proof directly) --> + dead variable elimination step must be handled separately + */ + methodData, config, factory, + beforeOptimizationsCFG, + uniqueNamer, + out var programDeclsUnoptimizedCfg, + !CommandLineOptions.Clo.GenerateIsaProgNoProofs); + return Tuple.Create(accessor, programDeclsUnoptimizedCfg); + }; + + { + // unoptimized CFG with original variables + + var unoptimizedCfgTheoryName = + uniqueNamer.GetName(afterPassificationImpl.Name + "_unoptimized_cfg_prog"); + + var config = getUnoptimizedCfgConfig(parentAccessorForUnoptimizedCfg != null); + (unoptimizedCfgProgAccess, var programDeclsUnoptimizedCfg) = + getUnoptimizedCfgAccess( + unoptimizedCfgTheoryName, + config, + beforeOptimizationsData, + beforeOptimizationsVarTranslationFactory + ); + + procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "unoptimized_orig_var", + unoptimizedCfgProgAccess); + + var unoptimizedCfgProgTheory = new Theory(unoptimizedCfgTheoryName, + new List + { + "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", + _proofGenConfig.GenerateBeforeAstCfgProg ? beforeAstToCfgProgAccess.TheoryName() : "\"../"+globalDataProgAccess.TheoryName()+"\"" + }, + programDeclsUnoptimizedCfg); + theories.Add(unoptimizedCfgProgTheory); + } + + if (proofGenInfo.EliminatedDeadVars) + { + // unoptimized CFG without dead variables --> different program representation due to DeBruijn indexing + + var unoptimizedCfgOptVarTheoryName = + uniqueNamer.GetName(afterPassificationImpl.Name + "_unoptimized_cfg_opt_var_prog"); + + (unoptimizedCfgOptVarProgAccess, var programDeclsUnoptimizedOptVarCfg) = + getUnoptimizedCfgAccess( + unoptimizedCfgOptVarTheoryName, + //since dead variables were eliminated, need to generate the local variable declarations without the dead variables + getUnoptimizedCfgConfig(true), + afterOptimizationsData, + afterOptimizationsVarTranslationFactory + ); + + procNameToTopLevelPrograms.Add(afterPassificationImpl.Proc.Name + "unoptimized_opt_var", unoptimizedCfgOptVarProgAccess); + + var unoptimizedCfgProgTheory = new Theory(unoptimizedCfgOptVarTheoryName, + new List + { + "Boogie_Lang.Semantics", "Boogie_Lang.TypeSafety", "Boogie_Lang.Util", + _proofGenConfig.GenerateBeforeAstCfgProg ? beforeAstToCfgProgAccess.TheoryName() : "\"../"+globalDataProgAccess.TheoryName()+"\"" + }, + programDeclsUnoptimizedOptVarCfg); + theories.Add(unoptimizedCfgProgTheory); + } + else + { + // no need for two different representations of unoptimized CFG + unoptimizedCfgOptVarProgAccess = unoptimizedCfgProgAccess; + } #endregion } - var generateProcForBeforeCfgToDag = - //_proofGenConfig.GenerateAstCfgE2E(proofGenInfo.GetOptimizationsFlag()) && - proofGenInfo.GetOptimizationsFlag(); + var generateProcForBeforeCfgToDag = proofGenInfo.GetOptimizationsFlag(); if (_proofGenConfig.GenerateBeforeCfgDagProg(proofGenInfo.GetOptimizationsFlag())) { #region before cfg to dag program var beforeCfgToDagTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_before_cfg_to_dag_prog"); - var parentAccessorForBeforeCfgToDag = beforeAstToCfgProgAccess; + var parentAccessorForBeforeCfgToDag = unoptimizedCfgOptVarProgAccess ?? beforeAstToCfgProgAccess; var beforeCfgToDagConfig = new IsaProgramGeneratorConfig( parentAccessorForBeforeCfgToDag ?? globalDataProgAccess, false, false, false, - parentAccessorForBeforeCfgToDag == null || proofGenInfo.GetOptimizationsFlag(), - //do not generate separate procedure if AST is going to connect directly to the CFG before the DAG - parentAccessorForBeforeCfgToDag == null || generateProcForBeforeCfgToDag ? specsConfigDefault : SpecsConfig.None, + parentAccessorForBeforeCfgToDag == null, + parentAccessorForBeforeCfgToDag == null || (proofGenInfo.EliminatedDeadVars && parentAccessorForBeforeCfgToDag != unoptimizedCfgOptVarProgAccess) ? + /* make sure to generate separate pre- and post if no parent accessor or dead variables were eliminated + and the parent accessor has generated the pre- and post without dead variables (which impacts output variable representation) + */ + specsConfigDefault : + SpecsConfig.None, parentAccessorForBeforeCfgToDag == null || proofGenInfo.GetOptimizationsFlag()); beforeCfgToDagProgAccess = new IsaProgramGenerator().GetIsaProgram( @@ -1017,7 +1079,7 @@ out var endToEndLemmaPrelim beforeOptimizationsCFG, beforeDagCfg, beforeOptAfterOptBlock, - unoptimizedCfgProgAccess, + unoptimizedCfgOptVarProgAccess, beforeCfgToDagProgAccess, ListCoalescedBlocks, CoalescedBlocksToTarget, @@ -1040,15 +1102,9 @@ out var endToEndLemmaPrelim IDictionary mappingWithHints = new Dictionary(); - //IDictionary mappingCopyBigblockToOrigBigblock = - //proofGenInfo.GetMappingCopyBigblockToOrigBigblock(); IDictionary mappingOrigBigBlockToOrigBlock = proofGenInfo.GetMappingOrigBigBlockToOrigBlock(); - - - IDictionary mappingOrigBlockToCopyBlock = beforeDagOrigBlock.InverseDict(); - IDictionary mappingBigBlockToHints = proofGenInfo.GetMappingCopyBigBlockToHints(); foreach (var pair in mappingOrigBigBlockToOrigBlock) @@ -1059,7 +1115,7 @@ out var endToEndLemmaPrelim var blockToBlockMapToReferTo = proofGenInfo.GetOptimizationsFlag() ? mappingOrigBlockToUnoptimizedCopy - : mappingOrigBlockToCopyBlock; + : beforeDagOrigBlock.InverseDict(); var copyBlock = blockToBlockMapToReferTo[origBlock]; var hints = mappingBigBlockToHints[origBigBlock]; From d73f40ee4d24564e27722f8d3390c0ddb01e6fb1 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Thu, 18 Apr 2024 09:44:29 +0200 Subject: [PATCH 090/123] fix bug --- Source/ProofGeneration/ProofGenerationLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 30b67f1ea..1da4ead8d 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -740,7 +740,7 @@ dead variable elimination step must be handled separately var unoptimizedCfgTheoryName = uniqueNamer.GetName(afterPassificationImpl.Name + "_unoptimized_cfg_prog"); - var config = getUnoptimizedCfgConfig(parentAccessorForUnoptimizedCfg != null); + var config = getUnoptimizedCfgConfig(parentAccessorForUnoptimizedCfg == null); (unoptimizedCfgProgAccess, var programDeclsUnoptimizedCfg) = getUnoptimizedCfgAccess( unoptimizedCfgTheoryName, From ad31b83ebb5ea056f285fcc86f32b68086f63fb9 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Thu, 18 Apr 2024 11:45:45 +0200 Subject: [PATCH 091/123] connect AST-to-CFG with CFG optimizations if no dead variables are eliminated also cleaned up conditions for when end-to-end theorem should be generated for a procedure (now this should be the case only for one phase) --- .../AstToCfg/AstToCfgEndToEnd.cs | 171 +++++++++--------- .../AstToCfg/AstToCfgManager.cs | 49 +++-- .../CFGOptimizationsEndToEnd.cs | 85 +++++---- .../CFGOptimizationsManager.cs | 7 +- .../CfgToDag/CfgToDagManager.cs | 16 +- .../PhasesUtil/EndToEndLemmaConfig.cs | 8 + .../{ => PhasesUtil}/PhasesTheories.cs | 18 +- Source/ProofGeneration/ProofGenConfig.cs | 5 +- .../ProofGeneration/ProofGenerationLayer.cs | 55 +++++- 9 files changed, 241 insertions(+), 173 deletions(-) create mode 100644 Source/ProofGeneration/PhasesUtil/EndToEndLemmaConfig.cs rename Source/ProofGeneration/{ => PhasesUtil}/PhasesTheories.cs (80%) diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs b/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs index 33eb85c90..7a10c7945 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgEndToEnd.cs @@ -35,7 +35,6 @@ public class AstToCfgEndToEnd private BoogieContextIsa boogieContext; private IProgramAccessor beforeCfgProgramAccessor; - //private IProgramAccessor afterCfgProgramAccessor; private readonly string varContextName = "\\0"; @@ -43,6 +42,7 @@ public class AstToCfgEndToEnd public IEnumerable EndToEndProof( string entryBlockAstLemma, + EndToEndLemmaConfig endToEndLemmaConfig, string cfgToDagEndToEndLemma, Term vcAssm, IProgramAccessor beforeCfgProgramAccessor, @@ -50,8 +50,12 @@ public IEnumerable EndToEndProof( ASTRepr ast, AstToCfgProofGenInfo proofGenInfo) { + if (endToEndLemmaConfig == EndToEndLemmaConfig.DoNotGenerate) + { + throw new ArgumentException("end-to-end lemma invoked even though disabled"); + } + this.beforeCfgProgramAccessor = beforeCfgProgramAccessor; - //this.afterCfgProgramAccessor = afterCfgProgramAccessor; boogieContext = new BoogieContextIsa( IsaCommonTerms.TermIdentFromName("A"), @@ -158,92 +162,97 @@ public IEnumerable EndToEndProof( new Proof(new List {proofSb.ToString()}) ); result.Add(helperLemma); - - var assumptions = new List(); - - string contName = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[bigblock0]; - Term contId = IsaCommonTerms.TermIdentFromName(contName); - Term initStateId = IsaBoogieTerm.Normal(IsaCommonTerms.TermIdentFromName("ns")); - Term astDecl = ast.GetAstAsTermList(proofGenInfo); - List continuations = ast.GetMainContinuations(proofGenInfo); - string continuationsAsString = null; - foreach (var str in continuations) + if (endToEndLemmaConfig == EndToEndLemmaConfig.GenerateForProcedure) { - continuationsAsString += str + " "; - } - - var initAstTerm = new TermApp - ( - IsaCommonTerms.TermIdentFromName("init_ast"), - astDecl, - IsaCommonTerms.TermIdentFromName("ns") + var assumptions = new List(); + + string contName = "cont_" + proofGenInfo.GetMappingCopyBigBlockToIndex()[bigblock0]; + Term contId = IsaCommonTerms.TermIdentFromName(contName); + Term initStateId = IsaBoogieTerm.Normal(IsaCommonTerms.TermIdentFromName("ns")); + + Term astDecl = ast.GetAstAsTermList(proofGenInfo); + List continuations = ast.GetMainContinuations(proofGenInfo); + string continuationsAsString = null; + foreach (var str in continuations) + { + continuationsAsString += str + " "; + } + + var initAstTerm = new TermApp + ( + IsaCommonTerms.TermIdentFromName("init_ast"), + astDecl, + IsaCommonTerms.TermIdentFromName("ns") ); - - BoogieContextIsa dummyBoogieContext = new BoogieContextIsa( - IsaCommonTerms.TermIdentFromName("A"), - IsaCommonTerms.TermIdentFromName("M"), - IsaCommonTerms.TermIdentFromName("\\"), - IsaCommonTerms.TermIdentFromName("\\"), - IsaCommonTerms.TermIdentFromName("\\") - ); - - var bigBlockMultiRedInitAst = IsaBoogieTerm.RedBigBlockMulti( - dummyBoogieContext, - initAstTerm, - IsaBoogieTerm.EndConfigTerm(), - IsaBoogieTerm.astId() - ); - - assumptions.Add(bigBlockMultiRedInitAst); - - var bigBlockMultiRed = IsaBoogieTerm.RedBigBlockMulti( - dummyBoogieContext, - IsaBoogieTerm.StartConfigTerm(bigblock0, contId, beforeCfgProgramAccessor, initStateId), - IsaBoogieTerm.EndConfigTerm(), - IsaBoogieTerm.astId() + + BoogieContextIsa dummyBoogieContext = new BoogieContextIsa( + IsaCommonTerms.TermIdentFromName("A"), + IsaCommonTerms.TermIdentFromName("M"), + IsaCommonTerms.TermIdentFromName("\\"), + IsaCommonTerms.TermIdentFromName("\\"), + IsaCommonTerms.TermIdentFromName("\\") ); - var proofMethods = new List - { - "using assms", - "by (simp add: " + continuationsAsString + ")" - }; - - var initializationLemmaName = "initialization"; - var initializationLemma = - new LemmaDecl( - initializationLemmaName, - ContextElem.CreateWithAssumptions(assumptions), - bigBlockMultiRed, - new Proof(proofMethods) + var bigBlockMultiRedInitAst = IsaBoogieTerm.RedBigBlockMulti( + dummyBoogieContext, + initAstTerm, + IsaBoogieTerm.EndConfigTerm(), + IsaBoogieTerm.astId() ); - result.Add(initializationLemma); - - //transform end to end theorem to a compact representation - var endToEndLemma = + + assumptions.Add(bigBlockMultiRedInitAst); + + var bigBlockMultiRed = IsaBoogieTerm.RedBigBlockMulti( + dummyBoogieContext, + IsaBoogieTerm.StartConfigTerm(bigblock0, contId, beforeCfgProgramAccessor, initStateId), + IsaBoogieTerm.EndConfigTerm(), + IsaBoogieTerm.astId() + ); + + var proofMethods = new List + { + "using assms", + "by (simp add: " + continuationsAsString + ")" + }; + + var initializationLemmaName = "initialization"; + var initializationLemma = new LemmaDecl( - "end_to_end_theorem_ast", - ContextElem.CreateWithAssumptions(new List {vcAssm}, new List {"VC"}), - ProcedureIsCorrect( - beforeCfgProgramAccessor.FunctionsDecl(), - IsaCommonTerms.TermIdentFromName(beforeCfgProgramAccessor.ConstsDecl()), - IsaCommonTerms.TermIdentFromName(beforeCfgProgramAccessor.GlobalsDecl()), - beforeCfgProgramAccessor.AxiomsDecl(), - beforeCfgProgramAccessor.ProcDecl()), - new Proof( - new List - { - ProofUtil.Apply(ProofUtil.Rule(ProofUtil.OF("end_to_end_util2",helperLemmaName))), - "apply (rule initialization)", - "unfolding " + beforeCfgProgramAccessor.ProcDeclName() + "_def", - "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 " + - beforeCfgProgramAccessor.ProcDeclName() + "_def " + beforeCfgProgramAccessor.CfgDeclName() + "_def") - } - ) ); - - result.Add(endToEndLemma); + initializationLemmaName, + ContextElem.CreateWithAssumptions(assumptions), + bigBlockMultiRed, + new Proof(proofMethods) + ); + result.Add(initializationLemma); + + //transform end to end theorem to a compact representation + var endToEndLemma = + new LemmaDecl( + "end_to_end_theorem_ast", + ContextElem.CreateWithAssumptions(new List { vcAssm }, new List { "VC" }), + ProcedureIsCorrect( + beforeCfgProgramAccessor.FunctionsDecl(), + IsaCommonTerms.TermIdentFromName(beforeCfgProgramAccessor.ConstsDecl()), + IsaCommonTerms.TermIdentFromName(beforeCfgProgramAccessor.GlobalsDecl()), + beforeCfgProgramAccessor.AxiomsDecl(), + beforeCfgProgramAccessor.ProcDecl()), + new Proof( + new List + { + ProofUtil.Apply(ProofUtil.Rule(ProofUtil.OF("end_to_end_util2", helperLemmaName))), + "apply (rule initialization)", + "unfolding " + beforeCfgProgramAccessor.ProcDeclName() + "_def", + "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 " + + beforeCfgProgramAccessor.ProcDeclName() + "_def " + + beforeCfgProgramAccessor.CfgDeclName() + "_def") + } + )); + + result.Add(endToEndLemma); + } + return result; } diff --git a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs index d534250c2..dc6211bcf 100644 --- a/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs +++ b/Source/ProofGeneration/AstToCfg/AstToCfgManager.cs @@ -8,6 +8,7 @@ using ProofGeneration.BoogieIsaInterface; using ProofGeneration.BoogieIsaInterface.VariableTranslation; using ProofGeneration.CFGRepresentation; +using ProofGeneration.PhasesUtil; using ProofGeneration.Util; namespace ProofGeneration.AstToCfg @@ -17,7 +18,7 @@ internal class AstToCfgManager public static Theory AstToCfgProof( string uniqueTheoryName, PhasesTheories phasesTheories, - bool generateEndtoEnd, + EndToEndLemmaConfig endToEndLemmaConfig, ProofGenConfig config, Term vcAssm, AstToCfgProofGenInfo proofGenInfo, @@ -122,6 +123,11 @@ public static Theory AstToCfgProof( } } + if (entryLemma == null) + { + throw new ProofGenUnexpectedStateException("AST-to-CFG phase: entry lemma not assigned"); + } + var absValType = new VarType("a"); var cfgToDagLemmasLocale = new LocaleDecl( "ast_to_cfg_lemmas", @@ -145,12 +151,17 @@ public static Theory AstToCfgProof( var theoryOuterDecls = new List(); theoryOuterDecls.Add(cfgToDagLemmasLocale); - if (generateEndtoEnd && !proofGenInfo.GetOptimizationsFlag()) + if (endToEndLemmaConfig != EndToEndLemmaConfig.DoNotGenerate) { + var phaseToConnectTo = config.GenerateCfgOptProof(proofGenInfo.GetOptimizationsFlag()) + ? PhasesTheories.Phase.CfgOptimizations + : PhasesTheories.Phase.CfgToDag; + var endToEndManager = new AstToCfgEndToEnd(); var endToEndDecls = endToEndManager.EndToEndProof( entryLemma.Name, - phasesTheories.EndToEndLemmaName(PhasesTheories.Phase.CfgToDag, false) + "_theorem_aux", + endToEndLemmaConfig, + phasesTheories.EndToEndLemmaName(phaseToConnectTo, true) + "_theorem_aux", vcAssm, beforeCfgProgAccess, afterCfgProgAccess, @@ -167,10 +178,15 @@ public static Theory AstToCfgProof( beforeCfgProgAccess.TheoryName(), afterCfgProgAccess.TheoryName() }; - - if (config.GenerateCfgDagProof) importTheories.Add(phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag)); - if (config.GeneratePassifProof) importTheories.Add(phasesTheories.TheoryName(PhasesTheories.Phase.Passification)); - if (config.GenerateVcProof) importTheories.Add(phasesTheories.TheoryName(PhasesTheories.Phase.Vc)); + + if (config.GenerateCfgOptProof(proofGenInfo.GetOptimizationsFlag())) + { + importTheories.Add(phasesTheories.TheoryName(PhasesTheories.Phase.CfgOptimizations)); + } + else if(config.GenerateCfgDagProof) + { + importTheories.Add(phasesTheories.TheoryName(PhasesTheories.Phase.CfgToDag)); + } return new Theory( uniqueTheoryName, @@ -178,25 +194,6 @@ public static Theory AstToCfgProof( theoryOuterDecls ); } - - public static bool PredHasLoop(BigBlock b, ASTRepr ast, out BigBlock predecessor) - { - IEnumerable bbs = ast.GetBlocksForwards(); - BigBlock[] bbsArray = bbs.ToArray(); - - for (var i = 0; i < bbsArray.Length; i++) - { - if (bbsArray[i] == b && i != 0 && bbsArray[i - 1].ec is WhileCmd) - { - predecessor = bbsArray[i - 1]; - return true; - } - } - - predecessor = null; - return false; - } - private static string GetLemmaName(BigBlock b, IsaUniqueNamer namer, IsaBigBlockInfo bbInfo) { return namer.GetName(b, "rel_" + bbInfo.CmdsQualifiedName(b).First()); diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs index 174facd82..ad87f047c 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs @@ -37,7 +37,7 @@ public class CFGOptimizationsEndToEnd public IEnumerable EndToEndProof( string entryBlockCfgOptLemma, - string cfgOptEndToEndLemma, + EndToEndLemmaConfig endToEndLemmaConfig, Term vcAssm, IProgramAccessor beforeOptProgAccess, IProgramAccessor afterOptProgAccess, @@ -46,6 +46,11 @@ public IEnumerable EndToEndProof( PhasesTheories phasesTheories, string procedureName) { + if (endToEndLemmaConfig == EndToEndLemmaConfig.DoNotGenerate) + { + throw new ArgumentException("CFG Optimizations Phase: end-to-end lemma invoked even though disabled"); + } + this.programAccessor = programAccessor; boogieContext = new BoogieContextIsa( IsaCommonTerms.TermIdentFromName("A"), @@ -99,43 +104,45 @@ public IEnumerable EndToEndProof( new Proof(new List {proofSb.ToString()}) ); result.Add(helperLemma); - - var endToEndLemma = - new LemmaDecl( - "end_to_end_theorem", - ContextElem.CreateWithAssumptions(new List {vcAssm}, new List {"VC"}), - ProcedureIsCorrect( - programAccessor.FunctionsDecl(), - IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), - IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()), - programAccessor.AxiomsDecl(), - programAccessor.ProcDeclName()), - new Proof( - new List - { - ProofUtil.Apply(ProofUtil.Rule(ProofUtil.OF("end_to_end_util",helperLemmaName))), - ProofUtil.Apply("assumption"), - "using VC apply simp", - ProofUtil.Apply("assumption+"), - ProofUtil.Apply($"unfold {programAccessor.ProcDeclName()}_def"), - ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.PreconditionsDeclName()+"_def", - beforeOptProgAccess.ProcDeclName()+"_def", - "exprs_to_only_checked_spec_1")), - ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.PostconditionsDeclName()+"_def ", - beforeOptProgAccess.ProcDeclName()+"_def", - "exprs_to_only_checked_spec_2")), - ProofUtil.Apply(ProofUtil.Simp()), - ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.ProcDeclName() + "_def")), - ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.ProcDeclName() + "_def")), - ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.ProcDeclName() + "_def")), - ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.CfgDeclName() + "_def")), - "done" - } - ) ); - - result.Add(endToEndLemma); - - + + if (endToEndLemmaConfig == EndToEndLemmaConfig.GenerateForProcedure) + { + var endToEndLemma = + new LemmaDecl( + "end_to_end_theorem", + ContextElem.CreateWithAssumptions(new List {vcAssm}, new List {"VC"}), + ProcedureIsCorrect( + programAccessor.FunctionsDecl(), + IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), + IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()), + programAccessor.AxiomsDecl(), + programAccessor.ProcDeclName()), + new Proof( + new List + { + ProofUtil.Apply(ProofUtil.Rule(ProofUtil.OF("end_to_end_util",helperLemmaName))), + ProofUtil.Apply("assumption"), + "using VC apply simp", + ProofUtil.Apply("assumption+"), + ProofUtil.Apply($"unfold {programAccessor.ProcDeclName()}_def"), + ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.PreconditionsDeclName()+"_def", + beforeOptProgAccess.ProcDeclName()+"_def", + "exprs_to_only_checked_spec_1")), + ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.PostconditionsDeclName()+"_def ", + beforeOptProgAccess.ProcDeclName()+"_def", + "exprs_to_only_checked_spec_2")), + ProofUtil.Apply(ProofUtil.Simp()), + ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.ProcDeclName() + "_def")), + ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.ProcDeclName() + "_def")), + ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.ProcDeclName() + "_def")), + ProofUtil.Apply(ProofUtil.Simp(beforeOptProgAccess.CfgDeclName() + "_def")), + "done" + } + ) ); + + result.Add(endToEndLemma); + } + return result; } @@ -145,7 +152,7 @@ private ContextElem LemmaContext( Term vcAssm, IProgramAccessor afterOptProgAccess ) - { + { var multiRed = IsaBoogieTerm.RedCFGMulti( BoogieContextIsa.CreateWithNewVarContext( boogieContext, diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs index 0a11116b5..126f6738f 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsManager.cs @@ -10,6 +10,7 @@ using ProofGeneration.BoogieIsaInterface; using ProofGeneration.BoogieIsaInterface.VariableTranslation; using ProofGeneration.CFGRepresentation; +using ProofGeneration.PhasesUtil; using ProofGeneration.Util; using ProofGenUtil; @@ -21,6 +22,7 @@ public class CfgOptimizationsManager public static Theory CfgOptProof( PhasesTheories phasesTheories, + EndToEndLemmaConfig endToEndLemmaConfig, CFGRepr beforeOptimizations, CFGRepr afterOptimizations, IDictionary beforeToAfter, // mapping from current block to target block @@ -31,7 +33,6 @@ public static Theory CfgOptProof( IDictionary> beforeDagBlockToLoops, Term vcAssm, string procedureName, - bool generateEnd2EndLemma, bool generateCfgDagProof, IDictionary selfLoops) { @@ -207,12 +208,12 @@ public static Theory CfgOptProof( GetGlobalBlockLemmaName(beforeOptimizations.entry, lemmaNamer), beforeOptimizations.entry, afterOptimizations.entry); outerDecls.Add(entryLemma); - if (generateEnd2EndLemma) + if (endToEndLemmaConfig != EndToEndLemmaConfig.DoNotGenerate) { var endToEndManager = new CFGOptimizationsEndToEnd(); var endToEndDecls = endToEndManager.EndToEndProof( "entry_lemma", - "end_to_end", + endToEndLemmaConfig, vcAssm, beforeOptCfgProgAccess, afterOptCfgProgAccess, diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs index ac6684a1c..e8c464577 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagManager.cs @@ -7,18 +7,12 @@ using ProofGeneration.BoogieIsaInterface; using ProofGeneration.BoogieIsaInterface.VariableTranslation; using ProofGeneration.CFGRepresentation; +using ProofGeneration.PhasesUtil; using ProofGeneration.Util; namespace ProofGeneration.CfgToDag { - public enum CfgToDagEndToEndLemma - { - DoNotGenerate, - GenerateForProcedure, - GenerateForEntryBlock - } - - public class CfgToDagManager + public class CfgToDagManager { /** * cases: @@ -30,7 +24,7 @@ public class CfgToDagManager */ public static Theory CfgToDagProof( PhasesTheories phasesTheories, - CfgToDagEndToEndLemma generateEndToEndLemma, + EndToEndLemmaConfig endToEndLemmaConfig, bool generatePassificationProof, bool generateVcProof, Term vcAssm, @@ -188,11 +182,11 @@ public static Theory CfgToDagProof( var theoryOuterDecls = new List(); theoryOuterDecls.Add(cfgToDagLemmasLocale); - if (generateEndToEndLemma != CfgToDagEndToEndLemma.DoNotGenerate) + if (endToEndLemmaConfig != EndToEndLemmaConfig.DoNotGenerate) { var endToEndManager = new CfgToDagEndToEnd(); var endToEndDecls = endToEndManager.EndToEndProof( - generateEndToEndLemma == CfgToDagEndToEndLemma.GenerateForProcedure, + endToEndLemmaConfig == EndToEndLemmaConfig.GenerateForProcedure, cfgToDagLemmasLocale.Name + "." + entryLemma.Name, phasesTheories.EndToEndLemmaName(PhasesTheories.Phase.Passification, true), vcAssm, diff --git a/Source/ProofGeneration/PhasesUtil/EndToEndLemmaConfig.cs b/Source/ProofGeneration/PhasesUtil/EndToEndLemmaConfig.cs new file mode 100644 index 000000000..a2b0aad8d --- /dev/null +++ b/Source/ProofGeneration/PhasesUtil/EndToEndLemmaConfig.cs @@ -0,0 +1,8 @@ +namespace ProofGeneration.PhasesUtil; + +public enum EndToEndLemmaConfig +{ + DoNotGenerate, + GenerateForProcedure, + GenerateForEntryBlock +} \ No newline at end of file diff --git a/Source/ProofGeneration/PhasesTheories.cs b/Source/ProofGeneration/PhasesUtil/PhasesTheories.cs similarity index 80% rename from Source/ProofGeneration/PhasesTheories.cs rename to Source/ProofGeneration/PhasesUtil/PhasesTheories.cs index cc713b553..af121a4f0 100644 --- a/Source/ProofGeneration/PhasesTheories.cs +++ b/Source/ProofGeneration/PhasesUtil/PhasesTheories.cs @@ -1,4 +1,4 @@ -namespace ProofGeneration +namespace ProofGeneration.PhasesUtil { public class PhasesTheories { @@ -63,5 +63,21 @@ private string MaybeQualifiedName(string theory, string name, bool qualify) { return qualify ? theory + "." + name : name; } + + public static EndToEndLemmaConfig EndToEndConfig(bool generateEndToEndTheorem, Phase currentPhase, Phase phaseWithProcEndToEnd) + { + if (!generateEndToEndTheorem) + { + return EndToEndLemmaConfig.DoNotGenerate; + } + + if (currentPhase == phaseWithProcEndToEnd) + { + return EndToEndLemmaConfig.GenerateForProcedure; + } + + return EndToEndLemmaConfig.GenerateForEntryBlock; + } + } } \ No newline at end of file diff --git a/Source/ProofGeneration/ProofGenConfig.cs b/Source/ProofGeneration/ProofGenConfig.cs index 137f0b348..c6673f7c0 100644 --- a/Source/ProofGeneration/ProofGenConfig.cs +++ b/Source/ProofGeneration/ProofGenConfig.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using ProofGeneration.PhasesUtil; namespace ProofGeneration { @@ -62,8 +63,8 @@ public ProofGenConfig AllOptionsDisabled() return AllOptions(false); } - public bool GenerateAstCfgE2E(bool optimizationsHaveAnEffect) => - GenerateAstCfgProof && (!optimizationsHaveAnEffect && GenerateCfgDagE2E); //currently do not produce E2E if optimizations have an effect + public bool GenerateAstCfgE2E(bool deadVarsElim) => + GenerateAstCfgProof && (!deadVarsElim && GenerateCfgDagE2E); //currently do not produce E2E if dead variables are eliminated public bool GenerateCfgDagE2E => GenerateCfgDagProof && GeneratePassifE2E; diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 1da4ead8d..8a8365857 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Diagnostics.Contracts; using System.Linq; @@ -17,6 +16,7 @@ using ProofGeneration.CFGRepresentation; using ProofGeneration.CfgToDag; using ProofGeneration.Passification; +using ProofGeneration.PhasesUtil; using ProofGeneration.ProgramToVCProof; using ProofGeneration.Util; using ProofGeneration.VCProofGen; @@ -797,9 +797,7 @@ dead variable elimination step must be handled separately #endregion } - - var generateProcForBeforeCfgToDag = proofGenInfo.GetOptimizationsFlag(); - + if (_proofGenConfig.GenerateBeforeCfgDagProg(proofGenInfo.GetOptimizationsFlag())) { #region before cfg to dag program @@ -1010,6 +1008,8 @@ out var endToEndLemmaPrelim #endregion } + var phaseWithEndToEndTheorem = GetPhaseWithEndToEndTheorem(_proofGenConfig, proofGenInfo.GetOptimizationsFlag(), proofGenInfo.EliminatedDeadVars); + IDictionary> beforeDagBlocktoLoops = null; IDictionary selfLoops = null; if (_proofGenConfig.GenerateCfgDagProof) @@ -1023,9 +1023,7 @@ out var endToEndLemmaPrelim beforeDagBlocktoLoops = getBeforeDagBlockToLoops(beforeDagAfterDagBlock, beforePassificationCfg, cfgToDagHintManager, out selfLoops); var cfgToDagProofTheory = CfgToDagManager.CfgToDagProof( phasesTheories, - //hacky: find better solution - _proofGenConfig.GenerateCfgDagE2E ? (generateProcForBeforeCfgToDag ? CfgToDagEndToEndLemma.GenerateForProcedure : CfgToDagEndToEndLemma.GenerateForEntryBlock) - : CfgToDagEndToEndLemma.DoNotGenerate, + PhasesTheories.EndToEndConfig(_proofGenConfig.GenerateCfgDagE2E, PhasesTheories.Phase.CfgToDag, phaseWithEndToEndTheorem), _proofGenConfig.GeneratePassifProof, _proofGenConfig.GenerateVcProof, vcAssm, @@ -1076,6 +1074,7 @@ out var endToEndLemmaPrelim var cfgOptimizationsProofTheory = CfgOptimizationsManager.CfgOptProof( phasesTheories, + PhasesTheories.EndToEndConfig(_proofGenConfig.GenerateCfgDagE2E, PhasesTheories.Phase.CfgOptimizations, phaseWithEndToEndTheorem), beforeOptimizationsCFG, beforeDagCfg, beforeOptAfterOptBlock, @@ -1086,7 +1085,6 @@ out var endToEndLemmaPrelim beforeDagBlocktoLoops, vcAssm, afterPassificationImpl.Name, - _proofGenConfig.GenerateCfgDagE2E, _proofGenConfig.GenerateCfgDagProof, selfLoops); theories.Add(cfgOptimizationsProofTheory); @@ -1130,13 +1128,14 @@ out var endToEndLemmaPrelim if (!proofGenInfo.GetOptimizationsFlag()) { + //if no optimizations were applied, then directly connect to CFG before CFG-to-DAG astCfgReprInput = beforeDagCfg; blockToBlockMapInput = beforeDagOrigBlock; beforeCfgToDagProgAccessInput = beforeCfgToDagProgAccess; - } else { + //optimizations were applied, then connect to CFG before optimizations astCfgReprInput = beforeOptimizationsCFG; blockToBlockMapInput = mappingUnoptimizedCopyToOrigBlock; beforeCfgToDagProgAccessInput = unoptimizedCfgProgAccess; @@ -1145,7 +1144,8 @@ out var endToEndLemmaPrelim var astToCfgProofTheory = AstToCfgManager.AstToCfgProof( phasesTheories.TheoryName(PhasesTheories.Phase.AstToCfg), phasesTheories, - _proofGenConfig.GenerateAstCfgE2E(proofGenInfo.GetOptimizationsFlag()), + PhasesTheories.EndToEndConfig(_proofGenConfig.GenerateAstCfgE2E(proofGenInfo.EliminatedDeadVars), + PhasesTheories.Phase.AstToCfg, phaseWithEndToEndTheorem), _proofGenConfig, vcAssm, proofGenInfo, @@ -1166,6 +1166,41 @@ out var endToEndLemmaPrelim StoreResult(uniqueNamer.GetName(afterPassificationImpl.Proc.Name), theories); } + /// + /// Return phase that must contain the end-to-end theorem with the corresponding source procedure if + /// the generation of end-to-end proofs is enabled. + /// + /// + /// Are there CFG optimizations? + /// Were dead variables eliminated? + /// + /// + private static PhasesTheories.Phase GetPhaseWithEndToEndTheorem(ProofGenConfig proofGenConfig, bool cfgOptimzations, bool deadVarsElim) + { + if (!cfgOptimzations && deadVarsElim) + { + throw new ArgumentException("dead variables eliminated but cfg optimizations not marked"); + } + + if (proofGenConfig.GenerateAstCfgE2E(deadVarsElim)) + { + return PhasesTheories.Phase.AstToCfg; + } + + if (proofGenConfig.GenerateCfgDagE2E && cfgOptimzations) + { + return PhasesTheories.Phase.CfgOptimizations; + } + + /* + Note that we could be more fine-grained here and instead return the passification or VC phases, if + the CFG-to-DAG phase end-to-end is disabled, but for now we only support the procedure version of the + end-to-end theorem until the CFG-to-DAG phase (the CFG-to-DAG end-to-end is usually disabled only for + debugging purposes). + */ + return PhasesTheories.Phase.CfgToDag; + } + private static CFGRepr GetCfgBeforeOptimizations(IList unoptimizedCFGBlocks) { var config = new CFGReprConfigBuilder().SetIsAcyclic(false).SetBlockCopy(true).SetDesugarCalls(true) From a5cf17735cd5780d013cf9449c9bf4712ad92b29 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Thu, 18 Apr 2024 13:40:40 +0200 Subject: [PATCH 092/123] Also generate and check proofs for CFG optimization benchmarks --- .github/workflows/ci.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c0c7073a..e08c91468 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,6 +66,15 @@ jobs: - name: Check external benchmark proofs run: | python3 etc/scripts/check_proofs.py --inputdir table_benchmarks_proofs --reps 1 + + - name: Generate CFG optimization benchmarks + run: | + BOOGIE_EXE=$(find $PWD -type f -name "BoogieDriver") + python3 etc/scripts/generate_proofs.py --inputdir ProofGenerationBenchmarks/cfg_optimizations_tests --outputdir cfg_optimizations_proofs --boogieproofExe $BOOGIE_EXE + + - name: Check CFG optimization proofs + run: | + python3 etc/scripts/check_proofs.py --inputdir cfg_optimizations_proofs --reps 1 - name: Generate Boogie benchmark proofs run: | From e4015e63bf11e937ddff078baee9a0dba5afa8c3 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 29 Apr 2024 10:39:02 +0200 Subject: [PATCH 093/123] add proof gen region blocks dead var elim --- Source/Core/DeadVarElim.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Source/Core/DeadVarElim.cs b/Source/Core/DeadVarElim.cs index b5cecf87f..a79d3703d 100644 --- a/Source/Core/DeadVarElim.cs +++ b/Source/Core/DeadVarElim.cs @@ -485,8 +485,10 @@ public static void CoalesceBlocks(Program program) public override Implementation VisitImplementation(Implementation impl) { + #region proofgen IDictionary CoalescedBlocksToTarget = new Dictionary(); IDictionary ListCoalescedBlocks = new Dictionary(); + #endregion //Contract.Requires(impl != null); Contract.Ensures(Contract.Result() != null); @@ -533,6 +535,7 @@ public override Implementation VisitImplementation(Implementation impl) if (!multiPredBlocks.Contains(succ)) { + #region proofgen if (!ListCoalescedBlocks.ContainsKey(b)) { List newList = new List(); @@ -553,6 +556,8 @@ public override Implementation VisitImplementation(Implementation impl) { CoalescedBlocksToTarget.Add(b, b); } + #endregion + foreach (Cmd /*!*/ cmd in succ.Cmds) { Contract.Assert(cmd != null); @@ -606,8 +611,11 @@ public override Implementation VisitImplementation(Implementation impl) } } + #region proofgen impl.CoalescedBlocksToTarget = CoalescedBlocksToTarget; impl.ListCoalescedBlocks = ListCoalescedBlocks; + #endregion + // Console.WriteLine("Final number of blocks = {0}", impl.Blocks.Count); return impl; } From d66f2c675db22d2c11a7bb4329549a2e51b50602 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 29 Apr 2024 10:39:44 +0200 Subject: [PATCH 094/123] update foundational_boogie --- foundational_boogie | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundational_boogie b/foundational_boogie index 6254cd790..b005c01e3 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit 6254cd7904468f3d7fece22c16ea6414f2924c1e +Subproject commit b005c01e3ca395cea80e3e4310e3bf0cc206ab27 From dee5441f48093e1b41bb50a7405c0a46ef4df515 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 29 Apr 2024 12:32:45 +0200 Subject: [PATCH 095/123] remove duplicate method for procedure correctness with CFG procedure body --- .../CFGOptimizationsEndToEnd.cs | 25 +++---------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs index ad87f047c..de8d9e28e 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsEndToEnd.cs @@ -111,12 +111,13 @@ public IEnumerable EndToEndProof( new LemmaDecl( "end_to_end_theorem", ContextElem.CreateWithAssumptions(new List {vcAssm}, new List {"VC"}), - ProcedureIsCorrect( + IsaBoogieTerm.ProcedureIsCorrectCfg( programAccessor.FunctionsDecl(), IsaCommonTerms.TermIdentFromName(programAccessor.ConstsDecl()), + IsaCommonTerms.TermIdentFromName(programAccessor.UniqueConstsDecl()), IsaCommonTerms.TermIdentFromName(programAccessor.GlobalsDecl()), programAccessor.AxiomsDecl(), - programAccessor.ProcDeclName()), + IsaCommonTerms.TermIdentFromName(programAccessor.ProcDeclName())), new Proof( new List { @@ -210,24 +211,4 @@ public static Term CfgOptLemmaConclusion(BoogieContextIsa boogieContext, Term po finalState); } - public static Term ProcedureIsCorrect(Term funDecls, Term constantDecls, Term globalDecls, Term axioms, - string name) - { - var typeInterpId = new SimpleIdentifier("A"); - return - TermQuantifier.MetaAll( - new List {typeInterpId}, - null, - new TermApp( - IsaCommonTerms.TermIdentFromName("Semantics.proc_is_correct"), - //TODO: here assuming that we use "'a" for the abstract value type carrier t --> make t a parameter somewhere - new TermWithExplicitType(new TermIdent(typeInterpId), - IsaBoogieType.AbstractValueTyFunType(new VarType("a"))), - funDecls, - constantDecls, - globalDecls, - axioms, - IsaCommonTerms.TermIdentFromName(name), - IsaBoogieTerm.SematicsProcSpecSatisfied)); - } } \ No newline at end of file From 8ec8769fe6777b21eca330986b2ecc4942a7bb44 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 29 Apr 2024 15:08:14 +0200 Subject: [PATCH 096/123] disable CFG optimization benchmarks on CI --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e08c91468..9508aa817 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,9 +72,9 @@ jobs: BOOGIE_EXE=$(find $PWD -type f -name "BoogieDriver") python3 etc/scripts/generate_proofs.py --inputdir ProofGenerationBenchmarks/cfg_optimizations_tests --outputdir cfg_optimizations_proofs --boogieproofExe $BOOGIE_EXE - - name: Check CFG optimization proofs - run: | - python3 etc/scripts/check_proofs.py --inputdir cfg_optimizations_proofs --reps 1 + #- name: Check CFG optimization proofs + # run: | + # python3 etc/scripts/check_proofs.py --inputdir cfg_optimizations_proofs --reps 1 - name: Generate Boogie benchmark proofs run: | From ed9123cc338702e7560c27b18ca84dd60a297adb Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 29 Apr 2024 18:51:57 +0200 Subject: [PATCH 097/123] restore if-then-else statements in ProofGenerationBenchmarks --- .../inline/expansion4.bpl | 4 -- .../stratifiedinline/bar4.bpl | 9 +-- .../textbook/DivMod.bpl | 46 +------------ .../external_benchmarks/modified/DivMod.bpl | 45 ++---------- .../modified/DivMod_if_stmt.bpl | 69 +++++++++++++++++++ 5 files changed, 77 insertions(+), 96 deletions(-) create mode 100644 ProofGenerationBenchmarks/external_benchmarks/modified/DivMod_if_stmt.bpl diff --git a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/inline/expansion4.bpl b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/inline/expansion4.bpl index 0b5342cc3..cfd0672d5 100644 --- a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/inline/expansion4.bpl +++ b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/inline/expansion4.bpl @@ -1,11 +1,7 @@ // RUN: %boogie "%s" > "%t" // RUN: %diff "%s.expect" "%t" -/* MANUAL REWRITE: function foo(x:int) : int { if x <= 0 then 1 else foo(x - 1) + 2 } -*/ -function foo(x:int) : int; -axiom( forall x:int :: ((x <= 0 ==> foo(x) == 1) && (x > 0 ==> foo(x) == foo(x - 1) + 2))); procedure bar() { diff --git a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/stratifiedinline/bar4.bpl b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/stratifiedinline/bar4.bpl index efeac9586..14583e3b4 100644 --- a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/stratifiedinline/bar4.bpl +++ b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/stratifiedinline/bar4.bpl @@ -27,20 +27,13 @@ modifies x, y; } -procedure main() returns (b: bool) +procedure main() returns (b: bool) modifies x, y; { assume x == y; call foo(); if (x == y) { call b := bar(); - /** MANUAL REWRITE: assume (if b then x+1 != y else x != y+1); - */ - if(b) { - assume x+1 != y; - } else { - assume x != y+1; - } } } diff --git a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/textbook/DivMod.bpl b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/textbook/DivMod.bpl index fc359d47c..fad75f353 100644 --- a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/textbook/DivMod.bpl +++ b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/textbook/DivMod.bpl @@ -7,11 +7,7 @@ // // Rustan Leino, 23 Sep 2010 -/** MANUAL REWRITE: function abs(x: int): int { if 0 <= x then x else -x } -**/ -function abs(x: int): int; -axiom (forall x: int :: ( 0<= x ==> abs(x) == x) && ( (!(0 <= x)) ==> abs(x) == -x)); function divt(int, int): int; function modt(int, int): int; @@ -43,29 +39,9 @@ procedure T_from_E(a,b: int) returns (q,r: int) qq := dive(a,b); rr := mode(a,b); - /** MANUAL REWRITE q := if 0 <= a || rr == 0 then qq else if 0 <= b then qq+1 else qq-1; r := if 0 <= a || rr == 0 then rr else if 0 <= b then rr-b else rr+b; - **/ - if(0 <= a || rr == 0) { - q := qq; - } else { - if (0<=b) { - q := qq+1; - } else { - q := qq-1; - } - } - if (0 <= a || rr == 0) { - r := rr; - } else { - if(0 <= b) { - r := rr-b; - } else { - r := rr+b; - } - } - assume true; + assume true; } procedure E_from_T(a,b: int) returns (q,r: int) @@ -84,26 +60,6 @@ procedure E_from_T(a,b: int) returns (q,r: int) qq := divt(a,b); rr := modt(a,b); - /* MANUAL REWRITE q := if 0 <= rr then qq else if 0 < b then qq-1 else qq+1; r := if 0 <= rr then rr else if 0 < b then rr+b else rr-b; - */ - if(0 <= rr) { - q := qq; - } else { - if (0< b) { - q := qq-1; - } else { - q := qq+1; - } - } - if (0 <= rr) { - r := rr; - } else { - if(0 < b) { - r := rr+b; - } else { - r := rr-b; - } - } } diff --git a/ProofGenerationBenchmarks/external_benchmarks/modified/DivMod.bpl b/ProofGenerationBenchmarks/external_benchmarks/modified/DivMod.bpl index bfefa3942..aec587030 100644 --- a/ProofGenerationBenchmarks/external_benchmarks/modified/DivMod.bpl +++ b/ProofGenerationBenchmarks/external_benchmarks/modified/DivMod.bpl @@ -1,5 +1,4 @@ -function abs(x: int): int; -axiom (forall x: int :: ( 0<= x ==> abs(x) == x) && ( (!(0 <= x)) ==> abs(x) == -x)); +function abs(x: int): int { if 0 <= x then x else -x } function divt(int, int): int; function modt(int, int): int; axiom (forall a,b: int :: divt(a,b)*b + modt(a,b) == a); @@ -19,25 +18,9 @@ procedure T_from_E(a,b: int) returns (q,r: int) var qq,rr: int; qq := dive(a,b); rr := mode(a,b); - if(0 <= a || rr == 0) { - q := qq; - } else { - if (0<=b) { - q := qq+1; - } else { - q := qq-1; - } - } - if (0 <= a || rr == 0) { - r := rr; - } else { - if(0 <= b) { - r := rr-b; - } else { - r := rr+b; - } - } - assume true; + q := if 0 <= a || rr == 0 then qq else if 0 <= b then qq+1 else qq-1; + r := if 0 <= a || rr == 0 then rr else if 0 <= b then rr-b else rr+b; + assume true; } procedure E_from_T(a,b: int) returns (q,r: int) requires b != 0; @@ -48,22 +31,6 @@ procedure E_from_T(a,b: int) returns (q,r: int) var qq,rr: int; qq := divt(a,b); rr := modt(a,b); - if(0 <= rr) { - q := qq; - } else { - if (0< b) { - q := qq-1; - } else { - q := qq+1; - } - } - if (0 <= rr) { - r := rr; - } else { - if(0 < b) { - r := rr+b; - } else { - r := rr-b; - } - } + q := if 0 <= rr then qq else if 0 < b then qq-1 else qq+1; + r := if 0 <= rr then rr else if 0 < b then rr+b else rr-b; } diff --git a/ProofGenerationBenchmarks/external_benchmarks/modified/DivMod_if_stmt.bpl b/ProofGenerationBenchmarks/external_benchmarks/modified/DivMod_if_stmt.bpl new file mode 100644 index 000000000..bfefa3942 --- /dev/null +++ b/ProofGenerationBenchmarks/external_benchmarks/modified/DivMod_if_stmt.bpl @@ -0,0 +1,69 @@ +function abs(x: int): int; +axiom (forall x: int :: ( 0<= x ==> abs(x) == x) && ( (!(0 <= x)) ==> abs(x) == -x)); +function divt(int, int): int; +function modt(int, int): int; +axiom (forall a,b: int :: divt(a,b)*b + modt(a,b) == a); +axiom (forall a,b: int :: + (0 <= a ==> 0 <= modt(a,b) && modt(a,b) < abs(b)) && + (a < 0 ==> -abs(b) < modt(a,b) && modt(a,b) <= 0)); +function dive(int, int): int; +function mode(int, int): int; +axiom (forall a,b: int :: dive(a,b)*b + mode(a,b) == a); +axiom (forall a,b: int :: 0 <= mode(a,b) && mode(a,b) < abs(b)); +procedure T_from_E(a,b: int) returns (q,r: int) + requires b != 0; + ensures q*b + r == a; + ensures 0 <= a ==> 0 <= r && r < abs(b); + ensures a < 0 ==> -abs(b) < r && r <= 0; +{ + var qq,rr: int; + qq := dive(a,b); + rr := mode(a,b); + if(0 <= a || rr == 0) { + q := qq; + } else { + if (0<=b) { + q := qq+1; + } else { + q := qq-1; + } + } + if (0 <= a || rr == 0) { + r := rr; + } else { + if(0 <= b) { + r := rr-b; + } else { + r := rr+b; + } + } + assume true; +} +procedure E_from_T(a,b: int) returns (q,r: int) + requires b != 0; + ensures q*b + r == a; + ensures 0 <= r; + ensures r < abs(b); +{ + var qq,rr: int; + qq := divt(a,b); + rr := modt(a,b); + if(0 <= rr) { + q := qq; + } else { + if (0< b) { + q := qq-1; + } else { + q := qq+1; + } + } + if (0 <= rr) { + r := rr; + } else { + if(0 < b) { + r := rr+b; + } else { + r := rr-b; + } + } +} From 4e11ca168b30130454e9a411aebaeb6df9770a13 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Mon, 29 Apr 2024 20:13:03 +0200 Subject: [PATCH 098/123] adjust find_supported_boogie_benchmarks.py to work with current version of code Note that since the code has changed, the filtering leads to slightly different results than earlier versions because different Boogie versions have different conditions for rejecting (or for outputting data about) a program. --- .../find_supported_boogie_benchmarks.py | 70 ++++++++++++++----- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/etc/scripts/find_supported_boogie_benchmarks.py b/etc/scripts/find_supported_boogie_benchmarks.py index 96f90df70..4e0920f3c 100644 --- a/etc/scripts/find_supported_boogie_benchmarks.py +++ b/etc/scripts/find_supported_boogie_benchmarks.py @@ -1,4 +1,5 @@ import os +import shutil import subprocess import time import sys @@ -8,11 +9,28 @@ boogie_proofgen_bin = 'boogieproof' boogie_orig_bin = 'boogieorig' -def adjust_and_filter(filename, output_filename): +# copies file to output directory such that the directory structure of the source destination is kept (relative to test_dir) +def store_file_in_output_dir(file_path, output_dir, test_dir): + relpath = os.path.relpath(file_path, test_dir) + print("Test dir: {}, File path: {}, Relative path: {}".format(test_dir, file_path, relpath)) + target_path = os.path.join(output_dir, relpath) + + os.makedirs(os.path.dirname(target_path), exist_ok=True) + + shutil.copyfile(file_path, target_path) + +def adjust_and_filter(filename, output_dir, test_dir): n_supported_success = 0 n_supported_error = 0 n_empty_files = 0 + if(os.path.exists(output_dir)): + print("Error: Output dir {} exists".format(output_dir)) + exit(1) + + os.mkdir(output_dir) + output_filename = os.path.join(output_dir, "origin_list.txt") + with open(output_filename, 'w') as output_file: with open(filename) as f: print("Starting next selection: Remove all attributes of files in first selection and check if they verify.") @@ -48,11 +66,15 @@ def adjust_and_filter(filename, output_filename): # space before 0, otherwise "10 errors" would succeed the test as well if " 0 errors" in str(output) and (not ("inconclusive" in str(output))): n_supported_success += 1 - print("Selected " + boogie_file) + + print("Selected " + boogie_file) + output_file.write(boogie_file+"\n") + + store_file_in_output_dir(file_path=boogie_file, output_dir=output_dir, test_dir=test_dir) else: n_supported_error += 1 - # print("Failure:" + boogie_file) + print("Failure:" + boogie_file) print("Found " + str(n_supported_success) + " potentially supported tests that are verified after removing all attributes.") @@ -68,8 +90,8 @@ def main(): required=True) parser.add_argument( - "-o", "--outputfile", - help="Specify output file containing the list of test that are verified by Boogie and that are (potentially) supported by proof generation.", + "-o", "--outputdir", + help="Specify output directory containing the tests are verified by Boogie and that are (potentially) supported by proof generation.", required=True) args = parser.parse_args() @@ -78,37 +100,49 @@ def main(): print(args.testdir + " is not a directory.") exit(1) - if(os.path.exists(args.outputfile)): - print(args.outputfile + " already exists.") + if(os.path.exists(args.outputdir)): + print(args.outputdir + " already exists.") exit(1) + # write all Boogie test file paths that are potentially supported by proof generation into a temporary file filename = time.strftime("%Y%m%d-%H%M%S")+"_potentially_supported.log" with open(filename, 'w') as potentially_supported_file: print("Starting coarse-grained selection of tests") + + def file_potentially_supported_from_output(output): + output_split = output.splitlines() + return len(output_split) > 0 and output_split[0].startswith("Success:") + n_candidate_files = 0 + for root, dirs, files in os.walk(args.testdir): for file in files: if file.endswith('.bpl'): test_file_path = os.path.join(root, file) + n_candidate_files += 1 + + print(test_file_path) + + # the option "/onlyCheckProofGenSupport" only performs a coarse-grained check whether + # proof generation supports a file and does not generate any proofs + process = subprocess.Popen([boogie_proofgen_bin, "/onlyCheckProofGenSupport",test_file_path], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output, error = process.communicate() + return_code = process.returncode + + if return_code == 0 and file_potentially_supported_from_output(output.decode('utf-8')): + print("success") + potentially_supported_file.write(test_file_path+"\n") + else: + print("error (return code: {}, error: {}, output: {})".format(return_code, error.decode('utf-8'), output.decode('utf-8'))) - with open(test_file_path) as f: - n_candidate_files += 1 - # the option "/onlyCheckProofGenSupport" only performs a coarse-grained check whether - # proof generation supports a file and does not generate any proofs - output = subprocess.check_output([boogie_proofgen_bin, "/onlyCheckProofGenSupport",test_file_path]).decode(sys.stdout.encoding) - - output_split = output.splitlines() - if len(output_split) > 0 and output_split[0].startswith("Success:"): - # print(output_split[0][8:]) - potentially_supported_file.write(output_split[0][8:]+"\n") print("Finished coarse-grained selection of tests") """ From the identified files, select those tests that verify after removing attributes (this has a side effect on the files --> attributes removed). """ - adjust_and_filter(filename, args.outputfile) + adjust_and_filter(filename, args.outputdir, args.testdir) # remove the temporary file os.remove(filename) From 0c2ea0294019187304062fd31eee818032950eb2 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Thu, 9 May 2024 12:32:09 +0200 Subject: [PATCH 099/123] replace xor with xorCustom in secure/simple.bpl and remove ProofGen(IgnoreFile) annotation Isabelle already defines the name xor. It would be good to change the proof generation to not use reserved Isabelle names in the first place so that such renamings are not required when generating proofs. --- .../secure/simple.bpl | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/secure/simple.bpl b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/secure/simple.bpl index 59a092ae7..cf2442fac 100644 --- a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/secure/simple.bpl +++ b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/secure/simple.bpl @@ -1,11 +1,12 @@ -//:: ProofGen(IgnoreFile) // Z3 4.1: /trace /proverOpt:O:smt.mbqi=true /proverOpt:O:smt.relevancy=0 -function xor(a: bool, b: bool) returns (bool) { (!a && b) || (a && !b) } + +/** MANUAL REWRITE: Replaced all xor with xorCustom (since xor is already defined in Isabelle) */ +function xorCustom(a: bool, b: bool) returns (bool) { (!a && b) || (a && !b) } procedure Incorrect_A( a: bool, b: bool) returns ( ap: bool, bp: bool) - ensures xor(ap, bp) == xor(a, b); + ensures xorCustom(ap, bp) == xorCustom(a, b); { ap := a; bp := b; @@ -14,7 +15,7 @@ returns ( ap: bool, bp: bool) procedure Incorrect_B( a: bool, b: bool) returns ( ap: bool, bp: bool) - ensures xor(ap, bp) == xor(a, b); + ensures xorCustom(ap, bp) == xorCustom(a, b); { ap := a; bp := b; @@ -23,7 +24,7 @@ returns ( ap: bool, bp: bool) procedure Incorrect_X( a: bool, b: bool) returns ( ap: bool, bp: bool) - ensures xor(ap, bp) == xor(a, b); + ensures xorCustom(ap, bp) == xorCustom(a, b); { ap := a; bp := b; @@ -32,27 +33,27 @@ returns ( ap: bool, bp: bool) procedure Correct_A( a: bool, b: bool) returns ( ap: bool, bp: bool) - ensures xor(ap, bp) == xor(a, b); + ensures xorCustom(ap, bp) == xorCustom(a, b); { havoc ap; - bp := xor(xor(ap, a), b); + bp := xorCustom(xorCustom(ap, a), b); } procedure Correct_B( a: bool, b: bool) returns ( ap: bool, bp: bool) - ensures xor(ap, bp) == xor(a, b); + ensures xorCustom(ap, bp) == xorCustom(a, b); { havoc ap; - bp := xor(xor(ap, a), b); + bp := xorCustom(xorCustom(ap, a), b); } procedure Correct_X( a: bool, b: bool) returns ( ap: bool, bp: bool) - ensures xor(ap, bp) == xor(a, b); + ensures xorCustom(ap, bp) == xorCustom(a, b); { havoc ap; - bp := xor(xor(ap, a), b); + bp := xorCustom(xorCustom(ap, a), b); } From 815d1c722b15ec5925d14d1f9e583e3901a7dc7b Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Thu, 9 May 2024 18:24:35 +0200 Subject: [PATCH 100/123] boogie proofs analysis --- etc/scripts/boogie_proofs_analysis.py | 178 ++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 etc/scripts/boogie_proofs_analysis.py diff --git a/etc/scripts/boogie_proofs_analysis.py b/etc/scripts/boogie_proofs_analysis.py new file mode 100644 index 000000000..c0f5a7a1e --- /dev/null +++ b/etc/scripts/boogie_proofs_analysis.py @@ -0,0 +1,178 @@ +import os +import argparse +import typing as typ +from enum import Enum +from typing import List + +class EndToEndKind(Enum): + full = 1 + ast_and_full_cfg = 2 + only_full_cfg = 3 + +class TestData(typ.NamedTuple): + file: str + num_procedures: int + isabelle_loc: int + end_to_end_proof: List[EndToEndKind] + # for each procedure proof provides end-to-end proof kind (i.e., length should match num_procedures) + +def file_exists_in_dir(file, path) -> bool: + return file in os.listdir(path) + +def check_string_exists_in_file(search_string, path) -> bool: + if not(os.path.isfile(path)): + print("ERROR: {} is not an existing file.".format(path)) + exit(1) + + matches = [line for line in open(path,'r') if search_string in line] + return matches != [] + + +def ast_to_cfg_proof(dir, procedure_name): + return os.path.join(dir, procedure_name+"_asttocfg_proof.thy") + +def cfg_opt_proof(dir, procedure_name): + return os.path.join(dir, procedure_name+"_cfgoptimizations_proof.thy") + +def cfg_to_dag_proof(dir, procedure_name): + return os.path.join(dir, procedure_name+"_cfgtodag_proof.thy") + +def get_e2e_kind(procedure_name, dir) -> EndToEndKind: + ast_exists : bool = os.path.isfile(ast_to_cfg_proof(dir, procedure_name)) + if not(os.path.isfile(cfg_to_dag_proof(dir, procedure_name))): + print("ERROR: CFG-to-DAG proof {} does not exist in {}".format(cfg_to_dag_proof(dir, procedure_name), dir)) + exit(1) + + # important to query cfg_to_dag first, since cfg_opt proof may not exist (relies on lazy evaluation of `or`) + # this is a method because if ast e2e exists then we do not need to evaluate this expression (+ want reuse) + def cfg_end_to_end(): + return (check_string_exists_in_file("lemma end_to_end_theorem:", cfg_to_dag_proof(dir, procedure_name)) or + check_string_exists_in_file("lemma end_to_end_theorem:", cfg_opt_proof(dir, procedure_name))) + + if ast_exists: + if check_string_exists_in_file("lemma end_to_end_theorem_ast:", ast_to_cfg_proof(dir, procedure_name)): + return EndToEndKind.full + + if cfg_end_to_end(): + return EndToEndKind.ast_and_full_cfg + + print("ERROR: no end-to-end theorem found in {}".format(dir)) + exit(1) + + if cfg_end_to_end(): + return EndToEndKind.only_full_cfg + + print("ERROR: no end-to-end theorem found in {}".format(dir)) + exit(1) + +def certificate_size(proof_dir_path) -> int: + length_certificate = 0 + for root, dirs, files in os.walk(proof_dir_path): + for file in files: + if file.endswith('.thy'): + file_path = os.path.join(os.path.join(proof_dir_path, root), file) + file_content = open(file_path, "r") + nonempty_lines = [line for line in file_content if line.strip() != "\n"] + length_certificate += len(nonempty_lines) + + return length_certificate + +def collect_data_single_boogie_file(proof_dir_path, num_procedures): + e2e_proof_kinds = [] + for procedure_proof in os.listdir(proof_dir_path): + procedure_proof_path = os.path.join(proof_dir_path, procedure_proof) + if(os.path.isdir(procedure_proof_path)): + if(not(procedure_proof.endswith("_proofs"))): + print("ERROR: procedure proof directory {} does not end with '_proofs'".format(procedure_proof_path)) + exit(1) + + procedure_name = procedure_proof.split("_proofs")[0] + e2e_proof_kind = get_e2e_kind(procedure_name, procedure_proof_path) + e2e_proof_kinds.append(e2e_proof_kind) + + if len(e2e_proof_kinds) != num_procedures: + print("ERROR: mismatch number of procedures and e2e proofs in {}".format(proof_dir_path)) + exit(1) + + return TestData(file=os.path.basename(proof_dir_path), num_procedures=num_procedures, isabelle_loc=certificate_size(proof_dir_path),end_to_end_proof=e2e_proof_kinds) + +def collect_complete_data(boogie_files_dir, boogie_proofs_dir) -> List[TestData]: + data = [] + boogie_proofs_dir_abs = os.path.abspath(boogie_proofs_dir) + for proof_dir in os.listdir(boogie_proofs_dir_abs): + proof_dir_path = os.path.join(boogie_proofs_dir_abs, proof_dir) + if not(os.path.isfile(os.path.join(proof_dir_path, "ROOT"))): + print("Skipping {}".format(proof_dir_path)) + continue + + if not(proof_dir.endswith("_proofs")): + print("ERROR: {} does not end with '_proofs'".format(proof_dir)) + exit(1) + + boogie_file_name = proof_dir.split("_proofs")[0]+".bpl" + boogie_file_path = os.path.join(boogie_files_dir, boogie_file_name) + if not(os.path.isfile(boogie_file_path)): + print("ERROR: Boogie file {} does not exist".format(boogie_file_path)) + exit(1) + + boogie_file_content = [line for line in open(boogie_file_path,'r')] + num_procedures = len([line for line in boogie_file_content if line.strip(" ").startswith("procedure ")]) + + if num_procedures != len([y for y in os.listdir(proof_dir_path) if os.path.isdir(os.path.join(proof_dir_path, y))]): + print("ERROR: Number of procedures and number of proofs do not match for {}".format(proof_dir_path)) + exit(1) + + data.append(collect_data_single_boogie_file(proof_dir_path, num_procedures)) + + return data + + +def main(): + parser = argparse.ArgumentParser() + + parser.add_argument( + "-t", "--testsdir", + help="Directory where the Boogie files are located, for which the proofs were generated.", + required=True) + + parser.add_argument( + "-p", "--proofsdir", + help="Directory where the Boogie proofs are located.", + required=True) + + + args = parser.parse_args() + + if (not(os.path.isdir(args.testsdir))): + print("The input directory " + args.testsdir+ " does not point to an existing directory.") + exit(1) + + if (not(os.path.isdir(args.proofsdir))): + print("The input directory " + args.proofsdir+ " does not point to an existing directory.") + exit(1) + + data : List[TestData] = collect_complete_data(boogie_files_dir=args.testsdir, boogie_proofs_dir=args.proofsdir) + + def count_e2e_kind(kind): + return sum([len([k for k in d.end_to_end_proof if k == kind]) for d in data]) + + num_full_proofs = count_e2e_kind(EndToEndKind.full) + num_ast_and_full_cfgproofs = count_e2e_kind(EndToEndKind.ast_and_full_cfg) + num_only_cfg_proofs = count_e2e_kind(EndToEndKind.only_full_cfg) + + print("Full proofs: {}, AST and full CFG proofs: {}, Only CFG proofs: {}".format( + num_full_proofs, + num_ast_and_full_cfgproofs, + num_only_cfg_proofs + )) + + total_num_procedures = sum([d.num_procedures for d in data]) + + if((num_full_proofs + num_ast_and_full_cfgproofs + num_only_cfg_proofs) != total_num_procedures): + print("ERROR: sum of E2E kinds does not match with length of data") + exit(1) + + + +if __name__ == '__main__': + main() \ No newline at end of file From ad804e411f36af5145d821dda608a03730a7c5d7 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Thu, 16 May 2024 20:22:23 +0200 Subject: [PATCH 101/123] remove duplicate file (same as functiondefine/fundef7.bpl) --- .../inline/test0.bpl | 50 ------------------- 1 file changed, 50 deletions(-) delete mode 100644 ProofGenerationBenchmarks/boogie_testsuite_benchmarks/inline/test0.bpl diff --git a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/inline/test0.bpl b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/inline/test0.bpl deleted file mode 100644 index 999b9e128..000000000 --- a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/inline/test0.bpl +++ /dev/null @@ -1,50 +0,0 @@ -// RUN: %boogie "%s" > "%t" -// RUN: %diff "%s.expect" "%t" -// inlined functions - -function Twice(x: int) returns (int) -{ - x + x -} - -function Double(x: int) returns (int) -{ - 3 * x - x -} - -function f(int) returns (int); -function g(int) returns (int); -function h(int) returns (int); -function k(int) returns (int); -axiom (forall x: int :: Twice(x) == f(x)); // here, Twice(x) and f(x) are both triggers -axiom (forall x: int :: Double(x) == g(x)); // since Double is inlined, the trigger here is just g(x) -axiom (forall x: int :: { f(x) } f(x) < h(x) ); -axiom (forall x: int :: { g(x) } g(x) < k(x) ); - -procedure P(a: int, b: int, c: int) -{ - // The following is provable, because Twice triggers its definition and the resulting f(a) - // triggers the relation to h(a). - assert Twice(a) < h(a); - if (*) { - // The following is NOT provable, because Double is inlined and thus no g(b) term is ever - // created - assert Double(b) < k(b); // error - } else { - // The following IS provable, because the explicit g(c) will cause both of the necessary - // quantifiers to trigger - assert g(c) == 2*c; - assert Double(c) < k(c); - } -} - -// nullary functions - -function Five() returns (int) { 5 } - -function Eight() returns (e: int) { 8 } - -procedure Q() -{ - assert 8 * Five() == 5 * Eight(); -} From 4c8992ca3892d89028b60c24a23bbb336ccdb014 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Thu, 16 May 2024 20:22:40 +0200 Subject: [PATCH 102/123] boogie_proofs_analysis update --- etc/scripts/boogie_proofs_analysis.py | 74 +++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/etc/scripts/boogie_proofs_analysis.py b/etc/scripts/boogie_proofs_analysis.py index c0f5a7a1e..99b537c39 100644 --- a/etc/scripts/boogie_proofs_analysis.py +++ b/etc/scripts/boogie_proofs_analysis.py @@ -3,6 +3,9 @@ import typing as typ from enum import Enum from typing import List +import csv +import time +import re class EndToEndKind(Enum): full = 1 @@ -11,7 +14,7 @@ class EndToEndKind(Enum): class TestData(typ.NamedTuple): file: str - num_procedures: int + num_procedure_proofs: int isabelle_loc: int end_to_end_proof: List[EndToEndKind] # for each procedure proof provides end-to-end proof kind (i.e., length should match num_procedures) @@ -72,13 +75,22 @@ def certificate_size(proof_dir_path) -> int: if file.endswith('.thy'): file_path = os.path.join(os.path.join(proof_dir_path, root), file) file_content = open(file_path, "r") - nonempty_lines = [line for line in file_content if line.strip() != "\n"] + nonempty_lines = [line for line in file_content if line.strip()] length_certificate += len(nonempty_lines) return length_certificate + +def count_num_abstract_procs(lines) -> int: + count = 0 + regex_pattern = r'procedure \w*\((\w|:)*\);' + for line in lines: + matches = re.findall(regex_pattern, line) + count += len(matches) + return count def collect_data_single_boogie_file(proof_dir_path, num_procedures): e2e_proof_kinds = [] + num_procedure_proofs = 0 for procedure_proof in os.listdir(proof_dir_path): procedure_proof_path = os.path.join(proof_dir_path, procedure_proof) if(os.path.isdir(procedure_proof_path)): @@ -89,12 +101,15 @@ def collect_data_single_boogie_file(proof_dir_path, num_procedures): procedure_name = procedure_proof.split("_proofs")[0] e2e_proof_kind = get_e2e_kind(procedure_name, procedure_proof_path) e2e_proof_kinds.append(e2e_proof_kind) + num_procedure_proofs += 1 + """ if len(e2e_proof_kinds) != num_procedures: print("ERROR: mismatch number of procedures and e2e proofs in {}".format(proof_dir_path)) exit(1) + """ - return TestData(file=os.path.basename(proof_dir_path), num_procedures=num_procedures, isabelle_loc=certificate_size(proof_dir_path),end_to_end_proof=e2e_proof_kinds) + return TestData(file=os.path.basename(proof_dir_path), num_procedure_proofs=num_procedure_proofs, isabelle_loc=certificate_size(proof_dir_path),end_to_end_proof=e2e_proof_kinds) def collect_complete_data(boogie_files_dir, boogie_proofs_dir) -> List[TestData]: data = [] @@ -112,20 +127,48 @@ def collect_complete_data(boogie_files_dir, boogie_proofs_dir) -> List[TestData] boogie_file_name = proof_dir.split("_proofs")[0]+".bpl" boogie_file_path = os.path.join(boogie_files_dir, boogie_file_name) if not(os.path.isfile(boogie_file_path)): - print("ERROR: Boogie file {} does not exist".format(boogie_file_path)) - exit(1) + # try finding any file with the same name + + candidates = [os.path.join(root,f) for root, dirs, files in os.walk(boogie_files_dir) for f in files if f == boogie_file_name] + if len(candidates) == 0: + print("ERROR: Boogie file {} does not exist".format(boogie_file_name)) + exit(1) + elif len(candidates) >= 2: + print("ERROR: Multiple candidates for Boogie file {}".format(boogie_file_name)) + exit(1) + + boogie_file_path = os.path.join(boogie_files_dir, candidates[0]) + if(not(os.path.exists(boogie_file_path))): + print("CODE ERROR: file {} does not exist".format(boogie_file_path)) + exit(1) boogie_file_content = [line for line in open(boogie_file_path,'r')] num_procedures = len([line for line in boogie_file_content if line.strip(" ").startswith("procedure ")]) - - if num_procedures != len([y for y in os.listdir(proof_dir_path) if os.path.isdir(os.path.join(proof_dir_path, y))]): - print("ERROR: Number of procedures and number of proofs do not match for {}".format(proof_dir_path)) + num_abstract_procedures = count_num_abstract_procs(boogie_file_content) #TODO: this computation of abstract procedures is incorrect + num_concrete_procedures = num_procedures - num_abstract_procedures + + #if num_abstract_procedures > 0: + #print("{} has {} abstract procedures".format(boogie_file_path, num_abstract_procedures)) + + """ + if num_concrete_procedures != len([y for y in os.listdir(proof_dir_path) if os.path.isdir(os.path.join(proof_dir_path, y))]): + print("ERROR: Number of non-abstract procedures in {} do not match number of proofs in {}".format(boogie_file_path, proof_dir_path)) exit(1) + """ - data.append(collect_data_single_boogie_file(proof_dir_path, num_procedures)) + data.append(collect_data_single_boogie_file(proof_dir_path, num_concrete_procedures)) return data +def write_data_into_csv(data : List[TestData], output_file): + with open(output_file, 'w', newline='') as output: + writer = csv.writer(output, delimiter=',') + + writer.writerow(["File", "# Procs", "Isabelle LOC", "E2E Kind"]) + for d in data: + e2e_repr = " ".join(e.name for e in d.end_to_end_proof) + writer.writerow([d.file, d.num_procedure_proofs, d.isabelle_loc, e2e_repr]) + def main(): parser = argparse.ArgumentParser() @@ -152,6 +195,13 @@ def main(): exit(1) data : List[TestData] = collect_complete_data(boogie_files_dir=args.testsdir, boogie_proofs_dir=args.proofsdir) + + num_boogie_files = len([f for root, dirs, files in os.walk(args.testsdir) for f in files if f.endswith(".bpl")]) + if(len(data) != num_boogie_files): + print("ERROR: length of data does not match number of Boogie files") + exit(1) + + print("Numer of E2E proofs {}".format(len(data))) def count_e2e_kind(kind): return sum([len([k for k in d.end_to_end_proof if k == kind]) for d in data]) @@ -166,12 +216,14 @@ def count_e2e_kind(kind): num_only_cfg_proofs )) - total_num_procedures = sum([d.num_procedures for d in data]) + total_num_procedure_proofs = sum([d.num_procedure_proofs for d in data]) - if((num_full_proofs + num_ast_and_full_cfgproofs + num_only_cfg_proofs) != total_num_procedures): + if((num_full_proofs + num_ast_and_full_cfgproofs + num_only_cfg_proofs) != total_num_procedure_proofs): print("ERROR: sum of E2E kinds does not match with length of data") exit(1) + output_file_name = time.strftime("%Y%m%d_%H%M")+os.path.basename(args.proofsdir)+"_analysis.csv" + write_data_into_csv(data, output_file_name) if __name__ == '__main__': From 72078c72da8a1a87d78d3d11489880a022dfa735 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 20 Aug 2024 16:32:23 +0200 Subject: [PATCH 103/123] support CFG transformation proofs if there are else-if branches --- Source/Core/AstToCfgProofGenInfo.cs | 9 ++++++--- Source/ProofGeneration/ProofGenerationLayer.cs | 6 +++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Source/Core/AstToCfgProofGenInfo.cs b/Source/Core/AstToCfgProofGenInfo.cs index e0039b7cb..ba714cc95 100644 --- a/Source/Core/AstToCfgProofGenInfo.cs +++ b/Source/Core/AstToCfgProofGenInfo.cs @@ -460,7 +460,7 @@ private void FillEmptyElseBranches(BigBlock b) FillEmptyElseBranches(thenBb); } - if (ifcmd.elseBlock == null) + if (ifcmd.elseIf == null && ifcmd.elseBlock == null) { IList emptyElseBranch = new List(); BigBlock emptyElseBranchBigBlock = new BigBlock(Token.NoToken, null, new List(), null, null); @@ -471,9 +471,12 @@ private void FillEmptyElseBranches(BigBlock b) ifcmd.elseBlock = new StmtList(emptyElseBranch, Token.NoToken); } - foreach (var elseBb in ifcmd.elseBlock.BigBlocks) + if (ifcmd.elseBlock != null) { - FillEmptyElseBranches(elseBb); + foreach (var elseBb in ifcmd.elseBlock.BigBlocks) + { + FillEmptyElseBranches(elseBb); + } } } else if (b.ec is WhileCmd wcmd) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 53f8dcbfa..7de58edd9 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -144,12 +144,12 @@ public static void Program(Program p) } } - private static bool AstContainsGotoOrBreak(AstToCfgProofGenInfo proofGenInfo) + private static bool AstContainsGotoOrBreakOrElseIf(AstToCfgProofGenInfo proofGenInfo) { IList ast = proofGenInfo.GetBigBlocks(); foreach (var b in ast) { - if (b.ec is BreakCmd || b.tc is GotoCmd) + if (b.ec is BreakCmd || b.tc is GotoCmd || (b.ec is IfCmd bIf && bIf.elseIf != null)) { return true; } @@ -580,7 +580,7 @@ public static void VCGenerateAllProofs( var map = AstToCfgProofGenInfoManager.GetImplToProofGenInfo(); proofGenInfo = map[afterPassificationImpl]; - if (AstContainsGotoOrBreak(proofGenInfo)) + if (AstContainsGotoOrBreakOrElseIf(proofGenInfo)) { _proofGenConfig.SetAstCfgProof(false); } From 2b088a5667fcda8669f3dd4cc8ef9cc096c963c5 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 21 Aug 2024 16:55:14 +0200 Subject: [PATCH 104/123] handle the case when a predecessor of a loop head has multiple successors In such a case a new block is added between the predecessor and the loop head. This new block asserts the invariant. --- .../CfgToDag/CfgToDagHintManager.cs | 25 ++++++++++++---- .../CfgToDag/CfgToDagLemmaManager.cs | 30 ++++++++++++++----- .../ProofGeneration/ProofGenerationLayer.cs | 11 +++++++ Source/VCGeneration/VCGen.cs | 4 +++ 4 files changed, 57 insertions(+), 13 deletions(-) diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagHintManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagHintManager.cs index 807a079cb..33d799919 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagHintManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagHintManager.cs @@ -15,6 +15,10 @@ public class CfgToDagHintManager //maps backedge nodes which are not present before the CFG-to-DAG to the corresponding loop head private readonly IDictionary newBackedgeNodesToLoopHead = new Dictionary(); + + //maps nodes before entry to loop which are not present before CFG-to-DAG to the corresponding loop head + private readonly IDictionary newPreLoopNodesToLoopHead = new Dictionary(); + private readonly IDictionary origToBeforeDag; private IDictionary _afterDagToOrig; @@ -53,7 +57,13 @@ public void AddNewBackedgeBlock(Block newBackedgeBlock, Block loopHead) { newBackedgeNodesToLoopHead.Add(newBackedgeBlock, loopHead); } - + + /// pre loop entry block that is newly added in the CFG-to-DAG phase. + /// corresponding loop head + public void AddNewPreLoopEntryBlock(Block newPreLoopEntryBlock, Block loopHead) + { + newPreLoopNodesToLoopHead.Add(newPreLoopEntryBlock, loopHead); + } public bool IsNewBackedgeBlock(Block afterDagBlock, out LoopHeadHint loopHeadHint) { @@ -78,15 +88,20 @@ public bool IsNewBackedgeBlock(Block afterDagBlock, out Block beforeDagLoopHead, beforeDagLoopHead = null; return false; } + + public bool IsNewPreLoopEntryBlock(Block afterDagBlock) + { + return newPreLoopNodesToLoopHead.ContainsKey(_afterDagToOrig[afterDagBlock]); + } - public bool IsLoopHead(Block block, out LoopHeadHint hint) + public bool IsLoopHead(Block beforeDagBlock, out LoopHeadHint hint) { - return loopHeadHints.TryGetValue(beforeDagToOrig[block], out hint); + return loopHeadHints.TryGetValue(beforeDagToOrig[beforeDagBlock], out hint); } - public LoopHeadHint GetLoopHead(Block block) + public LoopHeadHint GetLoopHead(Block beforeDagBlock) { - return loopHeadHints[beforeDagToOrig[block]]; + return loopHeadHints[beforeDagToOrig[beforeDagBlock]]; } } } \ No newline at end of file diff --git a/Source/ProofGeneration/CfgToDag/CfgToDagLemmaManager.cs b/Source/ProofGeneration/CfgToDag/CfgToDagLemmaManager.cs index 467bc13ad..9a9b1402a 100644 --- a/Source/ProofGeneration/CfgToDag/CfgToDagLemmaManager.cs +++ b/Source/ProofGeneration/CfgToDag/CfgToDagLemmaManager.cs @@ -797,22 +797,36 @@ to propagate the execution in the DAG } else { - /* need to find the empty block that was added in between (does not matter which one, if there - * are multiple such empty blocks) */ + // need to find the empty block that was added in between + var bSucAfterIsLoopHead = hintManager.IsLoopHead(bSuc, out _); + foreach (var afterSuc in afterSuccessors) { var afterSucSuccessors = afterDagCfg.GetSuccessorBlocks(afterSuc); - if (!afterSuc.Cmds.Any() && afterSucSuccessors.Count() == 1 && - afterSucSuccessors.First().Equals(bSucAfter)) + + // block in between must have a single expected successor + if (afterSucSuccessors.Count() != 1 || !afterSucSuccessors.First().Equals(bSucAfter)) { - addedBlock = afterSuc; - break; + continue; } + + /** if expected successor is not a loop head, then the block in between must be empty, + * otherwise the block in between must be a new pre entry loop block (which asserts the loop invariant) + */ + if ( (!bSucAfterIsLoopHead && !afterSuc.Cmds.Any()) + || + (bSucAfterIsLoopHead && hintManager.IsNewPreLoopEntryBlock(afterSuc)) ) + { + addedBlock = afterSuc; + break; //if there are multiple blocks that satisfy the criteria, then we can pick any, so break here + } } if (addedBlock == null) - throw new ProofGenUnexpectedStateException("Could not find block"); - + { + throw new ProofGenUnexpectedStateException("Could not find new target block added in between two source blocks"); + } + bSucAfterId = afterDagProgAccess.BlockInfo().BlockIds[addedBlock]; } diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 7de58edd9..6a30c980c 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -483,6 +483,17 @@ public static void NewBackedgeBlock(Block oldBackedgeBlock, Block newBackedgeBlo return; cfgToDagHintManager.AddNewBackedgeBlock(newBackedgeBlock, loopHead); } + + /// + /// Provide hint that the pre loop entry block is replaced by a new + /// pre entry loop block for a loop with loop head . + /// + public static void NewPreLoopEntryBlock(Block oldPreLoopEntryBlock, Block newPreLoopEntryBlock, Block loopHead) + { + if (CommandLineOptions.Clo.OnlyGenerateInitialProgramIsa()) + return; + cfgToDagHintManager.AddNewPreLoopEntryBlock(newPreLoopEntryBlock, loopHead); + } public static void SetTypeEraserFactory(TypePremiseEraserFactory factory) { diff --git a/Source/VCGeneration/VCGen.cs b/Source/VCGeneration/VCGen.cs index 435bf626f..b87eb8c26 100644 --- a/Source/VCGeneration/VCGen.cs +++ b/Source/VCGeneration/VCGen.cs @@ -1263,6 +1263,10 @@ private void ConvertCFG2DAGStandard(Implementation impl, Dictionary Date: Wed, 21 Aug 2024 17:42:17 +0200 Subject: [PATCH 105/123] use set and list representation in CFGOptimizationsLemmaManger.getConclusion --- .../CFGOptimizations/CFGOptimizationsLemmaManager.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index 1610d132f..360cbf409 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -629,12 +629,10 @@ Identifier finalStateId2 ); } - - - - public static Term getConclusion(List loopHeads, string name, Block beforeBlock, Block afterBlock, IProgramAccessor beforeOptProgAccess, IProgramAccessor afterOptProgAccess, bool isHybridBlock, List listCoalescedBlocks) { + var loopHeadsSet = new TermSet(loopHeads.Select(lh => IsaCommonTerms.TermIdentFromName(lh))); + var varContextName = "\\"; IList terms = new List(); terms.Add(IsaCommonTerms.TermIdentFromName("A")); @@ -648,9 +646,11 @@ public static Term getConclusion(List loopHeads, string name, Block befo terms.Add(new NatConst(afterOptProgAccess.BlockInfo().BlockIds[afterBlock])); if (isHybridBlock) { - terms.Add(IsaCommonTerms.TermIdentFromName("(" + string.Join("@", listCoalescedBlocks) + ")")); + var listCoalescedBlocksTerm = listCoalescedBlocks.Aggregate(IsaCommonTerms.EmptyList, + (x, y) => IsaCommonTerms.AppendList(x, IsaCommonTerms.TermIdentFromName(y))); + terms.Add(listCoalescedBlocksTerm); } - terms.Add(IsaCommonTerms.TermIdentFromName("{" + string.Join(",", loopHeads) + "}")); + terms.Add(loopHeadsSet); terms.Add(afterOptProgAccess.PostconditionsDecl()); Term conclusion = new TermApp(IsaCommonTerms.TermIdentFromName(name), terms); return conclusion; From 4216ee57529b02d79957eaddd0544eab923a6609 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 21 Aug 2024 17:47:04 +0200 Subject: [PATCH 106/123] update foundational_boogie --- foundational_boogie | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundational_boogie b/foundational_boogie index b005c01e3..91cded06b 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit b005c01e3ca395cea80e3e4310e3bf0cc206ab27 +Subproject commit 91cded06bdcc0e5245c852d125c54c69ad619d81 From 8773cc5f9fcaa78917170644b5cfa89b81669721 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 21 Aug 2024 17:49:51 +0200 Subject: [PATCH 107/123] change proof automation for CFG optimizations to deal with case where loop head set representation in a to-be-applied lemma differs from loop head set lemma in proof goal (even after applying the simplifier on the proof goal) --- .../CFGOptimizations/CFGOptimizationsLemmaManager.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs index 360cbf409..9af80be42 100644 --- a/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs +++ b/Source/ProofGeneration/CFGOptimizations/CFGOptimizationsLemmaManager.cs @@ -533,8 +533,9 @@ public LemmaDecl LoopHeadCoalesced( //Loop Head coalesced { "apply (rule loopHead_global_block_hybrid)", "apply (rule " + beforeOptProgAccess.BlockInfo().OutEdgesMembershipLemma(beforeBlock) + ")", - "apply simp", - "apply (rule " + HybridblockLemmaName(beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault()) + ")", + "apply (rule " + ProofUtil.OF("hybrid_block_lemma_loop_eq_loop_heads", + HybridblockLemmaName(beforeOptimizations.GetSuccessorBlocks(beforeBlock).FirstOrDefault())) + ")", + "apply blast", "apply (rule " + beforeOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(beforeBlock) + ")", "apply (rule " + afterOptProgAccess.BlockInfo().BlockCmdsMembershipLemma(afterBlock) + ")", "apply (unfold " + afterOptProgAccess.BlockInfo().CmdsQualifiedName(afterBlock) +"_def)" From 5c85cef8a09f96386b129608e616f6ea394a083b Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Sat, 21 Sep 2024 12:58:54 +0200 Subject: [PATCH 108/123] remove desugared version of DivMod --- .../modified/DivMod_if_stmt.bpl | 69 ------------------- 1 file changed, 69 deletions(-) delete mode 100644 ProofGenerationBenchmarks/external_benchmarks/modified/DivMod_if_stmt.bpl diff --git a/ProofGenerationBenchmarks/external_benchmarks/modified/DivMod_if_stmt.bpl b/ProofGenerationBenchmarks/external_benchmarks/modified/DivMod_if_stmt.bpl deleted file mode 100644 index bfefa3942..000000000 --- a/ProofGenerationBenchmarks/external_benchmarks/modified/DivMod_if_stmt.bpl +++ /dev/null @@ -1,69 +0,0 @@ -function abs(x: int): int; -axiom (forall x: int :: ( 0<= x ==> abs(x) == x) && ( (!(0 <= x)) ==> abs(x) == -x)); -function divt(int, int): int; -function modt(int, int): int; -axiom (forall a,b: int :: divt(a,b)*b + modt(a,b) == a); -axiom (forall a,b: int :: - (0 <= a ==> 0 <= modt(a,b) && modt(a,b) < abs(b)) && - (a < 0 ==> -abs(b) < modt(a,b) && modt(a,b) <= 0)); -function dive(int, int): int; -function mode(int, int): int; -axiom (forall a,b: int :: dive(a,b)*b + mode(a,b) == a); -axiom (forall a,b: int :: 0 <= mode(a,b) && mode(a,b) < abs(b)); -procedure T_from_E(a,b: int) returns (q,r: int) - requires b != 0; - ensures q*b + r == a; - ensures 0 <= a ==> 0 <= r && r < abs(b); - ensures a < 0 ==> -abs(b) < r && r <= 0; -{ - var qq,rr: int; - qq := dive(a,b); - rr := mode(a,b); - if(0 <= a || rr == 0) { - q := qq; - } else { - if (0<=b) { - q := qq+1; - } else { - q := qq-1; - } - } - if (0 <= a || rr == 0) { - r := rr; - } else { - if(0 <= b) { - r := rr-b; - } else { - r := rr+b; - } - } - assume true; -} -procedure E_from_T(a,b: int) returns (q,r: int) - requires b != 0; - ensures q*b + r == a; - ensures 0 <= r; - ensures r < abs(b); -{ - var qq,rr: int; - qq := divt(a,b); - rr := modt(a,b); - if(0 <= rr) { - q := qq; - } else { - if (0< b) { - q := qq-1; - } else { - q := qq+1; - } - } - if (0 <= rr) { - r := rr; - } else { - if(0 < b) { - r := rr+b; - } else { - r := rr-b; - } - } -} From 542bcb0b38323baf3b79fafb2da28ba0daa95c50 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Tue, 24 Sep 2024 12:11:49 +0200 Subject: [PATCH 109/123] proofGenConfig must be reset for every procedure --- Source/ProofGeneration/ProofGenerationLayer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/ProofGeneration/ProofGenerationLayer.cs b/Source/ProofGeneration/ProofGenerationLayer.cs index 6a30c980c..166f649a1 100644 --- a/Source/ProofGeneration/ProofGenerationLayer.cs +++ b/Source/ProofGeneration/ProofGenerationLayer.cs @@ -79,7 +79,7 @@ public class ProofGenerationLayer private static Block uniqueExitBlockOrig; //new ProofGenConfig().AllOptionsDisabled().SetCfgOptProof(true); - private static ProofGenConfig _proofGenConfig = new ProofGenConfig().AllOptionsEnabled(); + // //private static ProofGenConfig _proofGenConfig = new ProofGenConfig().AllOptionsDisabled().SetCfgOptProof(true); private static IProgramAccessor globalDataProgAccess; @@ -590,6 +590,7 @@ public static void VCGenerateAllProofs( { var map = AstToCfgProofGenInfoManager.GetImplToProofGenInfo(); proofGenInfo = map[afterPassificationImpl]; + ProofGenConfig _proofGenConfig = new ProofGenConfig().AllOptionsEnabled(); if (AstContainsGotoOrBreakOrElseIf(proofGenInfo)) { From 6c751367cbfe685c79b04524cfaa51de7c4dc31b Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Thu, 21 Nov 2024 10:16:05 +0100 Subject: [PATCH 110/123] update foundational_boogie to Isabelle 2024 --- foundational_boogie | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundational_boogie b/foundational_boogie index 91cded06b..63cb964f8 160000 --- a/foundational_boogie +++ b/foundational_boogie @@ -1 +1 @@ -Subproject commit 91cded06bdcc0e5245c852d125c54c69ad619d81 +Subproject commit 63cb964f8d9442e552c45f098f2f618684b0cf47 From 57c6b527b708129b3120991bc40acb7e5a9a5fb7 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 4 Dec 2024 16:42:40 +0100 Subject: [PATCH 111/123] minor analysis script adjustments and rename Lit to LitA in issue-32.bpl to avoid Isabelle Lit clash --- .../test20/issue-32.bpl | 4 +++- etc/scripts/boogie_proofs_analysis.py | 22 ++++++++++--------- etc/scripts/count_lines.py | 2 +- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/test20/issue-32.bpl b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/test20/issue-32.bpl index f980a2c78..709c383aa 100644 --- a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/test20/issue-32.bpl +++ b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/test20/issue-32.bpl @@ -3,8 +3,10 @@ // RUN: %diff "%s.expect" "%t" function Lit(x: T) : T; axiom Lit(true); +function LitA(x: T) : T; //renamed Lit to LitA to avoid Isabelle Lit clash +axiom LitA(true); procedure test() { - assert Lit(true); + assert LitA(true); } diff --git a/etc/scripts/boogie_proofs_analysis.py b/etc/scripts/boogie_proofs_analysis.py index 99b537c39..b29bde24d 100644 --- a/etc/scripts/boogie_proofs_analysis.py +++ b/etc/scripts/boogie_proofs_analysis.py @@ -15,6 +15,7 @@ class EndToEndKind(Enum): class TestData(typ.NamedTuple): file: str num_procedure_proofs: int + boogie_loc: int isabelle_loc: int end_to_end_proof: List[EndToEndKind] # for each procedure proof provides end-to-end proof kind (i.e., length should match num_procedures) @@ -68,15 +69,18 @@ def cfg_end_to_end(): print("ERROR: no end-to-end theorem found in {}".format(dir)) exit(1) +def count_non_empty_lines(file_path): + file_content = open(file_path, "r") + nonempty_lines = [line for line in file_content if line.strip()] + return len(nonempty_lines) + def certificate_size(proof_dir_path) -> int: length_certificate = 0 for root, dirs, files in os.walk(proof_dir_path): for file in files: if file.endswith('.thy'): file_path = os.path.join(os.path.join(proof_dir_path, root), file) - file_content = open(file_path, "r") - nonempty_lines = [line for line in file_content if line.strip()] - length_certificate += len(nonempty_lines) + length_certificate += count_non_empty_lines(file_path) return length_certificate @@ -88,7 +92,7 @@ def count_num_abstract_procs(lines) -> int: count += len(matches) return count -def collect_data_single_boogie_file(proof_dir_path, num_procedures): +def collect_data_single_boogie_file(proof_dir_path, boogie_loc): e2e_proof_kinds = [] num_procedure_proofs = 0 for procedure_proof in os.listdir(proof_dir_path): @@ -109,7 +113,7 @@ def collect_data_single_boogie_file(proof_dir_path, num_procedures): exit(1) """ - return TestData(file=os.path.basename(proof_dir_path), num_procedure_proofs=num_procedure_proofs, isabelle_loc=certificate_size(proof_dir_path),end_to_end_proof=e2e_proof_kinds) + return TestData(file=os.path.basename(proof_dir_path), num_procedure_proofs=num_procedure_proofs, boogie_loc = boogie_loc, isabelle_loc=certificate_size(proof_dir_path),end_to_end_proof=e2e_proof_kinds) def collect_complete_data(boogie_files_dir, boogie_proofs_dir) -> List[TestData]: data = [] @@ -144,8 +148,6 @@ def collect_complete_data(boogie_files_dir, boogie_proofs_dir) -> List[TestData] boogie_file_content = [line for line in open(boogie_file_path,'r')] num_procedures = len([line for line in boogie_file_content if line.strip(" ").startswith("procedure ")]) - num_abstract_procedures = count_num_abstract_procs(boogie_file_content) #TODO: this computation of abstract procedures is incorrect - num_concrete_procedures = num_procedures - num_abstract_procedures #if num_abstract_procedures > 0: #print("{} has {} abstract procedures".format(boogie_file_path, num_abstract_procedures)) @@ -156,7 +158,7 @@ def collect_complete_data(boogie_files_dir, boogie_proofs_dir) -> List[TestData] exit(1) """ - data.append(collect_data_single_boogie_file(proof_dir_path, num_concrete_procedures)) + data.append(collect_data_single_boogie_file(proof_dir_path, count_non_empty_lines(boogie_file_path))) return data @@ -164,10 +166,10 @@ def write_data_into_csv(data : List[TestData], output_file): with open(output_file, 'w', newline='') as output: writer = csv.writer(output, delimiter=',') - writer.writerow(["File", "# Procs", "Isabelle LOC", "E2E Kind"]) + writer.writerow(["File", "# Procs", "Boogie LOC", "Isabelle LOC", "E2E Kind"]) for d in data: e2e_repr = " ".join(e.name for e in d.end_to_end_proof) - writer.writerow([d.file, d.num_procedure_proofs, d.isabelle_loc, e2e_repr]) + writer.writerow([d.file, d.num_procedure_proofs, d.boogie_loc, d.isabelle_loc, e2e_repr]) def main(): diff --git a/etc/scripts/count_lines.py b/etc/scripts/count_lines.py index b15ca215d..666c31780 100644 --- a/etc/scripts/count_lines.py +++ b/etc/scripts/count_lines.py @@ -13,7 +13,7 @@ def print_theory_line_info(input_dir): has_theories = True file_path = os.path.join(os.path.join(dir_path, root), file) file_content = open(file_path, "r") - nonempty_lines = [line.strip("\n") for line in file_content if line != "\n"] + nonempty_lines = [line for line in file_content if line.strip()] length_certificate += len(nonempty_lines) if has_theories: From effb1076a7191bf3805376f397b2ee18f8330f9e Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Wed, 4 Dec 2024 19:44:01 +0100 Subject: [PATCH 112/123] minor -> fix rewrite issue-32.bpl --- .../boogie_testsuite_benchmarks/test20/issue-32.bpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/test20/issue-32.bpl b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/test20/issue-32.bpl index 709c383aa..b3d4c45d8 100644 --- a/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/test20/issue-32.bpl +++ b/ProofGenerationBenchmarks/boogie_testsuite_benchmarks/test20/issue-32.bpl @@ -1,9 +1,9 @@ //:: ProofGen(IgnoreFile) // RUN: %boogie "%s" > "%t" // RUN: %diff "%s.expect" "%t" -function Lit(x: T) : T; -axiom Lit(true); -function LitA(x: T) : T; //renamed Lit to LitA to avoid Isabelle Lit clash + +/** MANUEL REWRITE renamed Lit to LitA to avoid Isabelle Lit clash **/ +function LitA(x: T) : T; axiom LitA(true); procedure test() From 5292d74cf562b3f45d9ddd9263490595e95e837b Mon Sep 17 00:00:00 2001 From: gauravpartha <49554253+gauravpartha@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:23:38 +0100 Subject: [PATCH 113/123] Update README.md --- README.md | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index cf56b4c62..9956397e5 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ supported subset). The goal of this project is to increase the reliability of the Boogie verifier. Whenever the tool is run on a program, the proof generation extension generates -an Isabelle proof that shows a transformed version of the input program is +an Isabelle proof that shows that the input program is correct under the assumption of the VC that Boogie generates. Most of the source code in the `Source` folder is directly forked from the original @@ -22,7 +22,8 @@ Boogie performs various transformations on the input program before finally generating an AST. For the default Boogie options, the steps performed by Boogie are roughly as follows (and also in this order): -1. Parse source AST program to an internal CFG representation (from this point onwards +1. Parse input program into AST representation +1. Transform AST program to an internal CFG representation (from this point onwards only CFG representations are used) 2. Basic transformations 1: eliminate dead variables, coalesce blocks, prune unreachable blocks 3. CFG-to-DAG phase: eliminate cycles via loop invariants @@ -34,9 +35,12 @@ constant propagation 6. Basic transformations 3: Remove empty blocks, prune unreachable blocks 7. VC phase: generate VC using weakest precondition -Our certificate shows for each procedure that the CFG right before the CFG-to-DAG -phase is correct under the assumption of the VC. That is, we support all the -transformation listed above except those listed in points 1 and 2. +For a large part of our supported subset, our generated certificate shows that the input Boogie program represented +as an AST program (i.e., the representation after parsing) is correct under the assumption of the VC. +For some parts of our subset, we support only the validation of a subset of the transformation: +In particular, we currently do not support gotos and breaks in the AST-to-CFG transformation, and we also do not support the elimination of dead variables. +If the input program has gotos or breaks, and dead variables, then our generated certificate shows that the CFG representation *after* dead variable elimination (but before block coalescing) +is correct under the assumption of the VC (so, we can handle representations of gotos and breaks in CFGs). ## Modifications to the VC We change the VC that Boogie generates in the following ways: @@ -59,14 +63,11 @@ language features, we currently support: * Most operations on integers/booleans * Type and value quantification * Old expressions -* Any gotos/labels/while loops that Boogie accepts +* Any gotos/labels/while loops that Boogie accepts for the CFG transformations (but not yet for the AST-to-CFG transformation) * Commands: assertions, assumptions, assignments, havocs -Moreover, we currently do not support files that contain type constructors without -any polymorphism. The reason is that Boogie currently monomorphizes such programs, -which leads to a different VC. If you want to try such programs, just add some -polymorphic function to the program such as `function test(x:T):T` (that -does not have to be used anywhere). +We currently support only Boogie's type encoding in the VC given by the command-line option `/typeEncoding:p`. In particular, +we do not support Boogie's monomorphization type encoding. ## Dependencies Our tool has the same dependencies as Boogie for the generation of Isabelle proofs: @@ -74,11 +75,15 @@ Our tool has the same dependencies as Boogie for the generation of Isabelle proo * a supported SMT solver (see the [original Boogie repository](https://github.com/boogie-org/boogie) for details) -To check Isabelle proofs, one additionally requires Isabelle 2021, as well as +To check Isabelle proofs, one additionally requires Isabelle 2022, as well as an installation of the Isabelle session that provides the [formalization of Boogie](https://github.com/gauravpartha/foundational_boogie/). Installation of this session can be done by adding the path to `foundational_boogie/BoogieLang` -to the `ROOTS` file in the Isabelle home directory. +to the `ROOTS` file in the Isabelle home directory, or by running + +``` +isabelle components add -u foundational_boogie/BoogieLang +``` ## Building @@ -114,4 +119,4 @@ implies correctness of the input CFG of the CFG-to-DAG phase. When using the tool, one currently needs to make sure that no special characters are used that are reserved in Isabelle (such as `#` or `'`). Moreover, for files that do not verify, the tool cannot provide detailed information, since -the counterexample information is not available. \ No newline at end of file +the counterexample information is not available. From a378768c9fe3471cd47fd6028e596bb036cf19de Mon Sep 17 00:00:00 2001 From: gauravpartha <49554253+gauravpartha@users.noreply.github.com> Date: Sun, 8 Dec 2024 16:21:26 +0100 Subject: [PATCH 114/123] Update README.md README minor --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9956397e5..9d231e729 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ constant propagation For a large part of our supported subset, our generated certificate shows that the input Boogie program represented as an AST program (i.e., the representation after parsing) is correct under the assumption of the VC. -For some parts of our subset, we support only the validation of a subset of the transformation: +For some parts of our subset, we support only the validation of a subset of the transformations: In particular, we currently do not support gotos and breaks in the AST-to-CFG transformation, and we also do not support the elimination of dead variables. If the input program has gotos or breaks, and dead variables, then our generated certificate shows that the CFG representation *after* dead variable elimination (but before block coalescing) is correct under the assumption of the VC (so, we can handle representations of gotos and breaks in CFGs). @@ -113,8 +113,8 @@ directory already exists) in which the proofs are stored. In the proof generation output folder, a separate folder is created for each procedure. There are multiple Isabelle theory files in each folder. The main theorem for the procedure is the last Isabelle lemma in the file with the suffix -`cfg_to_dag_proof.thy`. This final lemma shows that the validity of the VC -implies correctness of the input CFG of the CFG-to-DAG phase. +`asttocfg_proof.thy` (if the AST-to-CFG or dead variable elimination is not supported, +then the relevant file ends with `cfgtodag_proof.thy` or `cfgoptimizations_proof.thy`. When using the tool, one currently needs to make sure that no special characters are used that are reserved in Isabelle (such as `#` or `'`). Moreover, for From 5c704ab5d1a1b7e10f836c97069a044ecc486148 Mon Sep 17 00:00:00 2001 From: gauravpartha Date: Sun, 8 Dec 2024 18:19:43 +0100 Subject: [PATCH 115/123] Transfer gauravpartha/foundational_boogie to viperproject/foundational-boogie --- .github/workflows/ci.yml | 6 +++--- .gitmodules | 6 +++--- foundational-boogie | 1 + foundational_boogie | 1 - 4 files changed, 7 insertions(+), 7 deletions(-) create mode 160000 foundational-boogie delete mode 160000 foundational_boogie diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9508aa817..2e0122b95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,8 +60,8 @@ jobs: # for the session so that it does not have to rechecked every time - name: Set up Isabelle Boogie language session run: | - echo "$PWD/foundational_boogie/BoogieLang" >> isabelle_dir/ROOTS - isabelle_dir/bin/isabelle build -b -j4 -d $PWD/foundational_boogie/BoogieLang Boogie_Lang + echo "$PWD/foundational-boogie/BoogieLang" >> isabelle_dir/ROOTS + isabelle_dir/bin/isabelle build -b -j4 -d $PWD/foundational-boogie/BoogieLang Boogie_Lang - name: Check external benchmark proofs run: | @@ -83,4 +83,4 @@ jobs: - name: Check Boogie benchmark proofs run: | - python3 etc/scripts/check_proofs.py --inputdir boogie_benchmarks_proofs --reps 1 \ No newline at end of file + python3 etc/scripts/check_proofs.py --inputdir boogie_benchmarks_proofs --reps 1 diff --git a/.gitmodules b/.gitmodules index 892c2c7c4..60e687d2c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ -[submodule "foundational_boogie"] - path = foundational_boogie - url = https://github.com/gauravpartha/foundational_boogie +[submodule "foundational-boogie"] + path = foundational-boogie + url = https://github.com/viperproject/foundational-boogie branch = cfg_optimizations diff --git a/foundational-boogie b/foundational-boogie new file mode 160000 index 000000000..90411340a --- /dev/null +++ b/foundational-boogie @@ -0,0 +1 @@ +Subproject commit 90411340ac568c7870e85dd9ec627b84f01e79a3 diff --git a/foundational_boogie b/foundational_boogie deleted file mode 160000 index 63cb964f8..000000000 --- a/foundational_boogie +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 63cb964f8d9442e552c45f098f2f618684b0cf47 From f5469170939d7cf915ea3878f34d7fb8dfb2e808 Mon Sep 17 00:00:00 2001 From: gauravpartha <49554253+gauravpartha@users.noreply.github.com> Date: Sun, 8 Dec 2024 18:23:47 +0100 Subject: [PATCH 116/123] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9d231e729..09e12bf92 100644 --- a/README.md +++ b/README.md @@ -77,12 +77,12 @@ for details) To check Isabelle proofs, one additionally requires Isabelle 2022, as well as an installation of the Isabelle session that provides the [formalization of -Boogie](https://github.com/gauravpartha/foundational_boogie/). Installation -of this session can be done by adding the path to `foundational_boogie/BoogieLang` +Boogie](https://github.com/gauravpartha/foundational-boogie/). Installation +of this session can be done by adding the path to `foundational-boogie/BoogieLang` to the `ROOTS` file in the Isabelle home directory, or by running ``` -isabelle components add -u foundational_boogie/BoogieLang +isabelle components add -u foundational-boogie/BoogieLang ``` ## Building From d16ad50a92ca043b1a8427f81fa1b121e6efe6bd Mon Sep 17 00:00:00 2001 From: gauravpartha <49554253+gauravpartha@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:21:12 +0100 Subject: [PATCH 117/123] Update README.md --- README.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 09e12bf92..cef711fde 100644 --- a/README.md +++ b/README.md @@ -54,9 +54,10 @@ with a "null" argument where a counterexample-related argument is expected. ## Supported subset -We currently support only the default Boogie options and we do not -support any attributes (the subsumption attribute is one exception). In terms of -language features, we currently support: +We currently support only the default Boogie options except for the type encoding where we support only the command-line option `/typeEncoding:p` +(for non-monomorphizable program, the option `/typeEncoding:p` is the default option in this version of Boogie). We do not support any attributes (the subsumption attribute is one exception). + +In terms of language features, we currently support: * Integers and booleans * Type constructors * (Polymorphic) functions @@ -66,9 +67,6 @@ language features, we currently support: * Any gotos/labels/while loops that Boogie accepts for the CFG transformations (but not yet for the AST-to-CFG transformation) * Commands: assertions, assumptions, assignments, havocs -We currently support only Boogie's type encoding in the VC given by the command-line option `/typeEncoding:p`. In particular, -we do not support Boogie's monomorphization type encoding. - ## Dependencies Our tool has the same dependencies as Boogie for the generation of Isabelle proofs: * [.NET Core](https://dotnet.microsoft.com) @@ -114,7 +112,7 @@ In the proof generation output folder, a separate folder is created for each procedure. There are multiple Isabelle theory files in each folder. The main theorem for the procedure is the last Isabelle lemma in the file with the suffix `asttocfg_proof.thy` (if the AST-to-CFG or dead variable elimination is not supported, -then the relevant file ends with `cfgtodag_proof.thy` or `cfgoptimizations_proof.thy`. +then the relevant file ends with `cfgtodag_proof.thy` or `cfgoptimizations_proof.thy`). When using the tool, one currently needs to make sure that no special characters are used that are reserved in Isabelle (such as `#` or `'`). Moreover, for From bc87dfce7d67b07e47f403c4199d551cde6b1629 Mon Sep 17 00:00:00 2001 From: gauravpartha <49554253+gauravpartha@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:35:53 +0100 Subject: [PATCH 118/123] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cef711fde..1104344bf 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,10 @@ with a "null" argument where a counterexample-related argument is expected. ## Supported subset -We currently support only the default Boogie options except for the type encoding where we support only the command-line option `/typeEncoding:p` -(for non-monomorphizable program, the option `/typeEncoding:p` is the default option in this version of Boogie). We do not support any attributes (the subsumption attribute is one exception). +We currently support only the default Boogie options and we do not support any attributes (the subsumption attribute is one exception). Moreover, we currently do not support files that contain type constructors without any polymorphism. The reason is that Boogie currently monomorphizes such programs, which leads to a different VC. If you want to try such programs, just add some polymorphic function to the program such as function test(x:T):T (that does not have to be used anywhere), which forces Boogie to apply the `/typeEncoding:p` command-line option (which specifies the type encoding that we do support, but which is overriden if the program is monomorphic). In terms of language features, we currently support: + * Integers and booleans * Type constructors * (Polymorphic) functions From 3d7e6cc85012e79197e36ddef5f7a31c5c47ed3d Mon Sep 17 00:00:00 2001 From: gauravpartha <49554253+gauravpartha@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:37:28 +0100 Subject: [PATCH 119/123] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1104344bf..a031b6be7 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ with a "null" argument where a counterexample-related argument is expected. ## Supported subset -We currently support only the default Boogie options and we do not support any attributes (the subsumption attribute is one exception). Moreover, we currently do not support files that contain type constructors without any polymorphism. The reason is that Boogie currently monomorphizes such programs, which leads to a different VC. If you want to try such programs, just add some polymorphic function to the program such as function test(x:T):T (that does not have to be used anywhere), which forces Boogie to apply the `/typeEncoding:p` command-line option (which specifies the type encoding that we do support, but which is overriden if the program is monomorphic). +We currently support only the default Boogie options and we do not support any attributes (the subsumption attribute is one exception). Moreover, we currently do not support files that contain type constructors without any polymorphism. The reason is that Boogie currently monomorphizes such programs, which leads to a different VC. If you want to try such programs, just add some polymorphic function to the program such as `function test(x:T):T` (that does not have to be used anywhere), which forces Boogie to apply the `/typeEncoding:p` command-line option (which specifies the type encoding that we do support, but adding this option explicitly is overriden if the program is monomorphizable). In terms of language features, we currently support: From 2693516f9545576256f3eee51fbe4723b6e4d6a9 Mon Sep 17 00:00:00 2001 From: gauravpartha <49554253+gauravpartha@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:38:45 +0100 Subject: [PATCH 120/123] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a031b6be7..3bd124def 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ with a "null" argument where a counterexample-related argument is expected. ## Supported subset -We currently support only the default Boogie options and we do not support any attributes (the subsumption attribute is one exception). Moreover, we currently do not support files that contain type constructors without any polymorphism. The reason is that Boogie currently monomorphizes such programs, which leads to a different VC. If you want to try such programs, just add some polymorphic function to the program such as `function test(x:T):T` (that does not have to be used anywhere), which forces Boogie to apply the `/typeEncoding:p` command-line option (which specifies the type encoding that we do support, but adding this option explicitly is overriden if the program is monomorphizable). +We currently support only the default Boogie options and we do not support any attributes (the subsumption attribute is one exception). Moreover, we currently do not support files that contain type constructors without any polymorphism. The reason is that Boogie currently monomorphizes such programs, which leads to a different VC. If you want to try such programs, just add some polymorphic function to the program such as `function test(x:T):T` (that does not have to be used anywhere), which forces Boogie to apply the `/typeEncoding:p` command-line option (which specifies the type encoding that we do support, but adding this option explicitly is overriden if the program is monomorphic). In terms of language features, we currently support: From 871e83fd56c341df082e91eca3a5548460cacb5a Mon Sep 17 00:00:00 2001 From: gauravpartha <49554253+gauravpartha@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:41:18 +0100 Subject: [PATCH 121/123] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3bd124def..ee76d30d2 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ with a "null" argument where a counterexample-related argument is expected. ## Supported subset -We currently support only the default Boogie options and we do not support any attributes (the subsumption attribute is one exception). Moreover, we currently do not support files that contain type constructors without any polymorphism. The reason is that Boogie currently monomorphizes such programs, which leads to a different VC. If you want to try such programs, just add some polymorphic function to the program such as `function test(x:T):T` (that does not have to be used anywhere), which forces Boogie to apply the `/typeEncoding:p` command-line option (which specifies the type encoding that we do support, but adding this option explicitly is overriden if the program is monomorphic). +We currently support only the default Boogie options and we do not support any attributes (the subsumption attribute is one exception). Moreover, we currently do not support files that contain type constructors without any polymorphism. The reason is that Boogie currently monomorphizes such programs, which leads to a different VC. If you want to try such programs, just add some polymorphic function to the program such as `function test(x:T):T` (that does not have to be used anywhere), which forces Boogie to apply the `/typeEncoding:p` command-line option (which specifies the type encoding that we do support, but this command-line option is overriden if the program is monomorphic). In terms of language features, we currently support: From b25cfe03e3a181f73f0b267fceee21fbb9d5ba62 Mon Sep 17 00:00:00 2001 From: gauravpartha <49554253+gauravpartha@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:52:50 +0100 Subject: [PATCH 122/123] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ee76d30d2..8d19d6e08 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,8 @@ In the proof generation output folder, a separate folder is created for each procedure. There are multiple Isabelle theory files in each folder. The main theorem for the procedure is the last Isabelle lemma in the file with the suffix `asttocfg_proof.thy` (if the AST-to-CFG or dead variable elimination is not supported, -then the relevant file ends with `cfgtodag_proof.thy` or `cfgoptimizations_proof.thy`). +then the relevant file ends with `cfgoptimizations_proof.thy` in general, but if we detect that the initial +CFG optimizations ("basic transformations 1" above) had no effect, then the relevant file ends with `cfgtodag_proof.thy`). When using the tool, one currently needs to make sure that no special characters are used that are reserved in Isabelle (such as `#` or `'`). Moreover, for From 4e2be7b0eff0ee7842927d41db4b94e03cb3b95e Mon Sep 17 00:00:00 2001 From: gauravpartha <49554253+gauravpartha@users.noreply.github.com> Date: Mon, 9 Dec 2024 17:55:00 +0100 Subject: [PATCH 123/123] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8d19d6e08..adabfafe0 100644 --- a/README.md +++ b/README.md @@ -111,9 +111,9 @@ directory already exists) in which the proofs are stored. In the proof generation output folder, a separate folder is created for each procedure. There are multiple Isabelle theory files in each folder. The main theorem for the procedure is the last Isabelle lemma in the file with the suffix -`asttocfg_proof.thy` (if the AST-to-CFG or dead variable elimination is not supported, +`asttocfg_proof.thy` in general. If the AST-to-CFG or dead variable elimination is not supported, then the relevant file ends with `cfgoptimizations_proof.thy` in general, but if we detect that the initial -CFG optimizations ("basic transformations 1" above) had no effect, then the relevant file ends with `cfgtodag_proof.thy`). +CFG optimizations ("basic transformations 1" above) had no effect, then the relevant file ends with `cfgtodag_proof.thy`. When using the tool, one currently needs to make sure that no special characters are used that are reserved in Isabelle (such as `#` or `'`). Moreover, for